learn

Making Pong

Difficulty: Intermediate

Pong screenshot
Click to enlarge

Introduction

This tutorial will show you how to create the classic computer game Pong. Pong is a very simple game that doen't show TNT Basic's full potential, however it is quick and easy to write and will show you some of the main concepts involved in creating a computer game.

To get the best from this tutorial it is recommended that you've ran through at least the programming tutorial in the learning zone, so you understand the basics of programming.

Steps to Making Pong

  1. Create the project file
  2. Create an input resource so the players can configure their keys
  3. Draw the bat and ball images and copy them into the image bank
  4. Draw a starfield backdrop
  5. Main loop
  6. Daw the sprites
  7. Bounce the ball of the walls and bats
  8. Handle sprite movement
  9. Declare the winner

Create the Project File

Launch Hieroglyph and select "New..." from the "File" menu. Name your file and save it.

You will now be presented with the info screen, enter "Pong" as the name of your program and set the creator code to "Pong" also.

What is the creator code?

The creator code is a four letter string that identifies your program. The creator code is used to save and retrieve input settings and to identify messages on the network when playing network games. You can choose any four letters for your creator code, however, you should try to avoid using the same creator code as existing TNT Basic games.

Create an Input Resource

What is an input resource?

The input resource allows the player to configure their controls. It also allows your game to support different input devices such as joysticks, game pads, mice and keyboards. It declares what kind of input is used by your game and their names.

Some games may have several input resources, perhaps reflecting controls used by different vehicles controlled by the player in the game.

All input in TNT Basic uses Apple's Input Sprocket for input, so you may also see the input resource referred to as an "Input Sprocket Setup Resource".

More information can be found in the input section of TNT Basic's online help.

Select the input tab in the Hieroglyph window. Select "Create new Input resource..." and click OK in the resulting dialog. You will now be presented with a window to edit your games input needs. Create two new input elements by clicking on the new page buttons and set them up as follows:

Input element 1 will be used to control player 1's bat, similarly input element 2 will control player 2's bat.

The type of both inputs is 'yaxi'. This stands for yaxis. You can select this from the popup menu on the right end of the "Type" row.

When you have done this, close the window and save the changes when prompted.

Now goto the code pane and enter the following code:

load input 128
edit input
activate input

This loads up the input resource and shows the configure keys dialog. You can run the program at this stage if you wish.

Draw the sprite images and copy them into the image bank

The usual practise when using sprites is to import graphics from files into your projects image banks (found under the graphics tab). To keep this tutorial simple and self contained we are going to draw our own images for the sprites when the program is run and then copy these into the image bank. These means we don't need to edit the image bank in Hieroglyph.

In the code section enter the following:

graphics mode 640,480
hide mouse

This switches TNT Basic into graphics mode so that we can use drawing operations. The screen is now at 640x480 resolution.

' blue bat
set pen colour blue
fill rect 5,0 to 10,50
set pen colour white
fill rect 0,0 to 5,50
copy image 0,0,10,50,-1,true to 0

This code creates the blue bat by drawing two rectangles and them copying it into the image bank as image 0. This is similarly done for the red bat and the ball:

' red bat
set pen colour red
fill rect 0,0 to 5,50
set pen colour white
fill rect 5,0 to 10,50
copy image 0,0,10,50,-1,true to 1

' ball
set pen colour white
fill oval 50,50 to 60,60
copy image 50,50,60,60,black,true to 2
set image offsets 2,5,5

At this point we now have three images in our image bank. Image 0 and 1 are the two bats, one in blue and one in red. Image 2 is the ball. The set image offsets command is used to centre the hotspot of the ball image into the middle of the sprite.

If we wanted, we could draw these images in a paint program and import them into an image bank in Hieroglyph. Then the code in this section could be replaced with a load images command.

Draw a Starfield Backdrop

For the backdrop of the game we could either generate a backdrop on the fly, or draw a picture imported into the graphics section of the project.

To use a picture, select the graphics tab and select the pictures list (the left most list). Choose "Create new picture..." from the resource menu and import any picture you want (you're best sticking to a 640x480 one seeing as that's the size of the screen). A wide range of picture formats are supported including JPEGS, PICTS, TIFFS and GIFS. Once this is done you can draw the backdrop with the draw picture command:

draw picture 128

The alternative to using a picture is to render the backdrop programatically, here we will generate a simple starfield to feature as the backdrop.

The following is a procedure for drawing 100 pixels at random coordinates on the screen in a random colour.

procedure DrawStarfield()
    int	star
	
    for star=1 to 100
	        set pixel colour random(0,640),random(0,480),random(black,white)
    next star
end proc

You place the procedure anywhere in your program, but by convention they are placed at the end of your code.

With the procedure written, you must now add the code to call it, enter the following after the code for generating the images:

set pen colour black
paint canvas
DrawStarfield()
set pen colour white
frame rect 0,0 to 640,480

This code switches to a black pen and paints the entire canvas, this is to erase the sprite images we drew in the previous code. It then draws the star field and then frames the screen with a white border.

The Main Loop

The main loops executes while the game is in progress. It terminates when the ball gets past one of the bats, causing one of the players to lose. The first thing to do before the main loop is to declare the variables that will be used in the loop, the following are needed:

int        input    		                    ' used for value of input from keyboard/mouse etc
float      ballx=320,bally=240            ' the x and y position of the ball
float      ballxvel,ballyvel=random(-4,4) ' the x and y velocities of the ball
int        winner=0   		                  ' the winner of the game, 0 means no winner
float      player1y=320,player2y=320      ' the y coords of the bats, 320 is middle of y screen

The code above also assigns a y velocity to the ball, it will be set off moving at some random speed up or down. Now we must assign a random speed to the x velocity, either to the left or the right at a speed of 4.

if random (0,1) = 1
	   ballxvel=4
else
	   ballxvel=-4
end if

Next comes the main loop itself. This loop repeats until the variable "winner" is set to something other than 0.

repeat

until winner > 0

The next sections look at exactly what should be entered into the main loop in order to get it to do something useful.

Draw the Sprites

The easiest part of the main loop is to draw the sprites, here's the code to do that, enter it immediately after the 'repeat' line:

sprite 0,630,player2y,0
sprite 1,0,player1y,1
sprite 2,ballx,bally,2
draw frame	

Here sprite 0 is used as the right most bat, it is displayed at 630 pixels across the screen and at player2y pixels down the screen, with image 0. Similarly, sprite 1 is used for the left bat. It is positioned at 0 pixels across the screen and player1y pixels down it, with image 1. The ball is represented by sprite 2, placed at ballx and bally with image 2.

Once the sprites are positioned, the screen is drawn using the draw frame command.

Bounce the ball off the floor, ceiling and bats

The ball is positioned at x position 'ballx' and y position 'bally'. It is moving at 'ballxvel' horizontally and 'ballyvel' vertically. If the ball is within a few pixels off the top or the bottom of the screen we need to move it back a step and then reverse its y velocity so that it will head away from the barrier, effectively bouncing. The following code accomplishes this:

' bounce the ball off the floor and ceiling
if bally<=5 or bally>=475
    ' move the ball away from what it just hit
    bally=bally-ballyvel
    ' then reverse the direction
    ballyvel=-ballyvel
end if

The next thing to check is if the ball has hit one of the bats this is accomplished with the following command:

int hitbat=sprite col (2,0 to 1)

This command checks to see if sprite 2 (the ball) has collided with any sprites numbered 0 to 1 (the bats). If it has it will put the number of the sprite hit into the variable 'hitbat'. If it hasn't then 'hitbat' will be set to -1.

If the ball has hit one of the sprites we need to move it back a step and then reverse its x velocity, in a similar manner as we did with the y velocity previously. Also, we want to make it so that the ball's y velocity is affected by exactly where on the bat it struck. If it strikes near the top of the bat we want it to be reflected upwards more and if it strikes near the bottom of the bat we want it to be reflected downwards more. Enter the following code:

if hitbat>-1
    ' move the ball away from the bat it just hit
    ballx=ballx-ballxvel
    ' reverse the balls direction
    ballxvel=-ballxvel
		
    ' change the yvelocity of the ball according to where on the bat the ball hit
    ' if it hit near the top of the bat then make the ball move upwards faster, if
    ' it hit near the bottom of the bat then make the ball move downwards faster,
    ' and if it hits in the middle of the bat simply reflect it without changing the
    ' yvelocity
    float batcentre
    if hitbat=0 then batcentre=player2y+25		' bat height is 50 so + 25 gives the middle of the bat
    if hitbat=1 then batcentre=player1y+25
		
    ballyvel=ballyvel+(bally-batcentre)*0.1
end if

The final check that needs making is to see if the ball got past either of the bats, if it did set the winner variable to the player that won.

if ballx<=5 then winner=2
if ballx>=635 then winner=1

Handling Sprite Movement

The final section of the main loop is the code that moves the sprites. The first thing that needs doing is to move the two bats. The input is retrieved using the 'poll input()' function, which returns a number between -100 and 100 depending on how far the player's joystick/mouse/gamepad/keyboard is moved. We can use this to reflect the speed that the bat should be moved at. The following code moves both the bats, stopping them if they hit the top of the screen:

' handle player movement
input=poll input (1)	' get player 1 input
player1y=player1y+input/20
if player1y<0 then player1y=0
if player1y>430 then player1y=430

input=poll input (2)	' get player 2 input
player2y=player2y+input/20	
if player2y<0 then player2y=0
if player2y>430 then player2y=430

You may notice that the value of the input is divided by 20 here, this is done to limit the maximum speed the bats can move at to 5 pixels a frame (the maximum input is 100 so dividing by 20 gives 5).

Finally we need to move the ball, this is accomplised simply with:

' move the ball
ballx=ballx+ballxvel
bally=bally+ballyvel	

That completes the main loop. You can run the game at this point if you wish!

Declaring the Winner

The final step is to declare the winner, this is done simply by printing on the screen whoever won the game and then waiting for them to click the mouse. This is accomplished with the following code, which should be entered after the main loop (ie after the 'until winner>0' line).

' print who won on the screen
if winner = 1
    set pen colour red
    draw text 270,100,"PLAYER 1 WINS!"
else
    set pen colour blue
    draw text 270,100,"PLAYER 2 WINS!"
end if

draw frame
deactivate input
wait mouse click

That completes this Game-in-60 tutorial, you've just written Pong in TNT Basic, congratulations!

Of course you needn't stop there, you can always go onto improve this version of Pong to have even more features. Some example improvements could be:

Good luck and have fun with TNT Basic!