PC Games

Orb
Lasagne Monsters
Three Guys Apocalypse
Water Closet
Blob Wars : Attrition
The Legend of Edgar
TBFTSS: The Pandoran War
Three Guys
Blob Wars : Blob and Conquer
Blob Wars : Metal Blob Solid
Project: Starfighter
TANX Squadron

Android Games

DDDDD
Number Blocks
Match 3 Warriors

Tutorials

2D shoot 'em up
2D top-down shooter
2D platform game
Sprite atlas tutorial
Working with TTF fonts
2D adventure game
Widget tutorial
2D shoot 'em up sequel
2D run and gun
Roguelike
Medals (Achievements)
2D turn-based strategy game
SDL 1 tutorials (outdated)

Latest Updates

SDL2 turn-based strategy tutorial
Thu, 14th April 2022

Water Closet ported to PlayStation Vita
Tue, 4th January 2022

The Legend of Edgar 1.35
Sat, 1st January 2022

Achievements tutorial
Thu, 2nd December 2021

SDL2 Rogue tutorial
Thu, 30th September 2021

All Updates »

Tags

android (3)
battle-for-the-solar-system (9)
blob-wars (9)
brexit (1)
code (6)
edgar (7)
games (39)
lasagne-monsters (1)
making-of (5)
match3 (1)
numberblocksonline (1)
orb (2)
site (1)
tanx (4)
three-guys (3)
three-guys-apocalypse (3)
tutorials (10)
water-closet (4)

Books


Alysha

When her village is attacked and her friends and family are taken away to be sold as slaves, Alysha Tanner sets out on a quest across the world to track them down and return them home. Along the way, she is aided by the most unlikely of allies - the world's last remaining dragon.

Click here to learn more and read an extract!

« Back to tutorial listing

— 2D Shoot 'Em Up Tutorial —
Part 4: Firing

Introduction

Note: this tutorial builds upon the ones that came before it. If you aren't familiar with the previous tutorials in this series you should read those first.

We're now ready to do something important in our tutorial: firing a bullet. Unpack the code and then type make to build. Once compiling is finished type ./shooter04 to run the code.

A 1280 x 720 window will open, coloured a light shade of blue. A spaceship sprite will also be shown, as in the screenshot above. The ship can now be moved using the arrow keys. Up, down, left, and right will move the ship in the respective directions. You can also fire a bullet by pressing the left control key. Due to the nature of this tutorial, you'll need to wait until the bullet has reached the right-hand side of the screen before you can fire again. Close the window by clicking on the window's close button.

Inspecting the code

To start with, let's add an extra variable to app in structs.h, one to track if we're pressing the fire control. We'll call it fire:


typedef struct {
	SDL_Renderer *renderer;
	SDL_Window *window;
	int up;
	int down;
	int left;
	int right;
	int fire;
} App;

Next, we need to update the Entity structure for firing our bullet (a bullet will be an Entity):


typedef struct {
	int x;
	int y;
	int dx;
	int dy;
	int health;
	SDL_Texture *texture;
} Entity;

We've added three new variables: dx, dy, and health. These variables will handle the delta x and y of the entity (for movement) and whether or not the thing is alive. A health of zero would mean the entity is dead and could be deleted, etc. Next, we'll make a couple of changes to input.c.


if (event->keysym.scancode == SDL_SCANCODE_LCTRL)
{
	app.fire = 1;
}

In doKeyDown we've added a check to see if the left control key is pressed. If so, we'll set the app.fire variable to 1. We'll also update doKeyUp to reset it to 0 when the key is released:


if (event->keysym.scancode == SDL_SCANCODE_LCTRL)
{
	app.fire = 0;
}

With those simple changes in place, let's update main.c to deal with our bullet:


int main(int argc, char *argv[])
{
	memset(&app, 0, sizeof(App));
	memset(&player, 0, sizeof(Entity));
	memset(&bullet, 0, sizeof(Entity));

	initSDL();

	atexit(cleanup);

	player.texture = loadTexture("gfx/player.png");
	player.x = 100;
	player.y = 100;

	bullet.texture = loadTexture("gfx/playerBullet.png");

	while (1)
	{
		prepareScene();

		doInput();

		player.x += player.dx;
		player.y += player.dy;

		if (app.up)
		{
			player.y -= 4;
		}

		if (app.down)
		{
			player.y += 4;
		}

		if (app.left)
		{
			player.x -= 4;
		}

		if (app.right)
		{
			player.x += 4;
		}

		if (app.fire && bullet.health == 0)
		{
			bullet.x = player.x;
			bullet.y = player.y;
			bullet.dx = 16;
			bullet.dy = 0;
			bullet.health = 1;
		}

		bullet.x += bullet.dx;
		bullet.y += bullet.dy;

		if (bullet.x > SCREEN_WIDTH)
		{
			bullet.health = 0;
		}

		blit(player.texture, player.x, player.y);

		if (bullet.health > 0)
		{
			blit(bullet.texture, bullet.x, bullet.y);
		}

		presentScene();

		SDL_Delay(16);
	}

	return 0;
}

We have a new bullet variable declaration (defined again in main.h), which, like player, is an Entity. We'll use memset to zero everything and then load a texture into it. Next, we'll add some code to test if we want to fire the bullet. For this, we'll test two things: whether app.fire is set to 1 and whether the bullet's health is 0. The second part of this test restricts us from firing the bullet again until its health is 0. If both these checks are true we'll set the bullet object's x and y to that of player, set it's dx to 16 and it's health to 1.

We'll always be attempting to move the bullet, whether it is alive or not. We do this by adding the bullet dx and dy to its x and y. Once the bullet reaches the right-hand side of the screen (bullet.x > SCREEN_WIDTH), we set its health to 0. Finally, we want to draw the bullet, using our blit function. We only do this if the bullet's health is greater than 0.

That's it for firing a bullet. Not a great number of changes, but we now have the ability to fire a bullet by holding down the left control key.

We've made some great steps so far, but we'll need to refactor and tune some of the code in order to make it more useful to us going forward; for one, you can only fire one shot at a time, which isn't going to be too exciting. We're also putting a lot of stuff into main, which really should be separated out into their own compilation units. The next tutorial will lay the foundations for creating something more fully fledged, allowing the tutorials that follow to ramp up significantly.

Exercises

  • Change the speed and direction the bullet moves.
  • Issue the bullet from the front of the player, as well as centrally.

Purchase

The source code for all parts of this tutorial (including assets) is available for purchase:

From itch.io

It is also available as part of the SDL2 tutorial bundle:

Directly

If you do not wish to create an itch.io account, you can also purchase the tutorial bundle using PayPal, and then download the tutorials directly from the main tutorials page.

SDL2_Tutorials.tar.gz 56.76MB 23rd April 2022

Click here to see the list of files in the archive

Mobile site