My second game ‘Skyroll’

Skyroll is an action game where you need to get as high in the sky as possible. You control a round smiley face by tilting your phone to make it roll into the direction of the gravity and jump by touching the screen. For PC controls you make use of the arrow keys / space or WASD (minus the ‘S’, there is no ducking or moving down).

Process

I always liked playing Doodle Jump, so the idea of an endless game where you need to get as high as possible was the starting point of the game idea. I did not want to copy the exact game mechanics, so I decided to instead of the player moving up to make the level move down at a constant speed which speeds up gradually after time. I was looking for graphics for the game and found the Physics Assets set by Kenney.nl. These elements were perfect for my platforms and the smileys (with some minor alterations) for the player and the enemies.

Physics Assets by Kenney.nl

Nape

The default physics in HaxeFlixel are fine for simple collisions, but I discovered that it is not easy to make circles collide with rectangles etc. I have always been fascinated by the impressive Physics Examples at Napephys.org (check them out if you are not familiar with them), so this was a perfect opportunity to use the Nape library for my game.

Instead of using FlxSprite you must use FlxNapeSprite as the parent class for object that you when to make collide with each other. Here is a part of the initialization of the Player class with extends the FlxNapeSprite:

Player.hx

1

2

3

4

5

6

7

8

9

10

...

loadGraphic(Assets.getBitmapData("images/player.png"));

createCircularBody(width*0.5,BodyType.KINEMATIC);

antialiasing=true;

setBodyMaterial(-1.0,.5,.5,1.5);

setDrag(0.98,1);

body.cbTypes.add(Player.CB_PLAYER);

body.userData.data=this;

...

The
BodyType.KINEMATIC makes the body static and not affected by physics, because I am using the player in the start menu as a background and make it jump when the player starts the game. At that point the body type is set to
BodyType.DYNAMIC and the Player will be affected by gravity.

To the body of the Player class I add a custom callback type (cbType)
Player.CB_PLAYER to be used when interacting with other bodies. The Enemy class has a
Enemy.CB_ENEMY callback type assigned in the same way. This makes it easy for the PlayState to add event listeners when the two bodies are interacting:

PlayState.hx

1

2

3

4

5

6

7

8

9

...

FlxNapeState.space.listeners.add(newInteractionListener(

CbEvent.BEGIN,

InteractionType.COLLISION,

Player.CB_PLAYER,

Enemy.CB_ENEMY,

onPlayerStartsCollidingWithEnemy

));

...

When the two bodies trigger the
CbEvent.BEGIN event the fuction
onPlayerStartsCollidingWithEnemy is called and the program can take action (lose a power up or die).

There are three different Platforms (Stone, Glass and Wood). Each of these platforms react differently when the Player interacts with them. For example the Glass type platform has the callback type
Platform.CB_PLATFORM_ONE_WAY which means that the player can jump through the bottom and keep standing on the platform. The event listener looks like this:

PlayState.hx

1

2

3

4

5

6

7

8

...

FlxNapeState.space.listeners.add(newPreListener(

InteractionType.COLLISION,

Platform.CB_PLATFORM_ONE_WAY,

Player.CB_PLAYER,

onPlayerStartsCollidingWithOneWayPlatform

));

...

This is a so-called PreListener which can determine if Nape needs to react to the collision of the bodies or ignore it. We want Nape to ignore the interaction and let the Player pass through the Platform when the Y-normal of the collision between the Platform and the Player is larger than 0:

This logic is taking from the OneWayPlatforms demo on the Napephys website.

Level generation

Level generation

The biggest challenge was creating a unique experience every time you play the game without becoming completely random or unplayable. After thinking about this for a (too) long time I came up with the following rules:

Divide the phases in ‘levels’.

Levels should be a collection of predefined rows

Rows can consist of 15 blocks to be filled by the Platforms (full width of the screen: one block is 36px and the screen width is 540px (15 * 36)).

Rows should be a collection of amounts of Platform types (e.g. 3 Wood and 5 Glass).

Platforms are made of 1, 2, or 3 blocks.

Every time a Row is drawn, the blocks are randomly placed in the 15 block space. Platforms are to be drawn with as many blocks as possible. So if a Row should consist of 5 Glass blocks, one Platform with 3 blocks and one Platform with 2 blocks with be randomly placed on the Row.

The use of levels makes it possible to for example only draw Rows that consist of Glass platforms and in the next level introduce Wood or Stone elements. See the source code of the Level Generator for more information.

AdMob

I wanted to experience with some kind of advertisement in the game. I have no illusions about earning (any) money with this game, but I am curious about the clicking behavior of players and how to implement this kind of library. I tested different libraries and choose the samcodes-admod library by Sam Twidale because it worked very well and is actively maintained (always important when using Open Source Software). Unfortunately it conflicted with the google analytics library (ganalytics) that I was using, so I dropped this and choose Flurry for analytics by using linden-flurry.

Conclusion

The plan was to finish this game within a month (again), but I failed to do so (again). The main reasons were using new techniques (Nape), creating everything from scratch (Menu, Popups, etc) and the implementation of the level generation. In the end I am happy to have a finished game. That’s what counts the most for me. See you soon(er hopefully 😉 for game #3!