In this part we're adding a visual score counter to our shooter game.
HaxePunk provides a class for rendering texts using an embedded font - Text. Just like with an Emitter, it needs to be applied to a "graphic" property of an Entity.
So we'll first create a new Entity subclass, Score.hx, which creates a new Text instance and assigns it as its own "graphic" value.
The actual score number is stored in an integer variable. We'll add a public method which will provide an interface to increment the score value.
The code of Score.hx looks like this:
package ;
import com.haxepunk.Entity;
import com.haxepunk.graphics.Text;
import flash.text.TextFormatAlign;
import com.haxepunk.HXP;
/**
* Score container and counter.
* @author Kirill Poletaev
*/
class Score extends Entity
{
private var score:Text;
private var points:Int;
public function new()
{
super();
score = new Text("Score: 0", 0, 50, HXP.width);
score.align = TextFormatAlign.CENTER;
score.size = 24;
graphic = score;
layer = -2;
points = 0;
}
public function add(num:Int) {
points += num;
score.text = "Score: " + points;
}
}
The Text() constructor has several optional parameters. We can set the initial text value, the coordinates of the text field, its width and height, as well as a set of options in a TextOptions object.
In the MainScene.hx class we need to instantiate this Score class. Add the instance to the scene, then pass the Score object reference as the third parameter in EnemyShip constructor.
package ;
import com.haxepunk.graphics.atlas.TextureAtlas;
import com.haxepunk.graphics.Image;
import com.haxepunk.HXP;
import com.haxepunk.Scene;
import com.haxepunk.utils.Input;
import com.haxepunk.utils.Key;
class MainScene extends Scene
{
private var player:PlayerShip;
private var spawnInterval:Int;
private var enemyGraphic:Image;
private var explosion:Explosion;
private var score:Score;
public function new()
{
super();
Input.define("up", [Key.UP, Key.W]);
Input.define("down", [Key.DOWN, Key.S]);
Input.define("left", [Key.LEFT, Key.A]);
Input.define("right", [Key.RIGHT, Key.D]);
var atlas:TextureAtlas = TextureAtlas.loadTexturePacker("atlas/atlas.xml");
enemyGraphic = new Image(atlas.getRegion("enemyShip"));
player = new PlayerShip(atlas);
add(player);
spawnInterval = Math.round(Math.random() * 50) + 50;
explosion = new Explosion(atlas);
add(explosion);
score = new Score();
add(score);
}
override public function update() {
super.update();
spawnInterval--;
if (spawnInterval == 0) {
var enemy = new EnemyShip(enemyGraphic, explosion, score);
add(enemy);
enemy.x = Math.round(Math.random() * (HXP.width-64));
enemy.y = -50;
spawnInterval = Math.round(Math.random() * 20)+30;
}
}
}
In the EnemyShip.hx class we receive and store a reference to this Score instance, and call its add() method when the ship is destroyed.
package ;
import com.haxepunk.Entity;
import com.haxepunk.HXP;
import com.haxepunk.graphics.Emitter;
/**
* Enemy ship entity.
* @author Kirill Poletaev
*/
class EnemyShip extends Entity
{
private var speed:Int;
private var health:Int;
private var explosion:Explosion;
private var score:Score;
public function new(g:Dynamic, explosion:Explosion, score:Score)
{
super();
graphic = g;
this.explosion = explosion;
this.score = score;
speed = Math.ceil(Math.random() * 3);
setHitbox(64, 48, 0, 0);
health = 5;
}
override public function update() {
this.y += speed;
if (this.y > HXP.height) {
scene.remove(this);
}
var collidedEntity = collide("bullet", x, y);
if (collidedEntity != null) {
health--;
scene.remove(collidedEntity);
explosion.explode(x, y);
}
if (health == 0) {
var i:Int = 0;
while(i<3){
explosion.explode(x, y);
i++;
}
score.add(1);
scene.remove(this);
}
}
}
If you test the game now, you'll notice a new score counter displayed. Every time you destroy an enemy ship the score increases.