<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Graham Long</title>
    <description>The latest articles on Forem by Graham Long (@longevitysoftware).</description>
    <link>https://forem.com/longevitysoftware</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F352959%2Fb6711f7b-493f-45b5-ac08-914d0e6a746c.jpeg</url>
      <title>Forem: Graham Long</title>
      <link>https://forem.com/longevitysoftware</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/longevitysoftware"/>
    <language>en</language>
    <item>
      <title>Gamedevlog: Tilemap Part 3d</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 01 Nov 2020 17:04:26 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-3d-4phm</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-3d-4phm</guid>
      <description>&lt;h1&gt;
  
  
  Generating a test map
&lt;/h1&gt;

&lt;p&gt;The first thing I did for this development was to generate a test map, I created 4 new simple tiles in blender:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One with a straight path running through it&lt;/li&gt;
&lt;li&gt;One with a T Junction path&lt;/li&gt;
&lt;li&gt;One which had a crossroads&lt;/li&gt;
&lt;li&gt;One which had a 90° Corner path&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I then mocked up a simple map in Paint, see below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--znf3vkmF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qon0c2zqz30agx4wob3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--znf3vkmF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qon0c2zqz30agx4wob3p.png" alt="Test map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then updated the existing .VTF files and created the necessary new ones to bring this level to life in my game.&lt;/p&gt;

&lt;p&gt;It immediately became apparent that to do this I would need to be able to rotate the base tile model, so I added a new line to the .vtf files, the new line used &lt;code&gt;BR&lt;/code&gt; (Base Rotation) tags and had the possible values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;None&lt;/code&gt; - No rotation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Left&lt;/code&gt; - 90° Rotation Left&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Right&lt;/code&gt; - 90° Rotation Right&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Flip&lt;/code&gt; - 180° Rotation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I then needed to pass this to the Tile class and parse it to apply the correct rotation to the model. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WN2ItBBc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/smqi5ptablzbv2qae9s3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WN2ItBBc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/smqi5ptablzbv2qae9s3.PNG" alt="Parsing the base model rotation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this was done, The test map was recreated as expected in the game and I could walk around from one end to the next and back again.&lt;/p&gt;

&lt;h1&gt;
  
  
  Dealing with Diagonal movement between tiles
&lt;/h1&gt;

&lt;p&gt;This was an outstanding issue from the Last development and was only a slight change compared to the already implemented single direction movements.&lt;br&gt;
I started by calculating where the players trajectory would intersect both of the edges that the player crosses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jV-jv68I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zy5o371f5o61o9k07mu0.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jV-jv68I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zy5o371f5o61o9k07mu0.PNG" alt="Two intersections"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then I calculated the distance from the start position to each of the intersection points. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Bg68wJoT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pabxbaelez6yj4ctjgub.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Bg68wJoT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pabxbaelez6yj4ctjgub.PNG" alt="Distance calcs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whichever point is the closest is the point that the player leaves the current tile, special consideration must be given to when the player leaves the tile at one of the corners i.e. when the intersection distance is equal for both edges, knowing this we can set the intersection point and adjust the tile accordingly.&lt;/p&gt;

&lt;p&gt;The Calculations for each of the 3 possibilities is nearly identical so I shall just show one:&lt;/p&gt;

&lt;p&gt;The intersection point is selected based on which point is closest and the next tile and offset are then set based on which way the tile map is shifting. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZM-sKXIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d5dvgv7g5lcu4nqrb9s8.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZM-sKXIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d5dvgv7g5lcu4nqrb9s8.PNG" alt="intersection calculation and offset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;currentTile&lt;/code&gt; is adjusted the same way as in the previous development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ULINz7sK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k8miu8q10viz4p8u5pkj.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ULINz7sK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k8miu8q10viz4p8u5pkj.PNG" alt="Setting the next tile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding to the map
&lt;/h1&gt;

&lt;p&gt;After a short period playing the demo map I soon grew tired of the look of the paths, and set all the tiles to have the grass base model.&lt;/p&gt;

&lt;p&gt;I then decided to add the ability to add models to each of the tiles, to do this I needed to specify the following in the .vtf files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The object to place on the map.&lt;/li&gt;
&lt;li&gt;The position of the object relative to the tile.&lt;/li&gt;
&lt;li&gt;The rotation of the object (only Y axis rotation for now).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The easiest way to implement this for now was on a single line, starting with a &lt;code&gt;GO&lt;/code&gt; (Game Object) tag, followed by the x offset, y offset, z offset, rotation and a final closing &lt;code&gt;GO&lt;/code&gt; tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aSjNHruq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/flz1k58mabzm5dnd8r5x.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aSjNHruq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/flz1k58mabzm5dnd8r5x.PNG" alt="Game Object Definition in VTF file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I created two models to test this out, a new rock model and a tree model which I extracted from the previous tree base model.&lt;/p&gt;

&lt;p&gt;Next I updated the &lt;code&gt;VrTileFormatParser&lt;/code&gt; class to parse the Game Object definitions and pass them onto the generated tile class as an &lt;code&gt;ArrayList&lt;/code&gt; called &lt;code&gt;gameObjects&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--492TXs6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nos5xlvs9hkekquxh44v.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--492TXs6q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nos5xlvs9hkekquxh44v.PNG" alt="gameObjects ArrayList definition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Parsing the GO tags was slightly more involved than the other tags as there are multiple information points on the single line, but this is no more complicated than parsing the obj files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mup2hAcr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2owrq4e3g77hy0c4ghgo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mup2hAcr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2owrq4e3g77hy0c4ghgo.PNG" alt="Parsing GO Tags"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally I needed to process the game object data in the &lt;code&gt;Tile&lt;/code&gt; class, in the &lt;code&gt;initialise&lt;/code&gt; method I added a loop to go through all the &lt;code&gt;Triple&lt;/code&gt;s passed into the class and create/modify objects based on their values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KeT4MHKP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cod16u6lsfgxbr3sdgur.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KeT4MHKP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cod16u6lsfgxbr3sdgur.PNG" alt="Adding Game Objects to a tile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;This seems to work pretty well, I have one tile with a few trees and rocks dotted across it and it looks pretty cool so far, it does remain to be seen if there are any performance issues with this but that can be looked at in future. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X7lbRpqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kmxjjilf8u1n0q1zork5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X7lbRpqG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kmxjjilf8u1n0q1zork5.png" alt="Populated Tile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One final thing, As this platform (dev.to) doesn't seem to have any other game development logs on it, I am going to move this one to somewhere more appropriate, when I decide where this will be I shall update this post with details.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Gamedevlog: TileMap Part 3c</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 25 Oct 2020 20:29:54 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-3c-bdm</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-3c-bdm</guid>
      <description>&lt;h1&gt;
  
  
  Determining where the player leaves the tile
&lt;/h1&gt;

&lt;p&gt;To continue where I left off last time I found the following formula on &lt;a href="https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection"&gt;wikipedia&lt;/a&gt;, which can be used to determine where two lines cross, I used this to determine where the players trajectory and the edge of the tile cross and therefore the point that the player leaves the tile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c6Tk1S-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k6iwk77hnsj0vkenzd4h.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c6Tk1S-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k6iwk77hnsj0vkenzd4h.PNG" alt="line line  intersect formula"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I plan on using this in multiple places I created a function which takes the start and end points of two lines and returns the position that the two lines intersect. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JEkEEiCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0zvy2l4wtevlqvjcnpms.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JEkEEiCv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0zvy2l4wtevlqvjcnpms.PNG" alt="line line intersect function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Some future improvements (TODOs)
&lt;/h3&gt;

&lt;p&gt;I know some people do not like putting TODOs in comments but for me it is a great way of keeping in the flow of coding without forgetting some of the smaller things which I can see will need tidying up or fixing. &lt;/p&gt;

&lt;p&gt;As can be seen in the comments above, this function does not check if the lines are parallel, there would be a division by zero if they were, which would crash the application, but as the function is only called to get the intersection point after checking that the two lines intersect, I shall add a TODO in the comments to remind me that there should be a check in for 0.0 value divisor.&lt;/p&gt;

&lt;p&gt;Also in the comments I have put a TODO to remind me that for this function it would make more sense to create a 2D version of &lt;code&gt;Position3Float&lt;/code&gt; and use that instead of &lt;code&gt;Position3Float&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Calculating where the player ends up on the tile map
&lt;/h1&gt;

&lt;p&gt;This is where things got complicated, so far I have only catered for the player moving up, down, left or right and not diagonally in any direction. &lt;/p&gt;

&lt;p&gt;The general flow of processing the player movement goes like this:&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_OJ0jYaY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0t4ne07m2v30re6ehq65.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_OJ0jYaY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0t4ne07m2v30re6ehq65.PNG" alt="Setup code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hopefully the comments explain what each variable here is for, some additional things to note are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;distanceTravelled&lt;/code&gt; must be set to anything except 0.0f otherwise the next loop will never be entered.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;endPosition&lt;/code&gt; is used to make up the returned position, setting it to the start position means if anything goes wrong the player will not move at all.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Checking if the player is still moving and has distance left to travel
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y4SlOFW---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2trhh589rjfdn3ypbnhp.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y4SlOFW---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2trhh589rjfdn3ypbnhp.PNG" alt="Main loop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This loop repeats while the player can still move and is still moving.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculating where the player would like to move to
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6DO_xgPn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qj5zs2qz5oxlxk9p2fwn.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6DO_xgPn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qj5zs2qz5oxlxk9p2fwn.PNG" alt="calculating travel position"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This takes the remaining distance and applies the fluidity of the current tile to work out how far the player will travel along this tile, it then multiplies the distance by the normalised direction vector and adds it to the start position to calculate where the player would end up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does this take the player to a new tile?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sbymHpmb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ckbk1ymoix1ar65im1rr.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sbymHpmb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ckbk1ymoix1ar65im1rr.PNG" alt="Changing tile code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code is similar to the existing code for checking for tile changes.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Finalise where the player moves to on this tile
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--faWUDagz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h75janmw10qj615iux2n.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--faWUDagz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h75janmw10qj615iux2n.PNG" alt="Where the player moves when statement"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is performed in a big when statement to allow each direction to be separate, at the minute, because I have not coded the diagonal transitions yet, the process is similar for each direction:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calculate where the players trajectory intersects the edge of the tile.&lt;/li&gt;
&lt;li&gt;Calculate the index of the tile the player is moving to.&lt;/li&gt;
&lt;li&gt;If the tile the player is moving to has a non 0.0 fluidity value then the &lt;code&gt;endPosition&lt;/code&gt; will be where the player intersects the tile edge - the tile size to wrap around to the opposite side of the tile like we did in the previous code.
The &lt;code&gt;currentTile&lt;/code&gt; is also updated as the player has now transitioned to this new tile.&lt;/li&gt;
&lt;li&gt;Otherwise the &lt;code&gt;endPosition&lt;/code&gt; will be where the player intersects the tile edge.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This does give a slight overlap between one tile and the next, e.g. any point at the edge of one tile is also technically on the edge of another tile as well.&lt;br&gt;
Whether this is of any consequence remains to be seen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the distances traveled and remaining
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gGRynCNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ke3gfmwunc2uqt3a58fc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gGRynCNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ke3gfmwunc2uqt3a58fc.PNG" alt="Updating distances"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One thing that may be confusing is how &lt;code&gt;endPoint&lt;/code&gt; and &lt;code&gt;intersectionPoint&lt;/code&gt; differ, if the player is on the same tile then they both have the same value, when the player enters a new tile the &lt;code&gt;endPoint&lt;/code&gt; is where the player entered the new tile and the &lt;code&gt;intersectionPoint&lt;/code&gt; is where they left the old tile.&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating the &lt;code&gt;TileMap&lt;/code&gt; after applying the player movement
&lt;/h1&gt;

&lt;p&gt;If the tile which the player is on has changed, the center tile is updated to be the new tile and all other tiles are reset based on this new center tile.&lt;br&gt;
Then all the tile offsets are reset as before.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;This update took me a while to get motivated to start but once I did it came together quite nicely.&lt;br&gt;
I should now be able to create a complete level which the player can move around consistently. &lt;/p&gt;

&lt;p&gt;The code at this point of the project can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.14"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stay Safe and Happy Coding.&lt;br&gt;
Until next time,&lt;br&gt;
Graham&lt;/p&gt;

</description>
      <category>android</category>
      <category>vrgame</category>
      <category>devlog</category>
      <category>tilemap</category>
    </item>
    <item>
      <title>Gamedevlog: TilMap Part 3b</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 18 Oct 2020 12:09:31 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-tilmap-part-3b-58d9</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-tilmap-part-3b-58d9</guid>
      <description>&lt;h1&gt;
  
  
  Building on Part 3a
&lt;/h1&gt;

&lt;p&gt;This main purpose of this update is to expand upon the previous work to generate a level by adding the following features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an empty tile which indicates the edge of a scene.&lt;/li&gt;
&lt;li&gt;Prevent the player from entering the empty tiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The Empty Tile
&lt;/h1&gt;

&lt;p&gt;For this I generated a simple tile model in blender and exported it as obj and mtl files:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eT7hqhxl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/29e0wbmlh4td908tw71m.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eT7hqhxl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/29e0wbmlh4td908tw71m.PNG" alt="empty tile model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then created an empty tile file which can be reference by all tiles at the edge of the scene.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JWcxkcAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zlorzvy6xa9ve1s394il.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JWcxkcAy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zlorzvy6xa9ve1s394il.PNG" alt="empty tile file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  VTF File changes
&lt;/h1&gt;

&lt;p&gt;The eagle eyed among you may have notice the new &lt;code&gt;TF&lt;/code&gt; line in the vtf file. &lt;br&gt;
I added this to set the fluidity of a tile i.e. how easily the player can move through the tile, this value will be multiplied by the distance the player wishes to move to determine how far they actually move.&lt;br&gt;
Most tiles will have a value of 1.0 for this, but tiles which the player can't enter will have a value of 0.0 to prevent any movement within the tile, going forward this will also allow tiles which slow the player down e.g. quicksand or mud or even tiles which speed up the players movement.&lt;/p&gt;

&lt;h1&gt;
  
  
  Other changes
&lt;/h1&gt;

&lt;p&gt;So far, as part of the process of using the fluidity value I have decided to revert back to using my &lt;code&gt;Vector3Float&lt;/code&gt; classes along with a new &lt;code&gt;Position3Float&lt;/code&gt; class rather than using &lt;code&gt;Triple&lt;/code&gt;s whenever this makes for more readable code, e.g. if the 3 values are simply related then I will leave them as a &lt;code&gt;Triple&lt;/code&gt; but if the 3 values represent either a 3D Vector or position in 3D space, I think it makes the code more readable to use the custom classes, it also allows me to add operator overloads to make subtracting one position from another possible among other things.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Plan for development
&lt;/h1&gt;

&lt;p&gt;From here I need to brush up on my math skills to determine where the player should move in the &lt;code&gt;TileMap&lt;/code&gt; based on the fluidity values. &lt;/p&gt;

&lt;p&gt;Then I shall generate a simple level which I can use for testing, and develop more of a sense of where the gameplay is heading, my current thinking is a VR world building game where you can place trees, plants, fences etc to build up your own environment, to do this I foresee the following advancements in the design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A HUD style menu, to select the objects which the player can place into the world.&lt;/li&gt;
&lt;li&gt;Enabling transparency so the player can see where the object would be before they place it.&lt;/li&gt;
&lt;li&gt;Updating the .vtf files when changes to the tile are made. &lt;/li&gt;
&lt;li&gt;Some sort of collision detection so objects are not placed on top of each other and so the player can't walk through the objects they have placed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until next time, Stay safe and happy coding.&lt;br&gt;
Graham&lt;/p&gt;

</description>
      <category>gamedevlog</category>
      <category>android</category>
      <category>vr</category>
      <category>tilemap</category>
    </item>
    <item>
      <title>Bubble Sort</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 11 Oct 2020 12:59:47 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/bubble-sort-4k0l</link>
      <guid>https://forem.com/longevitysoftware/bubble-sort-4k0l</guid>
      <description>&lt;h1&gt;
  
  
  What is bubble sort?
&lt;/h1&gt;

&lt;p&gt;This sorting algorithm is one of the simplest to understand, and is generally the first sorting algorithm taught to beginners. &lt;br&gt;
It is rarely used in the real world though, as it is outperformed by almost every other sorting algorithm.&lt;br&gt;
The basic idea of the algorithm is that, given an array of values, the larger (or smaller depending on the direction we are sorting the array) values are bubbled to their correct positions in the array by iterating through the values and swapping ones that are not in the correct order.&lt;/p&gt;
&lt;h1&gt;
  
  
  The algorithm step-by-step
&lt;/h1&gt;

&lt;p&gt;Given an array of values 2, 4, 8, 3, 7, to sort in ascending order, we need to loop through the values comparing each one to the next and if the next value is lower than this one, we swap the two values in place. &lt;br&gt;
This looks something like: &lt;br&gt;
At index 0&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 4, 8, 3, 7
This value = 2
Next value = 4
Next value is greater than this so do not swap
new values = 2, 4, 8, 3, 7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At index 1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 4, 8, 3, 7
This value = 4
Next value = 8
Next value is greater than this so do not swap
new values = 2, 4, 8, 3, 7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At index 2&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 4, 8, 3, 7
This value = 8
Next value = 3
Next value is less than this so swap them
new values = 2, 4, 3, 8, 7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At index 3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 4, 3, 8, 7
This value = 8
Next value = 7
Next value is less than this so swap them
new values = 2, 4, 3, 7, 8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After one iteration through the array, the values are still not sorted, so we need to repeat this process again.&lt;br&gt;
At index 0&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 4, 3, 7, 8
This value = 2
Next value = 4
Next value is greater than this so do not swap them
new values = 2, 4, 3, 7, 8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At index 1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 4, 3, 7, 8
This value = 4
Next value = 3
Next value is less than this so swap them
new values = 2, 3, 4, 7, 8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At index 2&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 3, 4, 7, 8
This value = 4
Next value = 7
Next value is greater than this so do not swap them
new values = 2, 3, 4, 7, 8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At index 3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;original values = 2, 3, 4, 7, 8
This value = 7
Next value = 8
Next value is greater than this so do not swap them
new values = 2, 3, 4, 7, 8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point we can visually see that the array is sorted but our algorithm does not yet know that we have finished, we need to keep iterating through the array until no swaps are performed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Performance of bubble sort
&lt;/h1&gt;

&lt;p&gt;Hopefully at this point you can see why this algorithm is so inefficient, especially for larger arrays.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time
&lt;/h3&gt;

&lt;p&gt;The best case scenario is an array that is already sorted, even then we still need to iterate through it once to confirm it is sorted, this is why the best case big O notation for this algorithm is O(n), as all n values need to be checked.&lt;/p&gt;

&lt;p&gt;For this small array we had to iterate through it 3 times, but for the worst case, a reverse sorted array we need to iterate through it n times, where n is the size of the array e.g. sorting the values 10, 8, 6, 4, 2 would take 5 iterations, this gives a worst case big O notation for this algorithm as O(n²), as all n values need to be checked n times.&lt;/p&gt;

&lt;h3&gt;
  
  
  Space
&lt;/h3&gt;

&lt;p&gt;Because the values can be swapped in the existing array, bubble sort can be performed without allocating any extra memory (as far as big O is concerned) therefore the space complexity is O(1)&lt;/p&gt;

&lt;h3&gt;
  
  
  Stability
&lt;/h3&gt;

&lt;p&gt;The stability of a sorting algorithm is whether the order that identical values were placed into the unsorted array is preserved after the sort e.g. if the input values are 3, 1, &lt;strong&gt;1&lt;/strong&gt; then, if the sorting algorithm is stable, 1 will be before &lt;strong&gt;1&lt;/strong&gt; in the sorted array, with an unstable sorting algorithm, 1 and &lt;strong&gt;1&lt;/strong&gt; could end up in any order.&lt;/p&gt;

&lt;p&gt;Bubble sort is considered a stable sort, as any two identical values will not be swapped.&lt;/p&gt;

&lt;h1&gt;
  
  
  Example Implementation
&lt;/h1&gt;

&lt;p&gt;Below is an example implementation of this algorithm in python: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kBwbLSQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fmhqb29x604pgxg4lxl0.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kBwbLSQT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fmhqb29x604pgxg4lxl0.PNG" alt="Python example bubble sort"&gt;&lt;/a&gt;&lt;br&gt;
Running this produces the following output:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ocNZCWm9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f4v9nplqrm7xwgb5zabt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ocNZCWm9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f4v9nplqrm7xwgb5zabt.PNG" alt="Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;Despite this algorithm being used very rarely in the wild, I don't think I could have started a sorting algorithms series without including it.&lt;br&gt;
If nothing else the bubble sort algorithm can be used as a benchmark to compare other algorithms against.&lt;/p&gt;

&lt;p&gt;Stay safe &amp;amp; Keep learning&lt;br&gt;
Graham&lt;/p&gt;

</description>
      <category>sorting</category>
      <category>algorithms</category>
      <category>bubble</category>
      <category>sort</category>
    </item>
    <item>
      <title>C coding quality tips</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 04 Oct 2020 19:16:02 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/c-coding-quality-tips-1j3e</link>
      <guid>https://forem.com/longevitysoftware/c-coding-quality-tips-1j3e</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;In this post I shall be outlining some of the things that I personally apply to my C coding and the reasons why I apply them.&lt;br&gt;
One caveat to this, which I feel is very important, when working in an established code base your code should follow the style of that code, consistency leads to easier to understand code than a mish-mash of styles. &lt;br&gt;
So jumping straight in with....&lt;/p&gt;

&lt;h1&gt;
  
  
  Types
&lt;/h1&gt;

&lt;p&gt;One thing which I do on every greenfield project is create a header file which defines custom types equivalent to the built in types but with the size as part of their name e.g.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RdhmNW7p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yappiqrs29ekr6jn0rgc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RdhmNW7p--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/yappiqrs29ekr6jn0rgc.PNG" alt="Example typedefs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I do this because not all processors use the same size for all built in types, if the code needs to be ported to a processor with different sized types, then it is only this header file that needs updating and all other modules should work as before. &lt;br&gt;
This also makes it clearer what value range a variable has when you declare it which can make it easier to catch bugs related to integer values overflowing during a code review. &lt;/p&gt;

&lt;h3&gt;
  
  
  Prefixing
&lt;/h3&gt;

&lt;p&gt;One thing which I’ve not done before is prefix these custom types with a lowercase t, I have seen this, or similar annotations done and think it is a nice touch which I’ll probably adopt going forward. &lt;/p&gt;

&lt;h1&gt;
  
  
  Enums
&lt;/h1&gt;

&lt;p&gt;I am a huge fan of Enums, any time when a variable has a finite number of values then I would use an Enum, it allows you to restrict the range of values passed as a function parameter and the values returned from a function.&lt;br&gt;
It also in my opinion makes code easier to read as values can be named to something meaningful e.g. rather than 0 for OK and any other value for an error, status codes returned from a function can be:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hx3KqETR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gli6wv9vmnsu31wk89qk.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hx3KqETR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gli6wv9vmnsu31wk89qk.PNG" alt="Status codes example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Prefixing
&lt;/h3&gt;

&lt;p&gt;Again this is something that I haven’t done but think would be a good addition is to prefix enums with a lowercase e to indicate that the value is an enum. &lt;/p&gt;

&lt;h1&gt;
  
  
  Enum values
&lt;/h1&gt;

&lt;p&gt;As a general rule when using an enum I do not care what value each enumeration is, but when the value of an enumeration is used, it should always be defined, even if the values are 0, 1, 2 etc, most compilers set the values from 0 but this can’t necessarily be guaranteed, therefore I like to declare the values of enums when the value will be used in the software.&lt;br&gt;
e.g. If the status codes above were checked against the value 0 in the code then I would instead define the value of each enumeration like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--284_ooeh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2eicelvgtpx3i1glns5g.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--284_ooeh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/2eicelvgtpx3i1glns5g.PNG" alt="Status codes with values defined"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Loops
&lt;/h1&gt;

&lt;p&gt;These are minor things which I do regarding loops. &lt;br&gt;
First, when incrementing a for loop index I use pre increment rather than post increment as this I have heard is minimally faster on most processors, the one exception I applied to this was when I worked with an msp430 processor, the compiler recommended I decremented the index as zero was easier to detect than non zero. &lt;/p&gt;

&lt;p&gt;Secondly, when creating a super loop, instead of using while(1) I will use while(true), where true is non zero or for(;;), the reason for this is something i read which said while(1) could be confused with while(l), even as unlikely as this is I still prefer while(true).&lt;/p&gt;

&lt;h1&gt;
  
  
  Const
&lt;/h1&gt;

&lt;p&gt;Whenever the value of a variable won’t change after it has been declared, I use the Const keyword to enforce its constant value, this has another positive in that it gives the compiler information that it can use to improve its optimisation of the code. &lt;/p&gt;

&lt;p&gt;Another area where I use Const is with pointers as function parameters, it’s a great way of adding limits on changes to the data and address pointed to. &lt;br&gt;
I can never remember the syntax for this so I always return to &lt;a href="https://www.geeksforgeeks.org/const-qualifier-in-c/amp/"&gt;this post&lt;/a&gt; from geeksforgeeks.org. &lt;/p&gt;

&lt;h1&gt;
  
  
  Wrapping up
&lt;/h1&gt;

&lt;p&gt;These points in this article are some of the things which I have picked up over my career, I’d love to hear your thoughts on these, and any other things that you apply when writing your C code. &lt;/p&gt;

&lt;p&gt;Stay safe.&lt;br&gt;
Graham&lt;/p&gt;

</description>
      <category>c</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Gamedevlog: TileMap Part 3a</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 27 Sep 2020 10:43:36 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-3a-29hp</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-3a-29hp</guid>
      <description>&lt;h1&gt;
  
  
  Building on Part 2
&lt;/h1&gt;

&lt;p&gt;As mentioned in part 2 we need a way of converting the tile map to an actual level that the player can navigate around. &lt;/p&gt;

&lt;p&gt;To start I added 8 Strings to the &lt;code&gt;Tile&lt;/code&gt; class one to represent each of the adjacent tiles, when a &lt;code&gt;Tile&lt;/code&gt; is then moved to the center, the &lt;code&gt;Tile&lt;/code&gt;s which were not already part of the &lt;code&gt;TileMap&lt;/code&gt; can be queried and loaded.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Vr Tile Format .vtf file
&lt;/h1&gt;

&lt;p&gt;I created a custom file format to hold the &lt;code&gt;Tile&lt;/code&gt; data, the files consist of multiple lines, with one parameter, surrounded by opening and closing tags, on each line. &lt;br&gt;
The initial tags will be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BM: The name of the base model will be between these tags.&lt;/li&gt;
&lt;li&gt;SU: The name of the .vtf file for the tile straight up from this one will be between these tags.&lt;/li&gt;
&lt;li&gt;SD: The name of the .vtf file for the tile straight down from this one will be between these tags.&lt;/li&gt;
&lt;li&gt;SL: The name of the .vtf file for the tile straight left from this one will be between these tags.&lt;/li&gt;
&lt;li&gt;SR: The name of the .vtf file for the tile straight right from this one will be between these tags.&lt;/li&gt;
&lt;li&gt;UL: The name of the .vtf file for the tile up and left from this one will be between these tags.&lt;/li&gt;
&lt;li&gt;UR: The name of the .vtf file for the tile up and right from this one will be between these tags.&lt;/li&gt;
&lt;li&gt;DL: The name of the .vtf file for the tile down and left from this one will be between these tags.&lt;/li&gt;
&lt;li&gt;DR: The name of the .vtf file for the tile down and left from this one will be between these tags.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the tags will be present but may be left blank if for example there is no &lt;code&gt;Tile&lt;/code&gt; straight up from the one being defined.&lt;/p&gt;

&lt;p&gt;To test this out I generated 9 files which will fill the tile map and will wrap around to create a continuous level e.g. the center tile, "Tile_0_0.vtf" looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FgW36MIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/79tx96ch23gwcb6s1d99.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FgW36MIf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/79tx96ch23gwcb6s1d99.PNG" alt="Tile file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Parsing the files
&lt;/h1&gt;

&lt;p&gt;To parse the files I generated a &lt;code&gt;VrTileFormatParser&lt;/code&gt; class which takes in a file name string of the file to parse along with the &lt;code&gt;ModelLoader&lt;/code&gt; and application context.&lt;/p&gt;

&lt;p&gt;I read all the lines of the file, populating function level variables with the parsed strings and then after reading the file, I created a new &lt;code&gt;Tile&lt;/code&gt; Class which can be returned using a call to &lt;code&gt;getParsedTile&lt;/code&gt; Function. &lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up the scene.
&lt;/h1&gt;

&lt;p&gt;When the &lt;code&gt;TileMap&lt;/code&gt; class is initialised, I First load the Center tile, This is hard coded as "Tile_0_0.vtf" but in future could be whichever &lt;code&gt;Tile&lt;/code&gt; the player was on when they saved or closed the game.&lt;/p&gt;

&lt;p&gt;I then initialise all the other &lt;code&gt;Tile&lt;/code&gt;s using the new strings defined for the center &lt;code&gt;Tile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qTiSdV_P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/odgz2ug8b3ajahmur74r.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qTiSdV_P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/odgz2ug8b3ajahmur74r.PNG" alt="Initialising the tile map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Updating the scene.
&lt;/h1&gt;

&lt;p&gt;When the play moves &lt;code&gt;Tile&lt;/code&gt;s, we can now populate the new &lt;code&gt;Tile&lt;/code&gt;s on the &lt;code&gt;TileMap&lt;/code&gt; in the same way that we initialised the &lt;code&gt;TileMap&lt;/code&gt; initially.&lt;/p&gt;

&lt;p&gt;Any &lt;code&gt;Tile&lt;/code&gt;s which were previously on the &lt;code&gt;TileMap&lt;/code&gt; were simply moved as before, the only other small change is, when moving diagonally the corner tiles are now updated where previously they were kept the same, see the example below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--20gdbEAX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gvxhehwthc0cuasafz5c.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--20gdbEAX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gvxhehwthc0cuasafz5c.PNG" alt="Updating the tile map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;The game is starting to look more like a game, we are able to simulate a vast world using just 9 tiles at a time and we can link tiles to other tiles to make a consistent experience.&lt;/p&gt;

&lt;p&gt;I have added some null and empty string checking but I know there is more to do on this front, also, I have set the adjacent tile strings in the &lt;code&gt;Tile&lt;/code&gt; class as public values, I think I will change these to private values with getters which will allow me to check for null or empty string conditions.&lt;/p&gt;

&lt;p&gt;The code at this point of the project can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.13"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Stay Safe.&lt;/p&gt;

</description>
      <category>android</category>
      <category>gamedevlog</category>
      <category>vrgame</category>
      <category>opengles2</category>
    </item>
    <item>
      <title>Gamedevlog: TileMap part 2</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sat, 19 Sep 2020 20:37:58 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-2-2h3e</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-2-2h3e</guid>
      <description>&lt;h1&gt;
  
  
  Building on part 1
&lt;/h1&gt;

&lt;p&gt;This will be a quick post this week, the next step on from part 1 is to move the tile that the player would have moved to, into the center and adjust all the other tiles accordingly. &lt;/p&gt;

&lt;p&gt;To do this I modified the &lt;code&gt;getPlayerPositionOnTileMap&lt;/code&gt; function, so that as well as adjusting the players position, I set bits in a &lt;code&gt;moveDirection&lt;/code&gt; variable to indicate the direction to shift the TileMap, then using a when statement I shifted the tiles around based on the value of &lt;code&gt;moveDirection&lt;/code&gt;.&lt;br&gt;
Finally if &lt;code&gt;moveDirection&lt;/code&gt; was set to anything apart from &lt;code&gt;DONT_MOVE&lt;/code&gt; I needed to reset all the tile offsets to their new positions. &lt;/p&gt;

&lt;h1&gt;
  
  
  Building on this
&lt;/h1&gt;

&lt;p&gt;Next, I wanted to spawn new tiles rather then just shuffling the existing ones, to do this I needed to ensure that the tiles were initialised within an OpenGL context, I couldn’t immediately see a clean way of doing this but in the end, I settled on adding a &lt;code&gt;mModelsHaveNotBeenInitialised&lt;/code&gt; variable to the &lt;code&gt;Tile&lt;/code&gt; class which was set to &lt;code&gt;true&lt;/code&gt; until the &lt;code&gt;initialise&lt;/code&gt; function is called, this allowed me to check the initialised state of the variables in the &lt;code&gt;draw&lt;/code&gt; function (and therefore within an active openGL context) and if the models had not been initialised I called the &lt;code&gt;initialise&lt;/code&gt; function, to make sure the offsets were correct, incase they had been set before the &lt;code&gt;initialise&lt;/code&gt; function was called, I added calls to the &lt;code&gt;setPosition&lt;/code&gt; function for each model to ensure it was drawn in the correct position.&lt;/p&gt;

&lt;h1&gt;
  
  
  Other small changes
&lt;/h1&gt;

&lt;p&gt;I noticed that sometimes the new models were being drawn at the origin of the scene before being translated to their correct position, which caused a flickering effect, to fix this I simply added a call to &lt;code&gt;GLES20.glFinish()&lt;/code&gt; in the &lt;code&gt;reRenderTheScene&lt;/code&gt; function which waits until the rendering is complete before exiting the function.&lt;/p&gt;

&lt;p&gt;Additionally I changed the old skybox textures to plain blue sides and a slightly modified cloud tile at the top of the scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xv5kQp6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xe3aheavrx0vfev827ns.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xv5kQp6v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xe3aheavrx0vfev827ns.gif" alt="Demo of the final scene"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This all seems to be going a bit too smoothly at the minute.... &lt;br&gt;
The next step forward is to make the tile map repeatable so the player can actually navigate consistently further than 2 tiles and back, I think this will be a big step so may be further broken into more than one blog post.&lt;/p&gt;

&lt;p&gt;The final code at this point in the project can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.12"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay Safe.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Gamedevlog: Tilemap part 1</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 13 Sep 2020 12:47:19 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-1-b2o</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-tilemap-part-1-b2o</guid>
      <description>&lt;h1&gt;
  
  
  What is a tilemap and why am I using one
&lt;/h1&gt;

&lt;p&gt;A tile map is a method of creating a level from a grid of tiles, it’s a common method in 2D games and allows a small number of images (sprites) to be repeated to build up a level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vp789pWb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k1tm74fmn84bojjs9v57.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vp789pWb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k1tm74fmn84bojjs9v57.jpeg" alt="Simple 2D TileMap example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above image we can see that with only 3 sprites we can create a whole platformer level. &lt;/p&gt;

&lt;p&gt;I am using a tile map to limit the size of the scene I need to render, instead of always drawing the whole scene.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EFcGEfTW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9jlnqkvffg42jwrkl6vr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EFcGEfTW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9jlnqkvffg42jwrkl6vr.jpeg" alt="My TileMap use"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine the image above is a birds eye view of the scene, if the player is in the tile at 0,0 then we only need to render the surrounding tiles highlighted green, as the player moves to the next tile then the map can be updated to keep the players tile always in the center. &lt;/p&gt;

&lt;p&gt;In future we can also use this to limit the number objects we need to perform collision detection on, but that is for another post. &lt;/p&gt;

&lt;h1&gt;
  
  
  The Tile Class
&lt;/h1&gt;

&lt;p&gt;This class represents each tile that makes up the scene. &lt;br&gt;
It holds an &lt;code&gt;ArrayList&lt;/code&gt; of models which are static within the tile, to start, this will just be a single &lt;code&gt;baseModel&lt;/code&gt; which is passed as a constructor parameter, but going forward will include other models like trees, houses, fences etc. &lt;/p&gt;

&lt;h1&gt;
  
  
  The TileMap Class
&lt;/h1&gt;

&lt;p&gt;This class holds an array of 9 &lt;code&gt;Tiles&lt;/code&gt;, the one the player is currently in and the 8 surrounding. &lt;/p&gt;

&lt;h1&gt;
  
  
  Putting this into action
&lt;/h1&gt;

&lt;p&gt;To implement this I needed to pass the &lt;code&gt;TileMap&lt;/code&gt; class the the &lt;code&gt;VrRenderer&lt;/code&gt; so that the models can be initialised and rendered with an active OpenGL context, this would leak a lot of unnecessary implementation details to the  &lt;code&gt;VrRenderer&lt;/code&gt; when the only two functions it would need are an initialisation function and a draw function, to clean this up I created a &lt;code&gt;DrawableInterface&lt;/code&gt; which only specified the two necessary functions, this was then implemented by the &lt;code&gt;TileMap&lt;/code&gt; and &lt;code&gt;Tile&lt;/code&gt; classes and a parameter of the &lt;code&gt;DrawableInterface&lt;/code&gt; type was passed to the &lt;code&gt;VrRenderer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once each tile is initialised, I needed to set the offset for that tile, to do this, and to allow me to move the tiles I created a &lt;code&gt;setTileOffset&lt;/code&gt; function in the  &lt;code&gt;Tile&lt;/code&gt; class which removed the current offset (originally 0) and then applied the new offset to all models in the tile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SMWNbiyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9270218l2tnrc4ujp7am.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SMWNbiyI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9270218l2tnrc4ujp7am.PNG" alt="setTileOffset function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To try this out I created 9, alternating black and white tiles, with the numbers 1 to 9, added them to the model loader class and set each one as the &lt;code&gt;baseModel&lt;/code&gt; for the 9 tiles. &lt;/p&gt;

&lt;h1&gt;
  
  
  The finishing touches
&lt;/h1&gt;

&lt;p&gt;To finish this step of the development I wanted to see how it would look to move from the center tile and have the tiles adjust themselves. &lt;/p&gt;

&lt;p&gt;To simulate this i added a function to the &lt;code&gt;TileMap&lt;/code&gt; class to take in the players current position and target movement delta and return the new player position.&lt;/p&gt;

&lt;p&gt;If applying the target delta would take the player outside the center tile i.e. more than half the tile size from the origin, then I subtracted or added the tile size to take the player to the opposite side of the tile. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8kZ5psAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lwbhr906c5h32o8x58zg.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8kZ5psAT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lwbhr906c5h32o8x58zg.PNG" alt="getPlayerPositionOnTileMap function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This function is Called from the &lt;code&gt;adjustPlayer&lt;/code&gt; function, I created a new interface to allow me to just pass in this function. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yKLJ72U8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/egnyx4btsvo4n3g0rvtz.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yKLJ72U8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/egnyx4btsvo4n3g0rvtz.PNG" alt="passing the tilemap as an interface"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and it is then called from the body of the function like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oBEkbV3Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v38ai4bup981n2j3bpyc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oBEkbV3Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v38ai4bup981n2j3bpyc.PNG" alt="Setting Player Position"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running the game, this method looks a bit strange as the tiles are not updated at the same time as moving the player out of a tile but I think the principal seems to work. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rfXFQgEc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1hk8rv04avb4kf5rgebe.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rfXFQgEc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1hk8rv04avb4kf5rgebe.gif" alt="Gif of the player moving across the tile map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;This development is another step closer to a playable game and every step forward is a win, the next step will be to shuffle the tiles around when the player transitions from one to the next to give the illusion of continuous movement across a scene.&lt;/p&gt;

&lt;p&gt;The code at this point of the project can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.11"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Gamedevlog: The First VR Test</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Mon, 07 Sep 2020 10:51:16 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-the-first-vr-test-c5h</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-the-first-vr-test-c5h</guid>
      <description>&lt;h1&gt;
  
  
  Preparations for the first VR test.
&lt;/h1&gt;

&lt;p&gt;To prepare for the first VR test I wanted to add the following features which I thought may be needed: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The ability to change the distance between the two camera positions using the xbox controller.&lt;/li&gt;
&lt;li&gt;The ability to switch the point that each camera was looking between a common point or independent points directly in front of each camera. &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Setting the distance between each camera
&lt;/h1&gt;

&lt;p&gt;To achieve this I added a variable to the &lt;code&gt;PlayerVision&lt;/code&gt; class to store the distance that each camera should be from the center &lt;code&gt;mHalfCameraDistance&lt;/code&gt;, this was then used instead of the hard coded 1 and -1 values when calculating each camera’s position. &lt;br&gt;
To modify this distance, I created two functions, one to increase the distance and one to decrease it by the passed in amounts.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting the cameras look at position
&lt;/h1&gt;

&lt;p&gt;To achieve this I added a boolean variable to the &lt;code&gt;PlayerVision&lt;/code&gt; class called &lt;code&gt;mLookStraightAhead&lt;/code&gt;, if this was set to true then the cameras would look directly ahead of themselves, however if the value was false, then the cameras would share a common look at point.&lt;/p&gt;

&lt;p&gt;This was done by calculating a common look at point which was in the look direction from the players position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wQ-V_gc6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5tmci999lxmg6i8y3s9s.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wQ-V_gc6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5tmci999lxmg6i8y3s9s.PNG" alt="Calculating common look at point"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The look direction for each camera was calculated as the look position minus the cameras position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iv0eLO_e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ix2m2b2oj5r2355whfvh.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iv0eLO_e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ix2m2b2oj5r2355whfvh.PNG" alt="Look direction example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Controlling these settings from the Xbox controller
&lt;/h1&gt;

&lt;p&gt;To facilitate controlling these settings from the Xbox controller I updated the &lt;code&gt;ButtonControlInterface&lt;/code&gt; and the &lt;code&gt;XboxController&lt;/code&gt; and &lt;code&gt;GameControlHub&lt;/code&gt; classes to allow detection and reporting of activity on the LB (L1) and RB (R1) buttons.&lt;br&gt;
Then in the main game loop I checked for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The action button pressed which would toggle between the two camera look at modes.&lt;/li&gt;
&lt;li&gt;The L1 button pressed which would decrease the distance between the two cameras.&lt;/li&gt;
&lt;li&gt;The R1 button pressed which would increase the distance between the two cameras. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OkmZgzjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h3k2w0jf28p3iskvd5re.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OkmZgzjW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/h3k2w0jf28p3iskvd5re.PNG" alt="Changes to the game loop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The first test
&lt;/h1&gt;

&lt;p&gt;With these changes implemented I placed the phone into the headset and pressed the L1 button to decrease the distance between the two cameras, this had the effect of increasing the distance???&lt;br&gt;
It turns out that when calculating my look direction I had been using a positive z value instead of a negative z value as all my calculations in this test had assumed. &lt;br&gt;
Fixing this issue by inverting the look direction, then highlighted the fact that all my controls had been set to work with this incorrect look direction, testing the values returned from the Xbox controller stick movements showed that these values were inverted (except the one used for Yaw) from what I had assumed, this was fixed by inverting the stick values in the &lt;code&gt;XboxController&lt;/code&gt; class. &lt;/p&gt;

&lt;h1&gt;
  
  
  The first real test
&lt;/h1&gt;

&lt;p&gt;With the above issues resolved, I once again placed the phone into the headset and my first impressions were good, while looking at objects close to the camera there was a kind of ghosting where you could see the difference between the two camera positions, decreasing the distance between the two cameras had the desired effect and at distances below about 1.0 (0.5 half distance) the image looked great.&lt;br&gt;
One interesting thing I did notice was that when changing the camera at the lower distances, I could see the 3D models move and then my brain would compensate and they would merge back to a single model again, I am assuming that this compensation is not possible at the larger distances between the two cameras, so as not to stress the eyes / brain too much I have decided to work with the half distance set to 0.1 for now. &lt;/p&gt;

&lt;p&gt;I did not notice any major difference when the two cameras were looking at a common or independent points but this may be something I notice as the scene grows.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;All things considered, this update was quite productive, I got the chance to brush up on my blender skills, fixed some issues with the game and had a successful VR test. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--84kSL0k5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9e3taxsla5b18hq4l9ay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--84kSL0k5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/9e3taxsla5b18hq4l9ay.png" alt="New VR Scene"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code at this point in the project can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.10"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vrgame</category>
      <category>android</category>
      <category>opengles2</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Gamedevlog: Simulating day and night</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 30 Aug 2020 20:10:05 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/gamedevlog-simulating-day-and-night-44ff</link>
      <guid>https://forem.com/longevitysoftware/gamedevlog-simulating-day-and-night-44ff</guid>
      <description>&lt;h1&gt;
  
  
  All in a days work
&lt;/h1&gt;

&lt;p&gt;To add some movement to the scene and make it more dynamic, I have decided to add a day/night cycle which will include. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 3D model for the sun which will move across the scene. &lt;/li&gt;
&lt;li&gt;The colour of the sun will change from white at midday, to a reddish orange at dawn and dusk and black at night. &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  The light source
&lt;/h1&gt;

&lt;p&gt;To introduce a light source I created a new &lt;code&gt;SunLight&lt;/code&gt; class which will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement a simple form of the model rendering code to render the sun model. &lt;/li&gt;
&lt;li&gt;Calculate the lights position and colour based on the time of day. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Calculating the suns position
&lt;/h2&gt;

&lt;p&gt;To work out where the sun should be at any given game time, I will take the result of the mod of the current system time in milliseconds the total time per day and then divide it by the total time per day to know how far into the day we are, then multiply that by 360° to get the current angle. &lt;br&gt;
At the start of the day (0 time) the sun shall be directly below the world so if we set a position directly down on the y axis and then rotate it by the current angle, this will be the position of the sun. &lt;/p&gt;

&lt;h2&gt;
  
  
  Calculating the suns colour
&lt;/h2&gt;

&lt;p&gt;Again we can make use of the angle generated for the suns position to cycle the colour between black at the start of the day, reddish orange at dawn and dusk and white at mid day. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Akr36xRx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/krpvqa2nitmxch7osajv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Akr36xRx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/krpvqa2nitmxch7osajv.png" alt="Suns Colour Sketch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was unsure how best to convert the angle into a colour but I started by setting the colour based on the angle using a &lt;code&gt;when&lt;/code&gt; statement with ranges for each of the colours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QHtjI5Eb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/njva1mxlt9s9so9ckfgb.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QHtjI5Eb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/njva1mxlt9s9so9ckfgb.PNG" alt="Initial way of determining colour"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was a good start but the transitions needed to be smoothed out and the skybox still looks the same throughout the day. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ng8KEwen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hp1053gnm5fb0rybzrh2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ng8KEwen--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hp1053gnm5fb0rybzrh2.gif" alt="Initial day and night gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To fix these issues I created a simple interpolation function to gradually merge from one colour to the next, this function only works as expected because at most I am changing two of the 3 colour values each time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0GMHibqy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a1j4s7t5yyjradfx3eaa.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0GMHibqy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/a1j4s7t5yyjradfx3eaa.PNG" alt="Interpolation function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was used in the when block like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jsVR9f_T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xn7o3n95bqrsmiiwzt9v.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jsVR9f_T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/xn7o3n95bqrsmiiwzt9v.PNG" alt="example of using the interpolation function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One final issue with this was that the sun always rotated around the scenes origin and not the player position, therefore the player could walk into the path of the sun, to fix this I passed the players position to the &lt;code&gt;UpdateSunLight&lt;/code&gt; function and translated the sun position by the players position.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MVKwqfD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/alxmykap38iwfvhm65s4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MVKwqfD7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/alxmykap38iwfvhm65s4.PNG" alt="Adding the players position to the suns position"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This gave the following Day/Night cycle which I am quite happy with at the moment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EhY0QwsW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dttcwgymx5hdqws25e04.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EhY0QwsW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dttcwgymx5hdqws25e04.gif" alt="Final Day / Night Cycle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;The game now has some dynamic lighting in the form of a day / night cycle which is a great improvement on the previous static lighting. &lt;/p&gt;

&lt;p&gt;The source code at this point in the project can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.9"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vrgame</category>
      <category>devlog</category>
      <category>android</category>
      <category>opengles2</category>
    </item>
    <item>
      <title>Simple object (.obj) and material (.mtl) file parser. </title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 23 Aug 2020 11:40:33 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/simple-object-obj-and-material-mtl-file-parser-25ad</link>
      <guid>https://forem.com/longevitysoftware/simple-object-obj-and-material-mtl-file-parser-25ad</guid>
      <description>&lt;h1&gt;
  
  
  Why object files and material files together.
&lt;/h1&gt;

&lt;p&gt;Object files and material files are both wavefront technology formats which are designed to work in combination. &lt;br&gt;
I have described the basics of object files as a standalone file &lt;a href="https://dev.to/longevitysoftware/simple-obj-object-file-parser-in-kotlin-4okb"&gt;in part 8 of this series&lt;/a&gt;. &lt;br&gt;
When combined with material files the object file contains a line detailing the name of the material file which starts with “mtllib” &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zFPcyZBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ltaqsnmm3rnd28gsf2ut.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zFPcyZBG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ltaqsnmm3rnd28gsf2ut.PNG" alt="mtllib example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and the faces are grouped by material, with each group starting with “usemtl” and the name of the material to use. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HVrTrGXs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5rl9gx25j9vsmn4lv4wq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HVrTrGXs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5rl9gx25j9vsmn4lv4wq.PNG" alt="usemtl example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Modifications to the existing object file parser.
&lt;/h1&gt;

&lt;p&gt;The first change will be to update the &lt;code&gt;faceMap&lt;/code&gt; to include a material name as well as the vertex, UV and normal indices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2hbfQdxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bxvon7vpwvi1943wv1z4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2hbfQdxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bxvon7vpwvi1943wv1z4.PNG" alt="new Facemap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need something to hold all the material data, for this, I generated a data class &lt;code&gt;MaterialData&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FNiuXYKQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jqsw5u9nyjf5limpcdpx.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FNiuXYKQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jqsw5u9nyjf5limpcdpx.PNG" alt="Material Data Class"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I then generated a function &lt;code&gt;parseMtlFile&lt;/code&gt; which takes in a &lt;code&gt;BufferedReader&lt;/code&gt; and parses the file to populate a hash map with the material names as the keys and a &lt;code&gt;MaterialData&lt;/code&gt; classes as the value. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rdjTraRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uz6wfphyhap6cexhqz71.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rdjTraRY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/uz6wfphyhap6cexhqz71.PNG" alt="mMaterial hash map definition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the object file specifies a material file to use, I take the file name and generate an &lt;code&gt;InputStream&lt;/code&gt; which I use to create a &lt;code&gt;BufferedReader&lt;/code&gt; and pass it to the &lt;code&gt;parseMtlFile&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r--JtHyS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/30cqvt0a2xvrk0eqi7vy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r--JtHyS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/30cqvt0a2xvrk0eqi7vy.PNG" alt="Calling ParseMtlFile function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Taking a step back to detail the .mtl file format, each Material file can detail multiple materials, each material definition starts with a line with the word "newmtl" and the material name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yot6LWhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4m6hyl5b3zqaha5gf93k.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yot6LWhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4m6hyl5b3zqaha5gf93k.PNG" alt="Material Definition"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we see a "newmtl" line we can generate a new &lt;code&gt;MaterialData&lt;/code&gt; class and add it to the &lt;code&gt;mMaterials&lt;/code&gt; hash map, I also store the material name so I can use it to populate the classes variables later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AzaEZ0EQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gx9pgzk1laot08m61zo0.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AzaEZ0EQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gx9pgzk1laot08m61zo0.PNG" alt="new material"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Following the "newmtl" line there are the following lines which are of interest to us.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ns - This value defines the Specular exponent of the material.&lt;/li&gt;
&lt;li&gt;Ka - This value defines the Ambient colour of the material.&lt;/li&gt;
&lt;li&gt;Kd - This value defines the diffuse colour of the material.&lt;/li&gt;
&lt;li&gt;Ks - This value defines the specular colour of the material.&lt;/li&gt;
&lt;li&gt;d - This value defined the dissolve (transparency) of the material.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Parsing each of these lines, we can populate the &lt;code&gt;MaterialData&lt;/code&gt; variables similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NFu8vycC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rg8b0rqi8l09kk8jdpcr.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NFu8vycC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rg8b0rqi8l09kk8jdpcr.PNG" alt="Parsing colour data"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Parsing the faces with this new material data
&lt;/h2&gt;

&lt;p&gt;Now that we have the material data we continue parsing the object file as before until we get to the faces.&lt;br&gt;
Before each section of faces there is a "usemtl" line which we parse to determine which material name to use for the following faces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7GQMikHo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0thqfyjpe6fj698x6ywc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7GQMikHo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0thqfyjpe6fj698x6ywc.PNG" alt="getting the name of the material to use"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I parse a face, I take this &lt;code&gt;materialName&lt;/code&gt; and use it to get the material from the &lt;code&gt;mMaterials&lt;/code&gt; hash map.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qkVuq5z4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3wxdvv2oo3lugw799fom.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qkVuq5z4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3wxdvv2oo3lugw799fom.PNG" alt="getting material from hash map"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The remainder of the face parsing is the same as before except that for each new index, I also populate new &lt;code&gt;FloatArray&lt;/code&gt;s for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;mFinalAmbientColour&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mFinalDiffuseColour&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mFinalSpecularColour&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mFinalSpecularExponent&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mFinalDissolve&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1lSpredW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/es63q7rvrkyzkb6jpztt.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1lSpredW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/es63q7rvrkyzkb6jpztt.PNG" alt="Populating final colours"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the material is not in the &lt;code&gt;mMaterials&lt;/code&gt; hash map for any reason then default values are used to populate the arrays.&lt;/p&gt;

&lt;h1&gt;
  
  
  The new &lt;code&gt;ModelData&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;To use all this new data I modified the &lt;code&gt;ModelData&lt;/code&gt; class to be a Kotlin data class and include the new colour information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CmtCFMHE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0whoyov0k5axa9dy8rkn.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CmtCFMHE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/0whoyov0k5axa9dy8rkn.PNG" alt="Model Data Class updates"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Using the new data
&lt;/h1&gt;

&lt;p&gt;Once we have the data, we need to update our shader code to use the values, this was pretty straight forward but did involve adding an attribute for each new value &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EpfKHkIc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/68zy1n97pcs6kck6u1z8.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EpfKHkIc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/68zy1n97pcs6kck6u1z8.PNG" alt="New attributes"&gt;&lt;/a&gt;&lt;br&gt;
and then passing it to the Fragment shader to be used in the lighting calculations&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_ISP6l55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kr71dgnxdcv66ssm25ku.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ISP6l55--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kr71dgnxdcv66ssm25ku.PNG" alt="Varying values"&gt;&lt;/a&gt;&lt;br&gt;
I also added a uniform variable to the fragment shader to pass the light colour in rather than having it hard coded.&lt;br&gt;
Finally, For each new attribute I generated a &lt;code&gt;FloatBuffer&lt;/code&gt; which is populated with the new material data in the same way as the Vertices and normal data was populated and then passed to the shaders in the &lt;code&gt;draw&lt;/code&gt; function in the same way as the vertices and normals.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;I now have different coloured models in my game which looks better than the monocolour models that I had before.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wlgcKb8S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o95ijc0upoelg11lbimw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wlgcKb8S--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/o95ijc0upoelg11lbimw.png" alt="Screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The final code for this update can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.8"&gt;here&lt;/a&gt;.&lt;br&gt;
Until next time....&lt;/p&gt;

</description>
      <category>android</category>
      <category>opengles2</category>
      <category>vrgame</category>
      <category>devlog</category>
    </item>
    <item>
      <title>Loading multiple models</title>
      <dc:creator>Graham Long</dc:creator>
      <pubDate>Sun, 16 Aug 2020 15:16:09 +0000</pubDate>
      <link>https://forem.com/longevitysoftware/loading-multiple-models-2imj</link>
      <guid>https://forem.com/longevitysoftware/loading-multiple-models-2imj</guid>
      <description>&lt;h1&gt;
  
  
  The Current Way
&lt;/h1&gt;

&lt;p&gt;Prior to this development, if I wanted to load multiple different models I had to load each one in the &lt;code&gt;VrRenderer&lt;/code&gt;s &lt;code&gt;onSurfaceCreated&lt;/code&gt; method and then pass the vertices, normals and indices to a &lt;code&gt;GenericGameObject&lt;/code&gt;, there is nothing majorly wrong with this but I wanted to make the process a bit easier. &lt;/p&gt;

&lt;h1&gt;
  
  
  The New Way
&lt;/h1&gt;

&lt;h2&gt;
  
  
  model data
&lt;/h2&gt;

&lt;p&gt;First I created a dto class (data transfer object) called &lt;code&gt;ModelData&lt;/code&gt; which is used to pass the vertices, normals, UVs and indices for a 3D model between other classes. I changed the &lt;code&gt;ObjectFileParser&lt;/code&gt; to return the parser data as a &lt;code&gt;ModelData&lt;/code&gt; object and similarly I changed the &lt;code&gt;GenericGameObject&lt;/code&gt; to take in a &lt;code&gt;ModelData&lt;/code&gt; object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loading all the models
&lt;/h2&gt;

&lt;p&gt;To load the model data I created a &lt;code&gt;ModelLoader&lt;/code&gt; class which parses all the available models object files in its &lt;code&gt;init&lt;/code&gt; function and puts the resulting &lt;code&gt;ModelData&lt;/code&gt; objects into a &lt;code&gt;HashMap&lt;/code&gt; with the file name as the key. &lt;br&gt;
The &lt;code&gt;ModelLoader&lt;/code&gt; class can then be used to get the &lt;code&gt;ModelData&lt;/code&gt; object for any already parsed model.&lt;br&gt;
In the event that a requested model is not in the &lt;code&gt;HashMap&lt;/code&gt; then a default cube is returned. &lt;/p&gt;

&lt;h2&gt;
  
  
  Using the &lt;code&gt;ModelLoader&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I create an instance of the &lt;code&gt;ModelLoader&lt;/code&gt; class in the &lt;code&gt;MainActivity&lt;/code&gt;s &lt;code&gt;onCreate&lt;/code&gt; method and pass it via the &lt;code&gt;VrGlSurgaceView&lt;/code&gt; to the &lt;code&gt;VrRenderer&lt;/code&gt; so I can generate &lt;code&gt;GenericGameObject&lt;/code&gt;s with any of the parsed model data.&lt;br&gt;
In anticipation of adding a tile based system into the game in future, I created a few basic 20x20 tiles which I added to the &lt;code&gt;ModelLoader&lt;/code&gt; to be used in the game.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A_oAg9CS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z0armflgogfjzrfelhka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A_oAg9CS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z0armflgogfjzrfelhka.png" alt="New Models in the scene"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusions
&lt;/h1&gt;

&lt;p&gt;This development is a stepping stone to implementing a tile map style world and as such is only a small change from the previous version.&lt;br&gt;
Now that I have a basic environment in the game, I have the following observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The SKyBox texture does not make sense with the scene now being all above 0.0 on the y axis.&lt;/li&gt;
&lt;li&gt;Each "tile"s are one single colour each which is not ideal.&lt;/li&gt;
&lt;li&gt;Similarly the floor is as reflective as the other parts of the models, again this is not what I want. &lt;/li&gt;
&lt;li&gt;The specular lighting on the models is in a very different place from one eyes camera to the other, this indicates to me that the distance between each camera is too great, but I shall need to trial this in my VR headset to confirm.&lt;/li&gt;
&lt;li&gt;A small observation is that the light is currently coming from directly above the player at the moment and it would be nice to have this orbiting the scene and maybe changing colour at "Dusk" and "Dawn".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until next time, the source code at this point in the project can be found &lt;a href="https://github.com/longevity-software/AndroidVrGameDemo/releases/tag/B1.7"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>android</category>
      <category>vrgame</category>
      <category>devlog</category>
      <category>opengles2</category>
    </item>
  </channel>
</rss>
