Author |
Topic: Simple game project (Read 2730 times) |
|
Shaun
New Member
member is offline


Posts: 2
|
 |
Simple game project
« Thread started on: Jun 16th, 2010, 11:19pm » |
|
Hello everyone, I'm new to this group! I've had an interest in computer programming for quite some time. I have tried to master some of the other languages before such as java and C#. I found them to be quite cyiptic and difficult to follow along with. especially the Object orientated style of those languages. when I first got the demo version of BBC basic i found it much easiler.
I have been playing around with Basic for over a year. Learning alittle more here and there. I have been trying to program a simple "space invaders" type game and i would like some tips on how i can improve it.
The part where i am stuck on is how do i run the PROC_fire routine so it does not slow the game right down. I have it in a repeat until loop within the proc and it has to complete before control is passed on to the move PROCS. This makes the game move out of sync with the fire routine.
I am such you will see it needs a lot of improvement!
Heres my source code:
REM Invaders MODE 6 OFF VDU 23,250,24,24,24,24,60,60,60,60 xleft% =20 REM xright%= 0 Yfire = 20 PRINT TAB(xleft%,22) CHR$(250) REPEAT IF INKEY(-26) PROC_moveleft IF INKEY(-122) PROC_moveright REM detect edge of screen CASE xleft% OF WHEN 39 xleft%=xleft% -1 WHEN 0 xleft% =xleft% +1 ENDCASE IF INKEY(-99) PROC_fire(xleft%) UNTIL FALSE DEF PROC_moveleft VDU 7 WAIT 2 PRINT TAB(xleft%, 22) CHR$(250) PRINT TAB(xleft%+ 1, 22) " " xleft%=xleft% - 1 ENDPROC DEF PROC_moveright VDU 7 WAIT 2 PRINT TAB(xleft%, 22) CHR$(250) PRINT TAB(xleft% - 1, 22) " " xleft%=xleft% + 1 ENDPROC DEF PROC_fire(xleft%) REPEAT WAIT 1 VDU 7 PRINT TAB(xleft%,Yfire) "|" PRINT TAB(xleft%,Yfire + 1) " " Yfire = Yfire - 1 UNTIL Yfire = 0 Yfire= 20 ENDPROC
|
|
Logged
|
|
|
|
softweir
New Member
member is offline


Posts: 12
|
 |
Re: Simple game project
« Reply #1 on: Jun 17th, 2010, 02:07am » |
|
The way to do it is to call PROCfire() every time through the loop, and use the value of Yfire and INKEY(-99) within PROCfire to decide what to do:-
Code:
REM Invaders
MODE 6
OFF
VDU 23,250,24,24,24,24,60,60,60,60
Delay=1
xleft =20
REM xright= 0
Yfire = 21
Slow = Delay : REM Used to slow down cannon movement. Increase Delay to slow cannon further
PRINT TAB(xleft,22) CHR$(250)
REPEAT
WAIT 1
Slow=Slow-1
IF Slow=0 THEN
IF INKEY(-26) AND xleft>0 PROC_moveleft
IF INKEY(-122) AND xleft<39 PROC_moveright
Slow=Delay
ENDIF
REM You would have got some odd artefacts at the edges of the
REM screen adjusting xleft outside of the movement PROCs
PROC_fire(xleft)
UNTIL FALSE
DEF PROC_moveleft
VDU 7
PRINT TAB(xleft, 22) CHR$(250)
PRINT TAB(xleft+ 1, 22) " "
xleft=xleft - 1
ENDPROC
DEF PROC_moveright
VDU 7
PRINT TAB(xleft, 22) CHR$(250)
PRINT TAB(xleft - 1, 22) " "
xleft=xleft + 1
ENDPROC
DEF PROC_fire(xleft)
IF INKEY(-99) AND Yfire=-1 THEN
Yfire=20
Xfire=xleft
ENDIF
IF Yfire=0 THEN
PRINT TAB(Xfire,Yfire) " " : REM Clear off last shot
Yfire=-1
ENDIF
IF Yfire>0 THEN
VDU 7
PRINT TAB(Xfire,Yfire) "|"
PRINT TAB(Xfire,Yfire + 1) " "
Yfire = Yfire - 1
ENDIF
ENDPROC
Notice that Yfire is set to a dummy value of -1 when no shot is being fired, at which point INKEY(-99) is tested. When Yfire is any other value the shot is running and there is no need to test INKEY(-99).
I think this will give you the right ideas, but I am abruptly exhausted and haven't run this at all so things may be very wrong! I'll come back to this later.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: Simple game project
« Reply #2 on: Jun 17th, 2010, 08:39am » |
|
on Jun 16th, 2010, 11:19pm, Shaun wrote:I have been trying to program a simple "space invaders" type game and i would like some tips on how i can improve it. |
|
The suggestion made by softweir is one way to go; rather than wait inside PROCfire until it's finished do just one 'step' in each call and return back to your 'main loop'. However, you'd still need to suppress further shots until the previous 'bullet' has reached its destination because the program has no means of having more than one bullet 'in flight' at the same time!
One thing you definitely need to change is that whilst your program is waiting for user input it gobbles up 100% CPU time! This is very bad practice, because it will cause your processor to get hot and, on a laptop, cause the battery to run down very quickly. It will also slow down any other programs running at the same time.
So whenever you're sitting waiting in an 'infinite loop' ensure you insert a WAIT (e.g. WAIT 1) statement somewhere to cut down the CPU load. In the code below I've simply removed your WAITs from the individual procedures and put one in the main loop instead.
Here's my suggested revised program:
Code: REM Invaders
MODE 6
OFF
VDU 23,250,24,24,24,24,60,60,60,60
xleft% =20
REM xright%= 0
Xfire = -1
Yfire = 20
Firing = FALSE
PRINT TAB(xleft%,22) CHR$(250)
REPEAT
WAIT 2
IF INKEY(-99) AND Xfire = -1 THEN Xfire = xleft%
IF INKEY(-26) PROC_moveleft
IF INKEY(-122) PROC_moveright
PROC_fire
UNTIL FALSE
DEF PROC_moveleft
VDU 7
PRINT TAB(xleft%, 22) " ";
IF xleft% > 0 xleft%=xleft% - 1
PRINT TAB(xleft%, 22) CHR$(250);
ENDPROC
DEF PROC_moveright
VDU 7
PRINT TAB(xleft%, 22) " ";
IF xleft% < 39 xleft%=xleft% + 1
PRINT TAB(xleft%, 22) CHR$(250);
ENDPROC
DEF PROC_fire
IF Xfire <> -1 THEN
VDU 7
PRINT TAB(Xfire,Yfire) " ";
Yfire = Yfire - 1
PRINT TAB(Xfire,Yfire) "|";
IF Yfire = 0 THEN
Xfire = -1
Yfire = 20
ENDIF
ENDIF
ENDPROC Richard.
|
|
Logged
|
|
|
|
Shaun
New Member
member is offline


Posts: 2
|
 |
Re: Simple game project
« Reply #3 on: Jul 13th, 2010, 6:15pm » |
|
Ok, i have made some improvements on my ascii based "space invaders" emulation. I omited out of posting untill i had something worth showing. Playing around with it i managed to set up a block of aliens which behave like the original game. This was an achievement for me as this is as far as i have gotten with any game i've tried to program.
What i would like to do now is to optimize my code. For example i have a lot of duplicate code which does the same things, but does it in reverse. The block of characters moves to the right edge of the "screen" then i shift it down a row and use duplicate code to move it back to the left...i could not find away to do it all in one procedure.
after thats been cleaned up i would like to now how to do basic collision detection between the "bullet" character and each one of the "alien" characters. I would like then to remove the character from the screen once a bullet has hit it.
I would be glad if someone can help me out with this, thank you.
Here is my source code thus far:
Code:
REM Invaders
MODE 6
REM VDU 23,22,448;520;40,25,16,0
OFF
REM player
VDU 23,250,24,24,60,255,255,255,255,255
VDU 23,241,0,0,0,127,255,255,255,255
VDU 23,242,0,0,0,254,255,255,255,255
REM
REM asteroid
VDU 23,240,24,36,82,169,149,74,36,24
REM alien 2
VDU 23,230,60,66,129,66,60,66,129,129
VDU 23,253,24,36,66,129,129,66,36,24
VDU 23,230,24,126,153,255,90,66,129,0
REM intialize Globel variables
xleft% =20
Xfire = -1
Yfire = 22
xalien=0
yalien =0
timer = 0
speed = 16
flag = TRUE
bullet$="|"
offset = 0
coloffset=0
DIM aliens$(20,10)
CHR = 230
FOR aliensx=0 TO 20
FOR aliensy = 0 TO 10
aliens$(aliensx,aliensy) = CHR$(CHR)
NEXT aliensy
NEXT aliensx
cannon$ = CHR$(241)+CHR$(250)+CHR$(242)
COLOUR 2
REM initial player print
PRINT TAB(xleft%,23) cannon$
REPEAT
COLOUR 2
WAIT 2
LINE 39,39 ,1230,39
IF INKEY(-99) AND Xfire = -1 THEN Xfire = xleft%
IF INKEY(-26) PROC_moveleft
IF INKEY(-122) PROC_moveright
PROC_fire
timer = timer + 1
IF timer = speed AND coloffset < 23 PROCAliens_move
IF timer = speed timer= 0
CASE coloffset OF
WHEN 5 speed = 6
WHEN 10 speed = 4
WHEN 15 speed = 2
ENDCASE
UNTIL coloffset = 19
CLS
PRINT TAB(14,7) "GAME OVER!"
PRINT TAB(6,9) "The invasion was successful"
PRINT TAB(8,11) "Plant earth is doomed!"
PRINT TAB(10,12) "press any key to reset"
REPEAT UNTIL INKEY(0)=-1
Key=GET
RUN
END
DEF PROCRedraw_cannon
COLOUR 2
PRINT TAB(xleft%, 23) cannon$;
ENDPROC
DEF PROC_moveleft
PRINT TAB(xleft%, 23) " ";
IF xleft% > 0 xleft%=xleft% - 1
PRINT TAB(xleft%, 23) cannon$;
ENDPROC
DEF PROC_moveright
PRINT TAB(xleft%, 23) " ";
IF xleft% < 37 xleft%=xleft% + 1
PRINT TAB(xleft%, 23) cannon$;
ENDPROC
DEF PROC_fire
COLOUR 15
IF Xfire <> -1 THEN
PRINT TAB(Xfire+1,Yfire) " ";
Yfire = Yfire - 1
PRINT TAB(Xfire+1,Yfire) bullet$;
IF Yfire = 0 THEN
Xfire = -1
Yfire = 22
ENDIF
ENDIF
ENDPROC
DEF PROCAliens_move
IF flag = TRUE THEN
REM Print block to screen
VDU 7
offset= offset + 1
COLOUR 15
FOR row=0 TO 20 STEP 2
FOR col= 0 TO 4
PRINT TAB(row+offset,col+coloffset) " " aliens$(row,col)
NEXT col
NEXT row
ENDIF
IF offset= 18 coloffset = coloffset +1 CLS PROCRedraw_cannon flag = FALSE
IF flag = FALSE THEN
REM Print block to screen
VDU 7
offset= offset - 1
COLOUR 15
FOR row=0 TO 20 STEP 2
FOR col= 0 TO 4
PRINT TAB(row+offset,col+coloffset) aliens$(row,col) " "
NEXT col
NEXT row
ENDIF
IF offset= 0 coloffset = coloffset +1 CLS PROCRedraw_cannon flag = TRUE
ENDPROC
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: Simple game project
« Reply #4 on: Jul 13th, 2010, 10:25pm » |
|
on Jul 13th, 2010, 6:15pm, Shaun wrote:What i would like to do now is to optimize my code. For example i have a lot of duplicate code which does the same things, but does it in reverse. |
|
To be honest there's not a lot wrong with your code as it stands. It's neatly laid out, there's plenty of 'whitespace', the variable names are meaningful etc. I wish everybody wrote code like that!
No doubt you could combine your similar routines into one, by passing a parameter which determines which of the similar actions they perform, but I doubt that the benefit (if any) would justify the complication.
If I was to criticise anything it would be the extensive use of global variables, and no LOCAL variables, so it hardly conforms to the principle of 'information hiding'. But really given the smallness of the program those techniques are probably inappropriate anyway.
Richard.
|
« Last Edit: Jul 13th, 2010, 10:32pm by admin » |
Logged
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Simple game project
« Reply #5 on: Jul 16th, 2010, 09:03am » |
|
Hi Shaun,
One relatively simple way to combine you left-moving and right-moving code is to use your flag to indicate the movement: if you switch it between +1 (for rightwards movement) and -1 (for leftwards), you can simply add it to the offset. To change direction, simply multiply flag by -1.
I didn't like the "blink" where you do CLS at the end of the line, so I have tried using *REFRESH OFF and *REFRESH ON. This also allows a CLS at beginning of EACH cycle, thus avoiding some complications in your PRINT statement. You could put these statements at the beginning and end of your whole programme, and then just use *REFRESH when you want something to be seen, but I didn't want to mess around with your overall programme too much! Contradicting that slightly, I have had to move the line drawing into this routine.
I note that you currently only display half of the aliens stored in your array, since you increase the offset by 2, but then refer directly to your array. You could either fill your array with only alternate slots filled with aliens (it might be helpful to fill the others with the ascii for "blank"), or you could advance offset by 1, but add 2*offset to the TAB position. Which you choose will have implications for your collision detection system....
Another approach might be to construct a string of aliens and spaces in advance, and then print the whole string at once. That would probably be faster, too.
I would suggest the easiest way to handle collision detection would be to test whether the bullet's Y coordinate lies in the range where the aliens are, and then test whether it is in a cell containing an alien. You could then change the value in that cell of the array to "blank", add 1 to the score, and reset Xfire to -1 .
Here is a slightly modified version of your routine. Note that you will need to give flag the value 1 instead of TRUE at the beginning.
Code:
DEF PROCAliens_move
REM Print block to screen
VDU 7
*REFRESH OFF
offset= offset + flag
CLS
PROCRedraw_cannon
COLOUR 15
FOR row=0 TO 20 STEP 2
FOR col= 0 TO 4
PRINT TAB(row+offset,col+coloffset) aliens$(row,col)
NEXT col
NEXT row
IF offset= 18 OR offset=0 THEN
coloffset = coloffset +1
flag* = -1
ENDIF
LINE 39,39 ,1230,39
*REFRESH ON
ENDPROC
Hope that is helpful - I look forward to seeing the completed game!
Best wishes,
D
|
|
Logged
|
|
|
|
|