├── .gitignore ├── README.md ├── assets ├── 1-up.ogg ├── ambience.ogg ├── bossgalagadefeat.ogg ├── bossgalagahit.ogg ├── bossgalagatractorbeam.ogg ├── captured fighter destroyed.ogg ├── challenging stage over.ogg ├── challenging stage perfect.ogg ├── challenging stage.ogg ├── coin_credit.ogg ├── die.ogg ├── fighter captured.ogg ├── fighter rescued.ogg ├── fightershoot.ogg ├── galaga.ico ├── galagaattack.ogg ├── galagadefeat1.ogg ├── galagadefeat2.ogg ├── name entry 1.ogg ├── name entry 2+.ogg ├── nextlevel.ogg ├── sprites.png ├── stage intro.ogg ├── stars border.png ├── stars1.png ├── stars2.png ├── stars3.png ├── stars4.png ├── text.png └── tractorbeamcaught.ogg ├── galaga.bas └── resources ├── 26482.png ├── Galaga.png ├── Galaga_marquee.png ├── galaga.avi ├── galaga.ico ├── galaga0[1].wav ├── galaga1[1].wav ├── galaga2[1].wav ├── galaga3[1].wav ├── galaga4[2].wav ├── galaga5[1].wav ├── galaga6[1].wav ├── galaga7[1].wav ├── galaga8[2].wav ├── galaga9[1].wav ├── galaga_marquee_small.png └── screencap.gif /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.exe 3 | scores.txt 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GALAGA 2 | ## Programmed by RokCoder 3 | 4 | Galaga is a 1981 fixed shooter arcade video game developed and published by Namco \ 5 | This version is a tribute to the original programmed using QB64PE 6 | 7 | ### V0.1 - 4th Feb 2023 - First shared version 8 | 9 | --- 10 | 11 | https://www.rokcoder.com \ 12 | https://www.github.com/rokcoder \ 13 | https://www.facebook.com/rokcoder \ 14 | https://www.youtube.com/rokcoder 15 | 16 | --- 17 | 18 | ### TODO 19 | Challenge wave styles 5 to 8 (once I can find a video of them being played without destroying the aliens so I can mimic the paths) \ 20 | Transforms (scorpions, spy ships and flag ships) not yet implemented 21 | -------------------------------------------------------------------------------- /assets/1-up.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/1-up.ogg -------------------------------------------------------------------------------- /assets/ambience.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/ambience.ogg -------------------------------------------------------------------------------- /assets/bossgalagadefeat.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/bossgalagadefeat.ogg -------------------------------------------------------------------------------- /assets/bossgalagahit.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/bossgalagahit.ogg -------------------------------------------------------------------------------- /assets/bossgalagatractorbeam.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/bossgalagatractorbeam.ogg -------------------------------------------------------------------------------- /assets/captured fighter destroyed.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/captured fighter destroyed.ogg -------------------------------------------------------------------------------- /assets/challenging stage over.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/challenging stage over.ogg -------------------------------------------------------------------------------- /assets/challenging stage perfect.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/challenging stage perfect.ogg -------------------------------------------------------------------------------- /assets/challenging stage.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/challenging stage.ogg -------------------------------------------------------------------------------- /assets/coin_credit.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/coin_credit.ogg -------------------------------------------------------------------------------- /assets/die.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/die.ogg -------------------------------------------------------------------------------- /assets/fighter captured.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/fighter captured.ogg -------------------------------------------------------------------------------- /assets/fighter rescued.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/fighter rescued.ogg -------------------------------------------------------------------------------- /assets/fightershoot.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/fightershoot.ogg -------------------------------------------------------------------------------- /assets/galaga.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/galaga.ico -------------------------------------------------------------------------------- /assets/galagaattack.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/galagaattack.ogg -------------------------------------------------------------------------------- /assets/galagadefeat1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/galagadefeat1.ogg -------------------------------------------------------------------------------- /assets/galagadefeat2.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/galagadefeat2.ogg -------------------------------------------------------------------------------- /assets/name entry 1.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/name entry 1.ogg -------------------------------------------------------------------------------- /assets/name entry 2+.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/name entry 2+.ogg -------------------------------------------------------------------------------- /assets/nextlevel.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/nextlevel.ogg -------------------------------------------------------------------------------- /assets/sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/sprites.png -------------------------------------------------------------------------------- /assets/stage intro.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/stage intro.ogg -------------------------------------------------------------------------------- /assets/stars border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/stars border.png -------------------------------------------------------------------------------- /assets/stars1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/stars1.png -------------------------------------------------------------------------------- /assets/stars2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/stars2.png -------------------------------------------------------------------------------- /assets/stars3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/stars3.png -------------------------------------------------------------------------------- /assets/stars4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/stars4.png -------------------------------------------------------------------------------- /assets/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/text.png -------------------------------------------------------------------------------- /assets/tractorbeamcaught.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/assets/tractorbeamcaught.ogg -------------------------------------------------------------------------------- /galaga.bas: -------------------------------------------------------------------------------- 1 | '====================================================================================================================================================================================================== 2 | ' GALAGA 3 | '------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 4 | ' Programmed by RokCoder 5 | '------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 6 | ' Galaga is a 1981 fixed shooter arcade video game developed and published by Namco 7 | ' This version is a tribute to the original programmed using QB64PE 8 | '------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 9 | ' V0.1 - 4th Feb 2023 - First shared version 10 | '------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 11 | ' https://github.com/rokcoder-qb64/galaga 12 | '------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 13 | ' https://www.rokcoder.com 14 | ' https://www.github.com/rokcoder 15 | ' https://www.facebook.com/rokcoder 16 | ' https://www.youtube.com/rokcoder 17 | '====================================================================================================================================================================================================== 18 | ' TODO 19 | ' Challenge wave styles 5 to 8 (once I can find a video of them being played without destroying the aliens so I can mimic the paths) 20 | ' Transforms (scorpions, spy ships and flag ships) not yet implemented 21 | ' 22 | ' BUGS 23 | ' Dying just before challenge stage resulted in READY and CHALLENGE STAGE overwriting each other 24 | '====================================================================================================================================================================================================== 25 | 26 | $VERSIONINFO:CompanyName=RokSoft 27 | $VERSIONINFO:FileDescription=QB64 Galaga 28 | $VERSIONINFO:InternalName=galaga.exe 29 | $VERSIONINFO:ProductName=QB64 Galaga 30 | $VERSIONINFO:OriginalFilename=galaga.exe 31 | $VERSIONINFO:LegalCopyright=(c)2023 RokSoft 32 | $VERSIONINFO:FILEVERSION#=0,1,0,0 33 | $VERSIONINFO:PRODUCTVERSION#=0,1,0,0 34 | $EXEICON:'./assets/galaga.ico' 35 | 36 | '====================================================================================================================================================================================================== 37 | 38 | OPTION _EXPLICIT 39 | OPTION _EXPLICITARRAY 40 | 41 | '===== General constants ============================================================================================================================================================================== 42 | 43 | CONST FALSE = 0 44 | CONST TRUE = NOT FALSE 45 | CONST MAX_ATTACKING_FORMATIONS = 10 46 | CONST MAX_ALIENS = 80 47 | CONST NUM_CHALLENGE_PATHS = 4 48 | CONST MAX_SPAWNS = 20 49 | CONST MAX_BULLETS_PER_SHIP = 2 50 | CONST MAX_BULLETS = MAX_BULLETS_PER_SHIP * 2 51 | CONST TEXTCHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -%.!c" 52 | CONST MAX_NAME_LEN = 14 53 | 54 | '===== Sound effect IDs =============================================================================================================================================================================== 55 | 56 | CONST SFX_BOSS_GALAGA_TRACTOR_BEAM = 0 57 | CONST SFX_TRACTOR_BEAM_CAUGHT = 1 58 | CONST SFX_AMBIENCE = 2 59 | CONST SFX_GALAGA_ATTACK = 3 60 | CONST SFX_FIGHTER_SHOOT = 4 61 | CONST SFX_STAGE_INTRO = 5 62 | CONST SFX_GALAGA_DEFEAT_1 = 6 63 | CONST SFX_GALAGA_DEFEAT_2 = 7 64 | CONST SFX_BOSS_GALAGA_DEFEAT = 8 65 | CONST SFX_BOSS_GALAGA_HIT = 9 66 | CONST SFX_CAPTURED_FIGHTER_DESTROYED = 10 67 | CONST SFX_FIGHTER_CAPTURED = 11 68 | CONST SFX_1_UP = 12 69 | CONST SFX_FIGHTER_RESCUED = 13 70 | CONST SFX_DIE = 14 71 | CONST SFX_NEXT_LEVEL = 15 72 | CONST SFX_CHALLENGING_STAGE = 16 73 | CONST SFX_CHALLENGING_STAGE_OVER = 17 74 | CONST SFX_CHALLENGING_STAGE_PERFECT = 18 75 | CONST SFX_NAME_ENTRY_1 = 19 76 | CONST SFX_NAME_ENTRY_NOT_1 = 20 77 | CONST SFX_COIN_CREDIT = 21 78 | 79 | '===== Game controls (Left arrow, right arrow and space bar) ========================================================================================================================================== 80 | 81 | CONST KEYDOWN_LEFT = 19200 82 | CONST KEYDOWN_RIGHT = 19712 83 | CONST KEYDOWN_FIRE = 32 84 | 85 | '===== Sprite IDs ===================================================================================================================================================================================== 86 | 87 | CONST SPRITE_PLAYER = 0 88 | CONST SPRITE_PLAYER_CAPTURED = 1 89 | CONST SPRITE_BOSS_GALAGA = 2 90 | CONST SPRITE_BOSS_GALAGA_HIT = 3 91 | CONST SPRITE_BUTTERFLY = 4 92 | CONST SPRITE_BEE = 5 93 | CONST SPRITE_FLAGSHIP = 6 94 | CONST SPRITE_SCORPION = 7 95 | CONST SPRITE_SPY_SHIP = 8 96 | CONST SPRITE_DRAGONFLY = 9 97 | CONST SPRITE_SATELLITE = 10 98 | CONST SPRITE_ENTERPRISE = 11 99 | CONST SPRITE_BEAM = 12 100 | CONST SPRITE_BULLET = 13 101 | CONST SPRITE_PLAYER_LIVES = 14 102 | CONST SPRITE_PLAYER_EXPLOSION = 15 103 | CONST SPRITE_ALIEN_EXPLOSION = 16 104 | CONST SPRITE_TEXT_WHITE = 17 105 | CONST SPRITE_TEXT_RED = 18 106 | CONST SPRITE_TEXT_BLUE = 19 107 | CONST SPRITE_TEXT_YELLOW = 20 108 | CONST SPRITE_FLAG = 21 109 | CONST SPRITE_BOMB = 22 110 | CONST SPRITE_SCORES = 23 111 | 112 | '===== Text colour IDs ================================================================================================================================================================================ 113 | 114 | CONST COLOUR_WHITE = 0 115 | CONST COLOUR_RED = 1 116 | CONST COLOUR_BLUE = 2 117 | CONST COLOUR_YELLOW = 3 118 | 119 | '===== Alien type IDs ================================================================================================================================================================================= 120 | 121 | CONST TYPE_NONE = -1 122 | CONST TYPE_BOSS_GALAGA = 0 123 | CONST TYPE_BOSS_GALAGA_SHOT = 1 124 | CONST TYPE_BUTTERFLY = 2 125 | CONST TYPE_BEE = 3 126 | CONST TYPE_PLAYER_CAPTURED = 4 127 | CONST TYPE_PLAYER = 5 128 | CONST TYPE_DRAGONFLY = 6 129 | CONST TYPE_SCORPION = 7 130 | 131 | '===== Paths to control alien flight - each path contains a list of commands ========================================================================================================================== 132 | 133 | CONST PT_NONE = 0 134 | CONST PT_NEW_WAVE_FROM_TOP = 1 135 | CONST PT_NEW_WAVE_FROM_SIDE = 2 136 | CONST PT_UP_AND_DIVE_WITH_BOSS = 3 137 | CONST PT_BUTTERFLY_PATH = 4 138 | CONST PT_BEE_PATH = 5 139 | CONST PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD = 6 140 | CONST PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER = 7 141 | CONST PT_NEW_AGGRESSIVE_WAVE_FROM_TOP = 8 142 | CONST PT_NEW_AGGRESSIVE_WAVE_FROM_OUTER_TOP = 9 143 | CONST PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE = 10 144 | CONST PT_NEW_AGGRESSIVE_WAVE_FROM_HIGHER_SIDE = 11 145 | CONST PT_UP_AND_DIVE_TO_CAPTURE = 12 146 | CONST PT_RETURN_WITH_CAPTURED = 13 147 | CONST PT_WAIT_FOR_CAPTURE = 14 148 | CONST PT_TAKE_HOSTAGE_POSITION = 15 149 | CONST PT_RESCUED_PLAYER = 16 150 | CONST PT_PLAYER_SWOOP = 17 151 | CONST PT_CHALLENGE1A = 18 152 | CONST PT_CHALLENGE1B = 19 153 | CONST PT_CHALLENGE2A = 20 154 | CONST PT_CHALLENGE2B = 21 155 | CONST PT_CHALLENGE3A = 22 156 | CONST PT_CHALLENGE3B = 23 157 | CONST PT_CHALLENGE3C = 24 158 | CONST PT_CHALLENGE4A = 25 159 | CONST PT_CHALLENGE4B = 26 160 | CONST PT_CHALLENGE4C = 27 161 | CONST PT_WAITING = 28 162 | CONST PT_INACTIVE = 29 163 | 164 | '===== Commands to control alien actions ============================================================================================================================================================== 165 | 166 | CONST CMD_NONE = 0 167 | CONST CMD_SET_POSITION = 1 168 | CONST CMD_MOVEMENT = 2 169 | CONST CMD_JOIN_FORMATION = 3 170 | CONST CMD_LEAVE_FORMATION = 4 171 | CONST CMD_MOVE_ABOVE_FORMATION = 5 172 | CONST CMD_CONTINUE_FLIGHT = 6 173 | CONST CMD_TO_HEIGHT = 7 174 | CONST CMD_BEE_RETURN = 8 175 | CONST CMD_SPEED = 9 176 | CONST CMD_DIVE_AT_PLAYER = 10 177 | CONST CMD_REMOVE = 11 178 | CONST CMD_DIVE_TO_BEAM = 12 179 | CONST CMD_WAIT_FOR_CAPTURE = 13 180 | CONST CMD_TAKE_HOSTAGE_POSITION = 14 181 | CONST CMD_DOUBLE_UP_PLAYER = 16 182 | CONST CMD_PLAYER_IN_STORAGE = 17 183 | CONST CMD_HOLD_FORMATION = 18 184 | CONST CMD_FIRE_BEAM = 19 185 | CONST CMD_PAUSE_ATTACK = 20 186 | CONST CMD_INACTIVE = 21 187 | CONST CMD_DEAD = 22 188 | CONST CMD_DESTROYED = 23 189 | 190 | '===== States for the various systems in the game ===================================================================================================================================================== 191 | 192 | CONST SHIP_EXPLODING = 0 193 | CONST SHIP_ACTIVE = 1 194 | CONST SHIP_INACTIVE = 2 195 | 196 | CONST PLAYER_INACTIVE = 0 197 | CONST PLAYER_SPAWNING = 1 198 | CONST PLAYER_DOUBLING_UP = 2 199 | CONST PLAYER_WAITING_TO_DOUBLE = 3 200 | CONST PLAYER_CAPTURING = 4 201 | CONST PLAYER_ACTIVE = 5 202 | 203 | CONST SPAWN_NONE = 0 204 | CONST SPAWN_EXPLOSION = 1 205 | CONST SPAWN_SCORE = 2 206 | 207 | CONST BULLET_NONE = 0 208 | CONST BULLET_ACTIVE = 1 209 | CONST BULLET_REMOVING = 2 210 | 211 | CONST FE_SHOW_SCORES = 0 212 | CONST FE_WAIT_START_PRESS = 1 213 | CONST FE_PAUSE_BEFORE_OVER = 2 214 | 215 | CONST BE_STATS = 0 216 | CONST BE_POST_STATS_PAUSE = 1 217 | CONST BE_ENTER_NAME = 2 218 | 219 | CONST WS_WAIT_FOR_ATTACK = 0 220 | CONST WS_PREPARE_BATCH = 1 221 | CONST WS_BRING_ON_BATCH = 2 222 | CONST WS_PLAY_STAGE = 3 223 | CONST WS_CHALLENGE_RESULTS = 4 224 | CONST WS_POST_STAGE = 5 225 | CONST WS_INITIALISE_WAVE = 6 226 | CONST WS_PAUSE = 7 227 | CONST WS_INITIALISE_PLAY = 8 228 | CONST WE_SHOW_PRE_GAME_OVERLAYS = 9 229 | 230 | '===== Game flow is controlled via event lists ======================================================================================================================================================== 231 | 232 | CONST EVENT_UPDATE_STARS = 0 233 | CONST EVENT_UPDATE_FRONT_END = 1 234 | CONST EVENT_RENDER_FRONT_END = 2 235 | CONST EVENT_UPDATE_ALIEN_MANAGER = 3 236 | CONST EVENT_UPDATE_PLAYER = 4 237 | CONST EVENT_UPDATE_BULLETS = 5 238 | CONST EVENT_UPDATE_ALIENS = 6 239 | CONST EVENT_RENDER_SCENE = 7 240 | CONST EVENT_PROCESS_FLAGS = 8 241 | CONST EVENT_UPDATE_BOMBS = 9 242 | CONST EVENT_RENDER_BACK_END = 10 243 | CONST EVENT_UPDATE_BACK_END = 11 244 | 245 | '====================================================================================================================================================================================================== 246 | 247 | TYPE EVENT 248 | event AS INTEGER 249 | initialised AS INTEGER 250 | END TYPE 251 | 252 | TYPE FRONTEND 253 | state AS INTEGER 254 | keyPressTarget AS INTEGER 255 | active AS INTEGER 256 | pauseCounter AS INTEGER 257 | END TYPE 258 | 259 | TYPE BACKEND 260 | state AS INTEGER 261 | pause AS INTEGER 262 | name AS STRING 263 | score AS STRING 264 | cursorX AS INTEGER 265 | cursor AS INTEGER 266 | substate AS INTEGER 267 | pos AS INTEGER 268 | timer AS INTEGER 269 | END TYPE 270 | 271 | TYPE FLAG 272 | flag AS INTEGER 273 | xpos AS INTEGER 274 | END TYPE 275 | 276 | TYPE SFX 277 | handle AS LONG 278 | oneShot AS INTEGER 279 | looping AS INTEGER 280 | END TYPE 281 | 282 | TYPE SPRITEDATA 283 | offset AS INTEGER 284 | num AS INTEGER 285 | END TYPE 286 | 287 | TYPE WAVEDATA 288 | section AS INTEGER 289 | state AS INTEGER 290 | aliensAttackingPauseCounter AS INTEGER 291 | aliensCanAttack AS INTEGER 292 | batchCounter AS INTEGER 293 | aliensArrived AS INTEGER 294 | aliensInFormation AS INTEGER 295 | postArrivalPause AS INTEGER 296 | formationCentreX AS INTEGER 297 | formationCentreY AS INTEGER 298 | formationDirection AS SINGLE 299 | challengingStage AS INTEGER 300 | simultaneousAttackCount AS INTEGER 301 | continuousDiverCount AS INTEGER 302 | bombAvailability AS INTEGER 303 | continuousAttack AS INTEGER 304 | hitCount AS INTEGER 305 | formationSpread AS SINGLE 306 | stageClear AS INTEGER 307 | hasCaptive AS INTEGER 308 | postPauseState AS INTEGER 309 | pauseCounter AS INTEGER 310 | substate AS INTEGER 311 | bombCount AS INTEGER 312 | playerInStorage AS INTEGER 313 | END TYPE 314 | 315 | TYPE ALIENDATA 316 | controlPath AS INTEGER 317 | xPos AS SINGLE 318 | yPos AS SINGLE 319 | direction AS INTEGER 320 | rotation AS SINGLE 321 | formationXOffset AS SINGLE 322 | formationYOffset AS SINGLE 323 | alienType AS INTEGER 324 | pathDelay AS INTEGER 325 | pathIndex AS INTEGER 326 | currentAction AS INTEGER 327 | fetchNewAction AS INTEGER 328 | bombCount AS INTEGER 329 | steps AS INTEGER 330 | deltaMove AS SINGLE 331 | deltaTurn AS SINGLE 332 | targetHeight AS INTEGER 333 | continualPath AS INTEGER 334 | attackGroup AS INTEGER 335 | pauseCounter AS INTEGER 336 | isCaptor AS INTEGER 337 | isCaptive AS INTEGER 338 | beamActive AS INTEGER 339 | captureCounter AS INTEGER 340 | explosionCounter AS INTEGER 341 | targetX AS SINGLE 342 | targetY AS SINGLE 343 | costume AS INTEGER 344 | doubleUpCounter AS INTEGER 345 | scoreCostume AS INTEGER 346 | batchNum AS INTEGER 347 | END TYPE 348 | 349 | TYPE PLAYER 350 | doubleShip AS INTEGER 351 | canFire AS INTEGER 352 | xPos AS INTEGER 353 | yPos AS INTEGER 354 | lives AS INTEGER 355 | fireKeyDown AS INTEGER 356 | state AS INTEGER 357 | END TYPE 358 | 359 | TYPE SHIP 360 | isHit AS INTEGER 361 | xPos AS INTEGER 362 | state AS INTEGER 363 | counter AS INTEGER 364 | END TYPE 365 | 366 | TYPE SPAWNED_ANIMATION 367 | spawnType AS INTEGER 368 | counter AS INTEGER 369 | xPos AS INTEGER 370 | yPos AS INTEGER 371 | value AS INTEGER 372 | END TYPE 373 | 374 | TYPE GAME 375 | frameCounter AS LONG 376 | stage AS INTEGER 377 | score AS LONG 378 | fps AS INTEGER 379 | extraLife AS LONG 380 | gameOver AS INTEGER 381 | hiscore AS LONG 382 | gameOverCounter AS INTEGER 383 | END TYPE 384 | 385 | TYPE BULLET 386 | xPos AS INTEGER 387 | yPos AS INTEGER 388 | state AS INTEGER 389 | waitToRemoveCounter AS INTEGER 390 | END TYPE 391 | 392 | TYPE BOMB 393 | xPos AS SINGLE 394 | yPos AS SINGLE 395 | deltaX AS SINGLE 396 | deltaY AS SINGLE 397 | END TYPE 398 | 399 | TYPE STARS 400 | overlay AS LONG 401 | yPos AS INTEGER 402 | scroll AS INTEGER 403 | END TYPE 404 | 405 | TYPE HISCORE 406 | score AS LONG 407 | name AS STRING 408 | END TYPE 409 | 410 | TYPE STATS 411 | bulletCount AS INTEGER 412 | bulletMissCount AS INTEGER 413 | END TYPE 414 | 415 | TYPE TEXT 416 | text AS STRING 417 | x AS INTEGER 418 | y AS INTEGER 419 | colour AS INTEGER 420 | END TYPE 421 | 422 | '====================================================================================================================================================================================================== 423 | 424 | DIM SHARED eventIndex% 425 | DIM SHARED virtualScreen& 426 | DIM SHARED spriteLoadOffset% 427 | DIM SHARED pathDataIndex% 428 | DIM SHARED initialiseAlienIndex% 429 | DIM SHARED textOffset% 430 | 431 | DIM SHARED frontend AS FRONTEND 432 | DIM SHARED backend AS BACKEND 433 | DIM SHARED waveData AS WAVEDATA 434 | DIM SHARED player AS PLAYER 435 | DIM SHARED game AS GAME 436 | DIM SHARED stars AS STARS 437 | DIM SHARED stats AS STATS 438 | 439 | DIM SHARED numberInAttackingFormation%(MAX_ATTACKING_FORMATIONS) 440 | DIM SHARED textColour%(4) 441 | DIM SHARED spriteHandle&(300) 442 | DIM SHARED bossScores%(4) 443 | DIM SHARED pathDataOffset%(100) 444 | DIM SHARED pathData!(1000) 445 | DIM SHARED starFrames&(4) 446 | 447 | DIM SHARED bullet(MAX_BULLETS) AS BULLET 448 | DIM SHARED spawnedAnimation(MAX_SPAWNS) AS SPAWNED_ANIMATION 449 | DIM SHARED alienData(MAX_ALIENS) AS ALIENDATA 450 | DIM SHARED sfx(25) AS SFX 451 | DIM SHARED spriteData(60) AS SPRITEDATA 452 | DIM SHARED ship(2) AS SHIP 453 | DIM SHARED hiscore(5) AS HISCORE 454 | DIM SHARED text(50) AS TEXT 455 | 456 | REDIM SHARED events(0) AS EVENT 457 | REDIM SHARED flagDisplay(0) AS FLAG 458 | REDIM SHARED bomb(0) AS BOMB 459 | 460 | '===== Game loop ====================================================================================================================================================================================== 461 | 462 | PrepareGalaga 463 | PrepareFrontendEvents 464 | DO: _LIMIT (game.fps%): ProcessEvents: LOOP 465 | 466 | '===== Error handlers ================================================================================================================================================================================= 467 | 468 | fileReadError: 469 | InitialiseHiscores 470 | RESUME NEXT 471 | 472 | fileWriteError: 473 | ON ERROR GOTO 0 474 | RESUME NEXT 475 | 476 | '===== Event system =================================================================================================================================================================================== 477 | 478 | SUB ResetEvents 479 | REDIM events(0) AS EVENT 480 | eventIndex% = -1 481 | END SUB 482 | 483 | SUB AddEvent (e%) 484 | DIM i% 485 | FOR i% = 0 TO UBOUND(events) - 1 486 | IF events(i%).event% = e% THEN EXIT SUB 487 | NEXT i% 488 | events(UBOUND(events)).event% = e% 489 | events(UBOUND(events)).initialised% = FALSE 490 | REDIM _PRESERVE events(UBOUND(events) + 1) AS EVENT 491 | END SUB 492 | 493 | SUB RemoveEvent (e%) 494 | DIM i%, j% 495 | FOR i% = 0 TO UBOUND(events) - 1 496 | IF events(i%).event% = e% THEN 497 | j% = i% 498 | FOR j% = i% TO UBOUND(events) - 2: events(j%) = events(j% + 1): NEXT j% 499 | REDIM _PRESERVE events(UBOUND(events) - 1) AS EVENT 500 | IF eventIndex% >= i% THEN eventIndex% = eventIndex% - 1 501 | EXIT SUB 502 | END IF 503 | NEXT i% 504 | END SUB 505 | 506 | SUB ProcessEvents 507 | eventIndex% = 0 508 | WHILE eventIndex% < UBOUND(events) 509 | SELECT CASE events(eventIndex%).event 510 | CASE EVENT_UPDATE_STARS: UpdateStars events(eventIndex%).initialised% 511 | CASE EVENT_UPDATE_FRONT_END: UpdateFrontEnd events(eventIndex%).initialised% 512 | CASE EVENT_RENDER_FRONT_END: RenderFrontend events(eventIndex%).initialised% 513 | CASE EVENT_UPDATE_ALIEN_MANAGER: UpdateAlienManager events(eventIndex%).initialised% 514 | CASE EVENT_UPDATE_PLAYER: UpdatePlayer events(eventIndex%).initialised% 515 | CASE EVENT_UPDATE_BULLETS: UpdateBullets events(eventIndex%).initialised% 516 | CASE EVENT_UPDATE_ALIENS: UpdateAliens events(eventIndex%).initialised% 517 | CASE EVENT_RENDER_SCENE: RenderScene events(eventIndex%).initialised% 518 | CASE EVENT_PROCESS_FLAGS: ProcessFlags events(eventIndex%).initialised% 519 | CASE EVENT_UPDATE_BOMBS: UpdateBombs events(eventIndex%).initialised% 520 | CASE EVENT_UPDATE_BACK_END: UpdateBackEnd events(eventIndex%).initialised% 521 | CASE EVENT_RENDER_BACK_END: RenderBackend events(eventIndex%).initialised% 522 | END SELECT 523 | IF eventIndex% > -1 THEN events(eventIndex%).initialised% = TRUE 524 | eventIndex% = eventIndex% + 1 525 | WEND 526 | END SUB 527 | 528 | '===== Preparing the event system for the front-end, main game and back-end =========================================================================================================================== 529 | 530 | SUB PrepareFrontendEvents 531 | ResetEvents 532 | AddEvent EVENT_UPDATE_STARS 533 | AddEvent EVENT_UPDATE_FRONT_END 534 | AddEvent EVENT_RENDER_FRONT_END 535 | 536 | END SUB 537 | 538 | SUB PrepareGameEvents 539 | ResetEvents 540 | AddEvent EVENT_UPDATE_ALIEN_MANAGER 541 | AddEvent EVENT_UPDATE_STARS 542 | AddEvent EVENT_UPDATE_PLAYER 543 | AddEvent EVENT_UPDATE_BULLETS 544 | AddEvent EVENT_UPDATE_ALIENS 545 | AddEvent EVENT_UPDATE_BOMBS 546 | AddEvent EVENT_RENDER_SCENE 547 | END SUB 548 | 549 | SUB PrepareBackendEvents 550 | ResetEvents 551 | AddEvent EVENT_UPDATE_STARS 552 | AddEvent EVENT_UPDATE_BACK_END 553 | AddEvent EVENT_RENDER_BACK_END 554 | END SUB 555 | 556 | '===== One time initialisations ======================================================================================================================================================================= 557 | 558 | SUB PrepareGalaga 559 | DIM m% 560 | m% = INT((_DESKTOPHEIGHT - 80) / 288) 561 | virtualScreen& = _NEWIMAGE(224, 288, 32) 562 | SCREEN _NEWIMAGE(224 * m%, 288 * m%, 32) 563 | _DELAY 0.5 564 | _SCREENMOVE _MIDDLE 565 | '$RESIZE:STRETCH 566 | _ALLOWFULLSCREEN _SQUAREPIXELS , _SMOOTH 567 | _TITLE "Galaga" 568 | _DEST virtualScreen& 569 | game.fps% = 30 570 | RANDOMIZE TIMER 571 | game.frameCounter& = 0 572 | textOffset% = 0 573 | textColour%(0) = SPRITE_TEXT_WHITE 574 | textColour%(1) = SPRITE_TEXT_RED 575 | textColour%(2) = SPRITE_TEXT_BLUE 576 | textColour%(3) = SPRITE_TEXT_YELLOW 577 | bossScores%(0) = 150 578 | bossScores%(1) = 400 579 | bossScores%(2) = 800 580 | bossScores%(3) = 1500 581 | LoadSprites 582 | AddPathData 583 | LoadAllSFX 584 | InitialiseStars 585 | ReadHiscores 586 | END SUB 587 | 588 | '===== High score management ========================================================================================================================================================================== 589 | 590 | SUB ReadHiscores 591 | DIM i%, handle& 592 | ON ERROR GOTO fileReadError 593 | IF NOT _FILEEXISTS("scores.txt") THEN InitialiseHiscores: EXIT SUB 594 | handle& = FREEFILE 595 | OPEN "scores.txt" FOR INPUT AS #handle& 596 | FOR i% = 0 TO 4 597 | INPUT #handle&, hiscore(i%).score& 598 | INPUT #handle&, hiscore(i%).name$ 599 | NEXT i% 600 | CLOSE #handle& 601 | ON ERROR GOTO 0 602 | END SUB 603 | 604 | SUB InitialiseHiscores 605 | DIM i% 606 | FOR i% = 0 TO 4 607 | IF i% = 0 THEN hiscore(i%).name$ = "WWW.ROKCODER.COM" ELSE hiscore(i%).name$ = "-c ROKCODER c-" 608 | hiscore(i%).score = 25000 - i% * 5000 609 | NEXT i% 610 | END SUB 611 | 612 | SUB WriteHiscores 613 | DIM i%, handle& 614 | ON ERROR GOTO fileWriteError 615 | handle& = FREEFILE 616 | OPEN "scores.txt" FOR OUTPUT AS #handle& 617 | FOR i% = 0 TO 4 618 | PRINT #handle&, hiscore(i%).score& 619 | PRINT #handle&, hiscore(i%).name$ 620 | NEXT i% 621 | CLOSE #handle& 622 | ON ERROR GOTO 0 623 | END SUB 624 | 625 | SUB ShowHighScores (highlight%) 626 | STATIC pretext$(5) 627 | DIM i%, c%, s$ 628 | IF pretext$(0) = "" THEN pretext$(0) = "1ST": pretext$(1) = "2ND": pretext$(2) = "3RD": pretext$(3) = "4TH": pretext$(4) = "5TH" 629 | PrintText "THE GALACTIC HEROES", 4, 4, 2 630 | PrintText "-- BEST 5 --", 7, 7, 1 631 | PrintText "SCORE NAME", 5, 10, 2 632 | FOR i% = 0 TO 4 633 | c% = COLOUR_BLUE 634 | IF i% = highlight% THEN c% = COLOUR_RED 635 | s$ = LTRIM$(STR$(hiscore(i%).score&)) 636 | PrintText pretext$(i%) + " " + s$ + SPACE$(7 + (LEN(hiscore(i%).name$) > MAX_NAME_LEN) - LEN(s$)) + hiscore(i%).name$, 1, 12 + i% * 2, c% 637 | NEXT i% 638 | PrintText "1ST BONUS FOR 20000 PTS", 4, 24, 3 639 | PrintText "2ND BONUS FOR 70000 PTS", 4, 27, 3 640 | PrintText "AND FOR EVERY 70000 PTS", 4, 30, 3 641 | PrintText "PRESS SPACE BAR", 7, 34, 2 642 | END SUB 643 | 644 | FUNCTION InsertScore% 645 | DIM i%, j% 646 | i% = 0 647 | WHILE game.score& <= hiscore(i%).score&: i% = i% + 1: WEND 648 | j% = 4 649 | WHILE j% > i%: hiscore(j%) = hiscore(j% - 1): j% = j% - 1: WEND 650 | hiscore(i%).name$ = " " 651 | hiscore(i%).score& = game.score& 652 | InsertScore% = i% 653 | END FUNCTION 654 | 655 | FUNCTION EditName$ (name$, x%, c$) 656 | EditName$ = LEFT$(name$, x%) + c$ + RIGHT$(name$, LEN(name$) - x% - 1) 657 | END FUNCTION 658 | 659 | '===== Front end state machine ======================================================================================================================================================================== 660 | 661 | SUB UpdateFrontEnd (initialised%) 662 | IF initialised% = FALSE THEN 663 | frontend.state% = FE_SHOW_SCORES 664 | game.hiscore& = hiscore(0).score& 665 | HideOverlays 666 | WriteHiscores 667 | END IF 668 | SELECT CASE frontend.state% 669 | CASE FE_SHOW_SCORES 670 | stars.scroll% = TRUE 671 | ShowHighScores -1 672 | frontend.keyPressTarget% = TRUE 673 | frontend.state% = FE_WAIT_START_PRESS 674 | frontend.active = TRUE 675 | CASE FE_WAIT_START_PRESS 676 | IF _KEYDOWN(KEYDOWN_FIRE) = frontend.keyPressTarget% THEN 677 | frontend.keyPressTarget% = NOT frontend.keyPressTarget% 678 | IF frontend.keyPressTarget% = TRUE THEN 679 | PlaySfx SFX_1_UP 680 | frontend.pauseCounter% = 0.8 * game.fps% 681 | frontend.state% = FE_PAUSE_BEFORE_OVER 682 | END IF 683 | END IF 684 | CASE FE_PAUSE_BEFORE_OVER 685 | frontend.pauseCounter% = frontend.pauseCounter% - 1 686 | IF frontend.pauseCounter% = 0 THEN 687 | frontend.active = FALSE 688 | game.gameOver% = FALSE 689 | PrepareGameEvents 690 | END IF 691 | END SELECT 692 | END SUB 693 | 694 | '===== Back end state machine ========================================================================================================================================================================= 695 | 696 | SUB UpdateBackEnd (initialised%) 697 | DIM p%, c$ 698 | IF initialised% = FALSE THEN backend.state% = BE_STATS 699 | SELECT CASE backend.state% 700 | CASE BE_STATS 701 | StopSfx SFX_BOSS_GALAGA_TRACTOR_BEAM 702 | HideOverlays 703 | backend.cursor% = FALSE 704 | PrintText "-RESULTS-", 9, 17, COLOUR_RED 705 | PrintText "SHOTS FIRED", 4, 20, COLOUR_YELLOW 706 | PrintText "NUMBER OF HITS", 4, 23, COLOUR_YELLOW 707 | PrintText "HIT-MISS RATIO", 4, 26, COLOUR_WHITE 708 | PrintText "%", 25, 26, COLOUR_WHITE 709 | PrintText LTRIM$(STR$(stats.bulletCount%)), 20, 20, COLOUR_YELLOW 710 | PrintText LTRIM$(STR$(stats.bulletCount% - stats.bulletMissCount%)), 20, 23, COLOUR_YELLOW 711 | p% = (stats.bulletCount% - stats.bulletMissCount%) * 1000 / stats.bulletCount% 712 | PrintText LTRIM$(STR$(INT(p% / 10))) + "." + LTRIM$(STR$(p% MOD 10)), 20, 26, COLOUR_WHITE 713 | backend.pause% = 6 * game.fps% 714 | backend.state% = BE_POST_STATS_PAUSE 715 | CASE BE_POST_STATS_PAUSE 716 | backend.pause% = backend.pause% - 1 717 | IF backend.pause% = 0 THEN 718 | HideOverlays 719 | StopSfx SFX_AMBIENCE 720 | IF game.score& > hiscore(4).score& THEN 721 | backend.state% = BE_ENTER_NAME 722 | backend.substate% = 0 723 | backend.score$ = LTRIM$(STR$(game.score&)) 724 | backend.name$ = SPC(MAX_NAME_LEN) 725 | backend.cursorX% = 0 726 | backend.pos% = InsertScore% 727 | IF backend.pos% = 0 THEN PlaySfx SFX_NAME_ENTRY_1 ELSE PlaySfxLooping SFX_NAME_ENTRY_NOT_1 728 | backend.timer% = 30 * game.fps% 729 | _KEYCLEAR 730 | ELSE 731 | PrepareFrontendEvents 732 | END IF 733 | END IF 734 | CASE BE_ENTER_NAME 735 | SELECT CASE backend.substate% 736 | CASE 0 737 | c$ = UCASE$(INKEY$) 738 | IF c$ <> "" THEN 739 | IF INSTR(TEXTCHARS, c$) > 0 AND backend.cursorX% < MAX_NAME_LEN THEN 740 | backend.name$ = EditName$(backend.name$, backend.cursorX%, c$) 741 | backend.cursorX% = backend.cursorX% + 1 742 | ELSE 743 | IF c$ = CHR$(8) AND backend.cursorX% > 0 THEN 744 | backend.cursorX% = backend.cursorX% - 1 745 | backend.name$ = EditName$(backend.name$, backend.cursorX%, " ") 746 | ELSEIF c$ = CHR$(0) + CHR$(83) AND backend.cursorX% < MAX_NAME_LEN THEN 747 | backend.name$ = EditName$(backend.name$, backend.cursorX%, " ") 748 | ELSEIF c$ = CHR$(0) + CHR$(75) AND backend.cursorX% > 0 THEN 749 | backend.cursorX% = backend.cursorX% - 1 750 | ELSEIF c$ = CHR$(0) + CHR$(77) AND backend.cursorX% < MAX_NAME_LEN THEN 751 | backend.cursorX% = backend.cursorX% + 1 752 | ELSEIF c$ = CHR$(13) THEN 753 | PrepareFrontendEvents 754 | END IF 755 | END IF 756 | END IF 757 | HideOverlays 758 | hiscore(backend.pos%).name$ = backend.name$ 759 | ShowHighScores backend.pos% 760 | backend.cursor% = game.frameCounter& MOD game.fps% < game.fps% / 2 761 | backend.timer% = backend.timer% - 1 762 | IF (backend.pos% = 0 AND NOT IsPlayingSfx%(SFX_NAME_ENTRY_1)) OR (backend.pos% > 0 AND backend.timer% = 0) THEN 763 | StopSfx SFX_NAME_ENTRY_1 764 | StopSfx SFX_NAME_ENTRY_NOT_1 765 | PrepareFrontendEvents 766 | END IF 767 | END SELECT 768 | END SELECT 769 | END SUB 770 | 771 | '===== Simple utility functions ======================================================================================================================================================================= 772 | 773 | FUNCTION ValidateAngle! (angle!) 774 | WHILE angle! > 180: angle! = angle! - 360: WEND 775 | WHILE angle! < -180: angle! = angle! + 360: WEND 776 | ValidateAngle! = angle! 777 | END FUNCTION 778 | 779 | FUNCTION Min! (value1!, value2!) 780 | IF value1! < value2! THEN Min! = value1! ELSE Min! = value2! 781 | END FUNCTION 782 | 783 | FUNCTION Max! (value1!, value2!) 784 | IF value1! > value2! THEN Max! = value1! ELSE Max! = value2! 785 | END FUNCTION 786 | 787 | '===== Simple asset loading functions ================================================================================================================================================================= 788 | 789 | SUB AssetError (fname$) 790 | SCREEN 0 791 | PRINT "Unable to load "; fname$ 792 | PRINT "Please make sure EXE is in same folder as galaga.bas" 793 | PRINT "(Set Run/Output EXE to Source Folder option in the IDE before compiling)" 794 | END 795 | END SUB 796 | 797 | FUNCTION LoadImage& (fname$) 798 | DIM asset&, f$ 799 | f$ = "./assets/" + fname$ + ".png" 800 | asset& = _LOADIMAGE(f$, 32) 801 | IF asset& = -1 THEN AssetError (f$) 802 | LoadImage& = asset& 803 | END FUNCTION 804 | 805 | FUNCTION SndOpen& (fname$) 806 | DIM asset&, f$ 807 | f$ = "./assets/" + fname$ 808 | asset& = _SNDOPEN(f$) 809 | IF asset& = -1 THEN AssetError (f$) 810 | SndOpen& = asset& 811 | END FUNCTION 812 | 813 | '===== Simple image/sprite handling functions ========================================================================================================================================================= 814 | 815 | SUB DrawImage (handle&, x%, y%) 816 | _PUTIMAGE (112 + x% - _WIDTH(handle&) / 2, 288 - (y% + 180) - _HEIGHT(handle&) / 2), handle& 817 | END SUB 818 | 819 | SUB DrawSprite (sprite%, offset%, x%, y%) 820 | DIM handle& 821 | handle& = spriteHandle&(spriteData(sprite%).offset% + offset%) 822 | _PUTIMAGE (112 + x% - _WIDTH(handle&) / 2, 288 - (y% + 180) - _HEIGHT(handle&) / 2), handle& 823 | END SUB 824 | 825 | SUB DrawSpriteSection (sprite%, offset%, x%, y%, u%, v%, uWidth%, vHeight%) 826 | DIM handle& 827 | handle& = spriteHandle&(spriteData(sprite%).offset% + offset%) 828 | _PUTIMAGE (112 + x% - _WIDTH(handle&) / 2, 288 - (y% + 180) - _HEIGHT(handle&) / 2), handle&, , (u%, v%)-(u% + uWidth% - 1, v% + vHeight% - 1) 829 | END SUB 830 | 831 | SUB DrawRotatedSprite (sprite%, x%, y%, angle%, costumeOffset%) 832 | DIM handle&, r%, offset%, x1%, x2%, y1%, y2% 833 | handle& = spriteHandle&(spriteData(sprite%).offset%) 834 | x1% = 112 + x% - _WIDTH(handle&) / 2 835 | y1% = 288 - (y% + 180) - _HEIGHT(handle&) / 2 836 | x2% = 112 + x% + _WIDTH(handle&) / 2 - 1 837 | y2% = 288 - (y% + 180) + _HEIGHT(handle&) / 2 - 1 838 | r% = _ROUND(ValidateAngle!(angle%) / 360 * 24) 839 | IF r% = 0 THEN 840 | DrawSprite sprite%, 6 + costumeOffset%, x%, y% 841 | ELSE 842 | SELECT CASE r% 843 | CASE 0 TO 6 844 | offset% = 6 - r% 845 | handle& = spriteHandle&(spriteData(sprite%).offset% + offset%) 846 | _PUTIMAGE (x2%, y1%)-(x1%, y2%), handle& 847 | CASE -6 TO -1 848 | offset% = 6 + r% 849 | handle& = spriteHandle&(spriteData(sprite%).offset% + offset%) 850 | _PUTIMAGE (x1%, y1%)-(x2%, y2%), handle& 851 | CASE 7 TO 12 852 | offset% = r% - 6 853 | handle& = spriteHandle&(spriteData(sprite%).offset% + offset%) 854 | _PUTIMAGE (x2%, y2%)-(x1%, y1%), handle& 855 | CASE -12 TO -7 856 | offset% = -6 - r% 857 | handle& = spriteHandle&(spriteData(sprite%).offset% + offset%) 858 | _PUTIMAGE (x1%, y2%)-(x2%, y1%), handle& 859 | END SELECT 860 | END IF 861 | END SUB 862 | 863 | SUB LoadSpriteStrip (sprite%, sheet&, x%, y%, w%, h%, dx%, num%) 864 | DIM i% 865 | spriteData(sprite%).offset% = spriteLoadOffset% 866 | spriteData(sprite%).num% = num% 867 | FOR i% = 0 TO num% - 1 868 | spriteHandle&(spriteLoadOffset%) = _NEWIMAGE(w%, h%, 32) 869 | _PUTIMAGE , sheet&, spriteHandle&(spriteLoadOffset%), (x%, y%)-(x% + w% - 1, y% + h% - 1) 870 | _SETALPHA 0, _RGB32(0, 0, 0), spriteHandle&(spriteLoadOffset%) 871 | x% = x% + dx% 872 | spriteLoadOffset% = spriteLoadOffset% + 1 873 | NEXT i% 874 | END SUB 875 | 876 | SUB AppendSpriteStrip (sprite%, sheet&, x%, y%, w%, h%, dx%, num%) 877 | DIM i% 878 | IF spriteData(sprite%).offset% + spriteData(sprite%).num% <> spriteLoadOffset% THEN END 'Crappy handling but that's fine 879 | spriteData(sprite%).num% = spriteData(sprite%).num% + num% 880 | FOR i% = 0 TO num% - 1 881 | spriteHandle&(spriteLoadOffset%) = _NEWIMAGE(w%, h%, 32) 882 | _PUTIMAGE , sheet&, spriteHandle&(spriteLoadOffset%), (x%, y%)-(x% + w% - 1, y% + h% - 1) 883 | _SETALPHA 0, _RGB32(0, 0, 0), spriteHandle&(spriteLoadOffset%) 884 | x% = x% + dx% 885 | spriteLoadOffset% = spriteLoadOffset% + 1 886 | NEXT i% 887 | END SUB 888 | 889 | '===== Load all sprites needed by the game code ======================================================================================================================================================= 890 | 891 | SUB LoadSprites 892 | DIM s&, t& 893 | spriteLoadOffset% = 0 894 | s& = LoadImage&("sprites") 895 | t& = LoadImage&("text") 896 | LoadSpriteStrip SPRITE_PLAYER, s&, 1, 1, 16, 16, 18, 7 897 | LoadSpriteStrip SPRITE_PLAYER_CAPTURED, s&, 1, 19, 16, 16, 18, 7 898 | LoadSpriteStrip SPRITE_BULLET, s&, 307, 136, 16, 16, 0, 1 899 | LoadSpriteStrip SPRITE_BOSS_GALAGA, s&, 1, 37, 16, 16, 18, 8 900 | LoadSpriteStrip SPRITE_BOSS_GALAGA_HIT, s&, 1, 55, 16, 16, 18, 8 901 | LoadSpriteStrip SPRITE_BUTTERFLY, s&, 1, 73, 16, 16, 18, 8 902 | LoadSpriteStrip SPRITE_BEE, s&, 1, 91, 16, 16, 18, 8 903 | LoadSpriteStrip SPRITE_SCORPION, s&, 1, 109, 16, 16, 18, 7 904 | LoadSpriteStrip SPRITE_DRAGONFLY, s&, 1, 163, 16, 16, 18, 7 905 | LoadSpriteStrip SPRITE_BEAM, s&, 289, 36, 48, 80, 50, 3 906 | LoadSpriteStrip SPRITE_PLAYER_LIVES, s&, 289, 172, 16, 16, 0, 1 907 | LoadSpriteStrip SPRITE_PLAYER_EXPLOSION, s&, 145, 1, 32, 32, 34, 4 908 | LoadSpriteStrip SPRITE_ALIEN_EXPLOSION, s&, 289, 1, 32, 32, 34, 5 909 | LoadSpriteStrip SPRITE_TEXT_WHITE, t&, 453, 443, 8, 8, 9, 25 910 | AppendSpriteStrip SPRITE_TEXT_WHITE, t&, 453, 452, 8, 8, 9, 17 911 | LoadSpriteStrip SPRITE_TEXT_RED, t&, 453, 462, 8, 8, 9, 25 912 | AppendSpriteStrip SPRITE_TEXT_RED, t&, 453, 471, 8, 8, 9, 17 913 | LoadSpriteStrip SPRITE_TEXT_BLUE, t&, 453, 481, 8, 8, 9, 25 914 | AppendSpriteStrip SPRITE_TEXT_BLUE, t&, 453, 490, 8, 8, 9, 17 915 | LoadSpriteStrip SPRITE_TEXT_YELLOW, t&, 453, 500, 8, 8, 9, 25 916 | AppendSpriteStrip SPRITE_TEXT_YELLOW, t&, 453, 509, 8, 8, 9, 17 917 | LoadSpriteStrip SPRITE_FLAG, s&, 381, 172, 16, 16, -18, 3 918 | AppendSpriteStrip SPRITE_FLAG, s&, 328, 172, 14, 16, 0, 1 919 | AppendSpriteStrip SPRITE_FLAG, s&, 317, 172, 8, 16, -10, 2 920 | LoadSpriteStrip SPRITE_BOMB, s&, 307, 118, 16, 16, 0, 1 921 | LoadSpriteStrip SPRITE_SCORES, s&, 343, 118, 16, 16, 18, 3 922 | AppendSpriteStrip SPRITE_SCORES, s&, 343, 136, 16, 16, 0, 1 923 | AppendSpriteStrip SPRITE_SCORES, s&, 397, 118, 16, 16, 18, 2 924 | AppendSpriteStrip SPRITE_SCORES, s&, 361, 136, 32, 16, 34, 2 925 | starFrames&(0) = LoadImage&("stars1") 926 | starFrames&(1) = LoadImage&("stars2") 927 | starFrames&(2) = LoadImage&("stars3") 928 | starFrames&(3) = LoadImage&("stars4") 929 | stars.overlay = LoadImage&("stars border") 930 | _FREEIMAGE s& 931 | END SUB 932 | 933 | '===== Rendering code for the front end, main game and back end ======================================================================================================================================= 934 | 935 | SUB RenderFrontend (initialised%) 936 | DIM handle& 937 | CLS 938 | RenderStars 939 | handle& = spriteHandle&(spriteData(SPRITE_PLAYER_LIVES).offset%) 940 | _PUTIMAGE (1 * 8, 23 * 8 + 3), handle& 941 | _PUTIMAGE (1 * 8, 26 * 8 + 3), handle& 942 | _PUTIMAGE (1 * 8, 29 * 8 + 3), handle& 943 | RenderText 944 | UpdateFromVirtualScreen 945 | END SUB 946 | 947 | SUB RenderBackend (initialised%) 948 | DIM handle& 949 | CLS 950 | RenderStars 951 | IF backend.state% = BE_ENTER_NAME THEN 952 | handle& = spriteHandle&(spriteData(SPRITE_PLAYER_LIVES).offset%) 953 | _PUTIMAGE (1 * 8, 23 * 8 + 3), handle& 954 | _PUTIMAGE (1 * 8, 26 * 8 + 3), handle& 955 | _PUTIMAGE (1 * 8, 29 * 8 + 3), handle& 956 | END IF 957 | RenderText 958 | IF backend.cursor% THEN handle& = spriteHandle&(spriteData(textColour%(COLOUR_WHITE)).offset% + INSTR(TEXTCHARS, " ") - 1): _PUTIMAGE ((12 + backend.cursorX%) * 8, (12 + backend.pos% * 2) * 8), handle& 959 | UpdateFromVirtualScreen 960 | END SUB 961 | 962 | SUB RenderScene (initialised%) 963 | STATIC matchingSprite%(32) 964 | DIM i%, frame%, sections% 965 | IF initialised% = FALSE THEN 966 | matchingSprite%(TYPE_PLAYER) = SPRITE_PLAYER 967 | matchingSprite%(TYPE_PLAYER_CAPTURED) = SPRITE_PLAYER_CAPTURED 968 | matchingSprite%(TYPE_BOSS_GALAGA) = SPRITE_BOSS_GALAGA 969 | matchingSprite%(TYPE_BOSS_GALAGA_SHOT) = SPRITE_BOSS_GALAGA_HIT 970 | matchingSprite%(TYPE_BUTTERFLY) = SPRITE_BUTTERFLY 971 | matchingSprite%(TYPE_BEE) = SPRITE_BEE 972 | matchingSprite%(TYPE_DRAGONFLY) = SPRITE_DRAGONFLY 973 | matchingSprite%(TYPE_SCORPION) = SPRITE_SCORPION 974 | END IF 975 | CLS 976 | RenderStars 977 | FOR i% = 0 TO MAX_ALIENS - 1 978 | IF alienData(i%).controlPath% <> PT_WAITING AND alienData(i%).controlPath% <> PT_INACTIVE AND (alienData(i%).currentAction <> CMD_WAIT_FOR_CAPTURE OR player.state% = PLAYER_CAPTURING) AND alienData(i%).pathDelay% = -1 THEN 979 | IF alienData(i%).currentAction% = CMD_HOLD_FORMATION THEN 980 | DrawRotatedSprite matchingSprite%(alienData(i%).alienType%), alienData(i%).xPos!, alienData(i%).yPos!, alienData(i%).rotation!, alienData(i%).costume% 981 | END IF 982 | END IF 983 | NEXT i% 984 | FOR i% = 0 TO MAX_ALIENS - 1 985 | IF alienData(i%).controlPath% <> PT_WAITING AND alienData(i%).controlPath% <> PT_INACTIVE AND (alienData(i%).currentAction <> CMD_WAIT_FOR_CAPTURE OR player.state% = PLAYER_CAPTURING) AND alienData(i%).pathDelay% = -1 THEN 986 | SELECT CASE alienData(i%).currentAction% 987 | CASE CMD_DEAD 988 | DrawSprite SPRITE_ALIEN_EXPLOSION, INT(alienData(i%).explosionCounter% / 2), alienData(i%).xPos!, alienData(i%).yPos! 989 | CASE CMD_HOLD_FORMATION, CMD_INACTIVE, CMD_DESTROYED, CMD_NONE 990 | CASE ELSE 991 | SELECT CASE alienData(i%).alienType% 992 | CASE TYPE_BOSS_GALAGA, TYPE_BOSS_GALAGA_SHOT, TYPE_BUTTERFLY, TYPE_BEE 993 | DrawRotatedSprite matchingSprite%(alienData(i%).alienType%), alienData(i%).xPos!, alienData(i%).yPos!, alienData(i%).rotation!, alienData(i%).costume% 994 | CASE ELSE 995 | DrawRotatedSprite matchingSprite%(alienData(i%).alienType%), alienData(i%).xPos!, alienData(i%).yPos!, alienData(i%).rotation!, 0 996 | END SELECT 997 | END SELECT 998 | END IF 999 | NEXT i% 1000 | i% = CaptorId% 1001 | IF i% > -1 THEN 1002 | IF alienData(i%).beamActive% = TRUE THEN 1003 | frame% = INT(alienData(i%).captureCounter% / 2) MOD 3 1004 | IF alienData(i%).captureCounter < 18 * 6 THEN 1005 | sections% = INT(alienData(i%).captureCounter% / 12) 1006 | ELSE 1007 | sections% = 8 - INT(alienData(i%).captureCounter% - 18 * 6) / 12 1008 | END IF 1009 | DrawSpriteSection SPRITE_BEAM, frame%, alienData(i%).xPos!, alienData(i%).yPos! - 48, 0, 0, 48, 8 * (sections% + 1) 1010 | END IF 1011 | END IF 1012 | FOR i% = 0 TO MAX_BULLETS - 1 1013 | IF bullet(i%).state% = BULLET_ACTIVE THEN DrawSprite SPRITE_BULLET, 0, bullet(i%).xPos%, bullet(i%).yPos% 1014 | NEXT i% 1015 | FOR i% = 0 TO UBOUND(bomb) - 1: DrawSprite SPRITE_BOMB, 0, bomb(i%).xPos!, bomb(i%).yPos!: NEXT i% 1016 | UpdateSpawnedAnimations 1017 | FOR i% = 0 TO 1 1018 | SELECT CASE ship(i%).state% 1019 | CASE SHIP_EXPLODING 1020 | DrawSprite SPRITE_PLAYER_EXPLOSION, INT(ship(i%).counter% / 8), ship(i%).xPos%, player.yPos% 1021 | CASE SHIP_ACTIVE 1022 | DrawSprite SPRITE_PLAYER, 6, ship(i%).xPos%, player.yPos% 1023 | END SELECT 1024 | NEXT i% 1025 | FOR i% = 0 TO player.lives% - 1: DrawSprite SPRITE_PLAYER_LIVES, 0, i% * 14 - 103, -172: NEXT i% 1026 | FOR i% = 0 TO UBOUND(flagDisplay) - 1: DrawSprite SPRITE_FLAG, flagDisplay(i%).flag, flagDisplay(i%).xpos%, -172: NEXT i% 1027 | RenderText 1028 | UpdateFromVirtualScreen 1029 | END SUB 1030 | 1031 | SUB RenderStars 1032 | DIM i% 1033 | FOR i% = 0 TO 1 1034 | DrawImage starFrames&(INT(game.frameCounter& / 4) MOD 4), 0, i% * 256 - 36 - (stars.yPos% MOD 256) 1035 | NEXT i% 1036 | DrawImage stars.overlay, 0, -36 1037 | END SUB 1038 | 1039 | SUB RenderText 1040 | DIM i%, x%, y%, c%, c$, j%, handle& 1041 | IF textOffset% > 0 THEN 1042 | FOR i% = 0 TO textOffset% - 1 1043 | x% = text(i%).x% 1044 | y% = text(i%).y% 1045 | c% = textColour%(text(i%).colour%) 1046 | FOR j% = 0 TO LEN(text(i%).text$) - 1 1047 | c$ = MID$(text(i%).text$, j% + 1, 1) 1048 | IF c$ <> " " THEN handle& = spriteHandle&(spriteData(c%).offset% + INSTR(TEXTCHARS, c$) - 1): _PUTIMAGE (x% * 8, y% * 8), handle& 1049 | x% = x% + 1 1050 | NEXT j% 1051 | NEXT i% 1052 | END IF 1053 | END SUB 1054 | 1055 | SUB UpdateFromVirtualScreen 1056 | game.frameCounter& = game.frameCounter& + 1 1057 | _PUTIMAGE , virtualScreen&, 0 1058 | _DISPLAY 1059 | END SUB 1060 | 1061 | '===== In-game text handling ========================================================================================================================================================================== 1062 | 1063 | SUB PrintText (text$, x%, y%, colour%) 1064 | text(textOffset%).text$ = text$ 1065 | text(textOffset%).x% = x% 1066 | text(textOffset%).y% = y% 1067 | text(textOffset%).colour% = colour% 1068 | textOffset% = textOffset% + 1 1069 | END SUB 1070 | 1071 | SUB HideOverlays 1072 | textOffset% = 0 1073 | ShowScoreAndHiscore 1074 | END SUB 1075 | 1076 | '===== In-game sprite animation spawning and destroying =============================================================================================================================================== 1077 | 1078 | SUB SpawnAnimation (spawnType%, alien AS ALIENDATA) 1079 | DIM i% 1080 | FOR i% = 0 TO MAX_SPAWNS - 1 1081 | IF spawnedAnimation(i%).spawnType% = SPAWN_NONE THEN 1082 | spawnedAnimation(i%).spawnType% = spawnType% 1083 | spawnedAnimation(i%).xPos% = alien.xPos! 1084 | spawnedAnimation(i%).yPos% = alien.yPos! 1085 | spawnedAnimation(i%).value% = alien.scoreCostume% 1086 | spawnedAnimation(i%).counter% = 0 1087 | EXIT FOR 1088 | END IF 1089 | NEXT i% 1090 | END SUB 1091 | 1092 | SUB UpdateSpawnedAnimations 1093 | DIM i% 1094 | FOR i% = 0 TO MAX_SPAWNS - 1 1095 | IF spawnedAnimation(i%).spawnType% <> SPAWN_NONE THEN 1096 | SELECT CASE spawnedAnimation(i%).spawnType% 1097 | CASE SPAWN_EXPLOSION 1098 | IF spawnedAnimation(i%).counter% = 10 THEN 1099 | spawnedAnimation(i%).spawnType% = SPAWN_NONE 1100 | ELSE 1101 | DrawSprite SPRITE_ALIEN_EXPLOSION, INT(spawnedAnimation(i%).counter% / 2), spawnedAnimation(i%).xPos%, spawnedAnimation(i%).yPos% 1102 | END IF 1103 | CASE SPAWN_SCORE 1104 | IF spawnedAnimation(i%).counter% >= 0.8 * game.fps% THEN 1105 | spawnedAnimation(i%).spawnType% = SPAWN_NONE 1106 | ELSE 1107 | DrawSprite SPRITE_SCORES, spawnedAnimation(i%).value%, spawnedAnimation(i%).xPos%, spawnedAnimation(i%).yPos% 1108 | END IF 1109 | END SELECT 1110 | spawnedAnimation(i%).counter% = spawnedAnimation(i%).counter% + 1 1111 | EXIT FOR 1112 | END IF 1113 | NEXT i% 1114 | END SUB 1115 | 1116 | '===== The "player" can consist of either one or two "ships" simultaneously =========================================================================================================================== 1117 | 1118 | SUB InitialisePlayer 1119 | DIM i% 1120 | player.doubleShip% = FALSE 1121 | player.canFire% = FALSE 1122 | player.xPos% = 9 1123 | player.yPos% = -156 1124 | player.state% = PLAYER_INACTIVE 1125 | FOR i% = 0 TO 1 1126 | ship(i%).isHit% = FALSE 1127 | ship(i%).state% = SHIP_INACTIVE 1128 | NEXT i% 1129 | END SUB 1130 | 1131 | SUB SpawnShip 1132 | DIM id% 1133 | player.lives% = player.lives% - 1 1134 | id% = 0 - (ship(0).state% = SHIP_ACTIVE) 1135 | ship(id%).isHit% = FALSE 1136 | ship(id%).state% = SHIP_ACTIVE 1137 | UpdateShip (id%) 1138 | END SUB 1139 | 1140 | SUB UpdatePlayer (initialised%) 1141 | DIM i% 1142 | SELECT CASE player.state% 1143 | CASE PLAYER_DOUBLING_UP 1144 | IF player.xPos% < 0 THEN 1145 | player.xPos% = Min!(0, player.xPos% + 2) 1146 | ELSEIF player.xPos% > 0 THEN 1147 | player.xPos% = Max!(0, player.xPos% - 2) 1148 | END IF 1149 | CASE PLAYER_ACTIVE 1150 | IF _KEYDOWN(KEYDOWN_LEFT) AND player.xPos% > -111 - 16 * (ship(0).state% = SHIP_ACTIVE) THEN player.xPos% = player.xPos% - 3 1151 | IF _KEYDOWN(KEYDOWN_RIGHT) AND player.xPos% < 111 + 16 * (ship(1).state% = SHIP_ACTIVE) THEN player.xPos% = player.xPos% + 3 1152 | 1153 | IF player.canFire% THEN 1154 | IF _KEYDOWN(KEYDOWN_FIRE) THEN 1155 | IF NOT player.fireKeyDown% THEN 1156 | player.fireKeyDown% = TRUE 1157 | fireBullet 1158 | END IF 1159 | ELSE 1160 | player.fireKeyDown% = FALSE 1161 | END IF 1162 | END IF 1163 | CASE PLAYER_SPAWNING 1164 | IF waveData.aliensInFormation% AND waveData.bombCount% = 0 THEN 1165 | waveData.aliensAttackingPauseCounter% = 60 1166 | waveData.aliensCanAttack% = TRUE 1167 | player.xPos% = 9 1168 | SpawnShip 1169 | player.state% = PLAYER_ACTIVE 1170 | END IF 1171 | END SELECT 1172 | FOR i% = 0 TO 1: UpdateShip i%: NEXT i% 1173 | END SUB 1174 | 1175 | SUB NewLife 1176 | IF player.state% = PLAYER_WAITING_TO_DOUBLE THEN EXIT SUB 1177 | IF player.lives% > 0 THEN 1178 | player.state% = PLAYER_SPAWNING 1179 | player.canFire% = FALSE 1180 | waveData.aliensCanAttack% = FALSE 1181 | ELSE 1182 | player.state% = PLAYER_INACTIVE 1183 | player.lives% = -1 1184 | game.gameOver% = TRUE 1185 | game.gameOverCounter% = 5 * game.fps% 1186 | waveData.aliensCanAttack% = FALSE 1187 | HideOverlays 1188 | PrintText "GAME OVER", 10, 18, COLOUR_BLUE 1189 | END IF 1190 | END SUB 1191 | 1192 | SUB UpdateShip (i%) 1193 | SELECT CASE ship(i%).state% 1194 | CASE SHIP_EXPLODING 1195 | ship(i%).counter% = ship(i%).counter% + 1 1196 | IF ship(i%).counter% = 32 THEN 1197 | ship(i%).state% = SHIP_INACTIVE 1198 | IF ship(0).state% <> SHIP_ACTIVE AND ship(1).state% <> SHIP_ACTIVE AND player.state% <> PLAYER_WAITING_TO_DOUBLE THEN 1199 | PrintText "READY", 10, 18, COLOUR_BLUE 1200 | NewLife 1201 | END IF 1202 | player.doubleShip% = FALSE 1203 | END IF 1204 | CASE SHIP_ACTIVE 1205 | ship(i%).xPos% = player.xPos% - 8 + 16 * i% 1206 | IF player.state% = PLAYER_CAPTURING THEN ship(i%).state% = SHIP_INACTIVE: EXIT SUB 1207 | IF ship(i%).isHit% = TRUE THEN 1208 | ship(i%).isHit% = FALSE 1209 | PlaySfx SFX_DIE 1210 | IF ship(0).state% <> SHIP_ACTIVE AND ship(1).state% <> SHIP_ACTIVE AND player.state% <> PLAYER_WAITING_TO_DOUBLE THEN waveData.aliensCanAttack% = FALSE 1211 | ship(i%).state% = SHIP_EXPLODING 1212 | ship(i%).counter% = 0 1213 | END IF 1214 | END SELECT 1215 | END SUB 1216 | 1217 | SUB DoubleUpShip 1218 | player.state% = PLAYER_DOUBLING_UP 1219 | player.canFire% = FALSE 1220 | END SUB 1221 | 1222 | SUB ShipDoubledUp 1223 | player.doubleShip% = ship(0).state% = SHIP_ACTIVE OR ship(1).state% = SHIP_ACTIVE 1224 | SpawnShip 1225 | player.state% = PLAYER_ACTIVE 1226 | player.canFire% = TRUE 1227 | StopSfx (SFX_FIGHTER_RESCUED) 1228 | player.lives = player.lives + 1 1229 | END SUB 1230 | 1231 | '===== Bullet management system ======================================================================================================================================================================= 1232 | 1233 | SUB InitialiseBullets 1234 | DIM i% 1235 | FOR i% = 0 TO MAX_BULLETS - 1: bullet(i%).state% = BULLET_NONE: NEXT i% 1236 | stats.bulletCount% = 0 1237 | stats.bulletMissCount% = 0 1238 | END SUB 1239 | 1240 | SUB fireBullet 1241 | DIM i% 1242 | FOR i% = 0 TO MAX_BULLETS_PER_SHIP - 1 1243 | IF bullet(i%).state% = BULLET_NONE AND bullet(i% + MAX_BULLETS_PER_SHIP).state% = BULLET_NONE THEN 1244 | PlaySfx SFX_FIGHTER_SHOOT 1245 | IF ship(0).state% = SHIP_ACTIVE THEN ActivateBullet i%: stats.bulletCount% = stats.bulletCount% + 1 1246 | IF ship(1).state% = SHIP_ACTIVE THEN ActivateBullet i% + MAX_BULLETS_PER_SHIP 1247 | EXIT SUB 1248 | END IF 1249 | NEXT i% 1250 | END SUB 1251 | 1252 | SUB ActivateBullet (i%) 1253 | bullet(i%).state% = BULLET_ACTIVE 1254 | bullet(i%).waitToRemoveCounter% = 0.1 * game.fps% 1255 | bullet(i%).xPos% = ship(INT(i% / MAX_BULLETS_PER_SHIP)).xPos% 1256 | bullet(i%).yPos% = player.yPos% 1257 | END SUB 1258 | 1259 | SUB UpdateBullets (initialised%) 1260 | DIM i% 1261 | FOR i% = 0 TO MAX_BULLETS - 1 1262 | IF bullet(i%).state% = BULLET_REMOVING THEN 1263 | IF i% < MAX_BULLETS_PER_SHIP THEN 1264 | bullet(i% + MAX_BULLETS_PER_SHIP).state% = BULLET_REMOVING 1265 | ELSE 1266 | bullet(i% - MAX_BULLETS_PER_SHIP).state% = BULLET_REMOVING 1267 | END IF 1268 | END IF 1269 | NEXT i% 1270 | FOR i% = 0 TO MAX_BULLETS - 1 1271 | SELECT CASE bullet(i%).state% 1272 | CASE BULLET_ACTIVE 1273 | bullet(i%).yPos% = bullet(i%).yPos% + 12 1274 | IF OffTop%(bullet(i%).yPos%) THEN 1275 | bullet(i%).state% = BULLET_NONE 1276 | IF i% < MAX_BULLETS_PER_SHIP THEN stats.bulletMissCount% = stats.bulletMissCount% + 1 1277 | END IF 1278 | CASE BULLET_REMOVING 1279 | bullet(i%).waitToRemoveCounter% = bullet(i%).waitToRemoveCounter% - 1 1280 | IF bullet(i%).waitToRemoveCounter% <= 0 THEN bullet(i%).state% = BULLET_NONE 1281 | END SELECT 1282 | NEXT i% 1283 | END SUB 1284 | 1285 | '===== Stars manager ================================================================================================================================================================================== 1286 | 1287 | SUB InitialiseStars 1288 | stars.scroll = FALSE 1289 | stars.yPos = 0 1290 | END SUB 1291 | 1292 | SUB UpdateStars (initialised%) 1293 | stars.yPos = stars.yPos - 2 * stars.scroll 1294 | END SUB 1295 | 1296 | '===== Construction of alien attack and movement patterns ============================================================================================================================================= 1297 | 1298 | FUNCTION ExtrasFromAbove% 1299 | ExtrasFromAbove% = Min!(8, game.stage% / 4) 1300 | END FUNCTION 1301 | 1302 | FUNCTION ExtrasFromSide% 1303 | ExtrasFromSide% = Min!(8, Max!(0, (game.stage% - 2) / 4)) 1304 | END FUNCTION 1305 | 1306 | FUNCTION WaveType% 1307 | IF game.stage% < 3 THEN WaveType% = game.stage% ELSE WaveType% = 4 - ((game.stage% - 3) MOD 4) 1308 | END FUNCTION 1309 | 1310 | FUNCTION ChallengeWaveType% 1311 | ChallengeWaveType% = (((game.stage% - 3) / 4) MOD NUM_CHALLENGE_PATHS) + 1 1312 | END FUNCTION 1313 | 1314 | SUB CreateWavePrepare 1315 | DIM i% 1316 | waveData.section% = 1 1317 | FOR i% = 0 TO MAX_ALIENS - 1 1318 | alienData(i%).controlPath% = PT_WAITING 1319 | alienData(i%).currentAction% = CMD_NONE 1320 | alienData(i%).alienType% = TYPE_NONE 1321 | alienData(i%).isCaptive% = FALSE 1322 | alienData(i%).isCaptor% = FALSE 1323 | NEXT i% 1324 | initialiseAlienIndex% = 0 1325 | END SUB 1326 | 1327 | SUB InitialiseAlien (pathName%, delay%, formationX!, formationY!, alienType%, direction%) 1328 | alienData(initialiseAlienIndex%).controlPath% = pathName% 1329 | alienData(initialiseAlienIndex%).currentAction% = CMD_NONE 1330 | alienData(initialiseAlienIndex%).formationXOffset! = formationX! 1331 | alienData(initialiseAlienIndex%).formationYOffset! = formationY! 1332 | alienData(initialiseAlienIndex%).direction% = direction% 1333 | alienData(initialiseAlienIndex%).alienType% = alienType% 1334 | alienData(initialiseAlienIndex%).pathDelay% = delay% 1335 | alienData(initialiseAlienIndex%).batchNum% = INT(initialiseAlienIndex% / 8) 1336 | initialiseAlienIndex% = initialiseAlienIndex% + 1 1337 | END SUB 1338 | 1339 | SUB CreateWave 1340 | SELECT CASE WaveType% 1341 | CASE 1: 1342 | SELECT CASE waveData.section% 1343 | CASE 1: CreateWaveType1Section1 1344 | CASE 2: CreateWaveType1Section2 1345 | CASE 3: CreateWaveType1Section3 1346 | CASE 4: CreateWaveType1Section4 1347 | CASE 5: CreateWaveType1Section5 1348 | END SELECT 1349 | CASE 2: 1350 | SELECT CASE waveData.section% 1351 | CASE 1: CreateWaveType2Section1 1352 | CASE 2: CreateWaveType2Section2 1353 | CASE 3: CreateWaveType2Section3 1354 | CASE 4: CreateWaveType2Section4 1355 | CASE 5: CreateWaveType2Section5 1356 | END SELECT 1357 | CASE 3: 1358 | SELECT CASE waveData.section% 1359 | CASE 1: CreateWaveType3Section1 1360 | CASE 2: CreateWaveType3Section2 1361 | CASE 3: CreateWaveType3Section3 1362 | CASE 4: CreateWaveType3Section4 1363 | CASE 5: CreateWaveType3Section5 1364 | END SELECT 1365 | END SELECT 1366 | waveData.section% = waveData.section% + 1 1367 | END SUB 1368 | 1369 | SUB CreateChallengeWave 1370 | SELECT CASE ChallengeWaveType% 1371 | CASE 1: 1372 | SELECT CASE waveData.section% 1373 | CASE 1: CreateChallengeWaveType1Section1 1374 | CASE 2: CreateChallengeWaveType1Section2 1375 | CASE 3: CreateChallengeWaveType1Section3 1376 | CASE 4: CreateChallengeWaveType1Section4 1377 | CASE 5: CreateChallengeWaveType1Section5 1378 | END SELECT 1379 | CASE 2: 1380 | SELECT CASE waveData.section% 1381 | CASE 1: CreateChallengeWaveType2Section1 1382 | CASE 2: CreateChallengeWaveType2Section2 1383 | CASE 3: CreateChallengeWaveType2Section3 1384 | CASE 4: CreateChallengeWaveType2Section4 1385 | CASE 5: CreateChallengeWaveType2Section5 1386 | END SELECT 1387 | CASE 3: 1388 | SELECT CASE waveData.section% 1389 | CASE 1: CreateChallengeWaveType3Section1 1390 | CASE 2: CreateChallengeWaveType3Section2 1391 | CASE 3: CreateChallengeWaveType3Section3 1392 | CASE 4: CreateChallengeWaveType3Section4 1393 | CASE 5: CreateChallengeWaveType3Section5 1394 | END SELECT 1395 | CASE 4: 1396 | SELECT CASE waveData.section% 1397 | CASE 1: CreateChallengeWaveType4Section1 1398 | CASE 2: CreateChallengeWaveType4Section2 1399 | CASE 3: CreateChallengeWaveType4Section3 1400 | CASE 4: CreateChallengeWaveType4Section4 1401 | CASE 5: CreateChallengeWaveType4Section5 1402 | END SELECT 1403 | END SELECT 1404 | waveData.section% = waveData.section% + 1 1405 | END SUB 1406 | 1407 | '===== Patterns for aliens entering the three different entrance types ================================================================================================================================ 1408 | 1409 | SUB CreateWaveType1Section1 1410 | DIM i% 1411 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -0.5, 2, TYPE_BUTTERFLY, 1 1412 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -0.5, 4, TYPE_BEE, -1 1413 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 0.5, 2, TYPE_BUTTERFLY, 1 1414 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 0.5, 4, TYPE_BEE, -1 1415 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -0.5, 3, TYPE_BUTTERFLY, 1 1416 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -0.5, 5, TYPE_BEE, -1 1417 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 0.5, 3, TYPE_BUTTERFLY, 1 1418 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 0.5, 5, TYPE_BEE, -1 1419 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1420 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, 1 1421 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, -1 1422 | NEXT i% 1423 | END SUB 1424 | 1425 | SUB CreateWaveType1Section2 1426 | DIM i% 1427 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, -1.5, 1, TYPE_BOSS_GALAGA, 1 1428 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, -1.5, 2, TYPE_BUTTERFLY, 1 1429 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, -0.5, 1, TYPE_BOSS_GALAGA, 1 1430 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, 1.5, 2, TYPE_BUTTERFLY, 1 1431 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 32, 0.5, 1, TYPE_BOSS_GALAGA, 1 1432 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 40, -1.5, 3, TYPE_BUTTERFLY, 1 1433 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 48, 1.5, 1, TYPE_BOSS_GALAGA, 1 1434 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 56, 1.5, 3, TYPE_BUTTERFLY, 1 1435 | FOR i% = 0 TO ExtrasFromSide% / 2 - 1 1436 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 64 + i% * 8, 0, 0, 0 + (i% MOD 2) * 2, 1 1437 | NEXT i% 1438 | END SUB 1439 | 1440 | SUB CreateWaveType1Section3 1441 | DIM i% 1442 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, 3.5, 2, TYPE_BUTTERFLY, -1 1443 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, 2.5, 2, TYPE_BUTTERFLY, -1 1444 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, 3.5, 3, TYPE_BUTTERFLY, -1 1445 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, 2.5, 3, TYPE_BUTTERFLY, -1 1446 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 32, -3.5, 2, TYPE_BUTTERFLY, -1 1447 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 40, -2.5, 2, TYPE_BUTTERFLY, -1 1448 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 48, -3.5, 3, TYPE_BUTTERFLY, -1 1449 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 56, -2.5, 3, TYPE_BUTTERFLY, -1 1450 | FOR i% = 0 TO ExtrasFromSide% / 2 - 1 1451 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 64 + i% * 8, 0, 0, TYPE_BUTTERFLY, -1 1452 | NEXT i% 1453 | END SUB 1454 | 1455 | SUB CreateWaveType1Section4 1456 | DIM i% 1457 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, 2.5, 4, TYPE_BEE, -1 1458 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 1.5, 4, TYPE_BEE, -1 1459 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, 2.5, 5, TYPE_BEE, -1 1460 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 1.5, 5, TYPE_BEE, -1 1461 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 32, -1.5, 4, TYPE_BEE, -1 1462 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 40, -2.5, 4, TYPE_BEE, -1 1463 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 48, -1.5, 5, TYPE_BEE, -1 1464 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 56, -2.5, 5, TYPE_BEE, -1 1465 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1466 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 64 + i% * 8, 0, 0, TYPE_BEE, 1 1467 | NEXT i% 1468 | END SUB 1469 | 1470 | SUB CreateWaveType1Section5 1471 | DIM i% 1472 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -4.5, 4, TYPE_BEE, 1 1473 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, -3.5, 4, TYPE_BEE, 1 1474 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -4.5, 5, TYPE_BEE, 1 1475 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, -3.5, 5, TYPE_BEE, 1 1476 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 32, 3.5, 4, TYPE_BEE, 1 1477 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 40, 4.5, 4, TYPE_BEE, 1 1478 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 48, 3.5, 5, TYPE_BEE, 1 1479 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 56, 4.5, 5, TYPE_BEE, 1 1480 | IF NOT waveData.playerInStorage% THEN 1481 | InitialiseAlien PT_WAIT_FOR_CAPTURE, 0, 0, 0, TYPE_PLAYER, 1 1482 | ELSE 1483 | waveData.playerInStorage% = FALSE 1484 | i% = RandomBoss% 1485 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 64, alienData(i%).formationXOffset!, 0, TYPE_PLAYER_CAPTURED, 1 1486 | alienData(initialiseAlienIndex% - 1).isCaptive% = TRUE 1487 | alienData(i%).isCaptor% = TRUE 1488 | END IF 1489 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1490 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 64 + i% * 8, 0, 0, TYPE_BEE, 1 1491 | NEXT i% 1492 | END SUB 1493 | 1494 | SUB CreateWaveType2Section1 1495 | DIM i% 1496 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -0.5, 2, TYPE_BUTTERFLY, 1 1497 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -0.5, 4, TYPE_BEE, -1 1498 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 0.5, 2, TYPE_BUTTERFLY, 1 1499 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 0.5, 4, TYPE_BEE, -1 1500 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -0.5, 3, TYPE_BUTTERFLY, 1 1501 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -0.5, 5, TYPE_BEE, -1 1502 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 0.5, 3, TYPE_BUTTERFLY, 1 1503 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 0.5, 5, TYPE_BEE, -1 1504 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1505 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, 1 1506 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, -1 1507 | NEXT i% 1508 | END SUB 1509 | 1510 | SUB CreateWaveType2Section2 1511 | DIM i% 1512 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, -1.5, 1, TYPE_BOSS_GALAGA, 1 1513 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 0, -1.5, 2, TYPE_BUTTERFLY, 1 1514 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, -0.5, 1, TYPE_BOSS_GALAGA, 1 1515 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 8, 1.5, 2, TYPE_BUTTERFLY, 1 1516 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, 0.5, 1, TYPE_BOSS_GALAGA, 1 1517 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 16, -1.5, 3, TYPE_BUTTERFLY, 1 1518 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, 1.5, 1, TYPE_BOSS_GALAGA, 1 1519 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 24, 1.5, 3, TYPE_BUTTERFLY, 1 1520 | FOR i% = 0 TO ExtrasFromSide% / 2 - 1 1521 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 32 + i% * 8, 0, 0, TYPE_BOSS_GALAGA, 1 1522 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_HIGHER_SIDE, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, 1 1523 | NEXT i% 1524 | END SUB 1525 | 1526 | SUB CreateWaveType2Section3 1527 | DIM i% 1528 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, 3.5, 2, TYPE_BUTTERFLY, -1 1529 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 0, 2.5, 2, TYPE_BUTTERFLY, -1 1530 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, 3.5, 3, TYPE_BUTTERFLY, -1 1531 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 8, 2.5, 3, TYPE_BUTTERFLY, -1 1532 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, -3.5, 2, TYPE_BUTTERFLY, -1 1533 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 16, -2.5, 2, TYPE_BUTTERFLY, -1 1534 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, -3.5, 3, TYPE_BUTTERFLY, -1 1535 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER, 24, -2.5, 3, TYPE_BUTTERFLY, -1 1536 | FOR i% = 0 TO ExtrasFromSide% / 2 - 1 1537 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, -1 1538 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_HIGHER_SIDE, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, -1 1539 | NEXT i% 1540 | END SUB 1541 | 1542 | SUB CreateWaveType2Section4 1543 | DIM i% 1544 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, 2.5, 4, TYPE_BEE, -1 1545 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 0, 1.5, 4, TYPE_BEE, -1 1546 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 2.5, 5, TYPE_BEE, -1 1547 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 8, 1.5, 5, TYPE_BEE, -1 1548 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -1.5, 4, TYPE_BEE, -1 1549 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 16, -2.5, 4, TYPE_BEE, -1 1550 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, -1.5, 5, TYPE_BEE, -1 1551 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 24, -2.5, 5, TYPE_BEE, -1 1552 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1553 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, -1 1554 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_OUTER_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, -1 1555 | NEXT i% 1556 | END SUB 1557 | 1558 | SUB CreateWaveType2Section5 1559 | DIM i% 1560 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -4.5, 4, TYPE_BEE, 1 1561 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 0, -3.5, 4, TYPE_BEE, 1 1562 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, -4.5, 5, TYPE_BEE, 1 1563 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 8, -3.5, 5, TYPE_BEE, 1 1564 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, 3.5, 4, TYPE_BEE, 1 1565 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 16, 4.5, 4, TYPE_BEE, 1 1566 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 3.5, 5, TYPE_BEE, 1 1567 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 24, 4.5, 5, TYPE_BEE, 1 1568 | IF NOT waveData.playerInStorage% THEN 1569 | InitialiseAlien PT_WAIT_FOR_CAPTURE, 0, 0, 0, TYPE_PLAYER, 1 1570 | ELSE 1571 | waveData.playerInStorage% = FALSE 1572 | i% = RandomBoss% 1573 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 32, alienData(i%).formationXOffset!, 0, TYPE_PLAYER_CAPTURED, 1 1574 | alienData(initialiseAlienIndex% - 1).isCaptive% = TRUE 1575 | alienData(i%).isCaptor% = TRUE 1576 | END IF 1577 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1578 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, 1 1579 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_OUTER_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, 1 1580 | NEXT i% 1581 | END SUB 1582 | 1583 | SUB CreateWaveType3Section1 1584 | DIM i% 1585 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -0.5, 2, TYPE_BUTTERFLY, 1 1586 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -0.5, 4, TYPE_BEE, -1 1587 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 0.5, 2, TYPE_BUTTERFLY, 1 1588 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 0.5, 4, TYPE_BEE, -1 1589 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -0.5, 3, TYPE_BUTTERFLY, 1 1590 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -0.5, 5, TYPE_BEE, -1 1591 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 0.5, 3, TYPE_BUTTERFLY, 1 1592 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 0.5, 5, TYPE_BEE, -1 1593 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1594 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, 1 1595 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, -1 1596 | NEXT i% 1597 | END SUB 1598 | 1599 | SUB CreateWaveType3Section2 1600 | DIM i% 1601 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, -1.5, 1, TYPE_BOSS_GALAGA, 1 1602 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, -0.5, 1, TYPE_BOSS_GALAGA, 1 1603 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, 0.5, 1, TYPE_BOSS_GALAGA, 1 1604 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, 1.5, 1, TYPE_BOSS_GALAGA, 1 1605 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, 3.5, 2, TYPE_BUTTERFLY, -1 1606 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, 3.5, 3, TYPE_BUTTERFLY, -1 1607 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, -3.5, 2, TYPE_BUTTERFLY, -1 1608 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, -3.5, 3, TYPE_BUTTERFLY, -1 1609 | FOR i% = 0 TO ExtrasFromSide% / 2 - 1 1610 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 32 + i% * 8, 0, 0, TYPE_BOSS_GALAGA, 1 1611 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, -1 1612 | NEXT i% 1613 | END SUB 1614 | 1615 | SUB CreateWaveType3Section3 1616 | DIM i% 1617 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, -1.5, 2, TYPE_BUTTERFLY, 1 1618 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, 1.5, 2, TYPE_BUTTERFLY, 1 1619 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, -1.5, 3, TYPE_BUTTERFLY, 1 1620 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, 1.5, 3, TYPE_BUTTERFLY, 1 1621 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 0, 2.5, 2, TYPE_BUTTERFLY, -1 1622 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 8, 2.5, 3, TYPE_BUTTERFLY, -1 1623 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 16, -2.5, 2, TYPE_BUTTERFLY, -1 1624 | InitialiseAlien PT_NEW_WAVE_FROM_SIDE, 24, -2.5, 3, TYPE_BUTTERFLY, -1 1625 | FOR i% = 0 TO ExtrasFromSide% / 2 - 1 1626 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, 1 1627 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE, 32 + i% * 8, 0, 0, TYPE_BUTTERFLY, -1 1628 | NEXT i% 1629 | END SUB 1630 | 1631 | SUB CreateWaveType3Section4 1632 | DIM i% 1633 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, 2.5, 4, TYPE_BEE, -1 1634 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 0, 1.5, 4, TYPE_BEE, -1 1635 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, 2.5, 5, TYPE_BEE, -1 1636 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 8, 1.5, 5, TYPE_BEE, -1 1637 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, -1.5, 4, TYPE_BEE, -1 1638 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 16, -2.5, 4, TYPE_BEE, -1 1639 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, -1.5, 5, TYPE_BEE, -1 1640 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 24, -2.5, 5, TYPE_BEE, -1 1641 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1642 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, -1 1643 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_OUTER_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, -1 1644 | NEXT i% 1645 | END SUB 1646 | 1647 | SUB CreateWaveType3Section5 1648 | DIM i% 1649 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 0, -4.5, 4, TYPE_BEE, 1 1650 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 0, -3.5, 4, TYPE_BEE, 1 1651 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 8, -4.5, 5, TYPE_BEE, 1 1652 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 8, -3.5, 5, TYPE_BEE, 1 1653 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 16, 3.5, 4, TYPE_BEE, 1 1654 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 16, 4.5, 4, TYPE_BEE, 1 1655 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 24, 3.5, 5, TYPE_BEE, 1 1656 | InitialiseAlien PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD, 24, 4.5, 5, TYPE_BEE, 1 1657 | IF NOT waveData.playerInStorage% THEN 1658 | InitialiseAlien PT_WAIT_FOR_CAPTURE, 0, 0, 0, TYPE_PLAYER, 1 1659 | ELSE 1660 | waveData.playerInStorage% = FALSE 1661 | i% = RandomBoss% 1662 | InitialiseAlien PT_NEW_WAVE_FROM_TOP, 32, alienData(i%).formationXOffset!, 0, TYPE_PLAYER_CAPTURED, 1 1663 | alienData(initialiseAlienIndex% - 1).isCaptive% = TRUE 1664 | alienData(i%).isCaptor% = TRUE 1665 | END IF 1666 | FOR i% = 0 TO ExtrasFromAbove% / 2 - 1 1667 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, 1 1668 | InitialiseAlien PT_NEW_AGGRESSIVE_WAVE_FROM_OUTER_TOP, 32 + i% * 8, 0, 0, TYPE_BEE, 1 1669 | NEXT i% 1670 | END SUB 1671 | 1672 | FUNCTION RandomBoss% 1673 | DIM i%, t% 1674 | t% = INT(RND * 4) 1675 | DO 1676 | IF alienData(i%).alienType = TYPE_BOSS_GALAGA THEN 1677 | t% = t% - 1 1678 | IF t% < 0 THEN RandomBoss% = i%: EXIT FUNCTION 1679 | END IF 1680 | i% = i% + 1 1681 | LOOP 1682 | END FUNCTION 1683 | 1684 | '===== Patterns for aliens entering the four different challenge types =============================================================================================================================== 1685 | 1686 | SUB CreateChallengeWaveType1Section1 1687 | InitialiseAlien PT_CHALLENGE1A, 0, 0, 0, TYPE_BEE, 1 1688 | InitialiseAlien PT_CHALLENGE1A, 0, 0, 0, TYPE_BEE, -1 1689 | InitialiseAlien PT_CHALLENGE1A, 8, 0, 0, TYPE_BEE, 1 1690 | InitialiseAlien PT_CHALLENGE1A, 8, 0, 0, TYPE_BEE, -1 1691 | InitialiseAlien PT_CHALLENGE1A, 16, 0, 0, TYPE_BEE, 1 1692 | InitialiseAlien PT_CHALLENGE1A, 16, 0, 0, TYPE_BEE, -1 1693 | InitialiseAlien PT_CHALLENGE1A, 24, 0, 0, TYPE_BEE, 1 1694 | InitialiseAlien PT_CHALLENGE1A, 24, 0, 0, TYPE_BEE, -1 1695 | END SUB 1696 | SUB CreateChallengeWaveType1Section2 1697 | InitialiseAlien PT_CHALLENGE1B, 0, 0, 0, TYPE_BOSS_GALAGA, 1 1698 | InitialiseAlien PT_CHALLENGE1B, 8, 0, 0, TYPE_BEE, 1 1699 | InitialiseAlien PT_CHALLENGE1B, 16, 0, 0, TYPE_BOSS_GALAGA, 1 1700 | InitialiseAlien PT_CHALLENGE1B, 24, 0, 0, TYPE_BEE, 1 1701 | InitialiseAlien PT_CHALLENGE1B, 32, 0, 0, TYPE_BOSS_GALAGA, 1 1702 | InitialiseAlien PT_CHALLENGE1B, 40, 0, 0, TYPE_BEE, 1 1703 | InitialiseAlien PT_CHALLENGE1B, 48, 0, 0, TYPE_BOSS_GALAGA, 1 1704 | InitialiseAlien PT_CHALLENGE1B, 56, 0, 0, TYPE_BEE, 1 1705 | END SUB 1706 | SUB CreateChallengeWaveType1Section3 1707 | InitialiseAlien PT_CHALLENGE1B, 0, 0, 0, TYPE_BEE, -1 1708 | InitialiseAlien PT_CHALLENGE1B, 8, 0, 0, TYPE_BEE, -1 1709 | InitialiseAlien PT_CHALLENGE1B, 16, 0, 0, TYPE_BEE, -1 1710 | InitialiseAlien PT_CHALLENGE1B, 24, 0, 0, TYPE_BEE, -1 1711 | InitialiseAlien PT_CHALLENGE1B, 32, 0, 0, TYPE_BEE, -1 1712 | InitialiseAlien PT_CHALLENGE1B, 40, 0, 0, TYPE_BEE, -1 1713 | InitialiseAlien PT_CHALLENGE1B, 48, 0, 0, TYPE_BEE, -1 1714 | InitialiseAlien PT_CHALLENGE1B, 56, 0, 0, TYPE_BEE, -1 1715 | END SUB 1716 | SUB CreateChallengeWaveType1Section4 1717 | InitialiseAlien PT_CHALLENGE1A, 0, 0, 0, TYPE_BEE, -1 1718 | InitialiseAlien PT_CHALLENGE1A, 8, 0, 0, TYPE_BEE, -1 1719 | InitialiseAlien PT_CHALLENGE1A, 16, 0, 0, TYPE_BEE, -1 1720 | InitialiseAlien PT_CHALLENGE1A, 24, 0, 0, TYPE_BEE, -1 1721 | InitialiseAlien PT_CHALLENGE1A, 32, 0, 0, TYPE_BEE, -1 1722 | InitialiseAlien PT_CHALLENGE1A, 40, 0, 0, TYPE_BEE, -1 1723 | InitialiseAlien PT_CHALLENGE1A, 48, 0, 0, TYPE_BEE, -1 1724 | InitialiseAlien PT_CHALLENGE1A, 56, 0, 0, TYPE_BEE, -1 1725 | END SUB 1726 | SUB CreateChallengeWaveType1Section5 1727 | InitialiseAlien PT_CHALLENGE1A, 0, 0, 0, TYPE_BEE, 1 1728 | InitialiseAlien PT_CHALLENGE1A, 8, 0, 0, TYPE_BEE, 1 1729 | InitialiseAlien PT_CHALLENGE1A, 16, 0, 0, TYPE_BEE, 1 1730 | InitialiseAlien PT_CHALLENGE1A, 24, 0, 0, TYPE_BEE, 1 1731 | InitialiseAlien PT_CHALLENGE1A, 32, 0, 0, TYPE_BEE, 1 1732 | InitialiseAlien PT_CHALLENGE1A, 40, 0, 0, TYPE_BEE, 1 1733 | InitialiseAlien PT_CHALLENGE1A, 48, 0, 0, TYPE_BEE, 1 1734 | InitialiseAlien PT_CHALLENGE1A, 56, 0, 0, TYPE_BEE, 1 1735 | END SUB 1736 | 1737 | SUB CreateChallengeWaveType2Section1 1738 | InitialiseAlien PT_CHALLENGE2A, 0, 0, 0, TYPE_BUTTERFLY, 1 1739 | InitialiseAlien PT_CHALLENGE2A, 0, 0, 0, TYPE_BUTTERFLY, -1 1740 | InitialiseAlien PT_CHALLENGE2A, 8, 0, 0, TYPE_BUTTERFLY, 1 1741 | InitialiseAlien PT_CHALLENGE2A, 8, 0, 0, TYPE_BUTTERFLY, -1 1742 | InitialiseAlien PT_CHALLENGE2A, 16, 0, 0, TYPE_BUTTERFLY, 1 1743 | InitialiseAlien PT_CHALLENGE2A, 16, 0, 0, TYPE_BUTTERFLY, -1 1744 | InitialiseAlien PT_CHALLENGE2A, 24, 0, 0, TYPE_BUTTERFLY, 1 1745 | InitialiseAlien PT_CHALLENGE2A, 24, 0, 0, TYPE_BUTTERFLY, -1 1746 | END SUB 1747 | SUB CreateChallengeWaveType2Section2 1748 | InitialiseAlien PT_CHALLENGE2B, 0, 0, 0, TYPE_BOSS_GALAGA, 1 1749 | InitialiseAlien PT_CHALLENGE2B, 8, 0, 0, TYPE_BUTTERFLY, -1 1750 | InitialiseAlien PT_CHALLENGE2B, 16, 0, 0, TYPE_BOSS_GALAGA, 1 1751 | InitialiseAlien PT_CHALLENGE2B, 24, 0, 0, TYPE_BUTTERFLY, -1 1752 | InitialiseAlien PT_CHALLENGE2B, 32, 0, 0, TYPE_BOSS_GALAGA, 1 1753 | InitialiseAlien PT_CHALLENGE2B, 40, 0, 0, TYPE_BUTTERFLY, -1 1754 | InitialiseAlien PT_CHALLENGE2B, 48, 0, 0, TYPE_BOSS_GALAGA, 1 1755 | InitialiseAlien PT_CHALLENGE2B, 56, 0, 0, TYPE_BUTTERFLY, -1 1756 | END SUB 1757 | SUB CreateChallengeWaveType2Section3 1758 | InitialiseAlien PT_CHALLENGE2B, 0, 0, 0, TYPE_BUTTERFLY, 1 1759 | InitialiseAlien PT_CHALLENGE2B, 0, 0, 0, TYPE_BUTTERFLY, -1 1760 | InitialiseAlien PT_CHALLENGE2B, 8, 0, 0, TYPE_BUTTERFLY, 1 1761 | InitialiseAlien PT_CHALLENGE2B, 8, 0, 0, TYPE_BUTTERFLY, -1 1762 | InitialiseAlien PT_CHALLENGE2B, 16, 0, 0, TYPE_BUTTERFLY, 1 1763 | InitialiseAlien PT_CHALLENGE2B, 16, 0, 0, TYPE_BUTTERFLY, -1 1764 | InitialiseAlien PT_CHALLENGE2B, 24, 0, 0, TYPE_BUTTERFLY, 1 1765 | InitialiseAlien PT_CHALLENGE2B, 24, 0, 0, TYPE_BUTTERFLY, -1 1766 | END SUB 1767 | SUB CreateChallengeWaveType2Section4 1768 | InitialiseAlien PT_CHALLENGE2A, 0, 0, 0, TYPE_BUTTERFLY, -1 1769 | InitialiseAlien PT_CHALLENGE2A, 8, 0, 0, TYPE_BUTTERFLY, -1 1770 | InitialiseAlien PT_CHALLENGE2A, 16, 0, 0, TYPE_BUTTERFLY, -1 1771 | InitialiseAlien PT_CHALLENGE2A, 24, 0, 0, TYPE_BUTTERFLY, -1 1772 | InitialiseAlien PT_CHALLENGE2A, 32, 0, 0, TYPE_BUTTERFLY, -1 1773 | InitialiseAlien PT_CHALLENGE2A, 40, 0, 0, TYPE_BUTTERFLY, -1 1774 | InitialiseAlien PT_CHALLENGE2A, 48, 0, 0, TYPE_BUTTERFLY, -1 1775 | InitialiseAlien PT_CHALLENGE2A, 56, 0, 0, TYPE_BUTTERFLY, -1 1776 | END SUB 1777 | SUB CreateChallengeWaveType2Section5 1778 | InitialiseAlien PT_CHALLENGE2A, 0, 0, 0, TYPE_BUTTERFLY, 1 1779 | InitialiseAlien PT_CHALLENGE2A, 8, 0, 0, TYPE_BUTTERFLY, 1 1780 | InitialiseAlien PT_CHALLENGE2A, 16, 0, 0, TYPE_BUTTERFLY, 1 1781 | InitialiseAlien PT_CHALLENGE2A, 24, 0, 0, TYPE_BUTTERFLY, 1 1782 | InitialiseAlien PT_CHALLENGE2A, 32, 0, 0, TYPE_BUTTERFLY, 1 1783 | InitialiseAlien PT_CHALLENGE2A, 40, 0, 0, TYPE_BUTTERFLY, 1 1784 | InitialiseAlien PT_CHALLENGE2A, 48, 0, 0, TYPE_BUTTERFLY, 1 1785 | InitialiseAlien PT_CHALLENGE2A, 56, 0, 0, TYPE_BUTTERFLY, 1 1786 | END SUB 1787 | 1788 | SUB CreateChallengeWaveType3Section1 1789 | InitialiseAlien PT_CHALLENGE3A, 0, 0, 0, TYPE_DRAGONFLY, 1 1790 | InitialiseAlien PT_CHALLENGE3B, 8, 0, 0, TYPE_DRAGONFLY, 1 1791 | InitialiseAlien PT_CHALLENGE3A, 16, 0, 0, TYPE_DRAGONFLY, 1 1792 | InitialiseAlien PT_CHALLENGE3B, 24, 0, 0, TYPE_DRAGONFLY, 1 1793 | InitialiseAlien PT_CHALLENGE3A, 32, 0, 0, TYPE_DRAGONFLY, 1 1794 | InitialiseAlien PT_CHALLENGE3B, 40, 0, 0, TYPE_DRAGONFLY, 1 1795 | InitialiseAlien PT_CHALLENGE3A, 48, 0, 0, TYPE_DRAGONFLY, 1 1796 | InitialiseAlien PT_CHALLENGE3B, 56, 0, 0, TYPE_DRAGONFLY, 1 1797 | END SUB 1798 | SUB CreateChallengeWaveType3Section2 1799 | InitialiseAlien PT_CHALLENGE3C, 0, 0, 0, TYPE_BOSS_GALAGA, 1 1800 | InitialiseAlien PT_CHALLENGE3C, 0, 0, 0, TYPE_DRAGONFLY, -1 1801 | InitialiseAlien PT_CHALLENGE3C, 8, 0, 0, TYPE_BOSS_GALAGA, 1 1802 | InitialiseAlien PT_CHALLENGE3C, 8, 0, 0, TYPE_DRAGONFLY, -1 1803 | InitialiseAlien PT_CHALLENGE3C, 16, 0, 0, TYPE_BOSS_GALAGA, 1 1804 | InitialiseAlien PT_CHALLENGE3C, 16, 0, 0, TYPE_DRAGONFLY, -1 1805 | InitialiseAlien PT_CHALLENGE3C, 24, 0, 0, TYPE_BOSS_GALAGA, 1 1806 | InitialiseAlien PT_CHALLENGE3C, 24, 0, 0, TYPE_DRAGONFLY, -1 1807 | END SUB 1808 | SUB CreateChallengeWaveType3Section3 1809 | InitialiseAlien PT_CHALLENGE3C, 0, 0, 0, TYPE_DRAGONFLY, 1 1810 | InitialiseAlien PT_CHALLENGE3C, 0, 0, 0, TYPE_DRAGONFLY, -1 1811 | InitialiseAlien PT_CHALLENGE3C, 8, 0, 0, TYPE_DRAGONFLY, 1 1812 | InitialiseAlien PT_CHALLENGE3C, 8, 0, 0, TYPE_DRAGONFLY, -1 1813 | InitialiseAlien PT_CHALLENGE3C, 16, 0, 0, TYPE_DRAGONFLY, 1 1814 | InitialiseAlien PT_CHALLENGE3C, 16, 0, 0, TYPE_DRAGONFLY, -1 1815 | InitialiseAlien PT_CHALLENGE3C, 24, 0, 0, TYPE_DRAGONFLY, 1 1816 | InitialiseAlien PT_CHALLENGE3C, 24, 0, 0, TYPE_DRAGONFLY, -1 1817 | END SUB 1818 | SUB CreateChallengeWaveType3Section4 1819 | InitialiseAlien PT_CHALLENGE3A, 0, 0, 0, TYPE_DRAGONFLY, 1 1820 | InitialiseAlien PT_CHALLENGE3B, 8, 0, 0, TYPE_DRAGONFLY, 1 1821 | InitialiseAlien PT_CHALLENGE3A, 16, 0, 0, TYPE_DRAGONFLY, 1 1822 | InitialiseAlien PT_CHALLENGE3B, 24, 0, 0, TYPE_DRAGONFLY, 1 1823 | InitialiseAlien PT_CHALLENGE3A, 32, 0, 0, TYPE_DRAGONFLY, 1 1824 | InitialiseAlien PT_CHALLENGE3B, 40, 0, 0, TYPE_DRAGONFLY, 1 1825 | InitialiseAlien PT_CHALLENGE3A, 48, 0, 0, TYPE_DRAGONFLY, 1 1826 | InitialiseAlien PT_CHALLENGE3B, 56, 0, 0, TYPE_DRAGONFLY, 1 1827 | END SUB 1828 | SUB CreateChallengeWaveType3Section5 1829 | InitialiseAlien PT_CHALLENGE3A, 0, 0, 0, TYPE_DRAGONFLY, -1 1830 | InitialiseAlien PT_CHALLENGE3B, 8, 0, 0, TYPE_DRAGONFLY, -1 1831 | InitialiseAlien PT_CHALLENGE3A, 16, 0, 0, TYPE_DRAGONFLY, -1 1832 | InitialiseAlien PT_CHALLENGE3B, 24, 0, 0, TYPE_DRAGONFLY, -1 1833 | InitialiseAlien PT_CHALLENGE3A, 32, 0, 0, TYPE_DRAGONFLY, -1 1834 | InitialiseAlien PT_CHALLENGE3B, 40, 0, 0, TYPE_DRAGONFLY, -1 1835 | InitialiseAlien PT_CHALLENGE3A, 48, 0, 0, TYPE_DRAGONFLY, -1 1836 | InitialiseAlien PT_CHALLENGE3B, 56, 0, 0, TYPE_DRAGONFLY, -1 1837 | END SUB 1838 | 1839 | SUB CreateChallengeWaveType4Section1 1840 | InitialiseAlien PT_CHALLENGE4A, 0, 0, 0, TYPE_SCORPION, 1 1841 | InitialiseAlien PT_CHALLENGE4B, 0, 0, 0, TYPE_SCORPION, 1 1842 | InitialiseAlien PT_CHALLENGE4A, 8, 0, 0, TYPE_SCORPION, 1 1843 | InitialiseAlien PT_CHALLENGE4B, 8, 0, 0, TYPE_SCORPION, 1 1844 | InitialiseAlien PT_CHALLENGE4A, 16, 0, 0, TYPE_SCORPION, 1 1845 | InitialiseAlien PT_CHALLENGE4B, 16, 0, 0, TYPE_SCORPION, 1 1846 | InitialiseAlien PT_CHALLENGE4A, 24, 0, 0, TYPE_SCORPION, 1 1847 | InitialiseAlien PT_CHALLENGE4B, 24, 0, 0, TYPE_SCORPION, 1 1848 | END SUB 1849 | SUB CreateChallengeWaveType4Section2 1850 | InitialiseAlien PT_CHALLENGE4C, 0, 0, 0, TYPE_BOSS_GALAGA, 1 1851 | InitialiseAlien PT_CHALLENGE4C, 8, 0, 0, TYPE_SCORPION, 1 1852 | InitialiseAlien PT_CHALLENGE4C, 16, 0, 0, TYPE_BOSS_GALAGA, 1 1853 | InitialiseAlien PT_CHALLENGE4C, 24, 0, 0, TYPE_SCORPION, 1 1854 | InitialiseAlien PT_CHALLENGE4C, 32, 0, 0, TYPE_BOSS_GALAGA, 1 1855 | InitialiseAlien PT_CHALLENGE4C, 40, 0, 0, TYPE_SCORPION, 1 1856 | InitialiseAlien PT_CHALLENGE4C, 48, 0, 0, TYPE_BOSS_GALAGA, 1 1857 | InitialiseAlien PT_CHALLENGE4C, 56, 0, 0, TYPE_SCORPION, 1 1858 | END SUB 1859 | SUB CreateChallengeWaveType4Section3 1860 | InitialiseAlien PT_CHALLENGE4C, 0, 0, 0, TYPE_SCORPION, -1 1861 | InitialiseAlien PT_CHALLENGE4C, 8, 0, 0, TYPE_SCORPION, -1 1862 | InitialiseAlien PT_CHALLENGE4C, 16, 0, 0, TYPE_SCORPION, -1 1863 | InitialiseAlien PT_CHALLENGE4C, 24, 0, 0, TYPE_SCORPION, -1 1864 | InitialiseAlien PT_CHALLENGE4C, 32, 0, 0, TYPE_SCORPION, -1 1865 | InitialiseAlien PT_CHALLENGE4C, 40, 0, 0, TYPE_SCORPION, -1 1866 | InitialiseAlien PT_CHALLENGE4C, 48, 0, 0, TYPE_SCORPION, -1 1867 | InitialiseAlien PT_CHALLENGE4C, 56, 0, 0, TYPE_SCORPION, -1 1868 | END SUB 1869 | SUB CreateChallengeWaveType4Section4 1870 | InitialiseAlien PT_CHALLENGE4A, 0, 0, 0, TYPE_SCORPION, 1 1871 | InitialiseAlien PT_CHALLENGE4B, 0, 0, 0, TYPE_SCORPION, 1 1872 | InitialiseAlien PT_CHALLENGE4A, 8, 0, 0, TYPE_SCORPION, 1 1873 | InitialiseAlien PT_CHALLENGE4B, 8, 0, 0, TYPE_SCORPION, 1 1874 | InitialiseAlien PT_CHALLENGE4A, 16, 0, 0, TYPE_SCORPION, 1 1875 | InitialiseAlien PT_CHALLENGE4B, 16, 0, 0, TYPE_SCORPION, 1 1876 | InitialiseAlien PT_CHALLENGE4A, 24, 0, 0, TYPE_SCORPION, 1 1877 | InitialiseAlien PT_CHALLENGE4B, 24, 0, 0, TYPE_SCORPION, 1 1878 | END SUB 1879 | SUB CreateChallengeWaveType4Section5 1880 | InitialiseAlien PT_CHALLENGE4A, 0, 0, 0, TYPE_SCORPION, -1 1881 | InitialiseAlien PT_CHALLENGE4B, 0, 0, 0, TYPE_SCORPION, -1 1882 | InitialiseAlien PT_CHALLENGE4A, 8, 0, 0, TYPE_SCORPION, -1 1883 | InitialiseAlien PT_CHALLENGE4B, 8, 0, 0, TYPE_SCORPION, -1 1884 | InitialiseAlien PT_CHALLENGE4A, 16, 0, 0, TYPE_SCORPION, -1 1885 | InitialiseAlien PT_CHALLENGE4B, 16, 0, 0, TYPE_SCORPION, -1 1886 | InitialiseAlien PT_CHALLENGE4A, 24, 0, 0, TYPE_SCORPION, -1 1887 | InitialiseAlien PT_CHALLENGE4B, 24, 0, 0, TYPE_SCORPION, -1 1888 | END SUB 1889 | 1890 | '===== Defining the commands that build up the paths ================================================================================================================================================== 1891 | 1892 | SUB AddPathData 1893 | SetPathType PT_NEW_WAVE_FROM_TOP 1894 | AddToPath_SetPosition 94, 12, 180 1895 | AddToPath_Movement 18, 3, -3 1896 | AddToPath_Movement 30, 3, 0 1897 | AddToPath_Movement 30, 3, 6 1898 | AddToPath_JoinFormation 1899 | SetPathType PT_NEW_WAVE_FROM_SIDE 1900 | AddToPath_SetPosition 0, 250, 270 1901 | AddToPath_Movement 48, 3, -2 1902 | AddToPath_Movement 48, 3, -6 1903 | AddToPath_JoinFormation 1904 | SetPathType PT_UP_AND_DIVE_WITH_BOSS 1905 | AddToPath_LeaveFormation 1906 | AddToPath_Movement 3, 2, 6 1907 | AddToPath_Movement 48, 2, 0 1908 | AddToPath_Movement 63, 2, 6 1909 | AddToPath_Movement 36, 2, 0 1910 | AddToPath_ContinueFlight 2, -1 1911 | AddToPath_MoveAboveFormation 1912 | AddToPath_JoinFormation 1913 | SetPathType PT_BUTTERFLY_PATH 1914 | AddToPath_LeaveFormation 1915 | AddToPath_Movement 12, 2, 6 1916 | AddToPath_Movement 40, 2, 0 1917 | AddToPath_Movement 46, 2, -2 1918 | AddToPath_Movement 30, 2, 2 1919 | AddToPath_ContinueFlight 2, -2 1920 | AddToPath_MoveAboveFormation 1921 | AddToPath_JoinFormation 1922 | SetPathType PT_BEE_PATH 1923 | AddToPath_LeaveFormation 1924 | AddToPath_Movement 10, 2, 6 1925 | AddToPath_ToHeight 188 1926 | AddToPath_Movement 108, 2, -2 1927 | AddToPath_BeeReturn 1928 | AddToPath_Movement 98, 2, -2 1929 | AddToPath_ContinueFlight 2, 0 1930 | AddToPath_MoveAboveFormation 1931 | AddToPath_JoinFormation 1932 | SetPathType PT_NEW_WAVE_FROM_TOP_SLIGHTLY_OUTWARD 1933 | AddToPath_SetPosition 110, 12, 180 1934 | AddToPath_Movement 18, 2.1623, -3 1935 | AddToPath_Movement 30, 3, 0 1936 | AddToPath_Movement 30, 4.6747, 6 1937 | AddToPath_Speed 3 1938 | AddToPath_JoinFormation 1939 | SetPathType PT_NEW_WAVE_FROM_SIDE_SLIGHTLY_HIGHER 1940 | AddToPath_SetPosition 0, 234, 270 1941 | AddToPath_Movement 48, 2.5585, -2 1942 | AddToPath_Movement 48, 1.3252, -6 1943 | AddToPath_Speed 3 1944 | AddToPath_JoinFormation 1945 | SetPathType PT_NEW_AGGRESSIVE_WAVE_FROM_TOP 1946 | AddToPath_SetPosition 94, 12, 180 1947 | AddToPath_Movement 18, 3, -3 1948 | AddToPath_Movement 30, 3, 0 1949 | AddToPath_Movement 30, 3, 6 1950 | AddToPath_DiveAtPlayer 1951 | AddToPath_Remove 1952 | SetPathType PT_NEW_AGGRESSIVE_WAVE_FROM_OUTER_TOP 1953 | AddToPath_SetPosition 110, 12, 180 1954 | AddToPath_Movement 18, 2.1623, -3 1955 | AddToPath_Movement 30, 3, 0 1956 | AddToPath_Movement 30, 4.6747, 6 1957 | AddToPath_Speed 3 1958 | AddToPath_DiveAtPlayer 1959 | AddToPath_Remove 1960 | SetPathType PT_NEW_AGGRESSIVE_WAVE_FROM_SIDE 1961 | AddToPath_SetPosition 0, 250, 270 1962 | AddToPath_Movement 48, 3, -2 1963 | AddToPath_Movement 48, 3, -6 1964 | AddToPath_DiveAtPlayer 1965 | AddToPath_Remove 1966 | SetPathType PT_NEW_AGGRESSIVE_WAVE_FROM_HIGHER_SIDE 1967 | AddToPath_SetPosition 0, 234, 270 1968 | AddToPath_Movement 48, 2.5585, -2 1969 | AddToPath_Movement 48, 1.3252, -6 1970 | AddToPath_Speed 3 1971 | AddToPath_DiveAtPlayer 1972 | AddToPath_Remove 1973 | SetPathType PT_UP_AND_DIVE_TO_CAPTURE 1974 | AddToPath_LeaveFormation 1975 | AddToPath_Movement 3, 2, 6 1976 | AddToPath_DiveToBeam 1977 | AddToPath_ContinueFlight 3, 0 1978 | AddToPath_MoveAboveFormation 1979 | AddToPath_JoinFormation 1980 | SetPathType PT_RETURN_WITH_CAPTURED 1981 | AddToPath_Movement 30, 2, 6 1982 | AddToPath_JoinFormation 1983 | SetPathType PT_WAIT_FOR_CAPTURE 1984 | AddToPath_WaitForCapture 1985 | SetPathType PT_TAKE_HOSTAGE_POSITION 1986 | AddToPath_TakeHostagePosition 1987 | SetPathType PT_RESCUED_PLAYER 1988 | AddToPath_DoubleUpPlayer 1989 | SetPathType PT_PLAYER_SWOOP 1990 | AddToPath_LeaveFormation 1991 | AddToPath_Movement 3, 2, 6 1992 | AddToPath_Movement 48, 2, 0 1993 | AddToPath_Movement 63, 2, 6 1994 | AddToPath_Movement 36, 2, 0 1995 | AddToPath_ContinueFlight 2, -1 1996 | AddToPath_PlayerInStorage 1997 | SetPathType PT_CHALLENGE1A 1998 | AddToPath_SetPosition 94, 12, 180 1999 | AddToPath_Movement 24, 3, 0 2000 | AddToPath_Movement 3, 3, -8 2001 | AddToPath_Movement 48, 3, 0 2002 | AddToPath_Movement 38, 3, -6 2003 | AddToPath_ContinueFlight 3, 0 2004 | AddToPath_Remove 2005 | SetPathType PT_CHALLENGE1B 2006 | AddToPath_SetPosition 0, 250, 270 2007 | AddToPath_Movement 54, 3, -1 2008 | AddToPath_Movement 4, 3, -9 2009 | AddToPath_Movement 20, 3, 0 2010 | AddToPath_Movement 20, 3, -9 2011 | AddToPath_Movement 20, 3, 0 2012 | AddToPath_Movement 16, 3, -9 2013 | AddToPath_ContinueFlight 3, 0 2014 | AddToPath_Remove 2015 | SetPathType PT_CHALLENGE2A 2016 | AddToPath_SetPosition 94, 12, 180 2017 | AddToPath_Movement 24, 3, 0 2018 | AddToPath_Movement 3, 3, -8 2019 | AddToPath_Movement 20, 3, 0 2020 | AddToPath_Movement 30, 0, -6 2021 | AddToPath_Movement 20, 3, 0 2022 | AddToPath_Movement 3, 3, 8 2023 | AddToPath_ContinueFlight 3, 0 2024 | AddToPath_Remove 2025 | SetPathType PT_CHALLENGE2B 2026 | AddToPath_SetPosition 0, 248, 270 2027 | AddToPath_Movement 36, 3, 0 2028 | AddToPath_Movement 180, 3, -2 2029 | AddToPath_ContinueFlight 3, 0 2030 | AddToPath_Remove 2031 | SetPathType PT_CHALLENGE3A 2032 | AddToPath_SetPosition 94, 12, 180 2033 | AddToPath_Movement 34, 3, 0 2034 | AddToPath_Movement 6, 3, -8 2035 | AddToPath_Movement 36, 3, 0 2036 | AddToPath_Movement 30, 0, -6 2037 | AddToPath_Movement 37, 3, 0 2038 | AddToPath_Movement 6, 3, 8 2039 | AddToPath_ContinueFlight 3, 0 2040 | AddToPath_Remove 2041 | SetPathType PT_CHALLENGE3B 2042 | AddToPath_SetPosition 94, 12, 180 2043 | AddToPath_Movement 34, 3, 0 2044 | AddToPath_Movement 6, 3, 8 2045 | AddToPath_Movement 36, 3, 0 2046 | AddToPath_Movement 30, 0, -6 2047 | AddToPath_Movement 37, 3, 0 2048 | AddToPath_Movement 6, 3, -8 2049 | AddToPath_ContinueFlight 3, 0 2050 | AddToPath_Remove 2051 | SetPathType PT_CHALLENGE3C 2052 | AddToPath_SetPosition 0, 250, 270 2053 | AddToPath_Movement 25, 3, 0 2054 | AddToPath_Movement 18, 0, 10 2055 | AddToPath_Movement 30, 3, 3 2056 | AddToPath_Movement 30, 3, 0 2057 | AddToPath_Movement 30, 3, 3 2058 | AddToPath_Movement 12, 3, 7.5 2059 | AddToPath_Movement 30, 3, 0 2060 | AddToPath_Movement 15, 0, -6 2061 | AddToPath_ContinueFlight 3, 0 2062 | AddToPath_Remove 2063 | SetPathType PT_CHALLENGE4A 2064 | AddToPath_SetPosition 94, 12, 180 2065 | AddToPath_Movement 6, 3, 0 2066 | AddToPath_Movement 10, 0, 9 2067 | AddToPath_Movement 36, 3, -5 2068 | AddToPath_Movement 36, 3, 5 2069 | AddToPath_Movement 72, 3, -5 2070 | AddToPath_Movement 36, 3, 5 2071 | AddToPath_Movement 36, 3, -5 2072 | AddToPath_Movement 10, 0, 9 2073 | AddToPath_ContinueFlight 3, 0 2074 | AddToPath_Remove 2075 | SetPathType PT_CHALLENGE4B 2076 | AddToPath_SetPosition 94, 12, 180 2077 | AddToPath_Movement 6, 3, 0 2078 | AddToPath_Movement 10, 0, -9 2079 | AddToPath_Movement 36, 3, 5 2080 | AddToPath_Movement 36, 3, -5 2081 | AddToPath_Movement 72, 3, 5 2082 | AddToPath_Movement 36, 3, -5 2083 | AddToPath_Movement 36, 3, 5 2084 | AddToPath_Movement 10, 0, -9 2085 | AddToPath_ContinueFlight 3, 0 2086 | AddToPath_Remove 2087 | SetPathType PT_CHALLENGE4C 2088 | AddToPath_SetPosition 0, 250, 270 2089 | AddToPath_Movement 8, 3, -8 2090 | AddToPath_Movement 36, 3, 0 2091 | AddToPath_Movement 4, 3, 16 2092 | AddToPath_Movement 72, 3, 5 2093 | AddToPath_Movement 12, 3, 0 2094 | AddToPath_Movement 72, 3, 5 2095 | AddToPath_Movement 12, 3, 0 2096 | AddToPath_Movement 72, 3, 5 2097 | AddToPath_Movement 12, 3, 0 2098 | AddToPath_Movement 8, 3, 8 2099 | AddToPath_ContinueFlight 3, 0 2100 | AddToPath_Remove 2101 | END SUB 2102 | 2103 | SUB SetPathType (pathType%) 2104 | pathDataOffset%(pathType%) = pathDataIndex% 2105 | END SUB 2106 | 2107 | SUB AddPathDataElement (d!) 2108 | pathData!(pathDataIndex%) = d! 2109 | pathDataIndex% = pathDataIndex% + 1 2110 | END SUB 2111 | 2112 | SUB AddToPath_SetPosition (x!, y!, angle!) 2113 | AddPathDataElement CMD_SET_POSITION 2114 | AddPathDataElement x! 2115 | AddPathDataElement y! 2116 | AddPathDataElement angle! 2117 | END SUB 2118 | 2119 | SUB AddToPath_Movement (frames!, deltaMove!, deltaAngle!) 2120 | AddPathDataElement CMD_MOVEMENT 2121 | AddPathDataElement frames! 2122 | AddPathDataElement deltaMove! 2123 | AddPathDataElement deltaAngle! 2124 | END SUB 2125 | 2126 | SUB AddToPath_JoinFormation 2127 | AddPathDataElement CMD_JOIN_FORMATION 2128 | END SUB 2129 | 2130 | SUB AddToPath_LeaveFormation 2131 | AddPathDataElement CMD_LEAVE_FORMATION 2132 | END SUB 2133 | 2134 | SUB AddToPath_MoveAboveFormation 2135 | AddPathDataElement CMD_MOVE_ABOVE_FORMATION 2136 | END SUB 2137 | 2138 | SUB AddToPath_ContinueFlight (deltaMove!, deltaAngle!) 2139 | AddPathDataElement CMD_CONTINUE_FLIGHT 2140 | AddPathDataElement deltaMove! 2141 | AddPathDataElement deltaAngle! 2142 | END SUB 2143 | 2144 | SUB AddToPath_ToHeight (tagetHeight!) 2145 | AddPathDataElement CMD_TO_HEIGHT 2146 | AddPathDataElement tagetHeight! 2147 | END SUB 2148 | 2149 | SUB AddToPath_BeeReturn 2150 | AddPathDataElement CMD_BEE_RETURN 2151 | END SUB 2152 | 2153 | SUB AddToPath_Speed (speed!) 2154 | AddPathDataElement CMD_SPEED 2155 | AddPathDataElement speed! 2156 | END SUB 2157 | 2158 | SUB AddToPath_DiveAtPlayer 2159 | AddPathDataElement CMD_DIVE_AT_PLAYER 2160 | END SUB 2161 | 2162 | SUB AddToPath_Remove 2163 | AddPathDataElement CMD_REMOVE 2164 | END SUB 2165 | 2166 | SUB AddToPath_DiveToBeam 2167 | AddPathDataElement CMD_DIVE_TO_BEAM 2168 | END SUB 2169 | 2170 | SUB AddToPath_WaitForCapture 2171 | AddPathDataElement CMD_WAIT_FOR_CAPTURE 2172 | END SUB 2173 | 2174 | SUB AddToPath_TakeHostagePosition 2175 | AddPathDataElement CMD_TAKE_HOSTAGE_POSITION 2176 | END SUB 2177 | 2178 | SUB AddToPath_DoubleUpPlayer 2179 | AddPathDataElement CMD_DOUBLE_UP_PLAYER 2180 | END SUB 2181 | 2182 | SUB AddToPath_PlayerInStorage 2183 | AddPathDataElement CMD_PLAYER_IN_STORAGE 2184 | END SUB 2185 | 2186 | '===== Overall management of aliens during game play ================================================================================================================================================== 2187 | 2188 | SUB InitialiseAliensForNewGame 2189 | DIM i% 2190 | waveData.hasCaptive% = FALSE 2191 | waveData.playerInStorage = FALSE 2192 | FOR i% = 0 TO MAX_ALIENS - 1 2193 | alienData(i%).currentAction% = CMD_NONE 2194 | alienData(i%).controlPath% = PT_INACTIVE 2195 | NEXT i% 2196 | END SUB 2197 | 2198 | SUB UpdateAlienManager (initialised%) 2199 | IF initialised% = FALSE THEN waveData.state% = WS_INITIALISE_PLAY 2200 | IF game.gameOver% THEN 2201 | game.gameOverCounter% = game.gameOverCounter% - 1 2202 | IF game.gameOverCounter% = 0 THEN 2203 | PrepareBackendEvents 2204 | EXIT SUB 2205 | END IF 2206 | END IF 2207 | SELECT CASE waveData.state% 2208 | CASE WS_INITIALISE_PLAY, WE_SHOW_PRE_GAME_OVERLAYS 2209 | WS_InitialisePlay 2210 | CASE WS_INITIALISE_WAVE 2211 | WS_InitialiseWave 2212 | CASE WS_WAIT_FOR_ATTACK 2213 | WS_WaitForAttack 2214 | CASE WS_PREPARE_BATCH 2215 | WS_PrepareBatch 2216 | CASE WS_BRING_ON_BATCH 2217 | WS_BringOnBatch 2218 | CASE WS_PLAY_STAGE 2219 | WS_PlayStage 2220 | CASE WS_CHALLENGE_RESULTS 2221 | WS_ChallengeResults 2222 | CASE WS_POST_STAGE 2223 | WS_PostStage 2224 | CASE WS_PAUSE 2225 | waveData.pauseCounter% = waveData.pauseCounter% - 1 2226 | IF waveData.pauseCounter% <= 0 THEN waveData.state% = waveData.postPauseState% 2227 | END SELECT 2228 | END SUB 2229 | 2230 | SUB WS_InitialisePlay 2231 | IF waveData.state% = WS_INITIALISE_PLAY THEN waveData.substate% = 0: waveData.postPauseState% = WE_SHOW_PRE_GAME_OVERLAYS: waveData.bombCount% = 0 2232 | SELECT CASE waveData.substate% 2233 | CASE 0 2234 | game.gameOver% = FALSE 2235 | player.lives% = 3 2236 | game.extraLife& = 20000 2237 | InitialiseAliensForNewGame 2238 | InitialisePlayer 2239 | InitialiseBullets 2240 | PlaySfx SFX_STAGE_INTRO 2241 | game.stage% = 1 2242 | stars.scroll% = FALSE 2243 | game.score& = 0 2244 | HideOverlays 2245 | PrintText "PLAYER 1", 10, 18, 2 2246 | waveData.pauseCounter = 4 * game.fps% 2247 | waveData.state% = WS_PAUSE 2248 | waveData.substate% = waveData.substate% + 1 2249 | CASE 1 2250 | HideOverlays 2251 | PrintText "STAGE 1", 10, 18, 2 2252 | AddEvent EVENT_PROCESS_FLAGS 2253 | waveData.pauseCounter = 1.6 * game.fps% 2254 | waveData.state% = WS_PAUSE 2255 | waveData.substate% = waveData.substate% + 1 2256 | CASE 2 2257 | stars.scroll% = TRUE 2258 | PrintText "PLAYER 1", 10, 16, 2 2259 | NewLife 2260 | waveData.pauseCounter = 1 * game.fps% 2261 | waveData.state% = WS_PAUSE 2262 | waveData.postPauseState% = WS_INITIALISE_WAVE 2263 | END SELECT 2264 | END SUB 2265 | 2266 | SUB WS_InitialiseWave 2267 | DIM quadrant%, i% 2268 | quadrant% = game.stage% / 4 2269 | waveData.simultaneousAttackCount% = Min!(8, 2 + quadrant% / 2) 2270 | waveData.continuousDiverCount% = Max!(30, 39 - (0.75 + quadrant%) / 4) 2271 | waveData.bombAvailability% = Min!(6, 2 + quadrant% / 4) 2272 | waveData.continuousAttack% = FALSE 2273 | waveData.challengingStage% = ((game.stage% - 3) MOD 4) = 0 2274 | waveData.aliensInFormation% = TRUE 2275 | waveData.hitCount% = 0 2276 | FOR i% = 0 TO MAX_ALIENS - 1 2277 | alienData(i%).attackGroup% = -1 2278 | NEXT i% 2279 | waveData.formationCentreX% = 0 2280 | waveData.formationCentreY% = 82 2281 | waveData.formationSpread! = 16 2282 | waveData.formationDirection! = 1 2283 | FOR i% = 0 TO MAX_ATTACKING_FORMATIONS - 1 2284 | numberInAttackingFormation%(i%) = 0 2285 | NEXT i% 2286 | CreateWavePrepare 2287 | waveData.state = WS_WAIT_FOR_ATTACK 2288 | END SUB 2289 | 2290 | SUB WS_WaitForAttack 2291 | IF waveData.aliensCanAttack% = FALSE THEN EXIT SUB 2292 | IF waveData.aliensAttackingPauseCounter% > 0 THEN 2293 | waveData.aliensAttackingPauseCounter% = waveData.aliensAttackingPauseCounter% - 1 2294 | IF waveData.aliensAttackingPauseCounter% = 0 THEN 2295 | player.canFire% = TRUE 2296 | END IF 2297 | EXIT SUB 2298 | END IF 2299 | HideOverlays 2300 | waveData.batchCounter% = 5 2301 | waveData.state% = WS_PREPARE_BATCH 2302 | END SUB 2303 | 2304 | SUB WS_PrepareBatch 2305 | waveData.aliensArrived% = FALSE 2306 | waveData.aliensInFormation% = TRUE 2307 | IF waveData.aliensCanAttack% = FALSE THEN 2308 | MoveFormation: 2309 | EXIT SUB 2310 | END IF 2311 | IF waveData.aliensAttackingPauseCounter% > 0 THEN 2312 | MoveFormation 2313 | waveData.aliensAttackingPauseCounter% = waveData.aliensAttackingPauseCounter% - 1 2314 | IF waveData.aliensAttackingPauseCounter% = 0 THEN 2315 | player.canFire% = TRUE 2316 | END IF 2317 | ELSE 2318 | IF waveData.challengingStage% = FALSE THEN 2319 | CreateWave 2320 | ELSE 2321 | CreateChallengeWave 2322 | END IF 2323 | waveData.postArrivalPause% = 15 2324 | waveData.state% = WS_BRING_ON_BATCH 2325 | END IF 2326 | END SUB 2327 | 2328 | SUB WS_BringOnBatch 2329 | IF waveData.postArrivalPause% > 0 THEN 2330 | MoveFormation 2331 | waveData.aliensArrived% = CheckAllArrived% 2332 | IF waveData.aliensArrived% = TRUE THEN 2333 | waveData.postArrivalPause% = waveData.postArrivalPause% - 1 2334 | END IF 2335 | ELSE 2336 | IF waveData.aliensAttackingPauseCounter% > 0 THEN 2337 | waveData.aliensAttackingPauseCounter% = waveData.aliensAttackingPauseCounter% - 1 2338 | IF waveData.aliensAttackingPauseCounter% = 0 THEN 2339 | player.canFire% = TRUE 2340 | HideOverlays 2341 | END IF 2342 | END IF 2343 | MoveFormation 2344 | waveData.aliensInFormation% = CheckInFormation% 2345 | IF waveData.formationCentreX% = 0 THEN 2346 | waveData.batchCounter% = waveData.batchCounter% - 1 2347 | IF waveData.batchCounter% > 0 THEN 2348 | waveData.state% = WS_PREPARE_BATCH 2349 | ELSE 2350 | IF waveData.challengingStage% = FALSE THEN 2351 | waveData.aliensCanAttack% = TRUE 2352 | waveData.formationDirection! = 0.096 2353 | waveData.stageClear% = FALSE 2354 | waveData.state% = WS_PLAY_STAGE 2355 | IF NOT waveData.challengingStage% THEN PlaySfxLooping SFX_AMBIENCE 2356 | ELSE 2357 | waveData.state% = WS_CHALLENGE_RESULTS 2358 | waveData.substate% = 0 2359 | END IF 2360 | END IF 2361 | END IF 2362 | END IF 2363 | END SUB 2364 | 2365 | SUB WS_PlayStage 2366 | DIM randVal% 2367 | waveData.continuousAttack% = waveData.hitCount% >= waveData.continuousDiverCount% AND waveData.aliensCanAttack% AND waveData.aliensAttackingPauseCounter% = 0 2368 | waveData.formationSpread! = waveData.formationSpread! + waveData.formationDirection! 2369 | IF waveData.formationSpread! <= 16 OR waveData.formationSpread! >= 22 THEN waveData.formationDirection! = -waveData.formationDirection! 2370 | waveData.aliensInFormation% = CheckInFormation% 2371 | IF waveData.aliensCanAttack% = TRUE THEN 2372 | IF waveData.aliensAttackingPauseCounter% > 0 THEN 2373 | waveData.aliensAttackingPauseCounter% = waveData.aliensAttackingPauseCounter% - 1 2374 | IF waveData.aliensAttackingPauseCounter% = 0 THEN 2375 | player.canFire% = TRUE 2376 | HideOverlays 2377 | END IF 2378 | ELSE 2379 | IF CountActiveFormations% < waveData.simultaneousAttackCount THEN 2380 | randVal% = RND * 5 2381 | SELECT CASE randVal% 2382 | CASE 0: BossFormationSwoop 2383 | CASE 1: BeeLoopBackupDive 2384 | CASE 2: ButterflyDiveOffScreen 2385 | CASE 3: CaptiveSwoop 2386 | CASE 4: IF waveData.continuousAttack = FALSE THEN BossCaptureDive 2387 | END SELECT 2388 | END IF 2389 | END IF 2390 | END IF 2391 | IF IsStageClear% THEN 2392 | StopSfx SFX_AMBIENCE 2393 | waveData.state% = WS_PAUSE 2394 | waveData.pauseCounter% = game.fps% 2395 | waveData.postPauseState% = WS_POST_STAGE 2396 | END IF 2397 | END SUB 2398 | 2399 | SUB WS_ChallengeResults 2400 | SELECT CASE waveData.substate% 2401 | CASE 0 2402 | waveData.state% = WS_PAUSE 2403 | waveData.pauseCounter% = game.fps% 2404 | waveData.substate% = 1 2405 | waveData.postPauseState% = WS_CHALLENGE_RESULTS 2406 | CASE 1 2407 | IF waveData.hitCount% = 40 THEN PlaySfx SFX_CHALLENGING_STAGE_PERFECT ELSE PlaySfx SFX_CHALLENGING_STAGE_OVER 2408 | waveData.state% = WS_PAUSE 2409 | waveData.pauseCounter% = game.fps% 2410 | waveData.substate% = 2 2411 | CASE 2 2412 | PrintText "NUMBER OF HITS", 5, 18, COLOUR_BLUE 2413 | waveData.state% = WS_PAUSE 2414 | waveData.pauseCounter% = game.fps% 2415 | waveData.substate% = 3 2416 | CASE 3 2417 | PrintText LTRIM$(STR$(waveData.hitCount%)), 21, 18, COLOUR_BLUE 2418 | waveData.state% = WS_PAUSE 2419 | waveData.pauseCounter% = game.fps% 2420 | IF waveData.hitCount% = 40 THEN waveData.substate% = 4 ELSE waveData.substate% = 11 2421 | CASE 4 TO 9 2422 | IF waveData.substate% MOD 2 = 0 THEN 2423 | PrintText "PERFECT", 10, 16, COLOUR_RED 2424 | ELSE 2425 | PrintText " ", 10, 16, COLOUR_RED 2426 | END IF 2427 | waveData.state% = WS_PAUSE 2428 | waveData.pauseCounter% = 0.2 * game.fps% 2429 | waveData.substate% = waveData.substate% + 1 2430 | CASE 10 2431 | ModifyScoreBy 10000 2432 | PrintText "NUMBER OF HITS", 5, 18, COLOUR_BLUE 2433 | PrintText LTRIM$(STR$(waveData.hitCount%)), 21, 18, COLOUR_BLUE 2434 | PrintText "PERFECT", 10, 16, 1 2435 | PrintText "SPECIAL BONUS 10000 PTS", 2, 20, COLOUR_YELLOW 2436 | waveData.state% = WS_PAUSE 2437 | waveData.pauseCounter% = 2 * game.fps% 2438 | waveData.substate% = 13 2439 | CASE 11 2440 | PrintText "BONUS", 8, 20, COLOUR_BLUE 2441 | waveData.state% = WS_PAUSE 2442 | waveData.pauseCounter% = 1.2 * game.fps% 2443 | waveData.substate% = 12 2444 | CASE 12 2445 | ModifyScoreBy waveData.hitCount% * 100 2446 | PrintText "NUMBER OF HITS", 5, 18, COLOUR_BLUE 2447 | PrintText LTRIM$(STR$(waveData.hitCount%)), 21, 18, COLOUR_BLUE 2448 | PrintText "BONUS", 8, 20, COLOUR_BLUE 2449 | PrintText LTRIM$(STR$(waveData.hitCount% * 100)), 15, 20, COLOUR_BLUE 2450 | waveData.state% = WS_PAUSE 2451 | waveData.pauseCounter% = 2 * game.fps% 2452 | waveData.substate% = 13 2453 | CASE 13 2454 | HideOverlays 2455 | waveData.state% = WS_PAUSE 2456 | waveData.pauseCounter% = 1 * game.fps% 2457 | waveData.substate% = 13 2458 | waveData.postPauseState% = WS_POST_STAGE 2459 | END SELECT 2460 | END SUB 2461 | 2462 | SUB WS_PostStage 2463 | IF NOT player.state% = PLAYER_ACTIVE THEN EXIT SUB 2464 | IF waveData.aliensAttackingPauseCounter% > 0 THEN waveData.aliensAttackingPauseCounter% = waveData.aliensAttackingPauseCounter% - 1: EXIT SUB 2465 | player.canFire% = TRUE 2466 | HideOverlays 2467 | game.stage% = game.stage% + 1 2468 | IF ((game.stage - 3) MOD 4) = 0 THEN 2469 | PrintText "CHALLENGING STAGE", 5, 18, 2 2470 | PlaySfx SFX_CHALLENGING_STAGE 2471 | ELSE 2472 | PrintText "STAGE" + STR$(game.stage%), 10, 18, 2 2473 | END IF 2474 | AddEvent EVENT_PROCESS_FLAGS 2475 | waveData.state% = WS_PAUSE 2476 | waveData.pauseCounter% = game.fps% * 2 2477 | waveData.postPauseState% = WS_INITIALISE_WAVE 2478 | END SUB 2479 | 2480 | '===== Helper functions for determining alien actions ================================================================================================================================================= 2481 | 2482 | FUNCTION IsStageClear% ' Have we completed the level? 2483 | DIM i% 2484 | FOR i% = 0 TO MAX_ALIENS - 1 2485 | IF CheckIsVisible%(alienData(i%)) THEN IsStageClear% = FALSE: EXIT FUNCTION 2486 | NEXT i% 2487 | IsStageClear% = TRUE 2488 | END FUNCTION 2489 | 2490 | FUNCTION OutlyingAlien% (alienType%) ' Fine the alien closest to the formation's edge 2491 | DIM maxX!, i% 2492 | OutlyingAlien% = -1 2493 | maxX! = -1 2494 | FOR i% = 0 TO MAX_ALIENS - 1 2495 | IF alienData(i%).alienType% = alienType% THEN 2496 | IF alienData(i%).currentAction% = CMD_HOLD_FORMATION THEN 2497 | IF ABS(alienData(i%).formationXOffset!) >= maxX! AND (maxX! = -1 OR RND < 0.5) THEN 2498 | OutlyingAlien% = i% 2499 | maxX! = ABS(alienData(i%).formationXOffset!) 2500 | END IF 2501 | END IF 2502 | END IF 2503 | NEXT i% 2504 | END FUNCTION 2505 | 2506 | FUNCTION CaptorId% ' Find the boss galaga that has kidnapped the player 2507 | DIM i% 2508 | FOR i% = 0 TO MAX_ALIENS - 1 2509 | IF alienData(i%).isCaptor% THEN CaptorId% = i%: EXIT FUNCTION 2510 | NEXT i% 2511 | CaptorId% = -1 2512 | END FUNCTION 2513 | 2514 | FUNCTION CaptiveId% ' Find the captive alien (looks like she player's ship) 2515 | DIM i% 2516 | FOR i% = 0 TO MAX_ALIENS - 1 2517 | IF alienData(i%).isCaptive% THEN CaptiveId% = i%: EXIT FUNCTION 2518 | NEXT i% 2519 | CaptiveId% = -1 2520 | END FUNCTION 2521 | 2522 | FUNCTION EmptyAttackFormationIndex% ' Find an unused formation id for an attack 2523 | DIM i% 2524 | FOR i% = 0 TO MAX_ATTACKING_FORMATIONS - 1 2525 | IF numberInAttackingFormation%(i%) = 0 THEN EmptyAttackFormationIndex% = i%: EXIT FUNCTION 2526 | NEXT i% 2527 | END FUNCTION 2528 | 2529 | FUNCTION CanShoot% (alien AS ALIENDATA) ' Check whether the player can shoot 2530 | CanShoot% = alien.alienType% <> TYPE_PLAYER AND (alien.isCaptor% = FALSE OR waveData.hasCaptive% = FALSE OR alien.beamActive% = FALSE) 2531 | END FUNCTION 2532 | 2533 | FUNCTION CanDoContinuousAttack% (alien AS ALIENDATA) ' Should the aliens be cintinually attacking without pause? 2534 | CanDoContinuousAttack% = alien.continualPath% = PT_UP_AND_DIVE_WITH_BOSS OR alien.continualPath% = PT_BUTTERFLY_PATH OR alien.continualPath% = PT_BEE_PATH 2535 | END FUNCTION 2536 | 2537 | FUNCTION OffSide% (x%) ' Are we off the side of the screen? 2538 | OffSide% = ABS(x%) > 112 + 8 2539 | END FUNCTION 2540 | 2541 | FUNCTION OffLeft% (x%) ' Are we off the left of the screen? 2542 | OffLeft% = x% < -112 - 8 2543 | END FUNCTION 2544 | 2545 | FUNCTION OffRight% (x%) ' Are we off the right of the screen? 2546 | OffRight% = x% > 112 + 8 2547 | END FUNCTION 2548 | 2549 | FUNCTION OffTop% (y%) ' Are we off the top of the screen? 2550 | OffTop% = y% > 108 + 8 2551 | END FUNCTION 2552 | 2553 | FUNCTION OffBottom% (y%) ' Are we off the bottom of the screen? 2554 | OffBottom% = y% < -180 - 8 2555 | END FUNCTION 2556 | 2557 | FUNCTION CheckInFormation% ' Check if all aliens are in their formation (i.e. with nobody attacking or diving) 2558 | DIM i% 2559 | CheckInFormation% = FALSE 2560 | FOR i% = 0 TO MAX_ALIENS - 1 2561 | IF CheckIsVisible(alienData(i%)) = TRUE AND NOT (alienData(i%).currentAction% = CMD_DOUBLE_UP_PLAYER OR alienData(i%).currentAction% = CMD_HOLD_FORMATION) THEN EXIT FUNCTION 2562 | NEXT i% 2563 | CheckInFormation% = TRUE 2564 | END FUNCTION 2565 | 2566 | FUNCTION CheckAllArrived% ' Check if all aliens have arrived 2567 | DIM i% 2568 | CheckAllArrived% = FALSE 2569 | FOR i% = 0 TO MAX_ALIENS - 1 2570 | IF (CheckIsVisible(alienData(i%)) = TRUE OR alienData(i%).currentAction% = CMD_INACTIVE) AND (alienData(i%).currentAction% <> CMD_HOLD_FORMATION) THEN 2571 | EXIT FUNCTION 2572 | END IF 2573 | NEXT i% 2574 | CheckAllArrived% = TRUE 2575 | END FUNCTION 2576 | 2577 | FUNCTION CheckIsVisible% (alien AS ALIENDATA) ' Check if an alien is currently visible 2578 | CheckIsVisible% = NOT (alien.currentAction% = CMD_WAIT_FOR_CAPTURE OR alien.currentAction% = CMD_DEAD OR alien.currentAction% = CMD_DESTROYED OR alien.currentAction% = CMD_INACTIVE OR alien.currentAction% = CMD_PLAYER_IN_STORAGE OR alien.currentAction% = CMD_REMOVE OR alien.controlPath% = PT_INACTIVE OR alien.controlPath% = PT_WAITING OR alien.pathDelay% > 0) 2579 | END FUNCTION 2580 | 2581 | FUNCTION CountActiveFormations% ' See how many groups of aliens are attacking 2582 | DIM i%, c% 2583 | c% = 0 2584 | FOR i% = 0 TO MAX_ATTACKING_FORMATIONS - 1 2585 | IF numberInAttackingFormation%(i%) > 0 THEN c% = c% + 1 2586 | NEXT i% 2587 | CountActiveFormations% = c% 2588 | END FUNCTION 2589 | 2590 | SUB SetPathTypeForAlien (alien AS ALIENDATA, pathName%, delay%, direction%) 2591 | alien.pathDelay% = delay% 2592 | alien.controlPath% = pathName% 2593 | alien.direction% = direction% 2594 | alien.continualPath% = pathName% 2595 | END SUB 2596 | 2597 | SUB AddToAttackingGroup (alien AS ALIENDATA, attackingGroup%) 2598 | alien.attackGroup% = attackingGroup% 2599 | numberInAttackingFormation%(attackingGroup%) = numberInAttackingFormation%(attackingGroup%) + 1 2600 | END SUB 2601 | 2602 | SUB RemoveFromAttackGroup (alien AS ALIENDATA) 2603 | IF alien.attackGroup% > -1 THEN 2604 | numberInAttackingFormation%(alien.attackGroup%) = numberInAttackingFormation%(alien.attackGroup%) - 1 2605 | alien.attackGroup% = -1 2606 | END IF 2607 | END SUB 2608 | 2609 | SUB CheckForBatchOfEight (alien AS ALIENDATA) ' Player scores bonuses for hitting batches of oncoming aliens during challenge stages 2610 | DIM i%, challengeNum% 2611 | FOR i% = alien.batchNum% * 8 TO alien.batchNum% * 8 + 7 2612 | IF alienData(i%).currentAction% <> CMD_DEAD AND alienData(i%).currentAction% <> CMD_DESTROYED THEN EXIT SUB 2613 | NEXT i% 2614 | challengeNum% = Min!(INT(INT((game.stage% - 3) / 4) / 2), 3) 2615 | alien.scoreCostume% = 4 + challengeNum% 2616 | SELECT CASE challengeNum% 2617 | CASE 0 2618 | ModifyScoreBy 1000 2619 | CASE 1 2620 | ModifyScoreBy 1500 2621 | CASE 2 2622 | ModifyScoreBy 2000 2623 | CASE 3 2624 | ModifyScoreBy 3000 2625 | END SELECT 2626 | END SUB 2627 | 2628 | '===== Set a boss galaga into a dive - he can take captured ships and/or adjacent aliens with him ===================================================================================================== 2629 | 2630 | SUB BossFormationSwoop 2631 | DIM bossIndex%, i%, bossCompany%, captive% 2632 | bossIndex% = -1 2633 | FOR i% = 0 TO MAX_ALIENS - 1 2634 | IF alienData(i%).alienType% = TYPE_BOSS_GALAGA OR alienData(i%).alienType% = TYPE_BOSS_GALAGA_SHOT THEN 2635 | IF alienData(i%).currentAction% = CMD_HOLD_FORMATION THEN 2636 | IF bossIndex% = -1 OR RND < 0.5 THEN bossIndex% = i% 2637 | END IF 2638 | END IF 2639 | NEXT i% 2640 | IF bossIndex% = -1 THEN EXIT SUB 2641 | PlaySfx SFX_GALAGA_ATTACK 2642 | SetPathTypeForAlien alienData(bossIndex%), PT_UP_AND_DIVE_WITH_BOSS, 0, (alienData(bossIndex%).formationXOffset! > 0) * -2 - 1 2643 | AddToAttackingGroup alienData(bossIndex%), EmptyAttackFormationIndex% 2644 | IF waveData.hasCaptive% THEN 2645 | IF alienData(bossIndex%).isCaptor% AND alienData(CaptiveId%).currentAction% = CMD_HOLD_FORMATION THEN 2646 | captive% = CaptiveId% 2647 | SetPathTypeForAlien alienData(captive%), PT_UP_AND_DIVE_WITH_BOSS, 0, (alienData(captive%).formationXOffset! > 0) * -2 - 1 2648 | AddToAttackingGroup alienData(captive%), EmptyAttackFormationIndex% 2649 | END IF 2650 | END IF 2651 | bossCompany% = -1 2652 | FOR i% = 0 TO MAX_ALIENS - 1 2653 | IF alienData(i%).alienType% = TYPE_BUTTERFLY THEN 2654 | IF alienData(i%).currentAction% = CMD_HOLD_FORMATION THEN 2655 | IF alienData(i%).formationXOffset! = alienData(bossIndex%).formationXOffset! AND alienData(i%).formationYOffset! = alienData(bossIndex%).formationYOffset! + 1 THEN bossCompany% = i%: EXIT FOR 2656 | END IF 2657 | END IF 2658 | NEXT i% 2659 | IF bossCompany% <> -1 THEN 2660 | SetPathTypeForAlien alienData(bossCompany%), PT_UP_AND_DIVE_WITH_BOSS, 0, (alienData(bossCompany%).formationXOffset! > 0) * -2 - 1 2661 | AddToAttackingGroup alienData(bossCompany%), EmptyAttackFormationIndex% 2662 | bossCompany% = -1 2663 | FOR i% = 0 TO MAX_ALIENS - 1 2664 | IF alienData(i%).alienType% = TYPE_BUTTERFLY THEN 2665 | IF alienData(i%).currentAction% = CMD_HOLD_FORMATION THEN 2666 | IF ABS(alienData(i%).formationXOffset! - alienData(bossIndex%).formationXOffset!) = 1 AND alienData(i%).formationYOffset! = alienData(bossIndex%).formationYOffset! + 1 AND (bossCompany% = -1 OR RND < 0.5) THEN bossCompany% = i% 2667 | END IF 2668 | END IF 2669 | NEXT i% 2670 | IF bossCompany% <> -1 THEN 2671 | SetPathTypeForAlien alienData(bossCompany%), PT_UP_AND_DIVE_WITH_BOSS, 0, (alienData(bossCompany%).formationXOffset! > 0) * -2 - 1 2672 | AddToAttackingGroup alienData(bossCompany%), EmptyAttackFormationIndex% 2673 | END IF 2674 | ELSE 2675 | FOR i% = 0 TO MAX_ALIENS - 1 2676 | IF alienData(i%).alienType% = TYPE_BUTTERFLY THEN 2677 | IF alienData(i%).currentAction% = CMD_HOLD_FORMATION THEN 2678 | IF ABS(alienData(i%).formationXOffset! - alienData(bossIndex%).formationXOffset!) = 1 AND alienData(i%).formationYOffset! = alienData(bossIndex%).formationYOffset! + 1 THEN 2679 | SetPathTypeForAlien alienData(i%), PT_UP_AND_DIVE_WITH_BOSS, 0, (alienData(i%).formationXOffset! > 0) * -2 - 1 2680 | AddToAttackingGroup alienData(i%), EmptyAttackFormationIndex% 2681 | END IF 2682 | END IF 2683 | END IF 2684 | NEXT i% 2685 | END IF 2686 | END SUB 2687 | 2688 | '===== Start a bee alien attack (possibly in a group) ================================================================================================================================================= 2689 | 2690 | SUB BeeLoopBackupDive 2691 | DIM targetIndex% 2692 | targetIndex% = OutlyingAlien%(TYPE_BEE) 2693 | IF targetIndex% <> -1 THEN 2694 | PlaySfx SFX_GALAGA_ATTACK 2695 | SetPathTypeForAlien alienData(targetIndex%), PT_BEE_PATH, 0, (alienData(targetIndex%).formationXOffset! > 0) * -2 - 1 2696 | AddToAttackingGroup alienData(targetIndex%), EmptyAttackFormationIndex% 2697 | END IF 2698 | END SUB 2699 | 2700 | '===== Start a butterfly alien attack (possibly in a group) =========================================================================================================================================== 2701 | 2702 | SUB ButterflyDiveOffScreen 2703 | DIM targetIndex% 2704 | targetIndex% = OutlyingAlien%(TYPE_BUTTERFLY) 2705 | IF targetIndex% <> -1 THEN 2706 | PlaySfx SFX_GALAGA_ATTACK 2707 | SetPathTypeForAlien alienData(targetIndex%), PT_BUTTERFLY_PATH, 0, (alienData(targetIndex%).formationXOffset! > 0) * -2 - 1 2708 | AddToAttackingGroup alienData(targetIndex%), EmptyAttackFormationIndex% 2709 | END IF 2710 | END SUB 2711 | 2712 | '===== A captured ship can swoop down on its own if its captor has been destroyed while in formation ================================================================================================== 2713 | 2714 | SUB CaptiveSwoop 2715 | IF waveData.hasCaptive% = TRUE THEN 2716 | IF alienData(CaptorId%).currentAction% = CMD_DESTROYED THEN 2717 | IF alienData(CaptiveId%).currentAction% = CMD_HOLD_FORMATION THEN 2718 | SetPathTypeForAlien alienData(CaptiveId%), PT_PLAYER_SWOOP, 0, (alienData(CaptiveId%).formationXOffset! > 0) * -2 - 1 2719 | AddToAttackingGroup alienData(CaptiveId%), EmptyAttackFormationIndex% 2720 | END IF 2721 | END IF 2722 | END IF 2723 | END SUB 2724 | 2725 | '===== Start a boss galaga swooping down to fire his capture beam ===================================================================================================================================== 2726 | 2727 | SUB BossCaptureDive 2728 | DIM bossIndex%, i% 2729 | IF waveData.hasCaptive% = FALSE AND player.doubleShip% = FALSE THEN 2730 | bossIndex% = -1 2731 | FOR i% = 0 TO MAX_ALIENS - 1 2732 | IF alienData(i%).alienType% = TYPE_BOSS_GALAGA OR alienData(i%).alienType% = TYPE_BOSS_GALAGA_SHOT THEN 2733 | IF alienData(i%).continualPath% = PT_UP_AND_DIVE_TO_CAPTURE AND alienData(i%).currentAction% <> CMD_DESTROYED THEN EXIT SUB 2734 | IF alienData(i%).currentAction% = CMD_HOLD_FORMATION THEN 2735 | IF bossIndex% = -1 OR RND < 0.5 THEN bossIndex% = i% 2736 | END IF 2737 | END IF 2738 | NEXT i% 2739 | IF bossIndex% = -1 THEN EXIT SUB 2740 | PlaySfx SFX_GALAGA_ATTACK 2741 | SetPathTypeForAlien alienData(bossIndex%), PT_UP_AND_DIVE_TO_CAPTURE, 0, (alienData(bossIndex%).formationXOffset! > 0) * -2 - 1 2742 | AddToAttackingGroup alienData(bossIndex%), EmptyAttackFormationIndex% 2743 | END IF 2744 | END SUB 2745 | 2746 | '===== Check for collisions against player or bullets ================================================================================================================================================= 2747 | 2748 | SUB CheckAgainstBullets (alien AS ALIENDATA) 2749 | DIM i% 2750 | IF CanShoot%(alien) = FALSE THEN EXIT SUB 2751 | FOR i% = 0 TO MAX_BULLETS - 1 2752 | IF bullet(i%).state% = BULLET_ACTIVE THEN 2753 | IF ABS(alien.xPos! - bullet(i%).xPos%) < 7 AND ABS(alien.yPos! - bullet(i%).yPos%) < 10 THEN 2754 | bullet(i%).state% = BULLET_REMOVING 2755 | HitAlien alien 2756 | END IF 2757 | END IF 2758 | NEXT i% 2759 | END SUB 2760 | 2761 | SUB CheckAgainstCollisions (alien AS ALIENDATA) 2762 | DIM i% 2763 | IF alien.alienType% = TYPE_PLAYER THEN EXIT SUB 2764 | IF ABS(alien.yPos! - player.yPos%) < 14 THEN 2765 | FOR i% = 0 TO 1 2766 | IF ABS(alien.xPos! - ship(i%).xPos%) < 14 AND ship(i%).state% = SHIP_ACTIVE AND NOT ship(i%).isHit% THEN 2767 | ship(i%).isHit% = TRUE 2768 | HitAlien alien 2769 | END IF 2770 | NEXT i% 2771 | END IF 2772 | END SUB 2773 | 2774 | '===== Functions supporting score modification and display ============================================================================================================================================ 2775 | 2776 | SUB ModifyScoreBy (score%) 2777 | IF game.score& < game.extraLife& AND game.score& + score% >= game.extraLife& THEN 2778 | PlaySfx SFX_1_UP 2779 | player.lives% = player.lives% + 1 2780 | IF game.extraLife& = 20000 THEN game.extraLife& = 70000 ELSE game.extraLife& = game.extraLife& + 70000 2781 | END IF 2782 | game.score& = game.score& + score% 2783 | IF game.score& > game.hiscore& THEN 2784 | game.hiscore& = game.score& 2785 | END IF 2786 | HideOverlays 2787 | END SUB 2788 | 2789 | SUB ShowScoreAndHiscore 2790 | ShowScore 2791 | ShowHiscore 2792 | END SUB 2793 | 2794 | SUB ShowScore 2795 | DIM score$ 2796 | score$ = LTRIM$(STR$(game.score&)) 2797 | PrintText score$, 6 - LEN(score$), 1, COLOUR_WHITE 2798 | END SUB 2799 | 2800 | SUB ShowHiscore 2801 | DIM score$ 2802 | score$ = LTRIM$(STR$(game.hiscore&)) 2803 | PrintText score$, 17 - LEN(score$), 1, COLOUR_WHITE 2804 | END SUB 2805 | 2806 | '===== An alien has been hit so determine the outcome ================================================================================================================================================= 2807 | 2808 | SUB HitAlien (alien AS ALIENDATA) 2809 | DIM i% 2810 | alien.scoreCostume% = -1 2811 | IF alien.alienType% = TYPE_BOSS_GALAGA THEN 2812 | PlaySfx SFX_BOSS_GALAGA_HIT 2813 | alien.alienType = TYPE_BOSS_GALAGA_SHOT 2814 | ELSE 2815 | SELECT CASE alien.alienType% 2816 | CASE TYPE_BOSS_GALAGA_SHOT 2817 | PlaySfx SFX_BOSS_GALAGA_DEFEAT 2818 | alien.scoreCostume% = 0 2819 | IF alien.currentAction% <> CMD_HOLD_FORMATION THEN 2820 | IF alien.attackGroup% = -1 THEN 2821 | alien.scoreCostume% = 1 2822 | ELSE 2823 | FOR i% = 0 TO MAX_ALIENS - 1 2824 | IF alienData(i%).attackGroup% = alien.attackGroup% THEN alien.scoreCostume% = alien.scoreCostume% + 1 2825 | NEXT i% 2826 | END IF 2827 | ModifyScoreBy bossScores%(alien.scoreCostume%) 2828 | END IF 2829 | IF waveData.hasCaptive% AND alien.isCaptor% AND alien.currentAction% <> CMD_HOLD_FORMATION AND alien.controlPath% <> PT_WAITING THEN 2830 | player.state% = PLAYER_WAITING_TO_DOUBLE 2831 | SetPathTypeForAlien alienData(CaptiveId%), PT_RESCUED_PLAYER, 0, 0 2832 | END IF 2833 | IF alien.beamActive% = TRUE THEN BeamCollapse 2834 | CASE TYPE_BUTTERFLY 2835 | PlaySfx SFX_GALAGA_DEFEAT_2 2836 | IF alien.currentAction% = CMD_HOLD_FORMATION THEN 2837 | ModifyScoreBy 80 2838 | ELSE 2839 | ModifyScoreBy 160 2840 | END IF 2841 | CASE TYPE_BEE 2842 | PlaySfx SFX_GALAGA_DEFEAT_2 2843 | IF alien.currentAction% = CMD_HOLD_FORMATION THEN 2844 | ModifyScoreBy 50 2845 | ELSE 2846 | ModifyScoreBy 100 2847 | END IF 2848 | CASE TYPE_PLAYER_CAPTURED 2849 | PlaySfx SFX_CAPTURED_FIGHTER_DESTROYED 2850 | ResetCaptive 2851 | ModifyScoreBy (1000) 2852 | CASE ELSE 2853 | 'TODO Haven't catered for transforms yet so we're only dealing with other types as part of challenge stages 2854 | PlaySfx SFX_GALAGA_DEFEAT_2 2855 | ModifyScoreBy (200) 2856 | END SELECT 2857 | alien.currentAction% = CMD_DEAD 2858 | IF waveData.challengingStage% THEN CheckForBatchOfEight alien 2859 | waveData.hitCount% = waveData.hitCount% + 1 2860 | RemoveFromAttackGroup alien 2861 | END IF 2862 | END SUB 2863 | 2864 | SUB ResetCaptive ' If a captured ship is no longer captured then we have some things to reset 2865 | DIM i% 2866 | i% = CaptiveId% 2867 | IF i% > -1 THEN alienData(i%).isCaptive% = FALSE 2868 | i% = CaptorId% 2869 | IF i% > -1 THEN alienData(i%).isCaptor% = FALSE: alienData(i%).beamActive% = FALSE 2870 | waveData.hasCaptive% = FALSE 2871 | END SUB 2872 | 2873 | '===== Individual alien management - following the commands on the alien's path ======================================================================================================================= 2874 | 2875 | SUB UpdateAliens (initialised%) 2876 | DIM i%, j% 2877 | FOR i% = 0 TO MAX_ALIENS - 1 2878 | IF alienData(i%).currentAction% <> CMD_DESTROYED THEN 2879 | IF alienData(i%).controlPath% <> PT_WAITING AND alienData(i%).controlPath% <> PT_INACTIVE THEN 2880 | IF alienData(i%).currentAction% <> CMD_DEAD THEN 2881 | FOR j% = 1 TO 60 / game.fps% ' Alien movement is defined at 60fps (so double for 30fps for example) 2882 | UpdatePosition alienData(i%) 2883 | NEXT j% 2884 | IF CheckIsVisible%(alienData(i%)) THEN 2885 | CheckAgainstBullets alienData(i%) 2886 | CheckAgainstCollisions alienData(i%) 2887 | END IF 2888 | IF alienData(i%).currentAction% = CMD_REMOVE THEN 2889 | alienData(i%).currentAction% = CMD_DESTROYED 2890 | ELSE 2891 | IF alienData(i%).currentAction% = CMD_DEAD THEN 2892 | IF alienData(i%).alienType% = TYPE_PLAYER_CAPTURED THEN 2893 | SetPathTypeForAlien alienData(i%), PT_WAIT_FOR_CAPTURE, 0, 1 2894 | RemoveFromAttackGroup alienData(i%) 2895 | SpawnAnimation SPAWN_EXPLOSION, alienData(i%) 2896 | IF alienData(i%).scoreCostume% > -1 THEN SpawnAnimation SPAWN_SCORE, alienData(i%) 2897 | alienData(i%).currentAction% = CMD_NONE 2898 | END IF 2899 | alienData(i%).rotation! = 0 2900 | alienData(i%).explosionCounter% = 0 2901 | END IF 2902 | END IF 2903 | ELSE 2904 | IF alienData(i%).explosionCounter% < 9 THEN 2905 | alienData(i%).explosionCounter% = alienData(i%).explosionCounter% + 1 2906 | ELSE 2907 | IF alienData(i%).scoreCostume% > -1 THEN SpawnAnimation SPAWN_SCORE, alienData(i%) 2908 | alienData(i%).currentAction% = CMD_DESTROYED 2909 | END IF 2910 | END IF 2911 | END IF 2912 | END IF 2913 | NEXT i% 2914 | END SUB 2915 | 2916 | SUB UpdatePosition (alien AS ALIENDATA) 2917 | ' Pull any data into local alien structure if starting a new control path 2918 | IF alien.controlPath% <> PT_NONE THEN 2919 | alien.pathIndex% = pathDataOffset%(alien.controlPath%) 2920 | alien.currentAction% = PT_INACTIVE 2921 | alien.fetchNewAction% = TRUE 2922 | alien.controlPath% = PT_NONE 2923 | END IF 2924 | ' Wait for any initial delay to time out before commencing a new control path 2925 | IF alien.pathDelay% > 0 THEN 2926 | alien.pathDelay% = alien.pathDelay% - 1 2927 | IF alien.pathDelay% = 0 THEN 2928 | alien.bombCount% = 0 2929 | IF waveData.bombAvailability% > 0 AND RND < 0.33 THEN alien.bombCount% = 1 2930 | END IF 2931 | EXIT SUB 2932 | END IF 2933 | alien.pathDelay% = -1 2934 | ' Grab a new command from the control path whenever necessary 2935 | DO UNTIL alien.fetchNewAction% = FALSE 2936 | alien.currentAction% = pathData!(alien.pathIndex%) 2937 | alien.pathIndex% = alien.pathIndex% + 1 2938 | alien.fetchNewAction% = FALSE 2939 | SetNewCommand alien 2940 | LOOP 2941 | ' Act out the current path command 2942 | SELECT CASE alien.currentAction% 2943 | CASE CMD_MOVEMENT: DoMovement alien 2944 | CASE CMD_JOIN_FORMATION: DoJoinFormation alien 2945 | CASE CMD_HOLD_FORMATION: DoHoldFormation alien 2946 | CASE CMD_CONTINUE_FLIGHT: DoContinueFlight alien 2947 | CASE CMD_MOVE_ABOVE_FORMATION: DoMoveAboveFormation alien 2948 | CASE CMD_TO_HEIGHT: DoToHeight alien 2949 | CASE CMD_DIVE_TO_BEAM: DoDiveToBeam alien 2950 | CASE CMD_FIRE_BEAM: DoFireBeam alien 2951 | CASE CMD_WAIT_FOR_CAPTURE: DoWaitForCapture alien 2952 | CASE CMD_TAKE_HOSTAGE_POSITION: DoTakeHostagePosition alien 2953 | CASE CMD_DOUBLE_UP_PLAYER: DoDoubleUpPlayer alien 2954 | CASE CMD_DIVE_AT_PLAYER: DoDiveAtPlayer alien 2955 | END SELECT 2956 | END SUB 2957 | 2958 | '===== When an alien starts a new command, various parameters need initialising ======================================================================================================================= 2959 | 2960 | SUB SetNewCommand (alien AS ALIENDATA) 2961 | SELECT CASE alien.currentAction% 2962 | CASE CMD_SET_POSITION: 2963 | alien.xPos! = (pathData!(alien.pathIndex%) - 112) * alien.direction% 2964 | alien.yPos! = 108 - pathData!(alien.pathIndex% + 1) 2965 | alien.rotation! = 180 + (180 - pathData!(alien.pathIndex% + 2)) * alien.direction% 2966 | alien.pathIndex% = alien.pathIndex% + 3 2967 | alien.fetchNewAction% = TRUE 2968 | CASE CMD_MOVEMENT: 2969 | alien.steps% = pathData!(alien.pathIndex%) 2970 | alien.deltaMove! = pathData!(alien.pathIndex% + 1) 2971 | alien.deltaTurn! = pathData!(alien.pathIndex% + 2) * alien.direction% 2972 | alien.pathIndex% = alien.pathIndex% + 3 2973 | CASE CMD_CONTINUE_FLIGHT: 2974 | alien.deltaMove! = pathData!(alien.pathIndex%) 2975 | alien.deltaTurn! = pathData!(alien.pathIndex% + 1) * alien.direction% 2976 | alien.pathIndex% = alien.pathIndex% + 2 2977 | CASE CMD_TO_HEIGHT: 2978 | alien.targetHeight% = 108 - pathData!(alien.pathIndex%) 2979 | alien.pathIndex% = alien.pathIndex% + 1 2980 | CASE CMD_WAIT_FOR_CAPTURE: 2981 | CASE CMD_PAUSE_ATTACK: 2982 | waveData.aliensAttackingPauseCounter% = pathData!(alien.pathIndex%) 2983 | alien.pathIndex% = alien.pathIndex% + 1 2984 | alien.fetchNewAction% = TRUE 2985 | CASE CMD_DOUBLE_UP_PLAYER: 2986 | player.state% = PLAYER_WAITING_TO_DOUBLE 2987 | waveData.aliensCanAttack% = FALSE 2988 | alien.doubleUpCounter% = 40 2989 | alien.alienType% = TYPE_PLAYER 2990 | SetCostumeWithOffset alien, 0 2991 | PlaySfx SFX_FIGHTER_RESCUED 2992 | CASE CMD_PLAYER_IN_STORAGE: 2993 | waveData.playerInStorage% = TRUE 2994 | CASE CMD_LEAVE_FORMATION: 2995 | IF waveData.continuousAttack% = FALSE OR alien.rotation! = 0 THEN 2996 | alien.steps% = 30 2997 | alien.deltaMove! = 2 2998 | alien.deltaTurn! = 6 * alien.direction% 2999 | alien.currentAction% = CMD_MOVEMENT 3000 | ELSE 3001 | alien.fetchNewAction% = TRUE 3002 | END IF 3003 | CASE CMD_BEE_RETURN: 3004 | IF waveData.continuousAttack% = FALSE THEN 3005 | alien.currentAction% = CMD_JOIN_FORMATION 3006 | ELSE 3007 | alien.fetchNewAction% = TRUE 3008 | END IF 3009 | CASE CMD_SPEED: 3010 | alien.deltaMove! = pathData!(alien.pathIndex%) 3011 | alien.pathIndex% = alien.pathIndex% + 1 3012 | alien.fetchNewAction% = TRUE 3013 | CASE CMD_DIVE_AT_PLAYER: 3014 | alien.targetX! = player.xPos% + ((ship(2).state% = SHIP_ACTIVE) - (ship(1).state% = SHIP_ACTIVE)) * 8 3015 | alien.targetY! = player.yPos% 3016 | alien.targetX! = alien.targetX! + (alien.targetX! - alien.xPos!) 3017 | alien.targetY! = alien.targetY! + (alien.targetY! - alien.yPos!) 3018 | END SELECT 3019 | END SUB 3020 | 3021 | '===== Perform the actions ============================================================================================================================================================================ 3022 | 3023 | SUB DoMovement (alien AS ALIENDATA) ' Moves a number of steps with delta movement and rotation 3024 | DropBombs alien 3025 | SetCostumeWithTime alien 3026 | Move alien, alien.deltaMove! 3027 | alien.rotation! = alien.rotation! + alien.deltaTurn! 3028 | alien.steps% = alien.steps% - 1 3029 | IF alien.steps% = 0 THEN alien.fetchNewAction% = TRUE 3030 | END SUB 3031 | 3032 | '===== Rejoin the formation at the top of the screen ================================================================================================================================================== 3033 | 3034 | SUB DoJoinFormation (alien AS ALIENDATA) 3035 | DIM targetX!, targetY!, deltaX!, deltaY! 3036 | DropBombs alien 3037 | GetFormationPosition alien, targetX!, targetY! 3038 | SetCostumeWithTime alien 3039 | deltaX! = targetX! - alien.xPos! 3040 | deltaY! = targetY! - alien.yPos! 3041 | IF deltaX! ^ 2 + deltaY! ^ 2 > 9 THEN 3042 | TurnTowardsDelta alien, deltaX!, deltaY!, 18 3043 | Move alien, alien.deltaMove! 3044 | ELSE 3045 | alien.xPos! = alien.xPos! + deltaX! 3046 | alien.yPos! = alien.yPos! + deltaY! 3047 | 3048 | IF waveData.continuousAttack% = FALSE THEN 3049 | IF ABS(ValidateAngle!(alien.rotation!)) < 6 THEN 3050 | alien.bombCount% = waveData.bombAvailability% 3051 | alien.rotation! = 0 3052 | alien.currentAction% = CMD_HOLD_FORMATION 3053 | RemoveFromAttackGroup alien 3054 | ELSE 3055 | alien.rotation! = alien.rotation! + (alien.rotation! < 0) * -12 - 6 3056 | END IF 3057 | ELSE 3058 | IF CanDoContinuousAttack%(alien) THEN 3059 | alien.bombCount% = waveData.bombAvailability% 3060 | alien.rotation! = 180 3061 | SetPathTypeForAlien alien, alien.continualPath%, 0, alien.direction% 3062 | PlaySfx SFX_GALAGA_ATTACK 3063 | ELSE 3064 | IF ABS(alien.rotation!) < 6 THEN 3065 | alien.bombCount% = waveData.bombAvailability% 3066 | alien.rotation! = 0 3067 | alien.currentAction% = CMD_HOLD_FORMATION 3068 | RemoveFromAttackGroup alien 3069 | ELSE 3070 | alien.rotation! = alien.rotation! + (alien.rotation! < 0) * -12 + 6 3071 | END IF 3072 | END IF 3073 | END IF 3074 | END IF 3075 | END SUB 3076 | 3077 | '===== Stay in the formation at the top of the screen ================================================================================================================================================= 3078 | 3079 | SUB DoHoldFormation (alien AS ALIENDATA) 3080 | GetFormationPosition alien, alien.xPos!, alien.yPos! 3081 | alien.continualPath% = PT_NONE 3082 | SetCostumeWithTime alien 3083 | END SUB 3084 | 3085 | '===== Continue flying at the current speed and direction ============================================================================================================================================= 3086 | 3087 | SUB DoContinueFlight (alien AS ALIENDATA) 3088 | DropBombs alien 3089 | Move alien, alien.deltaMove! 3090 | alien.rotation! = alien.rotation! + alien.deltaTurn! 3091 | SetCostumeWithTime alien 3092 | IF OffSide%(alien.xPos!) OR OffBottom%(alien.yPos!) OR OffTop%(alien.yPos!) THEN alien.fetchNewAction% = TRUE 3093 | END SUB 3094 | 3095 | '===== Move above the formation - probably after dropping off the bottom of the screen ================================================================================================================ 3096 | 3097 | SUB DoMoveAboveFormation (alien AS ALIENDATA) 3098 | DIM x!, y! 3099 | GetFormationPosition alien, x!, y! 3100 | alien.rotation! = 180 3101 | alien.xPos! = x! 3102 | alien.yPos! = 96 3103 | alien.fetchNewAction% = TRUE 3104 | END SUB 3105 | 3106 | '===== Continue with current speed and direction until reaching a target height ======================================================================================================================= 3107 | 3108 | SUB DoToHeight (alien AS ALIENDATA) 3109 | DIM y! 3110 | DropBombs alien 3111 | SetCostumeWithTime alien 3112 | y! = alien.yPos! 3113 | Move alien, alien.deltaMove! 3114 | IF (y! - alien.targetHeight%) * (alien.yPos! - alien.targetHeight%) <= 0 THEN 3115 | alien.fetchNewAction% = TRUE 3116 | END IF 3117 | END SUB 3118 | 3119 | '===== Dive down to a position where the capture beam can be fired ==================================================================================================================================== 3120 | 3121 | SUB DoDiveToBeam (alien AS ALIENDATA) 3122 | IF alien.yPos! >= -70 THEN 3123 | Move alien, 2 3124 | SetCostumeWithTime alien 3125 | ELSE 3126 | alien.beamActive% = TRUE 3127 | alien.yPos! = -70 3128 | alien.pauseCounter% = 0 3129 | alien.currentAction% = CMD_FIRE_BEAM 3130 | alien.isCaptor = TRUE 3131 | alien.rotation! = 180 3132 | SetCostumeWithOffset alien, 0 3133 | player.state% = PLAYER_ACTIVE 3134 | alien.captureCounter% = 0 3135 | PlaySfx SFX_BOSS_GALAGA_TRACTOR_BEAM 3136 | END IF 3137 | END SUB 3138 | 3139 | '===== Fire the capture beam ========================================================================================================================================================================== 3140 | 3141 | SUB DoFireBeam (alien AS ALIENDATA) 3142 | DIM sections% 3143 | IF alien.beamActive% = TRUE THEN 3144 | IF alien.captureCounter < 18 * 6 THEN sections% = INT(alien.captureCounter% / 12) ELSE sections% = 8 - INT(alien.captureCounter% - 18 * 6) / 12 3145 | IF sections% = 8 AND player.state% <> PLAYER_CAPTURING AND ABS(player.xPos% + ((ship(0).state% = SHIP_ACTIVE) * 8 - (ship(1).state% = SHIP_ACTIVE) * 8) - alien.xPos!) < 24 AND (ship(0).state% = SHIP_ACTIVE OR ship(1).state% = SHIP_ACTIVE) THEN 3146 | StopSfx SFX_BOSS_GALAGA_TRACTOR_BEAM 3147 | PlaySfx SFX_TRACTOR_BEAM_CAUGHT 3148 | player.state% = PLAYER_CAPTURING 3149 | END IF 3150 | 3151 | alien.captureCounter% = alien.captureCounter% + 1 3152 | IF alien.captureCounter% = 36 * 6 THEN 3153 | alien.beamActive% = FALSE 3154 | END IF 3155 | 3156 | ELSE 3157 | IF player.state% = PLAYER_CAPTURING THEN 3158 | IF alien.pauseCounter% = 0 THEN 3159 | PlaySfx SFX_FIGHTER_CAPTURED 3160 | PrintText "FIGHTER CAPTURED", 6, 19, COLOUR_RED 3161 | waveData.aliensCanAttack% = FALSE 3162 | ELSE 3163 | IF alien.pauseCounter% = 120 THEN 3164 | HideOverlays 3165 | SetPathTypeForAlien alien, PT_RETURN_WITH_CAPTURED, 0, alien.direction% 3166 | 3167 | END IF 3168 | END IF 3169 | alien.pauseCounter% = alien.pauseCounter% + 1 3170 | ELSE 3171 | alien.rotation! = 180 3172 | alien.fetchNewAction% = TRUE 3173 | ResetCaptive 3174 | END IF 3175 | END IF 3176 | END SUB 3177 | 3178 | SUB BeamCollapse ' If the alien firing the beam is detroyed (or for a few other reasons) we can remove the beam here 3179 | ResetCaptive 3180 | player.state% = PLAYER_ACTIVE 3181 | StopSfx SFX_BOSS_GALAGA_TRACTOR_BEAM 3182 | END SUB 3183 | 3184 | '===== The dummy invisible player ship sits in this state until the player is captured (at which point it takes its place) ============================================================================ 3185 | 3186 | SUB DoWaitForCapture (alien AS ALIENDATA) 3187 | DIM deltaX!, deltaY!, temp! 3188 | IF NOT waveData.hasCaptive% AND player.state% = PLAYER_CAPTURING THEN 3189 | waveData.hasCaptive% = TRUE 3190 | alien.isCaptive% = TRUE 3191 | alien.xPos! = player.xPos% - 8 - 16 * (ship(2).state% = SHIP_ACTIVE) 3192 | alien.yPos! = player.yPos% 3193 | alien.rotation! = 0 3194 | alien.alienType% = TYPE_PLAYER 3195 | SetCostumeWithOffset alien, 0 3196 | ELSE 3197 | IF waveData.hasCaptive% THEN 3198 | IF alienData(CaptorId%).beamActive% THEN 3199 | deltaX! = alienData(CaptorId%).xPos! - alien.xPos! 3200 | deltaY! = -86 - alien.yPos! 3201 | temp! = alien.rotation! 3202 | IF deltaX! ^ 2 + deltaY! ^ 2 > 2 THEN 3203 | alien.rotation! = _R2D(_ATAN2(deltaX!, deltaY!)) 3204 | Move alien, 1 3205 | alien.rotation! = temp! + 4 3206 | ELSE 3207 | alien.alienType% = TYPE_PLAYER_CAPTURED 3208 | SetCostumeWithOffset alien, 0 3209 | alien.xPos! = alien.xPos! + deltaX! 3210 | alien.yPos! = alien.yPos! + deltaY! 3211 | IF alien.rotation! MOD 360 <> 0 THEN alien.rotation! = temp! + 4 3212 | END IF 3213 | ELSE 3214 | IF alienData(CaptorId%).currentAction% = CMD_HOLD_FORMATION THEN 3215 | alien.formationXOffset! = alienData(CaptorId%).formationXOffset! 3216 | alien.formationYOffset! = 0 3217 | alien.alienType% = TYPE_PLAYER_CAPTURED 3218 | SetPathTypeForAlien alien, PT_TAKE_HOSTAGE_POSITION, 0, 0 3219 | ELSE 3220 | alien.xPos! = alienData(CaptorId%).xPos! 3221 | alien.yPos! = alienData(CaptorId%).yPos! - 16 3222 | END IF 3223 | END IF 3224 | END IF 3225 | END IF 3226 | END SUB 3227 | 3228 | SUB DoTakeHostagePosition (alien AS ALIENDATA) 3229 | DIM targetX!, targetY!, deltaX!, deltaY! 3230 | GetFormationPosition alien, targetX!, targetY! 3231 | deltaX! = targetX! - alien.xPos! 3232 | deltaY! = targetY! - alien.yPos! 3233 | IF deltaX! ^ 2 + deltaY! ^ 2 > 1 THEN 3234 | TurnTowardsDelta alien, deltaX!, deltaY!, 18 3235 | Move alien, 2 3236 | ELSE 3237 | alien.xPos! = alien.xPos! + deltaX! 3238 | alien.yPos! = alien.yPos! + deltaY! 3239 | IF ABS(ValidateAngle!(alien.rotation!)) < 18 THEN 3240 | alien.rotation! = 0 3241 | NewLife 3242 | PrintText "READY", 10, 18, COLOUR_BLUE 3243 | alien.currentAction% = CMD_HOLD_FORMATION 3244 | waveData.aliensCanAttack% = TRUE 3245 | waveData.aliensAttackingPauseCounter% = 60 3246 | ELSE 3247 | alien.rotation! = alien.rotation! + (alien.rotation! < 0) * -36 - 18 3248 | END IF 3249 | END IF 3250 | END SUB 3251 | 3252 | '===== This action reunites the player with the captive ship when it has been released ================================================================================================================ 3253 | 3254 | SUB DoDoubleUpPlayer (alien AS ALIENDATA) 3255 | IF alien.doubleUpCounter% > 0 OR NOT CheckInFormation% OR alien.rotation! < 0 OR alien.rotation! >= 18 THEN 3256 | alien.rotation! = ValidateAngle(alien.rotation! + 18) 3257 | IF alien.doubleUpCounter% > 0 THEN alien.doubleUpCounter% = alien.doubleUpCounter% - 1 3258 | ELSE 3259 | IF alien.doubleUpCounter% = 0 THEN 3260 | alien.doubleUpCounter% = -1 3261 | DoubleUpShip 3262 | END IF 3263 | IF alien.rotation! >= 0 AND alien.rotation! < 18 THEN 3264 | alien.rotation! = 0 3265 | IF alien.xPos! < 8 THEN 3266 | alien.xPos! = INT(alien.xPos! + 1) 3267 | ELSEIF alien.xPos! > 8 THEN 3268 | alien.xPos! = INT(alien.xPos! - 1) 3269 | ELSEIF alien.yPos! > -156 THEN 3270 | alien.yPos! = INT(alien.yPos! - 1) 3271 | ELSE 3272 | ResetCaptive 3273 | SetPathTypeForAlien alien, PT_WAIT_FOR_CAPTURE, 0, 0 3274 | ShipDoubledUp 3275 | waveData.aliensCanAttack% = TRUE 3276 | END IF 3277 | ELSE 3278 | alien.rotation! = ValidateAngle(alien.rotation! + 18) 3279 | END IF 3280 | END IF 3281 | END SUB 3282 | 3283 | '===== Dive in the direction of the player ============================================================================================================================================================ 3284 | 3285 | SUB DoDiveAtPlayer (alien AS ALIENDATA) 3286 | TurnTowardsDelta alien, alien.targetX! - alien.xPos!, alien.targetY! - alien.yPos!, 8 3287 | Move alien, alien.deltaMove! 3288 | IF OffSide%(alien.xPos!) OR OffBottom(alien.yPos!) THEN alien.fetchNewAction% = TRUE 3289 | END SUB 3290 | 3291 | '===== Moves the centre of the formation (which is used while the aliens are initially flying on to the screen) ======================================================================================= 3292 | 3293 | SUB MoveFormation 3294 | waveData.formationCentreX% = waveData.formationCentreX% + waveData.formationDirection! 3295 | IF ABS(waveData.formationCentreX%) > 30 THEN waveData.formationDirection! = -waveData.formationDirection! 3296 | END SUB 3297 | 3298 | '===== Moves an alien forward in the direction it is facing =========================================================================================================================================== 3299 | 3300 | SUB Move (alien AS ALIENDATA, deltaMove!) 3301 | alien.xPos! = alien.xPos! + SIN(_D2R(alien.rotation!)) * deltaMove! 3302 | alien.yPos! = alien.yPos! + COS(_D2R(alien.rotation!)) * deltaMove! 3303 | END SUB 3304 | 3305 | '===== Gets the position in the formation to return to ================================================================================================================================================ 3306 | 3307 | SUB GetFormationPosition (alien AS ALIENDATA, targetX!, targetY!) 3308 | targetX! = waveData.formationCentreX% + alien.formationXOffset! * waveData.formationSpread! 3309 | targetY! = waveData.formationCentreY% - alien.formationYOffset! * waveData.formationSpread! 3310 | END SUB 3311 | 3312 | '===== Turns towards a target angle with a maximum angle specified for the turn amount ================================================================================================================ 3313 | 3314 | SUB TurnTowardsDelta (alien AS ALIENDATA, deltaX!, deltaY!, maxTurn!) 3315 | DIM deltaAngle!, targetAngle! 3316 | targetAngle! = _R2D(_ATAN2(deltaX!, deltaY!)) 3317 | deltaAngle! = ValidateAngle!(targetAngle! - alien.rotation!) 3318 | IF ABS(deltaAngle!) > maxTurn! THEN 3319 | alien.rotation! = alien.rotation! + deltaAngle! / ABS(deltaAngle!) * maxTurn! 3320 | ELSE 3321 | alien.rotation! = targetAngle! 3322 | END IF 3323 | END SUB 3324 | 3325 | '===== Bomb manager =================================================================================================================================================================================== 3326 | 3327 | SUB DropBombs (alien AS ALIENDATA) 3328 | DIM n% 3329 | IF NOT waveData.challengingStage% AND (game.stage% > 1 OR waveData.aliensArrived%) AND waveData.aliensCanAttack% AND waveData.aliensAttackingPauseCounter% = 0 THEN 3330 | IF alien.bombCount% > 0 AND RND < 1 / 14 AND alien.yPos! > -20 THEN 3331 | n% = UBOUND(bomb) 3332 | REDIM _PRESERVE bomb(n% + 1) AS BOMB 3333 | bomb(n%).xPos! = alien.xPos! 3334 | bomb(n%).yPos! = alien.yPos! 3335 | BombTurnTowardsDelta bomb(n%), player.xPos% - alien.xPos!, player.yPos% - alien.yPos!, 20 3336 | alien.bombCount% = alien.bombCount% - 1 3337 | waveData.bombCount% = waveData.bombCount% + 1 3338 | END IF 3339 | END IF 3340 | END SUB 3341 | 3342 | SUB UpdateBombs (initialised%) 3343 | DIM n%, i%, j% 3344 | n% = UBOUND(bomb) 3345 | i% = n% - 1 3346 | WHILE i% >= 0 3347 | bomb(i%).xPos! = bomb(i%).xPos! + bomb(i%).deltaX! 3348 | bomb(i%).yPos! = bomb(i%).yPos! + bomb(i%).deltaY! 3349 | 3350 | IF (bomb(i%).deltaX < 0 AND OffLeft%(bomb(i%).xPos!)) OR (bomb(i%).deltaX >= 0 AND OffRight%(bomb(i%).xPos!)) OR OffBottom%(bomb(i%).yPos!) THEN 3351 | j% = i% 3352 | WHILE j% < n% - 1 3353 | bomb(j%) = bomb(j% + 1) 3354 | j% = j% + 1 3355 | WEND 3356 | n% = n% - 1 3357 | REDIM _PRESERVE bomb(n%) AS BOMB 3358 | waveData.bombCount% = waveData.bombCount% - 1 3359 | ELSE 3360 | IF ABS(bomb(i%).yPos! - player.yPos%) < 8 THEN 3361 | IF bomb(i%).xPos! > player.xPos% - 14 - 16 * (ship(0).state% <> SHIP_ACTIVE) AND bomb(i%).xPos! < player.xPos% + 14 + 16 * (ship(0).state% <> SHIP_ACTIVE) THEN 3362 | IF bomb(i%).xPos! < player.xPos% THEN ship(0).isHit% = TRUE ELSE ship(1).isHit% = TRUE 3363 | END IF 3364 | END IF 3365 | END IF 3366 | i% = i% - 1 3367 | WEND 3368 | END SUB 3369 | 3370 | SUB BombTurnTowardsDelta (bomb AS BOMB, deltaX!, deltaY!, maxTurn!) 3371 | DIM rotation! 3372 | rotation! = _R2D(_ATAN2(deltaX!, deltaY!)) 3373 | rotation! = ValidateAngle!(rotation!) 3374 | IF 180 - ABS(rotation!) > maxTurn! THEN 3375 | IF rotation! < 0 THEN rotation! = maxTurn! - 180 ELSE rotation! = 180 - maxTurn! 3376 | END IF 3377 | bomb.deltaX! = SIN(_D2R(rotation!)) * 4 3378 | bomb.deltaY! = COS(_D2R(rotation!)) * 4 3379 | END SUB 3380 | 3381 | '===== Sound manager ================================================================================================================================================================================== 3382 | 3383 | SUB LoadSfx (sfx%, sfx$, oneShot%) 3384 | sfx(sfx%).handle& = _SNDOPEN("assets/" + sfx$ + ".ogg") 3385 | IF sfx(sfx%).handle& = 0 THEN AssetError sfx$ 3386 | sfx(sfx%).oneShot% = oneShot% 3387 | END SUB 3388 | 3389 | SUB LoadAllSFX 3390 | LoadSfx SFX_BOSS_GALAGA_TRACTOR_BEAM, "bossgalagatractorbeam", TRUE 3391 | LoadSfx SFX_TRACTOR_BEAM_CAUGHT, "tractorbeamcaught", TRUE 3392 | LoadSfx SFX_AMBIENCE, "ambience", TRUE 3393 | LoadSfx SFX_GALAGA_ATTACK, "galagaattack", TRUE 3394 | LoadSfx SFX_FIGHTER_SHOOT, "fightershoot", TRUE 3395 | LoadSfx SFX_STAGE_INTRO, "stage intro", TRUE 3396 | LoadSfx SFX_GALAGA_DEFEAT_1, "galagadefeat1", TRUE 3397 | LoadSfx SFX_GALAGA_DEFEAT_2, "galagadefeat2", TRUE 3398 | LoadSfx SFX_BOSS_GALAGA_DEFEAT, "bossgalagadefeat", TRUE 3399 | LoadSfx SFX_BOSS_GALAGA_HIT, "bossgalagahit", TRUE 3400 | LoadSfx SFX_CAPTURED_FIGHTER_DESTROYED, "captured fighter destroyed", TRUE 3401 | LoadSfx SFX_FIGHTER_CAPTURED, "fighter captured", TRUE 3402 | LoadSfx SFX_1_UP, "1-up", TRUE 3403 | LoadSfx SFX_FIGHTER_RESCUED, "fighter rescued", TRUE 3404 | LoadSfx SFX_DIE, "die", TRUE 3405 | LoadSfx SFX_NEXT_LEVEL, "nextlevel", TRUE 3406 | LoadSfx SFX_CHALLENGING_STAGE, "challenging stage", TRUE 3407 | LoadSfx SFX_CHALLENGING_STAGE_OVER, "challenging stage over", TRUE 3408 | LoadSfx SFX_CHALLENGING_STAGE_PERFECT, "challenging stage perfect", TRUE 3409 | LoadSfx SFX_NAME_ENTRY_1, "name entry 1", TRUE 3410 | LoadSfx SFX_NAME_ENTRY_NOT_1, "name entry 2+", TRUE 3411 | LoadSfx SFX_COIN_CREDIT, "coin_credit", TRUE 3412 | END SUB 3413 | 3414 | SUB PlaySfx (sfx%) 3415 | IF sfx(sfx%).oneShot% THEN 3416 | _SNDPLAY sfx(sfx%).handle& 3417 | ELSE 3418 | _SNDPLAYCOPY sfx(sfx%).handle& 3419 | END IF 3420 | END SUB 3421 | 3422 | SUB PlaySfxLooping (sfx%) 3423 | IF sfx(sfx%).oneShot% THEN 3424 | _SNDLOOP sfx(sfx%).handle& 3425 | END IF 3426 | END SUB 3427 | 3428 | SUB StopSfx (sfx%) 3429 | IF sfx(sfx%).oneShot% THEN _SNDSTOP sfx(sfx%).handle& 3430 | END SUB 3431 | 3432 | FUNCTION IsPlayingSfx% (sfx%) 3433 | IsPlayingSfx% = _SNDPLAYING(sfx(sfx%).handle&) 3434 | END FUNCTION 3435 | 3436 | '===== Process the flags the appear to show the current wave number =================================================================================================================================== 3437 | 3438 | SUB ProcessFlags (initialised%) 3439 | STATIC pauseCounter AS INTEGER 3440 | STATIC values(6) AS INTEGER 3441 | STATIC width(6) AS INTEGER 3442 | STATIC flags(50) AS FLAG 3443 | STATIC nFlags% 3444 | DIM i%, x%, value%, numFlags% 3445 | IF initialised% = FALSE THEN 3446 | IF values%(0) = 0 THEN 3447 | values%(0) = 50: width%(0) = 16 3448 | values%(1) = 30: width%(1) = 16 3449 | values%(2) = 20: width%(2) = 16 3450 | values%(3) = 10: width%(3) = 14 3451 | values%(4) = 5: width%(4) = 8 3452 | values%(5) = 1: width%(5) = 8 3453 | END IF 3454 | REDIM flagDisplay(0) AS FLAG 3455 | nFlags% = 0 3456 | value% = game.stage% 3457 | i% = 0 3458 | nFlags% = 0 3459 | WHILE value% > 0 3460 | IF value% >= values%(i%) THEN 3461 | value% = value% - values%(i%) 3462 | flags(nFlags%).flag% = i% 3463 | nFlags% = nFlags% + 1 3464 | ELSE 3465 | i% = i% + 1 3466 | END IF 3467 | WEND 3468 | x% = 111 3469 | FOR i% = nFlags% - 1 TO 0 STEP -1 3470 | flags(i%).xpos% = x% - width%(flags(i%).flag) / 2 3471 | x% = x% - width%(flags(i%).flag) 3472 | NEXT i% 3473 | pauseCounter% = 0.2 * game.fps% 3474 | END IF 3475 | IF pauseCounter% > 0 THEN pauseCounter% = pauseCounter% - 1: EXIT SUB 3476 | numFlags% = UBOUND(flagDisplay) 3477 | flagDisplay(numFlags%) = flags(numFlags%) 3478 | REDIM _PRESERVE flagDisplay(numFlags% + 1) AS FLAG 3479 | IF game.stage% > 1 THEN PlaySfx SFX_NEXT_LEVEL 3480 | pauseCounter% = 0.2 * game.fps% 3481 | IF numFlags% + 1 = nFlags% THEN 3482 | RemoveEvent EVENT_PROCESS_FLAGS 3483 | END IF 3484 | END SUB 3485 | 3486 | '===== Controls costume animation for the handful of aliens that actually animate (other than rotation) =============================================================================================== 3487 | 3488 | SUB SetCostumeWithOffset (alien AS ALIENDATA, offset%) 3489 | alien.costume% = offset% 3490 | END SUB 3491 | 3492 | SUB SetCostumeWithTime (alien AS ALIENDATA) 3493 | IF alien.alienType% = TYPE_BOSS_GALAGA OR alien.alienType% = TYPE_BOSS_GALAGA_SHOT OR alien.alienType% = TYPE_BUTTERFLY OR alien.alienType% = TYPE_BEE THEN 3494 | SetCostumeWithOffset alien, INT((game.frameCounter& MOD 32) / 16) 3495 | END IF 3496 | END SUB 3497 | 3498 | '====================================================================================================================================================================================================== 3499 | 3500 | -------------------------------------------------------------------------------- /resources/26482.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/26482.png -------------------------------------------------------------------------------- /resources/Galaga.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/Galaga.png -------------------------------------------------------------------------------- /resources/Galaga_marquee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/Galaga_marquee.png -------------------------------------------------------------------------------- /resources/galaga.avi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga.avi -------------------------------------------------------------------------------- /resources/galaga.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga.ico -------------------------------------------------------------------------------- /resources/galaga0[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga0[1].wav -------------------------------------------------------------------------------- /resources/galaga1[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga1[1].wav -------------------------------------------------------------------------------- /resources/galaga2[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga2[1].wav -------------------------------------------------------------------------------- /resources/galaga3[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga3[1].wav -------------------------------------------------------------------------------- /resources/galaga4[2].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga4[2].wav -------------------------------------------------------------------------------- /resources/galaga5[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga5[1].wav -------------------------------------------------------------------------------- /resources/galaga6[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga6[1].wav -------------------------------------------------------------------------------- /resources/galaga7[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga7[1].wav -------------------------------------------------------------------------------- /resources/galaga8[2].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga8[2].wav -------------------------------------------------------------------------------- /resources/galaga9[1].wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga9[1].wav -------------------------------------------------------------------------------- /resources/galaga_marquee_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/galaga_marquee_small.png -------------------------------------------------------------------------------- /resources/screencap.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rokcoder-qb64/galaga/eaf9e2172d60e39f120381a479e215d9eee81636/resources/screencap.gif --------------------------------------------------------------------------------