Skip to content

Enemies

Zal0 edited this page Dec 18, 2021 · 9 revisions

Time to add a little bit of action to our game by adding an enemy.

  • Open the Game Boy Tile Designer and create a new 16x16 Sprite for our enemy (View->Tile Size->16x16). This is what I came up with:

enter image description here

Save the file into the res/sprites folder as enemy.gbr

  • Create a new file SpriteEnemy.c inside de src folder with the next content:
#include "Banks/SetAutoBank.h"

void START() {
}

void UPDATE() {
}

void DESTROY() {
}
  • In ZGB_Main.h add the new type for the Sprite after the SPRITE_PLAYER declaration. You need to use the macro _SPRITE_DMG indicating the code (SpriteEnemy) and the data (enemy, the name of the gbr file without the extension)
#define SPRITES \
_SPRITE_DMG(SpritePlayer, player)\
_SPRITE_DMG(SpriteEnemy, enemy)\
SPRITE_DEF_END

(don't forget the backslash at the end of the line!)

  • In StateGame.c create an instance in 70, 50
void START() {
	...
	SpriteManagerAdd(SpriteEnemy, 70, 50);
}
  • If you build the game now you'll see your player and the new enemy. It does nothing and there aren't any collisions yet

enter image description here

  • Write the next code on SpriteEnemy.c
#include "Banks/SetAutoBank.h"

#include "SpriteManager.h"

typedef struct {
	INT8 vy;
} CUSTOM_DATA;

void START() {
	CUSTOM_DATA* data = (CUSTOM_DATA*)THIS->custom_data;
	data->vy = 1;
}

void UPDATE() {
	CUSTOM_DATA* data = (CUSTOM_DATA*)THIS->custom_data;
	if(TranslateSprite(THIS, 0, data->vy)) {
		data->vy = -data->vy;
	}
}

void DESTROY() {
}

Here you can see how the field custom_data of the Sprites is mean to be used. Also TranslateSprite will return the index of the tile when a collision happens or 0 otherwise. In this case if there is a collision with the background the velocity of the sprite is negated making it changing its direction

  • In order to collide with the enemy you have to add the next code at the end of the method Update of SpritePlayer.c
#include "ZGBMain.h"
...

void UPDATE() {
	UINT8 i;
	Sprite* spr;
	...

	SPRITEMANAGER_ITERATE(i, spr) {
		if(spr->type == SpriteEnemy) {
			if(CheckCollision(THIS, spr)) {
				SetState(StateGame);
			}
		}
	}
}

"ZGBMain.h" needs to be included in order to get access to all the sprite types. SPRITEMANAGER_ITERATE is a macro that iterates through all the active sprites, if the sprite is of type SPRITE_ENEMY then we use the function CheckCollision to check if we are colliding with it (do it in this order). If that happens then SetState is called unloading the current state and loading the state passed as paramenter (even if it is the current one, like in this case)

Clone this wiki locally