120 lines
4.1 KiB
QBasic
120 lines
4.1 KiB
QBasic
|
|
REM GALAGA enemy behavior. The C engine loads this file, runs it once so the
|
||
|
|
REM definitions exist, and then calls one UPDATE function per enemy per frame.
|
||
|
|
REM There is no top-level code: definitions, then END.
|
||
|
|
REM
|
||
|
|
REM Names the engine binds before every call:
|
||
|
|
REM SELF@ - this enemy's record (ENEMY): the state machine's memory
|
||
|
|
REM ACTOR@ - the engine's live actor (ACTOR): position is the real thing
|
||
|
|
REM GAME@ - shared frame state (GAME): player position, wave, randomness
|
||
|
|
REM
|
||
|
|
REM SELF@.STATE# bits: 1 = entering 2 = in formation 4 = diving
|
||
|
|
REM
|
||
|
|
REM Two rules of this dialect that bite here, both from docs/03:
|
||
|
|
REM - the LEFT operand decides integer or float arithmetic, so a float
|
||
|
|
REM always goes first: SELF@.T% * 150 + 260, never 260 + 150 * SELF@.T%
|
||
|
|
REM - RETURN at the start of a line ends the DEF body, so every early
|
||
|
|
REM return rides an IF ... THEN, and only the last RETURN starts a line
|
||
|
|
|
||
|
|
REM Ease toward the formation slot, with a little entry swirl.
|
||
|
|
REM Answers 1 once the slot is reached, else 0.
|
||
|
|
DEF GLIDEHOME(DT%)
|
||
|
|
DX% = SELF@.HOMEX% - ACTOR@.X%
|
||
|
|
DY% = SELF@.HOMEY% - ACTOR@.Y%
|
||
|
|
K% = DT% * 4.5
|
||
|
|
IF K% > 1 THEN K% = 1
|
||
|
|
ACTOR@.X% = ACTOR@.X% + DX% * K% + SIN(SELF@.T% * 6) * 90 * DT%
|
||
|
|
ACTOR@.Y% = ACTOR@.Y% + DY% * K%
|
||
|
|
IF ABS(DX%) < 3 AND ABS(DY%) < 3 THEN RETURN 1
|
||
|
|
RETURN 0
|
||
|
|
|
||
|
|
REM One frame of a dive: accelerate downward, weave, lean toward the
|
||
|
|
REM player's column, and glide back in from the top after falling out.
|
||
|
|
DEF DIVESTEP(DT%, WEAVE%, LEAD%)
|
||
|
|
SPD% = SELF@.T% * 150 + 260
|
||
|
|
ACTOR@.Y% = ACTOR@.Y% + SPD% * DT%
|
||
|
|
ACTOR@.X% = ACTOR@.X% + SIN(SELF@.T% * 4) * WEAVE% * DT%
|
||
|
|
DX% = GAME@.PLAYERX% - ACTOR@.X%
|
||
|
|
IF DX% > 220 THEN DX% = 220
|
||
|
|
IF DX% < -220 THEN DX% = -220
|
||
|
|
ACTOR@.X% = ACTOR@.X% + DX% * LEAD% * DT%
|
||
|
|
IF ACTOR@.Y% > 1040 THEN BEGIN
|
||
|
|
ACTOR@.Y% = 0.0 - 90
|
||
|
|
SELF@.STATE# = 1
|
||
|
|
SELF@.T% = 0
|
||
|
|
BEND
|
||
|
|
RETURN 0
|
||
|
|
|
||
|
|
REM Raise the fire flag when diving roughly above the player. The engine
|
||
|
|
REM consumes FIRE# and does the spawning; the script only wishes.
|
||
|
|
DEF DECIDEFIRE(DT%)
|
||
|
|
DX% = GAME@.PLAYERX% - ACTOR@.X%
|
||
|
|
IF ABS(DX%) > 140 THEN RETURN 0
|
||
|
|
IF ACTOR@.Y% > GAME@.PLAYERY% THEN RETURN 0
|
||
|
|
IF SELF@.RND% < DT% * 1.5 THEN SELF@.FIRE# = 1
|
||
|
|
RETURN 0
|
||
|
|
|
||
|
|
REM Bee: enter, breathe in formation, occasionally dive nearly straight.
|
||
|
|
DEF UPDATEBEE(DT%)
|
||
|
|
SELF@.T% = SELF@.T% + DT%
|
||
|
|
IF SELF@.T% < 0 THEN RETURN 0
|
||
|
|
S# = SELF@.STATE#
|
||
|
|
IF (S# AND 1) > 0 THEN BEGIN
|
||
|
|
R# = GLIDEHOME(DT%)
|
||
|
|
IF R# = 1 THEN SELF@.STATE# = 2 : SELF@.T% = 0
|
||
|
|
BEND
|
||
|
|
IF (S# AND 2) > 0 THEN BEGIN
|
||
|
|
ACTOR@.X% = SELF@.HOMEX% + SIN(SELF@.T% * 1.7) * 16
|
||
|
|
ACTOR@.Y% = SELF@.HOMEY%
|
||
|
|
IF SELF@.RND% < DT% * 0.04 THEN SELF@.STATE# = 4 : SELF@.T% = 0
|
||
|
|
BEND
|
||
|
|
IF (S# AND 4) > 0 THEN BEGIN
|
||
|
|
R# = DIVESTEP(DT%, 130, 0.2)
|
||
|
|
R# = DECIDEFIRE(DT%)
|
||
|
|
BEND
|
||
|
|
RETURN 0
|
||
|
|
|
||
|
|
REM Butterfly: the same machine with a wide lateral weave on the dive.
|
||
|
|
DEF UPDATEBFLY(DT%)
|
||
|
|
SELF@.T% = SELF@.T% + DT%
|
||
|
|
IF SELF@.T% < 0 THEN RETURN 0
|
||
|
|
S# = SELF@.STATE#
|
||
|
|
IF (S# AND 1) > 0 THEN BEGIN
|
||
|
|
R# = GLIDEHOME(DT%)
|
||
|
|
IF R# = 1 THEN SELF@.STATE# = 2 : SELF@.T% = 0
|
||
|
|
BEND
|
||
|
|
IF (S# AND 2) > 0 THEN BEGIN
|
||
|
|
ACTOR@.X% = SELF@.HOMEX% + SIN(SELF@.T% * 2.1) * 24
|
||
|
|
ACTOR@.Y% = SELF@.HOMEY%
|
||
|
|
IF SELF@.RND% < DT% * 0.05 THEN SELF@.STATE# = 4 : SELF@.T% = 0
|
||
|
|
BEND
|
||
|
|
IF (S# AND 4) > 0 THEN BEGIN
|
||
|
|
R# = DIVESTEP(DT%, 260, 0.1)
|
||
|
|
R# = DECIDEFIRE(DT%)
|
||
|
|
BEND
|
||
|
|
RETURN 0
|
||
|
|
|
||
|
|
REM Boss: two hit points, a slow sway, and a dive that leads the player.
|
||
|
|
REM At one hit point it raises actor state bit 13 (8192), and the engine's
|
||
|
|
REM character mapping swaps the sprite - the boundary crossed the other way.
|
||
|
|
DEF UPDATEBOSS(DT%)
|
||
|
|
SELF@.T% = SELF@.T% + DT%
|
||
|
|
IF SELF@.T% < 0 THEN RETURN 0
|
||
|
|
IF SELF@.HP# = 1 THEN ACTOR@.STATE# = ACTOR@.STATE# OR 8192
|
||
|
|
S# = SELF@.STATE#
|
||
|
|
IF (S# AND 1) > 0 THEN BEGIN
|
||
|
|
R# = GLIDEHOME(DT%)
|
||
|
|
IF R# = 1 THEN SELF@.STATE# = 2 : SELF@.T% = 0
|
||
|
|
BEND
|
||
|
|
IF (S# AND 2) > 0 THEN BEGIN
|
||
|
|
ACTOR@.X% = SELF@.HOMEX% + SIN(SELF@.T% * 1.1) * 10
|
||
|
|
ACTOR@.Y% = SELF@.HOMEY%
|
||
|
|
IF SELF@.RND% < DT% * 0.03 THEN SELF@.STATE# = 4 : SELF@.T% = 0
|
||
|
|
BEND
|
||
|
|
IF (S# AND 4) > 0 THEN BEGIN
|
||
|
|
R# = DIVESTEP(DT%, 60, 0.9)
|
||
|
|
R# = DECIDEFIRE(DT%)
|
||
|
|
BEND
|
||
|
|
RETURN 0
|
||
|
|
|
||
|
|
END
|