Empty Your Mind Tutorial 4

From SwinGame

This tutorial will teach you how to use the SwinGameSDK to develop a simple danmaku game which looks cool. At the end of this tutorial you should be able to use pascal to implement your own space invaders or scrolling shooter style game which makes use of Vectors, animated Sprites, SoundEffects, and Music.

This page contains a Tutorial. Tutorials are designed to walk you through the development of a small game.
Warning: You must have completed the previous tutorial(s) to go through this tutorial

Contents

Bullet Data Structure

It is possible for you to implement the bullet data using a parallels arrays, but it can get unnecessarily complex. I will be defining a bullet data structure and an enumerations. We will need few things to represent a bullet data structure.

  • Bullet sprite
  • Damage it can cause (Integer)
  • Kind of a bullet
  • Alive (True if this bullet is alive)
  • Side (Enemy bullet or the player's bullet)

As you can see, we need to define enumerations for Kind of a bullet and Side. The implementation of the structure is shown bellow.

//Kind of a bullet
BulletKind = (
	Normal
);
 
//Side
BulletSide = (
	Player,
	Enemy
);
 
BulletData = record
	theSprite : Sprite;
	damage : Integer;
	kind : BulletKind;
	alive : Boolean;
	side : BulletSide;
end;

Creating A Bullet

We will have to create a bullet to fire a bullet. This is a simple initialisation process to set the bullet information. We need the following information to create a bullet.

  1. The name of a bullet image
  2. The ship data to know where the bullet was fired from
  3. The amount of damage the bullet can cause
  4. Kind of a bullet
  5. Side of a bullet
  6. Movement vector of a bullet

The following function will implement the initialisation of a bullet and return a new bullet.

function CreateBullet(imgName : String; shotFrom : ShipData; damage : Integer; 
				kind : BulletKind; side : BulletSide; vec : Vector) : BulletData;
begin
	result.theSprite := CreateSprite(GameImage(imgName));
	result.theSprite.xPos := shotFrom.theSprite.xPos + shotFrom.theSprite.width div 2 - result.theSprite.width div 2;
	result.theSprite.yPos := shotFrom.theSprite.yPos + shotFrom.theSprite.height div 2 - result.theSprite.height div 2;
	result.damage := damage;
	result.alive := true;
	result.side := side;
	result.kind := kind;
	result.theSprite.movement := vec;
end;

Managing Bullets

There will be hundreds of bullets flying on the screen at the same time. Therefore we must have an efficient bullet management system. To implement this, I'm going to have an array of BulletData which contains every bullet in the game. The new GameData record is…

GameData = record
	player : ShipData;
	images : Array of Sprite;
	bullets : Array of BulletData;
end;

You will also need to modify the LoadGame routine to initialise the game structure.

const BULLETCOUNT = 500;
…
//Initialise all bullets
SetLength(game.bullets, BULLETCOUNT);
for i := Low(game.bullets) to High(game.bullets) do
begin
	game.bullets[i].alive := false;
end;

This will kill all bullets at the start of the game and sets the maximum numbers of bullets to 500.

Shooting A Bullet pt.1

Shooting a bullet can be done very easily by going through the bullets array. The steps to shoot a bullet is…

  1. Find a dead bullet
  2. Copy the new bullet into the dead bullet
  3. Exit

The implementation:

procedure DeployBullet(bullet : BulletData; var bullets : Array of BulletData);
var
	i : Integer;
begin
	for i := Low(bullets) to High(bullets) do
	begin
		if not bullets[i].alive then begin
			bullets[i] := bullet;
			exit;
		end;
	end;
	WriteLn('No bullets to deploy…')
end;

Calling the DeployBullet routine by passing the appropriate parameters will shoot the bullet. However, we need to draw the bullets and update the positions. The following steps must be taken to implement this.

  1. Find a bullet which is alive
  2. Kill the bullet if the bullet is offscreen
  3. Draw the bullet
  4. Move the bullet
  5. Repeat the step 1 to 4 until all bullets are processed

The implementation of the steps:

procedure UpdateBullets(var bullets : Array of BulletData);
var
	i : Integer;
begin
	for i := Low(bullets) to High(bullets) do begin
		if bullets[i].alive then begin
			if IsSpriteOffscreen(bullets[i].theSprite) then begin
				bullets[i].alive := false;
				continue;
			end;
			DrawSprite(bullets[i].theSprite);
			UpdateSprite(bullets[i].theSprite);
		end;
	end;
end;

Continue to the next tutorial…

List Of Tutorials

  1. Introduction
  2. Player Ship
  3. Background
  4. Bullet pt.1
  5. Bullet pt.2
  6. Music and SoundEffect
  7. Enemies pt.1
  8. Enemies pt.2
  9. Collision Detection
  10. Further Extensions