Megapong 9 - Game Over

Posted October 14, 2019

NOTE:
This tutorial is most likely not compatible with versions of SGDK above 1.70. Unfortunately, I simply do not have the capacity or ability to update them right now. Read more about it here. Sorry.

Hold up!

If you like 90s platformers, check out my new game Kid Bubblegum!

Time to finish this game of ours! This time we’ll add a fail state and some general polish to complete the Megapong experience. Let’s jump right into it!

Making Things Easier for Us

First, let’s make things a bit easier for ourselves. We’ll have to show some messages on screen soon and we can create the following helper function to help us out:

/*Draws text in the center of the screen*/
void showText(char s[]){
	VDP_drawText(s, 20 - strlen(s)/2 ,15);
}

As you can see, this function takes a string (that is, a char[]) and then draws this string in the center of the screen using VDP_drawText and the power of math. This spares us from always having to specify the x- and y-positions of the text we want to draw.

Game Over

Now to implement a fail state. We’ll need a global variable to track the current game state, so let’s define one (outside of main()). We’ll also take this opportunity to write and store the messages we want displayed when the game starts/ends. Put these lines somehwere at the top of main.c near your other variable definitions:

game_on = FALSE;
char msg_start[22] = "PRESS START TO BEGIN!\0";
char msg_reset[37] = "GAME OVER! PRESS START TO PLAY AGAIN.";

Now to define what should happen when the game ends, that is when the ball is lost. We’ll do that in a function:

void endGame(){
	showText(msg_reset);
	game_on = FALSE;
}

Define this function after showText() since we’re using it in this one! The function should be pretty self-explanatory: We display our reset message, then set game_on to FALSE. So when does the game end? When the ball hits the lower bound of the screen, so we’ll call this function in moveBall(). Replace the following lines…

} else if(ball_pos_y + ball_height > BOTTOM_EDGE){
	ball_pos_y = BOTTOM_EDGE - ball_height;
	ball_vel_y = -ball_vel_y;
}

…with this one:

else if(ball_pos_y + ball_height > BOTTOM_EDGE){
	endGame();
}

Now the ball won’t bounce off the bottom edge anymore, meaning players can actually lose!

images/gameover.png

Starting

That’s the ending taken care of, but a game also needs a proper beginning. Right now the game starts the moment you open it, which isn’t ideal. But that’s where our game_on variable will come in handy once again! Let’s define a counterpart function to endGame():

void startGame(){
	score = 0;
	updateScoreDisplay();

	ball_pos_x = 0;
	ball_pos_y = 0;

	ball_vel_x = 1;
	ball_vel_y = 1;

	/*Clear the text from the screen*/
	VDP_clearTextArea(0,10,40,10);

	game_on = TRUE;
}

This function resets our score and HUD, positions the ball at (0,0) and then launches it by setting its velocity. It then calls VDP_clearTextArea which, as the name implies, clears an area of the screen of text. To be more specific, it clears a rectangle starting at tile coordinates (0,10) with a width of 40 tiles and a height of 10 tiles. We call this so any messages on the screen – msg_start or msg_reset – are cleared before the game begins. And finally, the function sets game_on to TRUE.

Okay, so where do we call this function? Well, remember our joypad callback function? Let’s put it in there, so it gets called whenever players press the Start button! In void myJoyHandler, add the following before checking for BUTTON_RIGHT and BUTTON_LEFT:

if(state & BUTTON_START){
	if(!game_on){
		startGame();
	}
}

Pressing the Start button will now start our game, but only if it’s not running already. However: If you compile the game and try it out now, you’ll notice that the ball starts moving immediately, whether you’ve pressed Start or not. This is because we’re missing one step: We have to tell the game to only move our entities when the game is actually running, meaning if game_on == TRUE. Modify your while(1) loop in main() so it looks like this:

while(1)
{
	if(game_on == TRUE){
		moveBall();
		positionPlayer();
	}

	SPR_update();
	SYS_doVBlankProcess();
}

return(0);

That way the ball and paddle will only be moved when the game has really begun, and stop moving once it’s over.

We’re almost done! Let’s just add some icing to the cake by welcoming the player to our game. In main(), after drawing the score label and updating the score, add this:

showText(msg_start);

This shows our previously defined start message on the screen.

images/gamestart.png

Since we’re already calling VDP_clearTextArea(0,10,40,10); in startGame() that’s all we need to do, as the message will be deleted once the game starts.

Done!

Congratulations, you have now developed your first Mega Drive game! It’s not going to set any sales charts on fire, but you made a Mega Drive game. How cool is that?

So what now? Well, you are free to improve upon the game! You could for example add a lives system to make it a bit easier for players. The ball currently also always starts at the same spot and goes in the same direction, which is a bit boring…maybe you could randomize that? There’s lots of stuff to do, so let your imagination run wild! And if you come up with something cool, share it in the comments below!

I’d like to thank you very much for reading. I hope you’ve found this tutorial helpful! If you want to see more tutorials like this one, consider becoming a patron on Patreon! You will get project files for each step of a tutorial and more.   

Actually…

Oh, and as an exclusive bonus to my Patrons there will actually be one more step for this tutorial next week, where we implement a cool little flashing effect. A pledge of $2 will get you this bonus step, as well as bonus steps for every future tutorial! So if you want to push your skills even further, consider chucking me a few bucks on Patreon!

If you've got problems or questions, join the official SGDK Discord! It's full of people a lot smarter and skilled than me. Of course you're also welcome to just hang out and have fun!

Join my Discord Server!

Hang out, get news, be excellent!

Come hang out!

Want To Buy Me a Coffee?

Coffee rules, and it keeps me going! I'll take beer too, though.

Check out the rest of this tutorial series!

  • Megapong 1 - Hello Mega Drive World!
  • Megapong 2 - Setting Up The Environment
  • Megapong 3 - Importing Resources
  • Megapong 4 - Palettes
  • Megapong 5 - Sprites
  • Megapong 6 - Input and Paddles
  • Megapong 7 - Collisions
  • Megapong 8 - Score and HUD
  • Megapong 9 - Game Over
  • Megapong BONUS - Flashing!
  • By using the Disqus service you confirm that you have read and agreed to the privacy policy.

    comments powered by Disqus