Page retrieved from the Internet Archive Wayback Machine

Using flags to handle concurrent operation of multiple events

Examples of the problem

Playing notes

shooting a bullet

basic idea for the solution

The general concept is to have no loops other than MainLoop. If something has to happen inside a loop, such a moving a bullet, use a flag to use MainLoop as the loop which processes this, rather than some other loop effectively inside of MainLoop.

example solutions

playing a note

...
       LoByteVar NoteFlags
NOTE_A_ON  EQU #00000001
NOTE_A_OFF EQU #00000000
NOTE_B_ON  EQU #00000010
NOTE_B_OFF EQU #00000000
...
MainLoop:
        ...
        call    GetKeys
        push    af
        and     PADF_UP
        call    nz,play_a
        call    z,stop_a        ; stop the note if the user has released the key
        pop     af
        and     PADF_LEFT
        call    nz,play_b
        ...
        jr      MainLoop
...
play_a: ld      a,[NoteFlags]
        and     NOTE_A_ON        ; is note a already being played
        ret     nz               ; yep. Don't retrigger it.
        ld      a,[NoteFlags]
        or      NOTE_A_ON        ; set the flag
        ld      [NoteFlags],a    ; save it
<code here to start the note a>
        ret
...
play_b: ld      a,[NoteFlags]
        and     NOTE_B_ON        ; is note b already being played
        ret     nz
        ld      a,[Noteflags]
        or      NOTE_B_On
        ld      [NoteFlags],a
        <code here to start the note b>
        ret
...
stop_a: ld      a,[NoteFlags]
        and     ~NOTE_A_ON
        ld      [NoteFlags],a
        <code here to stop note a>
        ret 

shooting a bullet

            LoByteVar ProjectileFlags
BULLET_SHOT EQU       #00000001
MainLoop:
        ...
        call    GetKeys
        push    af
        and     PADF_A
        call    nz,shoot_bullet
        ...
        call    processBullet
        jr      MainLoop
...
shoot_bullet: 
        ld      a,[ProjectileFlags]
        and     BULLET_SHOT
        ret     nz                    ; there's already a bullet out there. Don't shoot another
        ld      a, [ProjectileFlags]
        or      BULLET_SHOT           ; set the bullet flag
        ld      [ProjectileFlags],a   ; set the flag saying the bullet is being shot
<code here for initialization of the bullet, for example initial screen location>
        ret
...
processBullet:
        ld      a,[ProjectileFlags]
        and     BULLET_SHOT
        ret     z                     ; ain't no bullet. Go home.
        <move the bullet one iteration (one to left, one to right, one up, down, whatever)>
        <check if bullet has hit something or is off the screen or if it should die for some other reason. If so:>
        ld      a,[ProjectileFlags]
        and     ~BULLET_SHOT           ; reset the flag
        ret
        <otherwise, just return>
...
 

tips

ECE238Spr08/tutorials/Flags (last edited 2008-04-30 15:01:18 by JohnHarrison)