In this tutorial series you will learn how to make a simple single-player Pong-like game for the Sega Mega Drive using SGDK! If you just want to see the full source code, you can get it from Github.

Megapong 6 - Input and Paddles

Posted September 23, 2019

We have a moving ball now, but a Pong game needs paddles. We’ll add one now and learn about handling input in SGDK at the same time. Let’s go!

Creating a Paddle

First we’ll have to create a paddle for players to control. The process is very similar to the one in the previous post, so I won’t go into as much detail this time.

First, download the paddle image here. This is what it looks like (at 2x scale):

images/paddlepreview.png

Put the file you downloaded in res/sprites. Then add it to the resources.res file like this:

SPRITE  paddle  "sprites/paddle.png" 4 1 NONE

Remember that the size parameters are given in tiles! Our paddle is 32px wide, which equals 4 tiles at 8 pixels each.

Now we need a variable to store the paddle sprite. Below all the ball-related variables at the top of main.c, add this:

Sprite* player;

And while we’re up here, let’s add the variables we’ll need to handle the paddle’s position and movement directly below:

int player_pos_x = 144;
const int player_pos_y = 200;
int player_vel_x = 0;
const int player_width = 32;
const int player_height = 8;

Since the paddle will only move left and right, its height is set as const and we’re only tracking the x velocity.

Now with all of that taken care of we can add the sprite to the game. After SPR_init(0,0,0) in main(), add this (before or after adding the ball, it doesn’t matter):

player = SPR_addSprite(&paddle, player_pos_x, player_pos_y, TILE_ATTR(PAL1, 0, FALSE, FALSE));

And done! We now have a paddle in our game. We did this very quickly, so feel free to check out the previous post to get more details on the whole process.

Handling Input

Now it’s time to get interactive. Input in SGDK is handled via a callback function. What that means is that basically SGDK constantly keeps an eye on the connected controllers. If a button is pressed, it will automatically call a function you specify. This function then needs to check which button was pressed and tell the game what to do. It’s a pretty simple setup, so let’s write one of those callback functions! Here is the chunk of code that will make our paddle move according to our inputs:

void myJoyHandler( u16 joy, u16 changed, u16 state)
{
	if (joy == JOY_1)
	{
		/*Set player velocity if left or right are pressed;
		 *set velocity to 0 if no direction is pressed */
		if (state & BUTTON_RIGHT)
		{
			player_vel_x = 3;
		}
		else if (state & BUTTON_LEFT)
		{
			player_vel_x = -3;
		} else{
			if( (changed & BUTTON_RIGHT) | (changed & BUTTON_LEFT) ){
				player_vel_x = 0;
			}
		}
	}
}

Put this function somewhere at the top of main.c. I’d suggest putting it after the variables, before or after moveBall().

There’s quite a lot to unpack here, so let’s do it! First, let’s look at the parameters of our callback.

joy: This tells us which joypad was used. It will usually be JOY_1 or JOY_2, but SGDK actually supports up to 8 joypads.
changed: This tells us whether the state of a button has changed over the last frame. If the current state is different from the state in the previous frame, this will be 1 (otherwise 0).
state: This will be 1 if the button is currently pressed and 0 if it isn’t.

So after making sure that the input came from joypad 1 (the only one we’ll be using here), we check whether the D-Pad was pressed left or right. If so, we set the player velocity accordingly. However, if any of the directions has been released, we set the velocity to 0 so that the player stops moving.

Now that we have defined our callback function, we have to pass it to SGDK. At the beginning of main, before loading any of our tiles or sprites, add these two lines:

JOY_init();
JOY_setEventHandler( &myJoyHandler );

The first line initializes the joypad controls in SGDK. Without this step we wouldn’t be able to receive any input at all. The second line sets our defined function as the callback for joypad input. And that’s all we need to have working controls in our game! Since our function works as a callback, we don’t have to manually check for joypad input every frame. SGDK does that for us and invokes our function whenever it’s needed! Just remember to actually set that callback.

Moving The Player

But our input won’t do anything right now, because we’re not actually moving the player paddle. Just like with the ball, we’ll create a function to do that:

void positionPlayer(){
	/*Add the player's velocity to its position*/
	player_pos_x += player_vel_x;

	/*Keep the player within the bounds of the screen*/
	if(player_pos_x < LEFT_EDGE) player_pos_x = LEFT_EDGE;
	if(player_pos_x + player_width > RIGHT_EDGE) player_pos_x = RIGHT_EDGE - player_width;

	/*Let the Sprite engine position the sprite*/
	SPR_setPosition(player,player_pos_x,player_pos_y);
}

This is stuff we’ve done before, so I won’t dwell on it. Put the function near moveBall(). Finally call the function by adding positionPlayer(); in the game loop, right after moveBall(). For reference, the loop should now look like this:

while(1)
{
	moveBall();
	positionPlayer();
	
	SPR_update();
	VDP_waitVSync();
}

If you now compile the game and press left or right, you’ll see that the paddle is actually moving. And you’ll also notice that it won’t go off-screen! Woo!

images/movepaddle.gif

Now that we have moving parts, it’s time to smash them together! Next time we’ll take a look at collisions between sprites, so that we can actually keep our ball in the game with the paddle. It’s going to get exciting, so stay tuned and as always thanks for reading!

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!

  • 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!
  • 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