02-02-2025, 03:41 PM
Someone on the Discord forum suggested I share this ChatGPT o3-generated Asteroids clone on this thread. Arrow keys to move, space to fire, B to halt ship.
Code: (Select All)
'--------------------------------------------
' Asteroids Clone in QB64 Phoenix Edition
'--------------------------------------------
' === CONSTANTS AND GLOBAL DECLARATIONS ===
CONST SCREENSIZEX = 352 ' 352 pixels wide
CONST SCREENSIZEY = 256 ' 256 pixels tall
CONST MAX_SPEED = 5 ' Maximum speed for the spaceship
COMMON SHARED viewSizeX, viewSizeY
' --- Game Settings ---
CONST MAX_ASTEROIDS = 5 ' Number of asteroids
' --- Asteroid Variables (arrays are global and sized on declaration) ---
DIM SHARED astX(1 TO MAX_ASTEROIDS), astY(1 TO MAX_ASTEROIDS)
DIM SHARED astDX(1 TO MAX_ASTEROIDS), astDY(1 TO MAX_ASTEROIDS)
' --- Spaceship Variables ---
COMMON SHARED shipX, shipY ' Position of the spaceship
COMMON SHARED shipAngle ' Facing direction (in degrees)
COMMON SHARED shipSpeed ' Current speed
' --- Bullet Variables ---
COMMON SHARED bulletActive ' 0 = no bullet active, 1 = bullet is active
COMMON SHARED bulletX, bulletY ' Bullet position
COMMON SHARED bulletDX, bulletDY ' Bullet velocity
'============================================
' SET UP SCREEN AND INITIAL GAME VARIABLES
'============================================
'_FULLSCREEN
SCREEN _NEWIMAGE(SCREENSIZEX, SCREENSIZEY, 13) ' Third argument MUST be 13
_FONT 8 ' Ensures the font is 8x8 (QB64-specific)
' Set play area (for example, if you want to use ASCII coordinate notions)
viewSizeX = 32
viewSizeY = 24
' Initialize spaceship in the center of the screen.
shipX = SCREENSIZEX / 2
shipY = SCREENSIZEY / 2
shipAngle = 0 ' Facing right (0 degrees)
shipSpeed = 0
' Bullet is initially inactive.
bulletActive = 0
' Randomize and initialize asteroid positions and velocities.
RANDOMIZE TIMER
FOR ii = 1 TO MAX_ASTEROIDS
astX(ii) = RND * SCREENSIZEX
astY(ii) = RND * SCREENSIZEY
' Give each asteroid a random velocity between -1 and 1 (pixels per frame)
astDX(ii) = (RND * 2 - 1)
astDY(ii) = (RND * 2 - 1)
NEXT ii
'============================================
' MAIN GAME LOOP
'============================================
DO
' --- Handle Input ---
' Rotate spaceship left: key 4 (keycode 52 or alternate 19200)
IF _KEYDOWN(52) OR _KEYDOWN(19200) THEN
shipAngle = shipAngle - 5
END IF
' Rotate spaceship right: key 6 (keycode 54 or alternate 19712)
IF _KEYDOWN(54) OR _KEYDOWN(19712) THEN
shipAngle = shipAngle + 5
END IF
' Accelerate forward: use key 8 (keycode 56 or alternate 18432) as “up”
IF _KEYDOWN(56) OR _KEYDOWN(18432) THEN
shipSpeed = shipSpeed + 0.1
END IF
' Decelerate / Brake: use key 2 (keycode 50 or alternate 20480) as “down”
IF _KEYDOWN(50) OR _KEYDOWN(20480) THEN
shipSpeed = shipSpeed - 0.1
IF shipSpeed < 0 THEN shipSpeed = 0
END IF
' Halt momentum: B key (keycode 66 or alternate 98) sets speed to 0.
IF _KEYDOWN(66) OR _KEYDOWN(98) THEN
shipSpeed = 0
END IF
' Enforce maximum speed limit.
IF shipSpeed > MAX_SPEED THEN shipSpeed = MAX_SPEED
' Fire Bullet: space bar (keycode 32)
IF _KEYDOWN(32) THEN
IF bulletActive = 0 THEN
bulletActive = 1
bulletX = shipX
bulletY = shipY
' Set bullet velocity in the direction the ship is facing.
bulletDX = COS(shipAngle * 3.14159 / 180) * 4
bulletDY = SIN(shipAngle * 3.14159 / 180) * 4
END IF
END IF
' --- Update Game Objects ---
' Update spaceship position (using its current speed and angle)
shipX = shipX + COS(shipAngle * 3.14159 / 180) * shipSpeed
shipY = shipY + SIN(shipAngle * 3.14159 / 180) * shipSpeed
' Screen wrapping for spaceship:
IF shipX < 0 THEN shipX = SCREENSIZEX
IF shipX > SCREENSIZEX THEN shipX = 0
IF shipY < 0 THEN shipY = SCREENSIZEY
IF shipY > SCREENSIZEY THEN shipY = 0
' Update bullet if active:
IF bulletActive = 1 THEN
bulletX = bulletX + bulletDX
bulletY = bulletY + bulletDY
' If bullet goes off screen, deactivate it.
IF bulletX < 0 OR bulletX > SCREENSIZEX OR bulletY < 0 OR bulletY > SCREENSIZEY THEN
bulletActive = 0
END IF
END IF
' Update asteroids:
FOR ii = 1 TO MAX_ASTEROIDS
astX(ii) = astX(ii) + astDX(ii)
astY(ii) = astY(ii) + astDY(ii)
' Wrap asteroids around the screen.
IF astX(ii) < 0 THEN astX(ii) = SCREENSIZEX
IF astX(ii) > SCREENSIZEX THEN astX(ii) = 0
IF astY(ii) < 0 THEN astY(ii) = SCREENSIZEY
IF astY(ii) > SCREENSIZEY THEN astY(ii) = 0
NEXT ii
' --- Collision Detection ---
' Check collisions between bullet and asteroids.
IF bulletActive = 1 THEN
FOR ii = 1 TO MAX_ASTEROIDS
' Using 2 as bullet radius and 12 as asteroid radius.
IF isCollision(bulletX, bulletY, 2, astX(ii), astY(ii), 12) THEN
' On collision, reset the asteroid and deactivate the bullet.
astX(ii) = RND * SCREENSIZEX
astY(ii) = RND * SCREENSIZEY
bulletActive = 0
EXIT FOR
END IF
NEXT ii
END IF
' Check collisions between spaceship and asteroids.
' Here, we use an approximate collision radius of 10 for the spaceship.
FOR ii = 1 TO MAX_ASTEROIDS
IF isCollision(shipX, shipY, 10, astX(ii), astY(ii), 12) THEN
CALL ESCAPETEXT("GAME OVER")
END IF
NEXT ii
' --- Draw Everything ---
CLS ' Clear the screen
' Draw the spaceship as a triangle.
' Calculate the three vertices based on shipX, shipY and shipAngle.
shipTipX = shipX + COS(shipAngle * 3.14159 / 180) * 10
shipTipY = shipY + SIN(shipAngle * 3.14159 / 180) * 10
shipLeftX = shipX + COS((shipAngle + 140) * 3.14159 / 180) * 8
shipLeftY = shipY + SIN((shipAngle + 140) * 3.14159 / 180) * 8
shipRightX = shipX + COS((shipAngle - 140) * 3.14159 / 180) * 8
shipRightY = shipY + SIN((shipAngle - 140) * 3.14159 / 180) * 8
LINE (shipLeftX, shipLeftY)-(shipTipX, shipTipY), 15
LINE (shipTipX, shipTipY)-(shipRightX, shipRightY), 15
LINE (shipRightX, shipRightY)-(shipLeftX, shipLeftY), 15
' Draw bullet if it is active.
IF bulletActive = 1 THEN
CIRCLE (bulletX, bulletY), 2, 15
END IF
' Draw each asteroid as a circle.
FOR ii = 1 TO MAX_ASTEROIDS
CIRCLE (astX(ii), astY(ii)), 12, 15
NEXT ii
_DISPLAY ' Refresh the graphics screen
' --- Exit Check ---
IF _KEYDOWN(27) THEN CALL ESCAPE(0) ' Exit if ESC is pressed
_LIMIT 30 ' Limit frame rate to 30 FPS
LOOP
'============================================
' COLLISION DETECTION FUNCTION
'============================================
FUNCTION isCollision (obj1X, obj1Y, r1, obj2X, obj2Y, r2)
DIM dx, dy, distanceSquared, rSumSquared
dx = obj1X - obj2X
dy = obj1Y - obj2Y
distanceSquared = dx * dx + dy * dy
rSumSquared = (r1 + r2) * (r1 + r2)
IF distanceSquared <= rSumSquared THEN
isCollision = 1
ELSE
isCollision = 0
END IF
END FUNCTION
'============================================
' EXAMPLE FUNCTION (for reference)
'============================================
FUNCTION moveCheck (wPosX, wPosY)
' A dummy function to illustrate function returns.
moveCheck = 1
END FUNCTION
'============================================
' HELPER SUBROUTINES (NEVER MODIFY THESE)
'============================================
SUB ZLOCATE (wx, wy)
' Adjusts LOCATE since QB64’s LOCATE starts at row 1.
LOCATE wy + 1, wx + 1
END SUB
SUB ESCAPE (code)
' Display an exit message with the given code and end the program.
COLOR 15
ZLOCATE 10, 5: PRINT " "
ZLOCATE 10, 6: PRINT "ENDED WITH CODE:"; code; " "
ZLOCATE 10, 7: PRINT " "
END
END SUB
SUB ESCAPETEXT (wStr$)
' Display an exit message (for example, GAME OVER) and end the program.
COLOR 15
xPos = 1
yPos = 5
IF wStr$ = "" THEN wStr$ = "No text sent"
ZLOCATE xPos, yPos: PRINT " "
ZLOCATE xPos, yPos + 2: PRINT " " ' Clear line before text in case of wrap
ZLOCATE xPos, yPos + 1: PRINT " "; wStr$; " "
END
END SUB

