Procedural levels continued: randomized pits and performance enhancements

Posted on June 26, 2012 | 4 minute read

I did some more playing around with the procedural level stuff in ImpactJS tonight and have made a little bit of progress. Specifically the following has happened:

  • Randomized pit obstacles

  • Killing excess collider entities

  • Some other bits and pieces

Randomized pit obstacles

Right now I’m using the simplest possible way of spawning these in terms of formula: generating a random number between 0 and 500. If the number is less than 1 (so 0), a pit entity is spawned 700 pixels in front of the player.

So right now I have the following code in the main.js update function (I over-commented it in the code for the purpose of this post, just easier to make inline notes instead of commenting on stuff externally):

    var player = this.getEntitiesByType( EntityPlayer )[0];
	
    // Generate random number between 0 and 500
    var rand=Math.floor(Math.random()*501);
    // If random number is 0, spawn pit
    if (rand < 1) {
        var e = this.spawnEntity (EntityPit1, player.pos.x + 700, 420);
        // Pit appears behind player
        e.zIndex = -1;
        // Re-sort entities by zIndex
        this.sortEntitiesDeferred()
    }
	
    // If a pit isn't spawned, spawn collider entities in its place
    else {
        this.spawnEntity( EntityCollision, player.pos.x + 300, 420 );
    }

Eventually the formula to decide whether the pit gets spawned will be a little more refined and be impacted by things like difficulty, whether a pit already exists a certain distance away, etc.

The pit entity, like the collider entity, is killed when it scrolls out of view off of the left side of the screen.

Killing excess collider entities

In the screenshot I included within my previous post you can see that collider entities get spawned on top of each other, creating unnecessary instances of the entity. To avoid this, I did the following in the collision.js update function:

        // Kill the entity as soon as it's no longer in view of the screen window
        // or if its position is below the first row
        var i = this.pos.x - ig.game.screen.x;
        if( i<0 || this.pos.y > 420){
            this.kill();
        }

Collider entities also need to be killed when they come in contact with the pit entity, to make sure that our player can actually fall into the pit. To enable us to check whether a collider entity is touching a pit entity, we have to use the correct type and check settings:

collision.js:

    type: ig.Entity.TYPE.A,
    checkAgainst: ig.Entity.TYPE.B,
    // Entity is fixed to ensure it always stays in place.
    collides: ig.Entity.COLLIDES.FIXED,

pit1.js

    type: ig.Entity.TYPE.B,
    checkAgainst: ig.Entity.TYPE.A,
    // Entity is NEVER collides with anything, allowing player to pass through
    collides: ig.Entity.COLLIDES.NEVER,

The settings in player.js are exactly the same as those in the collider entity above, except its collides is set to PASSIVE instead of FIXED.

We can now use the check() function to detect when the pit entity is touching either the collider entity or the player entity. So in pit1.js I have this:

    check: function( other ) {
        if (other instanceof EntityCollision) {
            // Kill collider entities if they touch the pit entity
            other.kill();
        }

I didn’t close the check() function because there’s more:

Decreasing player’s velocity as they fall into the pit

The player currently moves to the right automatically as the game is running by using vel.x. However, when the player falls into the pit I want them to fall straight down instead of continuing to move to the right.

This was pretty simple to do: if the player entity is touching the pit entity and its pos.x is greater than the pos.x of the pit, decrease the player’s vel.x.

The problem here was that if the player jumps over the pit entity and doesn’t fall, but still touches it slightly with part of its collider its velocity is still decreased because it meets the above conditions. I ended up getting around this by checking whether the width of the player plus its position on the x axis is less than the width of the pit entity plus its position on the x axis. So directly under the above code in the pit1.js check() function I put this:

        else if (other instanceof EntityPlayer) {
            if (this.pos.x < other.pos.x && other.size.x + other.pos.x < this.size.x + this.pos.x) {
                other.vel.x = other.vel.x * 0.05;
            }
        }
    }

Bits and pieces

I’ve put in other stuff that will tie into the dynamic levels and difficulty in the long run, but those are peripheral bits and pieces that will be a bit too much to stick into this post. I might write about them a bit later on. There’s also some other small stuff like score tracking etc that’s now in.

Progress screenshot: [caption id="attachment_48371” align="aligncenter” width="300”]ImpactJS Javascript platformer progress Yellow: collider entities; Gray: pit entity; Red: repeating background tiles[/caption]




Categories:game dev dev games
comments powered by Disqus