Learn how to make a space shooter for the Sega Mega Drive using SGDK! I highly recommend working through the Megapong Tutorial first, as that explains a lot of the basics of MD coding.

Megalaga 2 - Entities


Alright, last time we created some scrolling space. But we’re not making a screen saver here! We’ll need entities to populate our game, entities to shoot with and entities to shoot at.

We could define all of those manually, which would look a little something like this:

int player_x;
int player_y;
int player_velx;
int player_vely;
int player_health;

int enemy1_x;
int enemy1_y;
int enemy1_velx;
int enemy1_vely;
int enemy1_health;

int enemy2_x;
int enemy2_y;
int enemy2_velx;
int enemy2_vely;
int enemy2_health;

int enemy3_x;
int enemy3_y;
int enemy3_velx;
int enemy3_vely;
int enemy3_health;

//And so on and so on...

That’s so long and dry that you probably scrolled past without reading all of it. And that’s understandable, obviously: We’re gonna have a lot of entities in our game, which would mean hours of typing, making typos, fixing typos and making new typos. But of course there is a better way!

In a modern programming language (well, even C++ is over 30 years old at this point but you know what I mean) we would use classes to instantiate objects, which would make things a lot easier than typing out all the variables for all entities. But C doesn’t have classes… so we’ll use the next best thing: structs. Structs group items of (potentially) different types into one big type. For example, we will create a struct of type Entity, which will contain our variables for the position, velocity, health etc. of our entities. This makes it a lot easier to handle everything. So let’s define it right now at the top of main.c!

typedef struct {
	int x;
	int y;
	int w;
	int h;
	int velx;
	int vely;
	int health;
	Sprite* sprite;
	char name[6];
} Entity;

This defines a struct of type Entity. Each variable of type Entity that we create will contain its own variables for its position, velocity and health. We’re also storing the width and height of a sprite (w and h respectively) as well as the actual sprite that will be drawn on screen. Finally, we’ll also be storing a name for each entity, which we won’t actually use but which is useful for debug purposes.

Now let’s use this struct to construct a player entity. After the above definition, add this line:

Entity player = {0, 0, 16, 16, 0, 0, 0, "PLAYER"};

As you can see, we’re creating a new variable called player of type Entity. And we initialize it immediately using the bracket notation. You can type whatever you want for the name (as long as it is six characters long).

Now we need to put the player on screen, but for that we’ll need an actual sprite to draw. And for that, we’ll need an image to import.

Importing the Graphic

Download the image using the link below:

Download player image

If you unzip the file and take a look, you’ll note that the image contains multiple sprites across two rows. That’s because this is a fancy animated sprite! Create a new folder in res called sprites, then put the image in there. Open up your resources.res file and import the image by adding this line:

SPRITE  ship    "sprites/imgship.bmp" 2 2 FAST 6

We’re importing the image under the generic name ship, we’ll find out why later. We’re telling the game that one sprite is 2 tiles wide and 2 tiles high, so that it automatically generates the animations for us. Each row of the image is one animation. We’re using FAST compression here and set the framerate of the animations to 6.

Now that we’ve got our image, let’s put the player on screen!

Finishing the player

In main(), add this chunk of code after the code dealing with our tiles:

SPR_init();

/*Add the player*/
player.x = 152;
player.y = 192;
player.health = 1;
player.sprite = SPR_addSprite(&ship,player.x,player.y,TILE_ATTR(PAL1,0,FALSE,FALSE));

First we initialize the sprite engine. Then we modify the variables in the player struct. To access the items in a struct, we use the dot notation as you can see. We’re setting the starting position of the player (in the horizontal center of the screen near the bottom edge) as well as its health. For this game, we’ll say that a health value of 1 means an entity is alive, and a value of 0 means that it’s dead. In a game with health bars you would of course use more values, but we’re just making a simple shooter.

Finally, we’ll add the sprite graphic to the entity using the usual SPR_addSprite function. We’ll use PAL1, the same palette the background uses. Finally we’ll tell SGDK to update the sprite engine twice: Once directly after adding the player sprite, then again at the end of the game loop before VDP_waitVSync().

//...
player.sprite = SPR_addSprite(&ship,player.x,player.y,TILE_ATTR(PAL1,0,FALSE,FALSE));
SPR_update();

while(1){
	//...
	SPR_update();
	VDP_waitVSync();
}

If you compile the game now you should see our player ship flying across the void of space using its animated booster!

images/player_added.gif

Looks good, doesn’t it? Now let’s prepare one final thing to help us down the line. We’ll write two functions that will help us deal with all the entities we’ll be creating. Add these before main():

void killEntity(Entity* e){
	e->health = 0;
	SPR_setVisibility(e->sprite,HIDDEN);
}

void reviveEntity(Entity* e){
	e->health = 1;
	SPR_setVisibility(e->sprite,VISIBLE);
}

As their names imply, these functions will kill and revive entities, respectively. They do this by setting the health value of the entity to 0 and by hiding their sprite using the SPR_setVisibility function. It’s all rather self-explanatory but will help us to save some time down the road.

Structs are a powerful tool to organize code and they will come in really handy when we’re dealing with multiple enemies and bullets. But that’s a topic for next time! Until then be excellent to each other!

If you have any questions, comments or criticism, post them in the comments below or reach out to me on Twitter @ohsat_games! Special thanks to Stephane Dallongeville for creating SGDK and everyone in the SGDK Discord for their help and keeping the dream alive!

Download the source code

All patrons on Patreon get the complete source code for this tutorial, as well as other perks such as early access! Become a Patron!
Just Want to Buy Me a Coffee?

Check out the rest of this tutorial series!

  • Megalaga 1 - Space
  • Megalaga 2 - Entities
  • Megalaga 3 - Enemies
  • Megalaga 4 - Enemy Movement and Input
  • Megalaga 5 - Bullets
  • Megalaga 6 - Collision and HUD
  • Megalaga 7 - Enemy Bullets
  • Megalaga 8 - Spam Protection
  • Megalaga 9 - Sound
  • Megalaga BONUS - Powerup
  • Get Words in Your Inbox!

    Be oldschool and sign up for my newsletter to get updates! Just enter your email address, prove you're not part of Skynet and you're good to go!



    Powered by CleverReach. I will not send you spam or sell/give your email address to someone else.  You can of course unsubscribe at any time. By clicking the subscribe button above, you confirm that you have read and agreed to our privacy policy.

    By using the Disqus service you confirm that you have read and agreed to the privacy policy.

    comments powered by Disqus

    Related Posts

    Streets of Rage 2 Design Docs

    A few years ago, Yuzo Koshiro posted a pile of old game design documents for Bare Knuckle 2 aka Streets of Rage 2 on the Ancient blog to commemorate the release of Streets of Rage 2 3D on the Nintendo 3DS. These documents gave a deep insight into the game’s inner workings, technical aspects, designs and even some cut content. They were an awesome resource for one of the most awesome games ever created.

    Read More

    Make a Space Shooter for the Mega Drive!

    It’s time for another SGDK tutorial series! After doing a single player Pong game and an endless runner, it’s time to reach for the stars… and make a space shooter! Apart from things like scrolling and animating sprites, this new series will show you how to deal with multiple entities and their collisions, how to randomly generate backgrounds and more! This project builds upon the previous tutorials, so if you’re new to SGDK programming and have not done those yet, I highly recommend starting with Megapong.
    Read More

    Patreon Revamps

    Hey there, what’s up? Things are continuing to evolve, as I’ve now updated my Patreon to give patrons more perks! Apart from early access to new tutorials and posts, the biggest one is probably the ability to peek behind the scenes…and there will be a lot to peek at in the coming months! This year I’m writing and submitting my MA thesis, meaning that I will have to do more stuff to make ends meet.
    Read More