Energy Grid Map Generation

As i've been balancing the numbers for the game. I realized that the way to win was to tech up as fast as possible, and just put solar panels everywhere. This just didn't have much in terms of strategy. I want the positioning of your gatherers to matter more. The simple way to do that is reduce the number of places you can build them.

The existing map generation is really simple. It finds an open 3x3 grid on the map where it can build a set of tiles, using a random number. The tile types currently in game are: Swamp, City, River, Open. The center of the 3x3 would always be something other than Open, and the surrounding tiles would be dependent on the center. Rivers more likely around a city, swamps more likely around a river. To reduce the available space problem, I tried increasing the number of 3x3 grids, but i could only do up to 4. A number of instances the game would never start as it couldnt find enough space for 5. So I decided to rethink how I generate the map.

The first option was to use the same 3x3 generation, but break the map out into 5 sections so it could reliably do this. Much like so:


Then 5 3x3 grids would be able to fit, so long as they confine to the section they're in. However when I started filling out different patterns, I wasn't feeling too keen on it as a solution.


This scenario for example leaves some large chunks of space, not really creating confined areas that the user is forced to place in gatherers. The idea of constricting the space is so the user has to consider how much pollution they create. So I had another thought. What if I set the open space using defined shapes? What about the letter L. I keep the width of the L set to two spaces, using a variable length for the long part and the short foot of the letter. I then also sketched out some on how this might look, going with the assumption I would apply four "L"s to the map.


I realize this looks confusing, as a number of the "L"s overlap there, but the yellow space is blocked, the open space is where you can build. In most cases, you're almost always touching protected space. Meaning pollution is hard to avoid. But there's still enough squares for you to work with to get enough energy.

To pull this off in code, the main piece was tracking horizontal & vertical "L"s to ensure i dont have them overlap 100%. So if a vertical rotated L sits on more of the left side of the map, make sure the next one sits  on the right side somewhere. Otherwise it was just a matter of mapping the X & Y values to these Ls to build out the list of open squares.

Then the yellow space is filled with protected tile types. Some remaining code to sort out is generating those protected tiles more logically. As right now it's a bit of a mess!


Spring update on Energy Grid

Back in the fall I started on a roadmap for Energy Grid, to figure out where take it. The main components that I set to focus on was rendering the tech tree. This led me to having to build out a number of systems, which led me to new challenges such as font/text wrapping.

Here’s where I’m at in the road map.

  • [x] Replace original tech upgrade system with 3 nodes in the tech tree, one for coal, oil, and solar power. With coal already being researched. As you sell resources, you receive money. Money should be able to be used to upgrade the other two types.
  • [x] Show tile researching in game menu
  • [x] Create new tile types: Cities, Rivers, Swaps/lakes. Update the map generation to place these in little hubs. Coal, oil, and solar have to be built on blank tiles.
  • [x] Add hydro power, only buildable on river tiles.
  • [x] Add the pollution system. Coal & Oil pollute adjacent tiles with rivers, swaps, or cities in them. Hydro pollutes the river tile it is on. The more tiles polluted, the more amount of money you get taxed on per second.
  • [ ] Implement the rest of the tech tree nodes. The tech tree itself is layed out, but many of the bonuses do not work yet. The remaining bonuses to be implemented can be seen in my last update.
  • [ ] Sell solar panels for money. Enabled via the tech tree, but acts as another source of income, instead of being a passive bonus.
  • [ ] Additional cities to power. This is to ramp up difficulty as you progress
  • [ ] Create final assets for the game.
  • [ ] Create menu screens
  • [ ] Create tutorial/intro to the game

Here’s the game in action as of today:


Technical challenges

Drawing the Tech Tree

With the tech tree having over a dozen nodes, with connecting lines, I wanted to accomplish two things:

The first, manage the tech tree with a data file. Managing positions and all the information in code would have been tricky. Given the ECS library I’m using has a bit boilerplate to create a new entity with a set of components, managing this with a dataset instead would be easier to adjust and make changes.

To make this happen, I created an upgrade struct, and decorated it with serde so JSON can be deserialized into it.

#[derive(Serialize, Deserialize)]
pub struct Upgrade {
    pub buff: Buff,
    pub time_to_research: f32,
    pub current_research_progress: f32,
    pub cost: i32,
    pub status: Status,

Then in the JSON file, if a given object has an array of children, my rust code would iterate through that to establish the parent/child relationship. As the research system completes an in progress upgrade, it checks this tree of parent/child to update the status of the child upgrades.

The position of each node in the tree is based on simple number values in the JSON objects. The Y depth I initially tried to do it based on node depth in the JSON tree, but that led to some rows being too packed. So instead I define the Y value as a tier. 1, 2, 3, 4, etc. This is then multiplied to position them in a nicely spaced out way. X is 0->1 value, where 0 is the furthest left in the tech tree container, 1 is the furthest right. Determining the numbers here required a bit more consideration to position the nodes evenly.

The second thing: create an arbitrary shape drawing API. Because I’m using a wrapper of code around OpenGL, I need to draw things with triangles. For a rectangle this is pretty straight forward to put together, but for a polygon with 7 sides, knowing how the triangles should make up the shape becomes complicated. This is known as tessellation. Thankfully Lyon has a tessellation crate to give me this information. I was able to use it to produce the vertices I need to draw an arbitrary shape.

The recursive function that goes through determining the x & y coordinates of each node, this is then used to determine the 4 points of each line, going from node to node.

let last_half_x = last_position.x + SIZE_F / 2.0;
let last_half_y = last_position.y + SIZE_F / 2.0;
let half_x = x + SIZE_F / 2.0;
let half_y = y + SIZE_F / 2.0;
let points = vec![
    Vector2::new(last_half_x, last_half_y),
    Vector2::new(half_x, half_y),
    Vector2::new(half_x + 2.0, half_y),
    Vector2::new(last_half_x + 2.0, last_half_y),
let entity = world
    .with(Shape::new(points, [0.7, 0.7, 0.7, 1.0]))

The Shape struct is my piece of code that leverages lyon to do the tessellation. Building out the vertices is done via:

let mut path_builder = Path::builder();
for (i, point) in points.iter().enumerate() {
    let p = lyon_point(point.x, point.y);
    if i == 0 {
    } else {


let path =;
let mut buffers = VertexBuffers::new();

// Create the tessellator.
let mut tessellator = FillTessellator::new();

// Compute the tessellation.
        &mut BuffersBuilder::new(&mut buffers, VertexCtor { color }),

Then i use the buffers variable inside my renderer, and pass it along with the Color data to my shader.

Map Generation

Procedural generation is not something I’ve done very much of. I knew that just looping through the 10x10 grid and selecting a tile type based on a random number would not be ideal, and would likely lead to not fun scenarios. So I started thinking about how one can make small dense areas on the map of the different types.

It got me thinking of a map with small hills, where ground level would be empty, ground+1 would be swamps, ground+2 rivers, ground+3 would be cities. To keep it simple, why not pick a node with the 8 surrounding nodes free, pick a random value between 2-4, and set the tile based on that number. Then set the 8 remaining tiles 0-(n), n being the value the center tile was. So it cannot be higher than the middle tile, but it can be lower, even empty.

let mut x = 0;
let mut y = 0;
// find the center first
loop {
    x = rng.gen_range(1, 9);
    y = rng.gen_range(1, 9);

    let mut all_nodes_free = true;

    'check_nodes: for i in 0..3 {
        for j in 0..3 {
            if set_nodes.contains_key(&(x + i, y + j)) {
                all_nodes_free = false;
                break 'check_nodes;

    if all_nodes_free {

First, I just do a naive random check to find an open set of 9 nodes.

Then i choose the value of the center node. These random numbers I am likely to change to better balance the map generation.

let weight: u32 = rng.gen_range(0, 101);
let mut highest = 1;
let tile_type = if weight >= 90 {
    highest = 4;
} else if weight >= 75 {
    highest = 3;
} else {
    highest = 2;

EcoSystem is what I called the swamp internally.

Then it was a matter of looping through the 3x3 grid in this 9 tile space to select the new types. Just using some random numbers for the different values.

for i in 0..3 {
    for j in 0..3 {
        if x + i == center_x && y + j == center_y {
        let tile_type = if highest == 4 {
            let weight: u32 = rng.gen_range(0, 101);
            if weight >= 90 {
            } else if weight >= 75 {
            } else if weight >= 55 {
            } else {
        } else if highest == 3 {
            let weight: u32 = rng.gen_range(0, 101);
            if weight >= 75 {
            } else if weight >= 50 {
            } else {
        } else if highest == 2 {
            let weight: u32 = rng.gen_range(0, 101);
            if weight >= 60 {
            } else {
        } else {

        set_nodes.insert((x + i, y + j), (tile_type, None));

We skip center, as that is already set. Then a different set of random numbers are used depending on what the center number was. The reason it’s done in a long set of if statements is so that it is easier to adjust. I could use an array of numbers to make this cleaner in code, but I didn’t want to couple the generation with the implementation when it’s still relatively easy to follow.

What's Next?

The next major focus is implementing the tech tree passives, and then testing them out. See how things work out balance wise, and how the game feels around the changes. After that, I will work towards making the city tiles what you are powering, and reserve tiles on screen for other cities to require power.

Taking My Jam Entry Further

My last post on here was about an archery game I started. That’s still a game I want to build, but at the end of July I decided to participate in Ludum Dare. Knowing I could re-purpose components and systems I built for the archery game, I felt confident that I could do a game jam with Rust.

You can play the game I created here:

Somethings went smoothly, others not so much. I had to figure out how to include things like fonts and sound in an async context when neither of those are thread safe. The short answer is to not include them in an async piece of code at all! The Rust compiler is pretty good at making sure you avoid race conditions, so really it’s best to listen to its errors, and re-think your design. In the end I had moved the actual font texture creation & playing the music into the main loop, which runs synchronously. The game systems written on top of Specs - Parallel ECS would simply flag data as being ready to draw new text, or play new sounds.

After completing this, and making some improvements to the draw code, I ported those back into the archery game. While my overall score in the game jam wasn’t that great, I had some really encouraging comments on my entry. So I’ve since then decided to expand it.

I’ve spent the last couple of months implementing their feedback, as well as my own changes:

  1. Allowing one to make any of the researched gatherers.
  2. Changing the selling energy concept to give you money, which you use to create more gatherers, or advance in tech.
  3. Implemented a proper scene graph.
  4. Gave the game a proper restart, instead of just exiting the process.

Now that I have the game in a good spot, I figured it’s time to start working on a proper game design. While I’ve always valued planning when it comes to projects at work, it’s not something I’ve done in depth for a side project. My game Snowball Effect was done at a high level when I worked on V2, but I didn’t have it all flushed out from the get go, I did it in a very agile way. So I’ve decided to really dive deep on this game, and not just figure out what the features are at a high level, but really think it through, even the numbers.

The map instead of just one tile type will have multiple. Ones that you can’t build on, can’t pollute, ones that you can only build certain types next to, etc. This will be used to create a new random map whenever you start a new game. Meaning saved games will also be a thing.

There will be a tech tree of how to go to other technologies, and how to research passive bonuses. The numbers in the below tree are place holder, I’ve worked out more accurate numbers that roll over better (to avoid remainders). I’m sure beyond that it will still require balancing.


I’m in process on figuring out a road map, and the UI design for the tech tree, along with new features. I look forward to sharing the gameplay of these changes once it’s ready.

Tilemap Parsing, Ground Detection

The past few months have been a fair bit of learning on doing graphics programming, and how to use some of the existing libraries with Rust. Now that I have some foundation, I've been able to start on actual logic needed for a game.

The first steps of this game has been getting tile map rendering working, and interacting with that tile data. I'm a fairly big fan of using Tiled. It's a fairly versatile editor, and a number of engines have direct support for it. In this case I'm working with the data more directly, as there's no real core support for tiled in popular Rust libraries. I'm using an awesome crate called tiled to parse the data into types, so I have that covered. It gives me layers in an array, each layer containing the tile IDs, right from the XML data. Tiled exports a number of formats, and I'm using CSV format. For example:

<layer name="back" width="30" height="20">
  <data encoding="csv">

The layer is placing a number of tiles in various coordinates. It's one long list, but because the tilemap stores its number of tiles by width and height, it can keep track of what number is in what row & column fairly easily. From there, it's a matter of grabbing the 5th and 6th tile from my tileset. My tileset is an image of 92x64, with the tiles sized at 32x32, so that means 5 & 6 are on the 2nd row. Writing some simple code with division & modulous operators, one can map the UVs pretty easily:

let iw = image.width as u32;
let ih = image.height as u32;
// how many tiles is it wide & high? In this case it's 3x2
let tiles_wide = iw / (tileset.tile_width + tileset.spacing);
let tiles_high = ih / (tileset.tile_height + tileset.spacing);
// how much from 0-1 does the 32x32 take up of the source image
let tile_width_uv = tileset.tile_width as f32 / iw as f32;
let tile_height_uv = tileset.tile_height as f32 / ih as f32;
// cell is the number 5 or 6 from the example above
// subtract 1 to make it zero indexing. Then it's the same math for x & y. Just use width vs height, and modulous vs division.
let x = ((*cell as u32 - 1u32) % tiles_wide) as f32 + tileset.margin as f32 / iw as f32;
let y = ((*cell as u32 - 1u32) / tiles_wide) as f32 + tileset.margin as f32 / ih as f32;
let i = index as usize;
let tiles_wide = tiles_wide as f32;
let tiles_high = tiles_high as f32;
// now we just map the quad against those coords, i being the current index for the quad
vertex_data[i].uv[0] = x / tiles_wide;
vertex_data[i].uv[1] = y / tiles_high + tile_height_uv;
vertex_data[i + 1].uv[0] = x / tiles_wide + tile_width_uv;
vertex_data[i + 1].uv[1] = y / tiles_high + tile_height_uv;
vertex_data[i + 2].uv[0] = x / tiles_wide + tile_width_uv;
vertex_data[i + 2].uv[1] = y / tiles_high;
vertex_data[i + 3].uv[0] = x / tiles_wide;
vertex_data[i + 3].uv[1] = y / tiles_high;

That's the background layer, the next layer is the ground. This goes through the same code to figure out the drawing, but i've added some additional logic so we can build out a set of data for movement.

 <layer name="ground" width="30" height="20">
  <data encoding="csv">

0 value tiles are simply empty. They are full on ignored. So I just have a few tiles for a platform higher up, and then a base ground. In this game, i'm looking at making the movement point to click, so therefore use pathfinding, much like how you might make an AI go from point A to B. Initially I had a meta layer, where I placed a tile for each spot the player could move to, but that means for each new type, I'd have to add additional tiles, such as ledges, higher up areas that you should jump to, etc. So instead, why not create this data programatically?

When parsing a layer, the code is going in a top-down direction, so we iterate each row, then each cell across the columns for that row. This means that when parsing the ground tiles, we can track the open tiles above them to build a set of walkable areas.

The first step is walking through and building out this data.

let mut tile_map_render_data: Vec<PlaneRenderer<R>> = Vec::new();
// For the ground tiles, they will be stored x by y, in order to be able to group them. This is explained further down in this blog post.
// You'll note usage of LinkedHashMap. This is from a crate, not the standard library. It gives us an ordered map, so we can preserve the order we parse the ground tiles, and group them.
let mut ground_tiles: LinkedHashMap<i32, Vec<i32>> = LinkedHashMap::new();
// Storing the data y by x, as that's the order the layer is parsed in from a hierarchy perspective. Rows = y, cols = x
let mut unpassable_tiles: HashMap<usize, Vec<usize>> = HashMap::new();
for layer in map.layers.iter() {
    // I mentioned the meta layer earlier. Not in use right now, but keeping this around as it might come in handy still
    if != "meta" {
        // just building the render data
        let tilemap_plane = TileMapPlane::new(&map, &layer);
        tile_map_render_data.push(PlaneRenderer::new(factory, &tilemap_plane, tiles_texture, target));
        // collision layers being a static array that contains "ground"
        if COLLISION_LAYERS.contains(& {
            // a simple function i created for iterating through a layer.
            for_each_cell(&layer, false, |x, y| {
                // building out the map of impassable tiles
                if unpassable_tiles.contains_key(&y) {
                    let mut xs = unpassable_tiles.get_mut(&y).unwrap();
                } else {
                    unpassable_tiles.insert(y, vec![x]);
                // if not the first row, as nothing will be above it!
                if y > 0 {
                    // if above row above has collision data, hence the y - 1
                    if let Some(xs) = unpassable_tiles.get(&(y - 1)) {
                        // if it does not contain one for this column
                        if !xs.contains(&x) {
                            add_column_above_to_ground(x, y, &mut ground_tiles);
                    // or if it has zero collision data
                    } else {
                        add_column_above_to_ground(x, y, &mut ground_tiles);

fn add_column_above_to_ground(x: usize, y: usize, ground_tiles: &mut LinkedHashMap<i32, Vec<i32>>) {
    // it is open, so let's add it
    // we track x by y instead of y by x, as we need to go in that order for the tile grouping of grounds
    let x = x as i32;
    let y = (y - 1) as i32;
    if ground_tiles.contains_key(&x) {
        let mut ys = ground_tiles.get_mut(&x).unwrap();
    } else {
        ground_tiles.insert(x, vec![y]);

With that data together, we can break it down into groups. The reason for building out the ground_tiles as X by Y instead of Y by X, is to parse each column one at a time. This ensures that when checking a single tile, we can check the full range of the previous column to know what group it falls into. If you go Y by X, you have the current row's data as you go left to right across it, but you won't know if the row below is accessible by the current tiles.

// still storing Y by X, to keep it consistent
let mut groups: Vec<Vec<(i32, i32)>> = Vec::new();

for (col, rows) in ground_tiles.iter() {
    for row in rows {
        let mut found = false;
        let mut temp_row = 0;
        let mut temp_col = 0;
        let mut target_group_index = 0;

        // find whichgroup of (y, x)s can be used
        for (i, group) in groups.iter().enumerate() {
            let last_cell = &group[group.len() - 1];
            // if the X (col) is 0 or +1 to the right. If the Y (row) is between +1 and -1 from the last
            if (col - last_cell.1 == 0i32 || col - last_cell.1 == 1i32) && row - last_cell.0 < 2i32 && row - last_cell.0 > -2i32 {
                temp_row = *row;
                temp_col = *col;
                target_group_index = i;
                found = true;

        // when its found, it means it can be added to a previous group, as it is within walkable range
        if found {
            groups.get_mut(target_group_index).unwrap().push((temp_row, temp_col));
        } else {
            groups.push(vec![(*row, *col)]);

With that data sorted out, we can then turn it into our usual Y by X map. Just faster to retrieve the data we need.

let mut hash_groups: Vec<HashMap<usize, Vec<usize>>> = Vec::new();

for group in groups {
    let mut coords: HashMap<usize, Vec<usize>> = HashMap::new();
    for (y, x) in group {
        let y = y as usize;
        let x = x as usize;
        if coords.contains_key(&y) {
            let mut xs = coords.get_mut(&y).unwrap();
        } else {
            coords.insert(y, vec![x]);


Snowball Effect Skins

As the game gets closer to release, I've worked on a few skins that you'll be able to purchase, and use to your heart's content. I wanted to make some that were a bit out there, and out of place, to make things more fun.

Since animating a rotating sphere proved difficult, I decided to make a flat texture, and leverage blender to make some of the frame by frame animations for these. First time doing 3d texturing in well over a decade, UVs are hard! I give much respect to those who work on 3d games, and animated motion pictures.

Here's the first skin I completed:

It's a large rock that gains & shrinks just as the normal snowball. I experimented with more of a golf ball type look, but felt it didn't give the look I want. So I ended up using a low poly sphere.

The next skin is a bowling ball.

The type of ball that most of us have rolled along a surface at some point. Bowling balls come in a range of patterns and designs. I wanted a nice blue one to keep with the existing colour theme. Then lined it with red, purple, green, orange bits so you can see it spin. Along with the typical three hols to grip the ball with.

To follow the trend of games that you play for a fun night out:

I naturally had to add an 8 ball. Making the texture for this was pretty straight forward, but as I mentioned earlier, getting the UVs right so it wasn't stretched was a challenge. I'm fairly happy with the result now, and I hope you like it.

By far my favourite skin though is this one:

I generally haven't caught on to the retro + pixel art trend going on in games, but I understand the appeal. I decided to give this a try, and I'm really happy how it turned out. I initially tried the same base colour as the standard snowball, but I found white worked better. I also added square versions of the little spots that wrap around the snowball.

Game Progress

As far as the state of development, I'm on the final touches of the game now. I'm working on getting game music complete, as well as working on an android build. Look out for a release coming soon!

Revive item implemented - Snowball Effect

This latest update includes the system for purchasing items, and the implementation of the revive item. So after doing a few runs and collecting coins, you can then buy yourself one or more revive items. If you have any avaialble, you'll see an additional button upon death

Using this will then bump up your snowball size immediately, and allow you to continue the game where you left off.

Snowball Effect, Challenges

As mentioned in the previous post, I altered the speed a little. Slowed it down to allow more reaction time, and give the player a better chance to see things as they happen. Feeling fairly happy with this change. Another change I needed to make concerned the UI, as I added in some new mechanics and the UI needed to be shifted around. You can see I moved the resource bar moved to the top.

The reason for this was the addition of a jump ability, the next addition to the player's toolbox. Upon completing the first challenge, the player will unlock the jump ability. The game will then start spawning a trap that requires a jump to get over it. You can see the jump button on the bottom right.

The jump also can be used to avoid the fire pits, but it does cost a bit more energy to use over throwing the snowball. Now, one can use it to go over multiple fire pits, depending on how they stack. So having both the jump & throw abilities can help for different situations.

In order to unlock the jump you need to complete a challenge. The actually criteria for the challenge hasn't been nailed down, but for now it's to throw 5 snowballs at 5 pits. When the game starts up, it will show you want your current challenge is.

Next Steps

Aside from a couple bugs I wish to tackle, the next set of things to work on will be primarily adding further challenges. Then after that start looking at powerups/items to use as you go through the game. This will involve both the implementation when going through the game, as well as a UI screen for it. I am considering doing a UI screen for the challenges you have yet to unlock as well.

Snowball Effect, new mechanic

One of my focuses with doing the new version of this game was to add abilities and other mechanics for the player to use. The first one I have now implemented is simply firing a little snowball on tap at a fire pit. This doesn't remove the fire pit from game, but changes its state so it no longer does damage to the player's snowball.

I played with an alternate input mechanism for this mechanic. I thought it would be neat to have the player swipe from either side of the screen to fire a snowball from that side of the screen at the closest target. This presented however a couple of problems:

  1. With gyro/tilt controls off, touch input was needed to move the snowball. How to best differentiate between swipes and movement intent?
  2. The closest target may not be the one the user wishes to avoid.

To further the last point, I tried playing with the code a fair bit to see if I could make it intelligent, but it never felt quite right. So I decided to go with the implementation that I settled on. Which is to simply tap the target. Upon doing so, a snowball flies across the screen. Upon collision with the fire pit, it changes to a disabled state:

Of course to prevent the user from staying still and constantly tapping at every hazard on screen, they need to gather a resource in order to fire a snowball. This is done by colliding with the blue shapes on the hill. As they do the bar on the right side fills up:

Next steps

I'm considering changing the pacing of the game a little bit with this change. It's hard to make out what the snowball actually is, as it flies across the screen rather quickly. Slowing the game down could make it more identifiable. Make fewer hazards and resource targets appear, but make them larger as well. Leading to more strategy on positioning instead of reaction. Not sure if this is the way I will take the game, just something I wish to play with.

Snowball update, random infinite runner

The game has not changed much looks wise since I last posted, but I've gotten some important functional changes done. The game now works with a randomly generated route, instead of a fixed one. What this means is the game can be truly infinite, and dynamic as I add more permutations and type of terrain.

To get into the technical changes for a bit, the original code uses a z position, which goes up in value each frame to move through the path. Now though once you pass a segment of the ground, it gets removed from the scene, and put back into the object pool. Once a full section is passed, such as a: hill, straight away, curve, or s curve, a new random section is added. This will go on indefinitely.

Originally each segment stored its index, in terms of where it is in relation to each other segment. I dropped this, in favour of using its array index instead. This allowed me to pull the first element of the array off easily, and add new ones to the end, without having to update a property. However, I did have to update the "world position" of each segment when a segment is removed. The world z position is based off of its array index, so when the array index changes, so must the world position. This is an extra O(n) operation I would really prefer to avoid, so it's something I'm going to have to continue to think on.

cleanupSegments() {
  const baseSegmentIndex = this.findSegmentIndex(position - SlopeBuilder.SEGMENT_LENGTH);
  const segment = this.children[baseSegmentIndex - 1];
  if (segment) {
    this.children.splice(baseSegmentIndex - 1, 1);
    position -= SlopeBuilder.SEGMENT_LENGTH;

    // TODO: Think if there's a way to avoid looping through all segments
    for (let i = 0; i < this.children.length; i++) {
      this.children[i].resetWorldZ(i, SlopeBuilder.SEGMENT_LENGTH);

As you can see here, I find the segment behind the current camera position. Fetch the segment from that. If a segment is returned, it gets pushed to the pool, removed from the collection. The setTrackLength method takes the children.length by the SEGMENT_LENGTH to determine the current length of the track, and cache it accordingly. The camera position is then negated by the SEGMENT_LENGTH as well. While one solution is to increment the position forever, numbers do have maximum storage values. So I went for the route of subtracting the position, and update the world position on each segment in the game world.

While the route generation is mostly random, down hill has a higher weight, so it will spawn a majority of the time. This is to give the feeling of still going down a large slope. I re-implemented the fire pit hazard, along greatly increased the rate at which collidable objects spawn on the route. Something I'm going to do soon is replace the art assets of both objects. I'm planning to simplify them on detail and number of colours, make it look more stream lined with the rest of the game, and go back to vector art for one of the items. The downside right now is the firepits or objects you collide into spawn in 1 of 3 positions in the lane. It looks a little too static, or programmed in. I hope to play with some variance on this, make it look more organic. The frequency of the objects is really high too, so I might try to put in some more non man made hazards, such as rocks and trees.

Thanks for reading. This game has my focus outside of my fulltime job now, so I should be able to post fairly regular updates.