Empty Your Mind Tutorial 2

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

Creating A Sprite

We need to create our ship so we can shoot bullets. To create an animating sprite, you will be using:

function CreateSprite(image : Bitmap; framesPerCell, frames, width, height: Integer): Sprite;

Frames per cell will define the number of frames per cell. The animation image is a single image file which contains animation. Sample image can be found in here. The game resources management is explained in here.

Steps I have taken to create the player's ship is:

  1. Create a sprite from the ship's image (multi-bitmap animation)
  2. Set the ship's x position to the middle of the screen
  3. Set the ship's y position (150 pixel offset from the bottom of the screen)
  4. Set the ship's speed

The following code is an implementation of the steps above.

procedure LoadGame(var game : GameData);
const
	PLAYEROFFSET = 150;
begin
	//Create the player ship
	game.player.theSprite := CreateSprite(GameImage('Ship'), 2, 2, 40, 43);
	game.player.theSprite.xPos := Round(ScreenWidth / 2 - game.player.theSprite.width / 2);
	game.player.theSprite.yPos := ScreenHeight - PLAYEROFFSET;
	game.player.speed := 4;
end;

Make sure that the LoadGame procedure is called from the MainGame procedure.

Drawing A Sprite

We have created a sprite but we cannot see it yet because we are not drawing. Drawing and updating the animation can be done very easily. Drawing and animation update can be done by:

DrawSprite(player.theSprite);
UpdateSpriteAnimation(player.theSprite);

Call these procedures in your loop before the RefreshScreen(). I highly recommend you to create a procedure which is dedicated to process everything related to the player to simplify the program.

Screenshot of working animation sprite:

Working animation sprite!
Note: Do not forget to call ClearScreen to clear the screen every loop.

Moving A Sprite

We have got the ship to display but we haven't got the ship to move. I'm going to show how to move a ship properly in three steps.

  • Move left and right
  • Move up and down
  • Move up-right, up-left, down-right and down-left

Moving left and right is the first step to move a player's ship. In order to move a player's ship, we need to…

  1. Check the key input
  2. Move the ship according to the input

We can the ship left and right by using the following code.

procedure MovePlayerShip(var player : ShipData);
begin
	if IsKeyPressed(VK_LEFT) then
		//if the left arrow key is the only key being pressed
		player.theSprite.xPos := player.theSprite.xPos - player.speed
	else if IsKeyPressed(VK_RIGHT) then
		//if the right key is the only key being pressed
		player.theSprite.xPos := player.theSprite.xPos + player.speed;
end;

Execute this procedure before drawing the player's ship and the ship will react to your key inputs. Now we are going to implement the up and down movement. This is very easy if you understand the left and right movement. The following code will extend the last procedure to detect the up and down movement.

procedure MovePlayerShip(var player : ShipData);
begin
	if IsKeyPressed(VK_LEFT) then
		//if the left arrow key is the only key being pressed
		player.theSprite.xPos := player.theSprite.xPos - player.speed
	else if IsKeyPressed(VK_RIGHT) then
		//if the right key is the only key being pressed
		player.theSprite.xPos := player.theSprite.xPos + player.speed
	else if IsKeyPressed(VK_DOWN) then
		//if the only key being pressed is the down arrow key
		player.theSprite.yPos := player.theSprite.yPos + player.speed
	else if IsKeyPressed(VK_UP) then
		//if the only key being pressed is the up arrow key
		player.theSprite.yPos := player.theSprite.yPos - player.speed;
end;

We now have a basic movement but we cannot go right-up, left-up and so on. This is the hardest part of the player's ship movement. To move right-up, we need to move the ship by the player's speed. Let's say the player's speed is 4. In this case, we need to move the ship by 4 pixel diagonally. To calculate the movement of X and Y from an angle, we need to come up with a formula. This can be done very easily by using Cos and Sin.

procedure UpdateEntityPosition(speed, angle : Single; var target : Sprite);
begin
	target.xPos := target.xPos + speed * SGSDK_Core.Cos(angle);
	target.yPos := target.yPos + speed * SGSDK_Core.Sin(angle);
end;

This procedure will directly modify the sprite's position. The usage of this procedure is…

UpdateEntityPosition(player.speed, 225, player.theSprite);

This example code will move the sprite to up-left by 4 pixel. Finally, we can implement the complete movement code by using the UpdateEntityPosition procedure.

procedure MovePlayerShip(var player : ShipData);
begin
	if IsKeyPressed(VK_LEFT) then
	begin
		//if the left arrow key is being pressed
		if IsKeyPressed(VK_UP) then
			//if the up arraw key is also being pressed
			UpdateEntityPosition(player.speed, 225, player.theSprite)
		else if IsKeyPressed(VK_DOWN) then
			//if the up down key is also being pressed
			UpdateEntityPosition(player.speed, 135, player.theSprite)
		else if not IsKeyPressed(VK_RIGHT) then
			//if the left arrow key is the only key being pressed
			player.theSprite.xPos := player.theSprite.xPos - player.speed
	end
	else if IsKeyPressed(VK_RIGHT) then
	begin
		//if the right arrow key is being pressed
		if IsKeyPressed(VK_UP) then
			//if the up arrow key is also being pressed
			UpdateEntityPosition(player.speed, 315, player.theSprite)
		else if IsKeyPressed(VK_DOWN) then
			//if the down arrow key is also being pressed
			UpdateEntityPosition(player.speed, 45, player.theSprite)
		//if the right key is the only key being pressed
		else player.theSprite.xPos := player.theSprite.xPos + player.speed
	end
	else if IsKeyPressed(VK_DOWN) and (not IsKeyPressed(VK_UP)) then
		//if the only key being pressed is the down arrow key
		player.theSprite.yPos := player.theSprite.yPos + player.speed
	else if IsKeyPressed(VK_UP) and (not IsKeyPressed(VK_DOWN)) then
		//if the only key being pressed is the up arrow key
		player.theSprite.yPos := player.theSprite.yPos - player.speed;
end;

We now have a ship movement in any direction! You might notice that the ship can go out of the screen. The procedure that limits the ship's movement can be written very easily.

procedure FixPosition(var theSprite : Sprite);
begin
	if theSprite.xPos < 0 then
	    theSprite.xPos := 0;
	if theSprite.yPos < 0 then
	    theSprite.yPos := 0;
	if theSprite.xPos > ScreenWidth() - theSprite.Width then
	    theSprite.xPos := ScreenWidth() - theSprite.Width;
	if theSprite.yPos > ScreenHeight() - theSprite.Height then
	    theSprite.yPos := ScreenHeight() - theSprite.Height;
end;

The FixPlayerPosition procedure will check if the player's ship has gone out of the screen and fix the position if it has.

Summary

In this tutorial, I have gone through:

  • Creating a sprite
  • Directly manipulating a sprite coordinate
  • Keyboard input processing

The current project files can be downloaded from here.

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