Last active
September 10, 2022 13:22
-
-
Save wesleywerner/0b2d5f1b28c7388866d41a990577ea84 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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