i-TECH Tutorial: Using Circles as Objects in Games

The object of this tutorial is to move a circle with the arrow keys, and have the circle interact with some other objects on the screen. The program uses CONST, CIRCLE, DO WHILE, INKEY$, SELECT CASE, SQR, and multidimensional arrays, which should be understood before using this tutorial. To start, here is the game code format:

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables

'Initialize the display

'Loop until the program ends

'Respond to user input

'Move the circle

'Initialize and move the other objects

'Accept user input

Step 1: Make the circle move


The variables X, Y, and SIZE will be used for the main circle. DIST controls how far your circle will move when you press a key. The game will run in SCREEN 12 (640*480*16) until the user presses escape.

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
dist = 8
key$ = ""
size = 32
x = 320
y = 240

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input

'Move the circle

'Initialize and move the other objects

'Accept user input
key$ = INKEY$

LOOP UNTIL key$ = CHR$(27)

The game will use SELECT CASE to process user input from the arrow keys. CHR$(0) + CHR$(72) is the up arrow key, and CASE CHR$(0) + CHR$(80) is the down arrow key. The IF statements stop the circle from leaving the screen.

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
dist = 8
key$ = ""
size = 32
x = 320
y = 240

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
END SELECT

'Move the circle

'Initialize and move the other objects

'Accept user input
key$ = INKEY$

LOOP UNTIL key$ = CHR$(27)

Now the game needs to display the circle. This displays the circle, but leaves a trail when it is moved. (The trail makes a very nice effect.)

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
dist = 8
key$ = ""
size = 32
x = 320
y = 240

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
END SELECT

'Move the circle
CIRCLE (x, y), size

'Initialize and move the other objects

'Accept user input
key$ = INKEY$

LOOP UNTIL key$ = CHR$(27)

When the circle moves, it has to be erased from its previous location, to avoid leaving a trail. After the circle is drawn at (X, Y), the variables X and Y are stored to the variables PX and PY. Then, after the program has looped, a black circle is drawn at (PX, PY) to erase the white one, and the white circle is redrawn at (X, Y), which lets it move as neccessary.

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
dist = 8
key$ = ""
size = 32
x = 320
y = 240

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
END SELECT

'Move the circle
CIRCLE (px, py), size, 0
CIRCLE (x, y), size
px = x: py = y

'Initialize and move the other objects

'Accept user input
key$ = INKEY$

LOOP UNTIL key$ = CHR$(27)

The erasing makes the circle flicker, so the game should only erase the circle if it is going to be moved. Also, the variable C is added so the user can change the color of the circle by pressing [Space]. This program works well, and is the end of step one.

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
c = 15
dist = 8
key$ = ""
size = 32
x = 320
y = 240

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT

'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c
px = x: py = y

'Initialize and move the other objects

'Accept user input
key$ = INKEY$

LOOP UNTIL key$ = CHR$(27)

Step 2: Add other objects and make them interact with the circle


You might wonder how fast QBasic is re-reading the DO WHILE loop. This adds "1" to the varaible framecount each time it loops, and then displays that variable:

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
c = 15
dist = 8
framecount = 0
key$ = ""
size = 32
x = 320
y = 240

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT

'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c
px = x: py = y

'Initialize and move the other objects

'Accept user input
key$ = INKEY$

framecount = framecount + 1: LOCATE 3, 5: PRINT "Frames: "; framecount
LOOP UNTIL key$ = CHR$(27)

The program is easily running at over 1,000 frames per second, which is approximately fifty times faster than necessary. Next, the program will use some other objects. They will be smaller circles. These other objects will use the two-dimensional array of integers o([the number of objects in the game],[however many numbers are needed for each object]). Each object will use an x-coordinate, a y-coordinate, and a color. The objects do not need to be defined before the game starts, because they will be positioned as the game runs. Note the array and the ocount constant variable (oxy-moronically named).

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
c = 15
dist = 8
framecount = 0
key$ = ""
CONST ocount = 64
size = 32
x = 320
y = 240
DIM o(1 TO ocount, 3) 'The three is for coordinates and colors

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT

'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c
px = x: py = y

'Initialize and move the other objects

'Accept user input
key$ = INKEY$

framecount = framecount + 1: LOCATE 3, 5: PRINT "Frames: "; framecount
LOOP UNTIL key$ = CHR$(27)

The objects will not exist on the screen the whole time, so the game needs to know whether the objects exist or not. So, if the color is black (that is color zero), the game will not think the object is there. Every time the game loops, it should attempt to make a new object exist if it does not already. This game will pick a random object each time it loops, and if that object is not being displayed, then the game gives random coordinates to that object and gives it a random color. This will display the object since its color is no longer black (except the object display is not yet written).

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
c = 15
dist = 8
framecount = 0
key$ = ""
CONST ocount = 64
size = 32
x = 320
y = 240
DIM o(1 TO ocount, 3) 'The three is for coordinates and colors

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT

'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c
px = x: py = y

'Initialize and move the other objects
a = INT(RND * ocount) + 1 'Tries to initialize this object
IF o(a, 3) = 0 THEN o(a, 1) = INT(RND * 640): o(a, 2) = INT(RND * 480): o(a, 3) = INT(RND * 15) + 1

'Accept user input
key$ = INKEY$

framecount = framecount + 1: LOCATE 3, 5: PRINT "Frames: "; framecount
LOOP UNTIL key$ = CHR$(27)

The objects won't be moving, so displaying them is a bit easier, although the game needs the variable OSIZE to size these objects. This game has sixty-four objects, so the game now runs at about 100 frames per second. Speed will not be a problem for this game, but it is more limiting for these types of games than memory is.

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
c = 15
dist = 8
framecount = 0
key$ = ""
CONST ocount = 64
CONST osize = 12
size = 32
x = 320
y = 240
DIM o(1 TO ocount, 3) 'The three is for coordinates and colors

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT

'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c
px = x: py = y

'Initialize and move the other objects
a = INT(RND * ocount) + 1 'Tries to initialize this object
IF o(a, 3) = 0 THEN o(a, 1) = INT(RND * 640): o(a, 2) = INT(RND * 480): o(a, 3) = INT(RND * 15) + 1

FOR a = 1 TO ocount 'Loops for each object to display
IF o(a, 3) > 0 THEN CIRCLE (o(a, 1), o(a, 2)), osize, o(a, 3)
NEXT a

'Accept user input
key$ = INKEY$

framecount = framecount + 1: LOCATE 3, 5: PRINT "Frames: "; framecount
LOOP UNTIL key$ = CHR$(27)

Now the game needs interaction. The game needs to know when the main circle touches one of the objects, and that is calculated through the pythagorean theorem. The distance between the main circle and object A is SQR((x - o(a, 1)) * (x - o(a, 1)) + (y - o(a, 2)) * (y - o(a, 2))). If that value is smaller than the size of the main circle plue the size of the object, then the two are overlapping. When the circle and object collide with each other, the main circle will change color, and the smaller circle (object) will disappear. To make an object disappear, it has to be erased from the display, and its color has to be set to zero. Once the object has disappeared, it is soon re-created.

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
c = 15
dist = 8
framecount = 0
key$ = ""
CONST ocount = 64
CONST osize = 12
size = 32
x = 320
y = 240
DIM o(1 TO ocount, 3) 'The three is for coordinates and colors

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT

'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c
px = x: py = y

'Initialize and move the other objects
a = INT(RND * ocount) + 1 'Tries to initialize this object
IF o(a, 3) = 0 THEN o(a, 1) = INT(RND * 640): o(a, 2) = INT(RND * 480): o(a, 3) = INT(RND * 15) + 1

FOR a = 1 TO ocount 'Loops for each object to display
IF SQR((x - o(a, 1)) * (x - o(a, 1)) + (y - o(a, 2)) * (y - o(a, 2))) < size + osize AND o(a, 3) > 0 THEN
c = INT(RND * 7) + 9 'Changes circle color
CIRCLE (o(a, 1), o(a, 2)), osize, 0 'Erases the object
o(a, 3) = 0 'Sets the object color to black so it no longer exists
END IF

IF o(a, 3) > 0 THEN CIRCLE (o(a, 1), o(a, 2)), osize, o(a, 3)
NEXT a

'Accept user input
key$ = INKEY$

framecount = framecount + 1: LOCATE 3, 5: PRINT "Frames: "; framecount
LOOP UNTIL key$ = CHR$(27)

Instead of showing how many frames have been run in the program, the game will loop for 5,000 frames (CONST FRAMESTOTAL), and show the user how many frames are left. So the DO LOOP must be changed to stop when FRAMECOUNT equals FRAMESTOTAL. Now the program needs a scoring feature. The variable SCORE will increase by one every time the circle overlaps an object. The PRINT statement also must be changed to show the time (frames) left and the score.

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor

'Declare and initialize variables
c = 15
dist = 8
framecount = 0
CONST framestotal = 5000
key$ = ""
CONST ocount = 64
CONST osize = 12
score = 0
size = 32
x = 320
y = 240
DIM o(1 TO ocount, 3) 'The three is for coordinates and colors

'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS

'Loop until the program ends
DO

'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT

'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c
px = x: py = y

'Initialize and move the other objects
a = INT(RND * ocount) + 1 'Tries to initialize this object
IF o(a, 3) = 0 THEN o(a, 1) = INT(RND * 640): o(a, 2) = INT(RND * 480): o(a, 3) = INT(RND * 15) + 1

FOR a = 1 TO ocount 'Loops for each object to display
IF SQR((x - o(a, 1)) * (x - o(a, 1)) + (y - o(a, 2)) * (y - o(a, 2))) < size + osize AND o(a, 3) > 0 THEN
c = INT(RND * 7) + 9 'Changes circle color
CIRCLE (o(a, 1), o(a, 2)), osize, 0 'Erases the object
o(a, 3) = 0 'Sets the object color to black so it no longer exists
score = score + 1
END IF

IF o(a, 3) > 0 THEN CIRCLE (o(a, 1), o(a, 2)), osize
NEXT a

'Accept user input
key$ = INKEY$

framecount = framecount + 1: LOCATE 3, 5: PRINT "Score: "; score; " | Time left: "; framestotal - framecount
LOOP UNTIL key$ = CHR$(27) OR framecount = framestotal

I got 275 points! {:-D) The program is now finished, but it has no name. Give it one! The program is currently fifty-eight lines long, but it can be shrunk by using colons to fit more on a single line. Now it is under thirty lines long (only twenty if the comments are removed)!

'i-TECH Tutorial: Using Circles as Objects in Games
'(C) 2006 i-TECH and Kristopher Windsor
'Declare and initialize variables
c = 15: dist = 8: framecount = 0: CONST framestotal = 5000: key$ = "": CONST ocount = 64: CONST osize = 12: score = 0: size = 32: x = 320: y = 240: DIM o(1 TO ocount, 3)
'Initialize the display
SCREEN 12: WIDTH 80, 60: CLS
'Loop until the program ends
DO
'Respond to user input
SELECT CASE key$
CASE CHR$(0) + CHR$(72): IF y > 0 THEN y = y - dist
CASE CHR$(0) + CHR$(75): IF x > 0 THEN x = x - dist
CASE CHR$(0) + CHR$(77): IF x < 639 THEN x = x + dist
CASE CHR$(0) + CHR$(80): IF y < 479 THEN y = y + dist
CASE " ": c = INT(RND * 7) + 9
END SELECT
'Move the circle
IF x <> px OR y <> py THEN CIRCLE (px, py), size, 0
CIRCLE (x, y), size, c: px = x: py = y
'Initialize and move the other objects
a = INT(RND * ocount) + 1: IF o(a, 3) = 0 THEN o(a, 1) = INT(RND * 640): o(a, 2) = INT(RND * 480): o(a, 3) = INT(RND * 15) + 1
FOR a = 1 TO ocount 'Loops for each object to display
IF SQR((x - o(a, 1)) * (x - o(a, 1)) + (y - o(a, 2)) * (y - o(a, 2))) < size + osize AND o(a, 3) > 0 THEN c = INT(RND * 7) + 9: CIRCLE (o(a, 1), o(a, 2)), osize, 0: o(a, 3) = 0: score = score + 1
IF o(a, 3) > 0 THEN CIRCLE (o(a, 1), o(a, 2)), osize
NEXT a
'Accept user input
key$ = INKEY$
framecount = framecount + 1: LOCATE 3, 5: PRINT "Score: "; score; " | Time left: "; framestotal - framecount
LOOP UNTIL key$ = CHR$(27) OR framecount = framestotal

The End! Support and Feedback at kristopherwindsor@yahoo.com. This tutorial was written by Kristopher Windsor in June 2006.