04-25-2024, 05:43 PM
(This post was last modified: 04-25-2024, 05:45 PM by TerryRitchie.)
You can also control a player's fire rate by using a latching method that keeps track of a key's current state (pressed or released).
I made a quick demo to show how this can be used in a game.
I have no idea why my comments get skewed when posting using the QB tags? This happens when exporting to HTML as well. I wish someone would look into this.
I made a quick demo to show how this can be used in a game.
I have no idea why my comments get skewed when posting using the QB tags? This happens when exporting to HTML as well. I wish someone would look into this.
Code: (Select All)
'+-----------------------------------------------------------------------------------+
'| Controlling Bullets |
'| |
'| "Wearing the player out" |
'| ---------------------- |
'| |
'| This method forces the player to release the fire button to fire the next bullet. |
'| This allows the player to rapid fire as fast as they can push the button which in |
'| turn wears the player out. |
'| |
'| A "latching" method is used to keep track of the fire button's current state. |
'| This method is also used in the player's ship movements to keep the game from |
'| registering the UP and DOWN arrow keys being pressed at the same time and the |
'| RIGHT and LEFT arrows keys from being pressed at the same time as well. |
'| |
'| |
'| This method can be combined with frame timers to limit the number of bullets per |
'| second as well. |
'| |
'| Demo by Terry Ritchie 04/25/24 |
'+-----------------------------------------------------------------------------------+
OPTION _EXPLICIT ' force declaration of all variables
'+-----------------------+
'| Define game constants |
'+-----------------------+
CONST SCREENWIDTH% = 800 ' game screen width
CONST SCREENHEIGHT% = 600 ' game screen height
CONST BUTTONUP% = 0 ' button position is up (depressed)
CONST BUTTONDOWN% = 1 ' button position is down (pressed)
'+-----------------------------+
'| Define variables structures |
'+-----------------------------+
TYPE KEY ' DEFINE KEYBOARD KEY
Key AS INTEGER ' scan code of key
Position AS INTEGER ' position of keyboard key (the "latch")
END TYPE
TYPE BUTTON ' DEFINE GAME BUTTONS
North AS KEY ' up arrow key
South AS KEY ' down arrow key
East AS KEY ' right arrow key
West AS KEY ' left arrow key
Fire AS KEY ' space bar key
END TYPE
TYPE BULLET ' DEFINE BULLET
Active AS INTEGER ' bullet active (y/n)
x AS INTEGER ' center x coordinate of bullet
y AS INTEGER ' center y coordinate of bullet
Speed AS SINGLE ' bullet speed
END TYPE
TYPE SHIP ' DEFINE PLAYER SHIP
x AS INTEGER ' center x coordinate of ship
y AS INTEGER ' center y coordinate of ship
MaxX AS INTEGER ' maximum x coordinate of ship \
MaxY AS INTEGER ' maximum y coordinate of ship \ Ship bounding box
MinX AS INTEGER ' minimum x coordinate of ship /
MinY AS INTEGER ' minimum y coordinate of ship /
END TYPE
'+------------------+
'| Define variables |
'+------------------+
DIM Button AS BUTTON ' game buttons
REDIM Bullet(0) AS BULLET ' player bullet array
DIM Ship AS SHIP ' player ship
'+----------------------+
'| Initialize variables |
'+----------------------+
Button.North.Key = 18432 ' up arrow key scan code
Button.South.Key = 20480 ' down arrow key scan code
Button.East.Key = 19712 ' right arrow key scan code
Button.West.Key = 19200 ' left arrow key scan code
Button.Fire.Key = 32 ' space bar key scan code
Ship.x = 20 ' initial ship x coordinate
Ship.y = (SCREENHEIGHT - 1) \ 2 ' initial ship y coordinate
Ship.MinX = 20 ' ship minimum x coordinate
Ship.MinY = 20 ' ship minimum y coordinate
Ship.MaxX = SCREENWIDTH \ 2 - 1 ' ship maximum x coordinate
Ship.MaxY = SCREENHEIGHT - 21 ' ship maximum y coordinate
'+--------------------------------------------------------------------------------------------------------------------+
'| BEGIN MAIN PROGRAM |
'+--------------------------------------------------------------------------------------------------------------------+
SCREEN _NEWIMAGE(SCREENWIDTH, SCREENHEIGHT, 32) ' enter game graphics screen
DO ' begin main program loop
_LIMIT 60 ' nice and smooth at 60 FPS
CLS ' clear the game screen
DisplayDirections ' display game's directions
'+-----------------------------------+
'| Update the player's ship position |
'+-----------------------------------+
MoveShip ' update and draw player ship
'+-----------------------------------------------+
'| Test for the fire button in the down position |
'+-----------------------------------------------+
IF _KEYDOWN(Button.Fire.Key) THEN ' fire button pressed? (space bar key)
'+------------------------------------------------------------------------------+
'| Test if the fire button has been released since the last time it was pressed |
'+------------------------------------------------------------------------------+
IF Button.Fire.Position = BUTTONUP THEN ' yes, has fire button been released?
'+------------------------------------------------------------+
'| Set the fire button into the down position and fire bullet |
'+------------------------------------------------------------+
Button.Fire.Position = BUTTONDOWN ' yes, latch fire button in down position
FireBullet Ship.x + 15, Ship.y ' fire a bullet from the nose of the ship
END IF
ELSE ' no, fire button is not pressed
Button.Fire.Position = BUTTONUP ' latch fire button in up position
END IF
'+------------------------------------+
'| Update the active bullet positions |
'+------------------------------------+
ManageBullets ' update and draw all active bullets
_DISPLAY ' update game screen with changes
LOOP UNTIL _KEYDOWN(27) ' leave main loop when ESC pressed
SYSTEM ' return to the operating system
'+--------------------------------------------------------------------------------------------------------------------+
'| END MAIN PROGRAM |
'+--------------------------------------------------------------------------------------------------------------------+
'+--------------------------------------------------------------------------------------------------------------------+
'| Declare subroutines and functions |
'+--------------------------------------------------------------------------------------------------------------------+
' ____________________________________________________________________________________________________________________
'/ \
SUB DisplayDirections () ' DisplayDirections |
' ________________________________________________________________________________________________________________/
'/ \
'| Displays the game's directions to the player. |
'\________________________________________________________________________________________________________________/
LOCATE 2, 2
PRINT "FORCE PLAYER TO PRESS AND RELEASE FIRE KEY"
LOCATE 4, 2
PRINT " - ARROW KEYS TO MOVE"
LOCATE 5, 2
PRINT " - SPACE BAR TO FIRE"
LOCATE 6, 2
PRINT " - ESC TO LEAVE GAME"
END SUB
' ____________________________________________________________________________________________________________________
'/ \
SUB MoveShip () ' MoveShip |
' ________________________________________________________________________________________________________________/
'/ \
'| Updates the ship location according to player keypresses then draws the ship on the game screen. |
'\________________________________________________________________________________________________________________/
SHARED Button AS BUTTON ' need access to game buttons
SHARED Ship AS SHIP ' need access to player ship
'+---------------------------------+
'| Check for forward ship movement |
'+---------------------------------+
IF _KEYDOWN(Button.East.Key) THEN ' forward thrust button pressed? (right arrow key)
IF Button.West.Position = BUTTONUP THEN ' yes, is the reverse button pressed?
Button.East.Position = BUTTONDOWN ' no, latch forward button in down position
Ship.x = Ship.x + 5 ' move ship forward
IF Ship.x > Ship.MaxX THEN Ship.x = Ship.MaxX ' keep x within upper limit
END IF
ELSE ' no, forward thrust button is not pressed
Button.East.Position = BUTTONUP ' latch forward thrust button in up position
END IF
'+---------------------------------+
'| Check for reverse ship movement |
'+---------------------------------+
IF _KEYDOWN(Button.West.Key) THEN ' reverse button pressed? (left arrow key)
IF Button.East.Position = BUTTONUP THEN ' yes, is the forward thrust button pressed?
Button.West.Position = BUTTONDOWN ' no, latch reverse button in down position
Ship.x = Ship.x - 5 ' move ship backward
IF Ship.x < Ship.MinX THEN Ship.x = Ship.MinX ' keep x within lower limit
END IF
ELSE ' no, reverse button is not pressed
Button.West.Position = BUTTONUP ' latch reverse button in up position
END IF
'+--------------------------------+
'| Check for upward ship movement |
'+--------------------------------+
IF _KEYDOWN(Button.North.Key) THEN ' upward button pressed? (up arrow key)
IF Button.South.Position = BUTTONUP THEN ' yes, is the downward button pressed?
Button.North.Position = BUTTONDOWN ' no, latch upward button in down position
Ship.y = Ship.y - 5 ' move ship upward
IF Ship.y < Ship.MinY THEN Ship.y = Ship.MinY ' keep y within lower limit
END IF
ELSE ' no, upward button is not pressed
Button.North.Position = BUTTONUP ' latch upward button in up position
END IF
'+----------------------------------+
'| Check for downward ship movement |
'+----------------------------------+
IF _KEYDOWN(Button.South.Key) THEN ' downward button pressed? (down arrow key)
IF Button.North.Position = BUTTONUP THEN ' yes, is the upward button pressed?
Button.South.Position = BUTTONDOWN ' no, latch downward button in down position
Ship.y = Ship.y + 5 ' move ship downward
IF Ship.y > Ship.MaxY THEN Ship.y = Ship.MaxY ' keep y within upper limit
END IF
ELSE ' no, downward button is not pressed
Button.South.Position = BUTTONUP ' latch downward button in up position
END IF
'+------------------+
'| Draw player ship |
'+------------------+
LINE (Ship.x - 15, Ship.y - 10)-(Ship.x - 15, Ship.y + 10) ' draw triangular ship
LINE -(Ship.x + 15, Ship.y)
LINE -(Ship.x - 15, Ship.y - 10)
END SUB
' ____________________________________________________________________________________________________________________
'/ \
SUB ManageBullets () ' ManageBullets |
' ________________________________________________________________________________________________________________/
'/ \
'| Updates and draws all currently active bullets to the game screen. |
'\________________________________________________________________________________________________________________/
SHARED Bullet() AS BULLET ' need access to player bullet array
DIM Index AS INTEGER ' array index counter
'+------------------------------------------+
'| Scan the bullet array for active bullets |
'+------------------------------------------+
Index = -1 ' reset index counter value
DO ' begin array search loop
Index = Index + 1 ' increment array index counter
IF Bullet(Index).Active THEN ' is this bullet active?
'+------------------------------------------------------+
'| This bullet is active, update its location and speed |
'+------------------------------------------------------+
Bullet(Index).x = Bullet(Index).x + Bullet(Index).Speed ' yes, move bullet to the right
Bullet(Index).Speed = Bullet(Index).Speed * 1.05 ' increase speed slightly
'+-----------------------------------------------------+
'| Check to see if the bullet has left the game screen |
'+-----------------------------------------------------+
IF Bullet(Index).x >= _WIDTH(0) - 1 THEN ' has bullet left the game screen?
'+------------------------------------------------+
'| This bullet has left the screen, deactivate it |
'+------------------------------------------------+
Bullet(Index).Active = 0 ' yes, deactivate bullet
ELSE ' no, bullet still on game screen
'+----------------------------------------------+
'| This bullet is still on game screen, draw it |
'+----------------------------------------------+
CIRCLE (Bullet(Index).x, Bullet(Index).y), 5 ' draw the bullet
PAINT (Bullet(Index).x, Bullet(Index).y) ' paint the bullet
END IF
END IF
LOOP UNTIL Index = UBOUND(Bullet) ' leave when all indexes checked
END SUB
' ____________________________________________________________________________________________________________________
'/ \
SUB FireBullet (x AS INTEGER, y AS INTEGER) ' FireBullet |
' ________________________________________________________________________________________________________________/
'/ \
'| Initiates a bullet at the supplied coordinates |
'| |
'| x,y - the on screen coordinates where the bullet will materialize |
'\________________________________________________________________________________________________________________/
SHARED Bullet() AS BULLET ' need access to player bullet array
DIM Index AS INTEGER ' array index counter
'+-------------------------------------------------------+
'| Scan the bullet array for an index that is not active |
'+-------------------------------------------------------+
Index = -1 ' reset index counter
DO ' begin array search loop
Index = Index + 1 ' increment array index counter
LOOP UNTIL Index = UBOUND(Bullet) OR Bullet(Index).Active = 0 ' leave when inactive found or at end of array
'+------------------------------------------------------------------------------+
'| Test if the index value from the search loop yielded an inactive array index |
'+------------------------------------------------------------------------------+
IF Bullet(Index).Active THEN ' was an inactive array index found?
'+------------------------------------------------------------------------------------------------------+
'| No inactive bullets were found in the array so the array size will need to be increased by one. The |
'| maximum size of the array will eventually be determined by the speed of the player's button presses. |
'+------------------------------------------------------------------------------------------------------+
Index = Index + 1 ' no, increase the array index size
REDIM _PRESERVE Bullet(Index) AS BULLET ' resize the array while preserving exisiting data
END IF
'+---------------------------------------------------+
'| Add the new bullet's information the bullet array |
'+---------------------------------------------------+
Bullet(Index).x = x ' new bullet's x coordinate
Bullet(Index).y = y ' new bullet's y coordinate
Bullet(Index).Speed = 5 ' new bullet's initial speed
Bullet(Index).Active = 1 ' this array index is active
SOUND 880, .5 ' awesome bullet sound
END SUB