Skip to content

Instantly share code, notes, and snippets.

@wesleywerner
Last active September 10, 2022 13:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wesleywerner/0b2d5f1b28c7388866d41a990577ea84 to your computer and use it in GitHub Desktop.
Save wesleywerner/0b2d5f1b28c7388866d41a990577ea84 to your computer and use it in GitHub Desktop.
mis,bom,bas={},{},{} -- Initialize tables to store:
-- mis: missiles fired (both enemy and player)
-- bom: explosions (booms)
-- bas: player missile batteries (bases)
tax,tay,kb,sco,shk=64,64,1,0,0 -- Initialize globals:
-- tax, tay: targeting reticule XY
-- kb: flag if player is using keyboard input (1), or mouse input
-- sco: player score (0)
-- shk: screen shake effect amount (0)
for n=0,3 do -- Add four player bases at XY positions.
add(bas,{x=16+n*32,y=120+rnd(5)}) -- Vary Y to give the effect of sized buildings.
end
function _update() -- Called every game tick
shk=max(0,shk-.25) -- Decrement shake amount, clamped to zero.
for m in all(mis)do -- Update missiles:
m.x,m.y,_b=clp(m.x+cos(m.a)*m.s, -- Move position by angle (a) at speed (s).
m.y+sin(m.a)*m.s) -- Store if new position is out-of-bounds (_b),
-- ie set _b truthy to destroy the missile.
m.d-=m.s -- Decrease missile distance by its speed.
if(m.d<0)_b=1 -- If missile distance zeroed: set _b truthy.
-- Only player missiles have sane distances.
-- Enemy missiles have distances beyond the size
-- of the play field (256) and wont hit this
-- condition.
for b in all(bom)do -- Update explosions (inside missile loop!):
if not m.b and -- The current missile is *not* attached to a player base
-- (This allows player missiles to pass through explosions, but enemy missiles get hit).
dist(b.x-m.x,b.y-m.y)<b.r then -- Distance from missile (m) to explosion (b) is inside blast radius (r).
_b=1 -- Flag missile for destruction.
sco+=#bas -- Increment score * number of bases.
end
end
if _b then -- If missile flagged for destruction.
if(m.b)m.b.w=nil -- Clear attached base's reload flag (w) so it can fire again.
del(mis,m) -- Remove this missile.
if(m.y>16)boom(m.x,m.y,m.c) -- Create explosion at missile location
end -- except for missiles at the very top of the display
end -- (this fixes explosions auto-propagating "explosively"
-- around wave 22)
for b in all(bom)do -- Update explosions:
b.r+=.4 -- Increase blast radius.
if(b.r>b.s)del(bom,b) -- Remove explosion if blast radius (r) > expected size (s).
for a in all(bas)do -- Test for all bases (inside explosion loop!):
if b.y>a.y and -- Explosion Y > base Y
dist(b.x-a.x,b.y-a.y)<b.r then -- Distance from explosion to base is < blast radius.
boom(a.x,a.y,8) -- Create new explosion (red, 8) at base location.
del(bas,a) -- Remove base.
shk=5 -- Set screen shake amount.
end
end
end
if(#bas==0)return -- Stop further updates if player has zero bases.
if btnp(4,1) then -- Input: left shift.
kb=not kb -- Toggle kb flag.
poke(0x5f2d,kb and 0x0 or 0x3) -- Enabled/disable mouse input.
end
if btnp(5)then -- Input: X button.
for n=1,6do -- Try multiple times:
b=rnd(bas) -- Pick random base.
if not b.w then -- Base has no active missile in flight.
print"\as9x6i0g2eb" -- SFX.
fire(b.x,128,b) -- Fire missile from base position and
-- attach base (b) to missile.
b.w=1 -- Flag base as waiting (w) to reload.
break -- Stop further firings.
end
end
end
wave=ceil(20*time()/300) -- Calculate wave as the product (20) of time passed per 5 mins (300 seconds).
if(#mis<wave)fire() -- Fire enemy missile if number of missiles are less than wave number.
end
function _draw() -- Main drawing routine.
if shk>0then -- Shake is truthy.
cls(1) -- Clear display, helps circumvent artifacts regarding the fade-out effect.
print"\as8i6x3c4s3c0" -- SFX.
if(#bas==0)boom(rnd(128),128,8+rnd(3)) -- Zero player bases spawns explosions while shaking.
end
camera(rnd(shk),rnd(shk)) -- Apply shake to camera.
for i=1,64do -- Draw randomly filled circles to give the fade-out effect.
circfill(rnd(128),rnd(128),4,1)
end
line(0,127,128,127,4) -- Draws a brown line where bases stand on.
for b in all(bas)do -- Draws each base as a gray rectangle.
rectfill(b.x-3,b.y,b.x+3,128,6)
end
for m in all(mis)do -- Draw each missile as a point.
pset(m.x,m.y,m.c)
end
for m in all(bom)do -- Draw each explosion as a filled circle.
circfill(m.x,m.y,m.r,m.c)
end
rectfill(0,0,128,6,4) -- Print the score & wave on a filled rectangle.
print("score:"..sco.." wave:"..wave,1,1,6)
if(#bas==0)then -- Print game over message if player has no bases.
print("earth lost",44,64,8)
return -- Stop further drawings.
end
circ(tax,tay,1,1) -- Draw targeting reticule with background color.
-- Prevents artifacts of the reticule moving on-screen
-- with the fade-out effect.
if kb then -- Test keyboard input.
if(btn(0))tax-=4 -- Offset targeting reticule position.
if(btn(1))tax+=4
if(btn(2))tay-=4
if(btn(3))tay+=4
else
tax,tay=stat(32),stat(33) -- Read targeting reticule position from mouse cursor.
end
circ(tax,tay,1,7) -- Draw updated reticule position.
end
function fire(x,y,b) -- Fire a missile, for both enemy and player.
-- Enemy missiles have nil XYB parameters.
d=x and dist(tax-x,tay-y) or 0x100 -- Distance:
-- For player: Calculate distance to targeting reticule.
-- For enemy: Fixed distance at 256 (0x100).
a=x and atan2(tax-x,tay-y) -- Angle:
-- For player: atan from XY to reticule
-- For enemy: nil
x,y=x or rnd(126),y or 1 -- X and Y position:
-- For player: unchanged
-- For enemy: random x, 1 for y
a=a or atan2(rnd(120)-x,128-y) -- Angle (re-evaluation):
-- For player: unchanged
-- For enemy: atan from XY to random position on bottom of display
add(mis,{x=x,y=y,a=a, -- Add missile to table.
s=b and 2or.5,d=d,
c=b and 10 or 8+rnd(8),b=b})
end
function boom(x,y,c) -- Add explosion (boom) to table.
print"\as8i6x3c4s3c0" -- SFX
add(bom,{x=x,y=y,r=1,s=8+rnd(15),c=c}) -- xy: position
end -- r: current radius
-- s: maximum size
-- c: color
function clp(a,b) -- Clamp two values to display boundary.
-- Returns both new values and if either of them went outside bounds.
a=min(128,max(0,a))
b=min(128,max(0,b))
return a,b,a==0 or a==128 or b==0 or b==128
end
function dist(a,b) -- Get distance between XY deltas.
return sqrt((abs(a)^2)+(abs(b)^2))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment