Day 4
Oh, right, there needs to be a Game.
In-game we’ll have:
- A HUD
- The Player
- Some enemies
- Lots of bullets flying around
So each one is a class of its own.
Again, we don’t want to use the heap. Instead of using something like
Player *player = new Player()
, all of the entities are stored directly in the state, like this:
Enemy enemy[enemyCount];
Bullet playerBullet[bulletCount];
Bullet enemyBullet[bulletCount];
Player player;
That means that a pool of enemies and bullets are created in the beginning.
When the player shoots, a “dead” bullet will be picked from the playerBullet
array and it will be considered “live” until its life (ticksToLive
) runs out.
Enemies are recycled in a similar way.
I wanted to be able to place them on the map using Tiled.
By using a custom tile property, I can define what type of enemy should be spawned in a certain position:
With that I can freely place enemy spawn points on the map:
I don’t want the spawn points to be visible, however, so I put them on their own hidden layer.
Now, when the screen scrolls to the right and a new column of tiles becomes visible, I need to check if there are any spawn points on it and create the corresponding Enemy:
void StateGame::spawnEnemies(){
int spawnColumn = (-cameraX + PROJ_LCDWIDTH) / POK_TILE_W;
if(spawnColumn == prevSpawnColumn){
return;
}
prevSpawnColumn = spawnColumn;
for(int y = 0; y < Level1[1]; ++y){
auto tile = Level1Enum(spawnColumn, y);
if(tile&Karen)
spawnEnemy(spawnColumn, y, EnemySprite::Karen);
if(tile&Bob)
spawnEnemy(spawnColumn, y, EnemySprite::Bob);
}
}
As for the HUD, I use another Tilemap that only gets drawn when the player’s HP changes:
void StateGame::updateHUD(){
if(!uidirty)
return;
uidirty = false;
PD::setTASRowMask(0b1111'11000000'00000000);
uimap.draw(0, 0);
PD::setCursor(3 * POK_TILE_W + 5, 9 * POK_TILE_H - 3);
PD::fontSize = 2;
PD::color = 49;
PD::bgcolor = PD::invisiblecolor;
PD::print(player.getHP());
PD::update();
PD::setTASRowMask(0b0000'00111111'11111111);
}
By using a mask, the HUD’s tilemap won’t try to draw over the game. Once it’s done, it inverts mask so that the game won’t draw over the HUD.