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.

Snowball, rolling hills

I took a break from development on Snowball Effect for around a month. I participated in LibGDX Jam. You can check out my entry here if you wish.

Before the holidays I implemented hills into the generation system. This evening I finally got the sprites clipping properly, which you can see here!

This was accomplished by referencing a few tutorials on building an oldschool racer from the NES & SNES days: codeincomplete. The terrain is in segments. A segment has two pieces of data, each pertaining to the top & bottom sides of the segment. Each side contains an object storing the position, width and scale. It also stores a Vector3 for its original world starting position. This is never changed. The world Vector3 stores the z coordinate, an index of where it sits relative to other segments. It also stores a y coodinate, which is its z coordinate * height.

It then has a Vector3 called camera, which is used to cache the calculated starting values stored in world, and add them against the game's camera position. This is what makes them "move" along the screen.

These vectors are used to calculate the screen position & scale needed each frame. It uses set values I have making up the game world & height.

Segments are drawn from the bottom of the screen, up to the middle where they cap out. As it goes along in a given frame, it stores the lowest Y value achieved. This Y value is stored on each segment. This Y value is then used when the sprites are drawn, from top to bottom, so they draw over top of each other properly.

Drawing a sprite takes its segements top Y value, subtracting its scaled height. It then calculates the amount to clip off by doing:

let clipH = clipY ? Math.max(0, ypos + scaledHeight - clipY) : 0;

So if there's a clipY coordinate, it finds the bottom of the sprite, subtracts the coordinate. Then cap the clipH so it doesn't surpass the sprite's scaled height.

The source image coordinates are relative to the sprite sheet, but the height is then dependent on the clip value.

spriteHeight - (spriteHeight * clipH / scaledHeight)

Height in this case is the sprite's true height, not the scaled value. It subtracts itself, from the percentange that the clip amount takes off of the scaled height. This ensures the amount drawn from the image respects the projection scaling.

The destination height is then simply:

scaledHeight - clipH.

Initially I was drawing from the center of the sprite, so positioned in the middle instead of top left. This lead to a lot of calculation problems with the scaling.

Curves in snowball

It's been a busy week, but I found some time to get back to working on the game. I implemented the much needed curves to the terrain generation.

It feels pretty cool! I definitely need to get it working in random, so I can add a curve, chop off segments behind the player, and then generate new ones on the fly. After that, I will look at adding up & down slopes.

In addition to gamedev, i've been doing a fair bit of advent of code, which is a programmer challenge advent calendar. The problems do tend to align with mathematic challenges, but are more programmer-y than project euler. I've been using Rust to do them, but you can use any language. Check it out if you're looking for a nice break from the usual.

Projection in snowball fixed.

Pretty happy with this progress. I fixed the numnbers and managed to get the projection working correctly. Though a major problem i had was the original code I referred to for this style assumed an anchor point of being smack in the middle of the sprite. MelonJS like a lot of 2d game engines defaults to top left for the anchor point.

In MelonJS 3, a lot of work was done to fix the anchor point and improve it's capabilities. So once I updated from 2.1.3 to 3.0, and fixed my code to follow the changes, the projection essentially fixed itself. So now, it looks like this:

The updated game is playable here:

Snowball v2

A little bit ago I decided to take a break from the stealth prototype, and revisit my snowball game to make it good.

I have a game out on ios already, and you can play it on in your browser here: I decided to re-visit it as I feel like I can make it a much better game. What i've done so far is got rid of the level system, and I'm going towards an infinite runner. Where instead of having a max length of a slope, you just keep going. Slowly getting bigger. As you collide into things, you fill up a skill bar. You can use this resource to have snowmen launch themselves at fire pits. I have other ideas as well for things like jumping, putting an ice shield on you, etc. The dev version is available here:

If you hit too many fire pits, or other traps and get to small, game over. The idea is to keep growing and stay alive as long as possible.

Another major flaw with the game is the fact the backdrop is not all that interesting. So something I am working on now is making it more dynamic. Instead of a static image, im going about implementing a 3d feel similar to retro car/racing games. What i have so far:

The trees still need to be redone. But i have the collidable objects rendering on the slope. The calculations still need some adjustment. Once I have that right, I can update the trees to render along side the slope properly, and add terrain to the side as well.

From there add things like curves, and and down hill, etc.