Player

by @collinhover

In this tutorial, we're going to setup a simple side-scrolling player character, make a laser gun ability, and attach some input handlers so we can shoot some bad guys. You can extend this setup into a top-down game by flipping the TOP_DOWN config switch. Boom, headshot!

Prerequisites

We're assuming you've read at least the Getting Started tutorial and have a game with at least one level for testing purposes. You'll also need to grab the following media if you want to work through this with us:

  1. The player sprite sheet at examples/jumpnrun/media/player.png.
  2. The projectile sprite sheet at examples/jumpnrun/media/projectile.png. (these can both be found in the Impact++ repo).

The Player Character

Lets start with a player character. In your game's entities folder, located at lib/game/entities/, create a new file called player.js. To create the most basic of player characters, place the following code into the new file:

ig.module( 'game.entities.player' )
.requires(
    'plusplus.abstractities.player'
)
.defines(function () {
    ig.EntityPlayer = ig.global.EntityPlayer = ig.Player.extend({
        size: {x: 8, y: 14},
        offset: {x: 4, y: 2},
        animSheet: new ig.AnimationSheet( "media/player.png", 16, 16),
        animInit: "idleX",
        animSettings: {
            idleX: { sequence: [0], frameTime: 0.1 }
        }
    });
});

The idea here is to create a new entity, ig.EntityPlayer, that extends Impact++'s player abstract which has all sorts of built in functionality. We've set the sprite frame size to 16x16, set the player bounding box or collision box to 8x14, and offset the sprite frame slightly to account for the collision box's size.

Lets also add a few animations preemptively, which the player character will use automatically based on what they are doing at any given moment. Inside the animSettings property of your player character, add:

moveX: { sequence: [0, 1, 2, 3, 4, 5], frameTime: 0.07 },
jumpX: { sequence: [8, 9], frameTime: 0.1 },
fallX: { sequence: [6, 7], frameTime: 0.4 }

The Laser Beam

Before we can shoot anything, we need something to shoot out of something that does the shooting. Lets start with the thing we'll shoot, a laser beam. In your game's entities folder, located at lib/game/entities/, create a new file called laser.js and place the following code into the new file:

ig.module( 'game.entities.laser' )
.requires(
    'plusplus.abstractities.projectile'
)
.defines(function () {
    ig.EntityLaser = ig.global.EntityLaser = ig.Projectile.extend({
        collides: ig.EntityExtended.COLLIDES.LITE,
        size: {x: 4, y: 4},
        offset: {x: 2, y: 2},
        animSheet: new ig.AnimationSheet( "media/projectile.png', 8, 8),
        animInit: "idleX",
        animSettings: {
            moveX: { sequence: [0], frameTime: 1 },
            deathX: { sequence: [1,2,3,4,5], frameTime: 0.05 }
        }
    });
});

The idea here is to create a new entity, ig.EntityLaser, that extends Impact++'s projectile abstract which has all sorts of built in functionality. Similar to the player and character abstracts, the projectile can automatically play certain animations based on its state. Lets add a few more properties in the class definition to make use of these automatically handled states:

damage: 2, // lasers hurt
lifeDuration: 2, // lasers eventually fade (like a particle)
gravityFactor: 0, // lasers ignore gravity
friction: {x:0, y:0}, // lasers have no friction
bounciness: 0, // lasers don't bounce
collisionKills: true, // lasers stop if they hit a wall

The Laser Gun

To be fair, we won't actually make a laser gun. What we're going to do now is tap into the Impact++ abilities and use the shoot ability to create a character usable ability for our player character. In your game folder, located at lib/game/, add a new folder named abilities and inside it create a new file called laser-gun.js. Place the following code into the new file:

ig.module( 'game.abilities.laser-gun' )
.requires(
    'plusplus.abilities.ability-shoot',
    'game.entities.laser'
)
.defines(function () {
    ig.LaserGun = ig.AbilityShoot.extend({
        spawningEntity: ig.EntityLaser,
        offsetVelX: 200
    });
});

All we're doing here is extending the shoot ability to make a specific shooting ability that shoots lasers with a specific velocity in the direction our character is facing. Note that we're requiring the laser beam projectile and setting it as the spawningEntity (or thing we want to shoot out) of our laser gun ability.

Bringing it Together

Back to the player entity, we need to add a few things to hook the laser gun into place. Require the ability: 'game.abilities.laser-gun', and add the shooting animation to the animSettings: shootX: { sequence: [2], frameTime: 0.25 }. Next, create the ability and store it with the player:

initProperties: function() {
    this.parent();
    this.shoot = new ig.LaserGun(this);
    this.abilities.addDescendants([this.shoot]);
}

The initProperties method is part of the Impact++ entity init pattern. It is recommended to use initType or initProperties for any properties that will only be created once in an entity's existence, and resetCore or resetExtras for any properties that need to be reset each time an entity to added to the game.

Fourth, handle input to activate the ability:

handleInput: function() {
    this.parent();
    if (ig.input.pressed('shoot')) {
        this.shoot.activate({
            x: this.flip.x ? this.pos.x : this.pos.x + this.size.x,
            y: this.pos.y + this.size.y * 0.5
        });
    }
}

And finally, add the input to the game by opening your game's main file, located at lib/game/main.js. Here, we'll set it so that our game binds the "F" key to the "shoot" input, which our player is already waiting for:

inputStart: function () {
    this.parent();
    ig.input.bind(ig.KEY.F, 'shoot');
},
inputEnd: function () {
    this.parent();
    ig.input.unbind(ig.KEY.F, 'shoot');
}

Now you're all set to run n' jump n' blast!

Learn More!

Player
Player Manager
Ability Shoot
Config file