/ Canvas

Developer Diary: Jetpack game HTML5 – Day 4

Milestone of the day:
Create coin structures and make them collide with the player

Day 4: Creating coin structures

Part 1: Creating a single coin

Ok, let's start by creating a single coin. This is fairly easy, all we have to do is create the coin component.

[javascript]
/*

  • Define the coin component
    */
    Crafty.c("coin", {
    init: function()
    {
    this.addComponent("2D, Canvas, coin_normal, Box2D");
    this.box2d({
    bodyType: 'kinematic',
    shape: "box"
    });

     this.fixtures[0].m_isSensor = true;
    
     this.bind("EnterFrame", function()
     {
         this.body.SetLinearVelocity(new b2Vec2(-game_speed, 0));
         if(this._x < -14) this.destroy();
     });
    

    }
    });
    [/javascript]

The coin_normal component that I add is the name of the sprite that I've defined.

[javascript]
Crafty.sprite(14, "assets/sprites/coin.png", {
coin_normal: [0, 0]
});
[/javascript]

One special thing that I did, is set the first fixture (should be the only one) to isSensor. That way, the player can move trough the coins.

[javascript]this.fixtures[0].m_isSensor = true;[/javascript]

To add a coin to the game, simply create the coin entity.
(also create a isCoin boolean and set it to true, we'll need this later for our collision detection):

[javascript]
var cn = Crafty.e("coin")
.attr({
x: (Crafty.viewport.width + (14column))/ptm,
y: (randY + (14
row))/ptm,
isCoin: true
});
[/javascript]

Part 2: Defining coin structures

This is the tricky part, here I will try to create coin structures. Example: Bob coin structure This structure spells out "Bob". But you can use your imagination and create all sorts of structures.

So how do we do this? Well, I chose to do it using 2D arrays. To start off, I've created a new Javascript file and named it "coin_structures.js". In this file I will create all possible coin structures.

I will not explain 2D arrays here. If you don't know what a 2D array is, I suggest you do some research.
Let's start simple. I'm going to create an "X" structure.

[javascript]
var coin_structure_x =
[
[1,0,1],
[0,1,0],
[1,0,1]
];
[/javascript]

I'm using 1's and 0's to define the structure. A 1 means that there will be a coin and 0 means that there will be nothing.

A more complex example (bob):

[javascript]
var coin_structure_bob =
[
[1,1,1,0, 0, 0,1,1,0, 0, 1,1,1,0],
[1,0,0,1, 0, 1,0,0,1, 0, 1,0,0,1],
[1,1,1,0, 0, 1,0,0,1, 0, 1,1,1,0],
[1,0,0,1, 0, 1,0,0,1, 0, 1,0,0,1],
[1,1,1,0, 0, 0,1,1,0, 0, 1,1,1,0]
];
[/javascript]

Now that we've defined what the structure looks like, we have to add it to the game.

Part 3: Adding the coin structures to the game

This was a very tricky part. I had to do a lot of research but in the end it was actually very simple. I started looking at tile engines and I've found out how to do this.

Let's have a look at the code:

[javascript]
function createCoinStructure(structure)
{
var randY = Crafty.math.randomInt(0, Crafty.viewport.height-(14*structure.length));

for(row = 0; row <= structure.length-1; row++)
{
    for(column = 0; column <= structure[0].length-1; column++)
    {
        if(structure[row][column] == 1){
            //console.log(structure[row][column]);
            var cn = Crafty.e("coin")
            .attr({
                x: (Crafty.viewport.width + (14*column))/ptm,
                y: (randY + (14*row))/ptm,
                isCoin: true
            });
            cn.body.SetPosition(new b2Vec2(cn._x, cn._y));
        }
    }
}

}
[/javascript]

This function will spawn the coin structure in the game at a random y value.
The parameter that we pass in this function is a coin structure. (it's just the 2D array)

We then loop over every row, inside that row we loop over every column. So we go from up to down and left to right.
If the structure has a 1 at the current [row][column] coordinate, we can create a coin at that position.

The x position is then the width of the viewport (so that it spawn outside the screen) + the width of the coin (14) multiplied by the current column.
(don't forget to divide by the amount of pixels per meter (ptm), this is needed for Box2D's coordinate system)

We then do the same for the y value.

Part 4: Adding collision

This is very easy if you've read day 3 (Developer Diary: Jetpack game HTML5 – Day 3).

All we have to do is add the following code to the game loop (onEnterFrame):

[javascript]
// Check to see if you've hit a coin
if(spriteA.isPlayer && spriteB.isCoin)
{
coin_hit(bodyB);
}
else if(spriteB.isPlayer && spriteA.isCoin)
{
coin_hit(bodyA);
}
[/javascript]

The coin_hit function will increase your score and destroy the coin.
The parameter is the body of the coin that you've hit.

[javascript]
function coin_hit(coinBody)
{
var sprite = coinBody.GetUserData();
sprite.destroy();
sprite = null;
world.DestroyBody(coinBody);
game_score++;
}
[/javascript]

Part 5: Creating the CoinSpawner

And finally, we have to spawn a random coin structure in the game every x seconds. (I chose 10 seconds)

This is basically the same as the EnemySpawner.

[javascript]
function createCoinSpawner()
{
//Enemy spawner (just an entity; not assigned to a variable)
Crafty.e("coinSpawner").bind("EnterFrame", function(e) {
if(frame_number_coins == coins_delay) {
var rand = Crafty.math.randomInt(0, coin_structures.length-1);
createCoinStructure(coin_structures[rand]);
frame_number_coins = 0;
}

    frame_number_coins++;
});

}
[/javascript]

All I've added is a variable (rand) that chooses a random integer between 0 and the size of the coin_structures array-1.
The coin_structures array is a global variable that holds all the possible coin structures in the game.

Pfew! That was a lot.
I hope you've learned something.

Michiel De Mey

Michiel De Mey

Full-time geek, Full Stack Engineer and Full Metal Hero. NodeJs, AngularJs, API design, WebSockets, WebSec & IoT enthusiast. Former San Francisco resident.

Read More