Now we can move sprites in STOS we need to put things together to see how we can actually begin creating playable games.
Along the way we will look at some more new features and concepts so you can understand more of how STOS works versus programming languages and game engines you might be used to.
Avoid the Monster
As our first example, let's create a minimalist bad-guy avoidance game. This isn't intended to be super fun, just ensure we know how to have a bad guy sprite that can cause the game to end when our player character is eaten.
So far we have only used one sprite so my sprite bank now includes a background tile as Sprite 2 and the monster sprite as Sprite 3.
Remember to place our sprites on screen we use the following:
sprite 1,x,y,1
sprite 3,bx,by,3
We have X/Y for the player and BX/BY (baddie X/Y) for the enemy sprite.
To hunt the player we adjust the baddie X and Y incrementally using the following logic:
230 if bx>x then dec bx
240 if bx<x then inc bx
250 if by>y then dec by
260 if by<y then inc by
The problem is, if we do this without any kind of delay, the monster will eat us too quickly.
210 inc tx
220 if tx < 10 then goto 290
230 if bx>x then dec bx
240 if bx<x then inc bx
250 if by>y then dec by
260 if by<y then inc by
270 tx=0
280 :
290 rem @player
This counts (TX for 'ticks') to 10 before moving then resets the counter. This way you can speed it up or slow it down, or even have the speed set by the level of difficulty.
You will note the goto
- goto got a bad reputation but in retro games it is pretty standard operating procedure, especially when you drop down to assembly language.
Background Tiles and Beating the Sprite Limits
One thing we quickly come up against even with a very simple "avoid the monster" game like this one is the 15 sprite limit.
It turns out that you can paste a copy of a sprite using put sprite N
where N is the number of the sprite. STOS will "stamp" the sprite wherever it is currently located, then when you move the sprite the image is left behind.
I use a couple of for
loops, one for rows and one for columns, and repeatedly paste the tile sprite over and over.
60 wx=0 : wy=0
70 for iy=0 to 5
80 for ix=0 to 9
90 sprite 2,wx,wy,2
100 put sprite 2
110 wx=wx+32
120 wait vbl
130 next ix
140 wx=0
150 wy=wy+32
160 next iy
Of course once we start building full level scenes and maps, we won't just be using a repeating tile!
Collision Detection and Game Over
We almost have everything we need to build a basic game, all apart from a way for the game to be over that is!
STOS includes three built-in collision detection options.
The first, and the one I chose, is to detect two sprites are overlapping.
To do this we use collide
, and we specify the sprite number we wish to test for collisions with (in our case, the player sprite), and then the collision zone around the sprite "hot spot". I chose 16x16 because I thought it would be fun for the player to get eaten only when the monster's mouth is biting him.
360 if collide(1,16,16) = 8 then goto 420
You can also set up collision "zones", which are rectangular coordinate boxes that you can check the sprite has entered.
This is a good way to set an exit/door for our little guy to escape from the monster, but can also be used to detect button or menu clicks in a mouse-driven game.
The final option is to check for the color of the pixel under your sprite hot spot. This is the main way you can check for organically shaped collisions but it does mean losing one of your 16 colours or checking for the absence of color (IE. no collisions when the sprite is over the plain background).
Full Game Code for Demo 1
10 cls : mode 0 : curs off : hide on
20 colour 11,$0
30 load "c:\sprite.mbk"
40 ink 0
50 bar 0,0 to 319,40
60 wx=0 : wy=0
70 for iy=0 to 5
80 for ix=0 to 9
90 sprite 2,wx,wy,2
100 put sprite 2
110 wx=wx+32
120 wait vbl
130 next ix
140 wx=0
150 wy=wy+32
160 next iy
170 :
180 k$="" : q=0 : x=100 : y=100
190 bx=0 : by=32 : tx=0
200 while q=0
210 inc tx
220 if tx < 10 then goto 290
230 if bx>x then dec bx
240 if bx<x then inc bx
250 if by>y then dec by
260 if by<y then inc by
270 tx=0
280 :
290 rem @player
300 k$=inkey$
310 if k$ = "q" then q=1
320 if scancode = 75 then x=x-1
330 if scancode = 77 then x=x+1
340 if scancode = 72 then y=y-1
350 if scancode = 80 then y=y+1
360 if collide(1,16,16) = 8 then goto 420
370 sprite 1,x,y,1
380 sprite 3,bx,by,3
390 wait vbl
400 wend
410 :
420 rem @over
430 default