Main forum > Tutorials
Horizontal Shooter Tutorial
bigsofty:
Excellent tutorial, well done! I like the way this is evolving on a difficulty level :good:
Steinbock:
In the second last part of this tutorial we will first automate the adding of objects. Thereafter we will concerne with collisions.
Last time we added with
--- Code: (glbasic) --- IF ScrollX=128 THEN ObjectADD(ID_ENEMY1,320,120)
IF ScrollX=160 THEN ObjectADD(ID_ENEMY2,320,120)
--- End code ---
in level00.gbas the objects manually. But in a completed game are much more required, and it would be very laborious to call every single object separatly. Therefore we read out the datas from a predefined file level00.evt. For this we must expand our existing event-type (TEvent).
--- Code: (glbasic) --- IX% = 0
ID%[256]
Pos%[256]
X%[256]
Y%[256]
--- End code ---
IX is a pointer to the actual listentry, ID is the objectID, Pos is the scrollposition WHEN the object shall appear and X,Y the position WERE the object shall appear.
With
--- Code: (glbasic) --- // init events
OPENFILE(1,"./isdo/level00.evt",TRUE)
FOR p=0 TO 254
READUWORD 1,val
Event.Pos[p]=val
NEXT
FOR p=0 TO 254
READUWORD 1,val
Event.ID[p]=val
NEXT
FOR p=0 TO 254
READUWORD 1,val
Event.X[p]=val
NEXT
FOR p=0 TO 254
READUWORD 1,val
Event.Y[p]=val
NEXT
--- End code ---
in level00.gbas we load these datas into our eventlist. The request when a object shall appear, we do in the subroutine EventHANDLER in library.gbas.
--- Code: (glbasic) ---//=============================================================================
SUB EventHANDLER:
//=============================================================================
LOCAL ix%,typ%
ix=Event.IX
IF ScrollX=Event.Pos[ix]
SELECT Event.ID[ix]
CASE ID_ENEMY1 TO ID_ENEMY2
ObjectADD(Event.ID[ix],Event.X[ix],Event.Y[ix])
ENDSELECT
INC Event.IX,1
ENDIF
ENDSUB // EventHANDLER
--- End code ---
First we request the current index in the eventlist, then we check the type and add the corresponding object to the scene. The rest goes as if by magic.
And now to the collisions. There are different possibilities in GLBasic.
BOXCOLL cheks, if 2 rectangles interleaf eachother
SPRCOLL check, if visible pixels of 2 sprites interleaf eachother
We use a routine based on BOXCOLL. For this we define a so-called collisionbox for player, playershots and objects. This box can also be bigger or smaller then the sprite.
We have to expand the types.
--- Code: (glbasic) --- CollTop
CollBottom
CollLeft
CollRight
--- End code ---
The size of the collisionbox of objects we specify with function
--- Code: (glbasic) ---//=============================================================================
FUNCTION SetCollBox: ix%,left,top,right,bottom
//=============================================================================
Object.CollLeft[ix]=Object.PosX[ix]+left
Object.CollTop[ix]=Object.PosY[ix]+top
Object.CollRight[ix]=Object.PosX[ix]+right
Object.CollBottom[ix]=Object.PosY[ix]+bottom
--- End code ---
For test pruposes you can outcomment the following 3 lines. Then the collisionboxes appear half-transparent.
--- Code: (glbasic) --- //ALPHAMODE 0.5
//DRAWRECT Object.CollLeft[ix],Object.CollTop[ix],Object.PosX[ix]+right-Object.CollLeft[ix],Object.PosY[ix]+bottom-Object.CollTop[ix],0xFFFFFF
//ALPHAMODE 0.0
--- End code ---
For the player we build a separate box.
--- Code: (glbasic) ---//=============================================================================
SUB PlayerHANDLER:
//=============================================================================
Player.CollTop=Player.PosY
Player.CollBottom=Player.PosY+31
Player.CollLeft=Player.PosX
Player.CollRight=Player.PosX+16
DRAWSPRITE SPR_PLAYER+(INTEGER((bAND(Player.Timer,3)/2))),Player.PosX,Player.PosY
ENDSUB // PlayerHANDLER
--- End code ---
the same for the 8 shots in ShotHANDLER.
--- Code: (glbasic) --- Shot.CollTop [ix]=Shot.PosY[ix]
Shot.CollBottom[ix]=Shot.PosY[ix]+6
Shot.CollLeft [ix]=Shot.PosX[ix]
Shot.CollRight [ix]=Shot.PosX[ix]+6
--- End code ---
It's important to make the assignements with every change of position.
Now the check if an object collides eather with player or with playershot.
--- Code: (glbasic) ---//=============================================================================
FUNCTION CheckCollPlayer: ix%
//=============================================================================
IF Player.CollTop>Object.CollBottom[ix] OR Player.CollBottom<Object.CollTop[ix] OR Player.CollLeft>Object.CollRight[ix] OR Player.CollRight<Object.CollLeft[ix]
RETURN COLL_NONE
ELSE
RETURN COLL_PLAYER
ENDIF
RETURN COLL_NONE
--- End code ---
With ix we pass the index of object wich we check. If the object touches the player we return COLL_PLAYER, else we return COLL_NONE.
The same for playershots.
--- Code: (glbasic) ---//=============================================================================
FUNCTION CheckCollShot: ix%
//=============================================================================
LOCAL i%
FOR i=0 TO Shot.Count-1
IF Shot.State[i]
IF Shot.CollTop[i]>Object.CollBottom[ix] OR Shot.CollBottom[i]<Object.CollTop[ix] OR Shot.CollLeft[i]>Object.CollRight[ix] OR Shot.CollRight[i]<Object.CollLeft[ix]
RETURN COLL_NONE
ELSE
Shot.State[i]=0
RETURN COLL_SHOT
ENDIF
ENDIF
NEXT
RETURN COLL_NONE
ENDFUNCTION // CheckCollShot
--- End code ---
But this time we return COLL_SHOT and clear also the current shotentry.
We give the command for collisiondetection for every object in the scripts. As example we take ID_ENEMY1 in enemies.gbas:
--- Code: (glbasic) --- SetCollBox(ix,0,0,15,15)
--- End code ---
Sets the size of collisionbox.
Then we check if ENEMY1 was hitted by a playershot.
--- Code: (glbasic) --- IF CheckCollShot(ix)=COLL_SHOT
Object.State[ix]=0
EffectADD(ID_EFFECT1,Object.PosX[ix],Object.PosY[ix])
ENDIF
--- End code ---
If yes, we clear the object out of the list and add an effect (explosion).
Effect are nothing else than object but they do not need a collisionbox. The reason to distinguish between effects and objects is
--- Code: (glbasic) --- GOSUB KeyHANDLER
GOSUB LayerBGDRAW
GOSUB ShotHANDLER
GOSUB EventHANDLER
GOSUB ObjectHANDLER
GOSUB PlayerHANDLER
GOSUB LayerFGDRAW
GOSUB EffectHANDLER
GOSUB StatusDRAW
--- End code ---
that we draw effects AFTER objects. Otherwise perhaps we can' see the effects behind other objects.
[attachment deleted by admin]
Steinbock:
In the last part we look, how to add a power-up and thus change the shotpower.
Then finally we add a backgroundmusic and some soundeffects. As always there is an attachement with samplecode.
If you worked through the 6th part, you know, we have 2 different enemytypes: ENEMY1 and ENEMY2.
In the program we can see ENEMY2 as RED enemy. Now this one shall, if it is hitted, leave a power-up.
For this we just have to add an object in our EnemySCRIPT.
--- Code: (glbasic) --- ObjectADD(ID_POWERUP,Object.PosX[ix],Object.PosY[ix])
--- End code ---
The script for the power-up item on the other hand you will find in file items.gbas.
--- Code: (glbasic) --- CASE ID_POWERUP
SELECT Object.State[ix]
CASE 1
IF Object.PosX[ix]>-16
DEC Object.PosX[ix],0.5
ELSE
Object.State[ix]=0
ENDIF
ENDSELECT
DRAWSPRITE SPR_POWERUP,Object.PosX[ix],Object.PosY[ix]
SetCollBox(ix,0,0,15,15)
IF CheckCollPlayer(ix)=COLL_PLAYER
Object.State[ix]=0
PLAYSOUND(SFX_EXTRA,GetPan(Object.PosX[ix]),0.7)
SPR_SHOT=24
ENDIF
ENDSELECT
--- End code ---
We check this item on collision with the player. If a collision occurs, we close the item in the objectlist and change our shot.
Now to the sound. This is an easy thing under GLBasic.
In file level000.gbas we load our soundeffects and allocate them a constant.
--- Code: (glbasic) --- LOADSOUND "./isdo/sfx/shot.wav",SFX_SHOT,4
LOADSOUND "./isdo/sfx/explosion.wav",SFX_EXPLOSION,4
LOADSOUND "./isdo/sfx/extra.wav",SFX_EXTRA,4
--- End code ---
Thereafter we load our backgroundmusic, setting the volume and play it.
--- Code: (glbasic) --- PLAYMUSIC "./isdo/sfx/music.wav",TRUE
MUSICVOLUME 0.9
--- End code ---
In GLBasic a soundeffect will be played with the command PLAYSOUND.
If you look on the ItemSCRIPT for example
--- Code: (glbasic) ---
PLAYSOUND(SFX_EXTRA,GetPan(Object.PosX[ix]),0.7)
--- End code ---
the soundeffect with ID SFX_EXTRA will be played with a volume of 0.7.
Function GetPan in our library causes, the effect sounds depending of objectposition (left/right).
Ok. That's it. Now i hope to helped some of you with this tutorial. And as i said, if i can help someone, i will try to do.
As a little bonus you can download here isdo_090406.zip - 11.13MB a 1min section of my project I.S.D.O. The playercollision is off. The backgroundmusics origin: "MOD-Archiv".
--- Code: (glbasic) ---Steuerung->WIN:
startmenu: cursorkey up/down = menucursor up and down
"x"-key = select menuentry
game: cursorkey up/down = move
"x"-key = shoot
ENTER-key = return to startmenu
--- End code ---
And now enjoy!! =D
[attachment deleted by admin]
sf-in-sf:
Hi!
Using CONSTANT is safer than GLOBAL or LOCAL when declaring genuine constants.
Navigation
[0] Message Index
[*] Previous page
Go to full version