BBC BASIC for Windows
« Simple game project »

Welcome Guest. Please Login or Register.
Apr 5th, 2018, 10:58pm



ATTENTION MEMBERS: Conforums will be closing it doors and discontinuing its service on April 15, 2018.
Ad-Free has been deactivated. Outstanding Ad-Free credits will be reimbursed to respective payment methods.

If you require a dump of the post on your message board, please come to the support board and request it.


Thank you Conforums members.

BBC BASIC for Windows Resources
Online BBC BASIC for Windows documentation
BBC BASIC for Windows Beginners' Tutorial
BBC BASIC Home Page
BBC BASIC on Rosetta Code
BBC BASIC discussion group
BBC BASIC for Windows Programmers' Reference

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: Simple game project  (Read 2730 times)
Shaun
New Member
Image


member is offline

Avatar




PM


Posts: 2
xx 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


User IP Logged

softweir
New Member
Image


member is offline

Avatar




PM


Posts: 12
xx 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.
User IP Logged

admin
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1145
xx 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.
User IP Logged

Shaun
New Member
Image


member is offline

Avatar




PM


Posts: 2
xx 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
      

 
User IP Logged

admin
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM


Posts: 1145
xx 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 » User IP Logged

DDRM
Administrator
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 321
xx 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
User IP Logged

Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

| |

This forum powered for FREE by Conforums ©
Terms of Service | Privacy Policy | Conforums Support | Parental Controls