2023-09-13 05:49:01 +00:00
|
|
|
pico-8 cartridge // http://www.pico-8.com
|
|
|
|
version 41
|
|
|
|
__lua__
|
|
|
|
-- generic shmup
|
|
|
|
-- by kistaro windrider
|
|
|
|
-- dev docs in tab 8
|
|
|
|
|
|
|
|
game = 1
|
|
|
|
win = 2
|
|
|
|
lose = 3
|
|
|
|
|
|
|
|
debug = {}
|
|
|
|
|
2023-09-13 06:35:27 +00:00
|
|
|
function usplit(str)
|
|
|
|
return unpack(split(str))
|
|
|
|
end
|
|
|
|
function csv(s)
|
|
|
|
local ret=split(s,"\n")
|
|
|
|
for i,v in ipairs(ret) do
|
|
|
|
ret[i] = type(v) == "string" and split(v) or {v} end
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
2023-09-13 05:49:01 +00:00
|
|
|
function _init()
|
|
|
|
init_bullet_mt()
|
|
|
|
init_powerup_mt()
|
|
|
|
init_ship_mt()
|
|
|
|
wipe_level()
|
|
|
|
primary_ship.main_gun = new_gun_of(zap_gun_t)
|
|
|
|
load_level(example_level)
|
|
|
|
state = game
|
|
|
|
pal(2,129)
|
|
|
|
pal()
|
|
|
|
end
|
|
|
|
|
|
|
|
-- health gradients for 1..5 hp
|
|
|
|
-- exactly, then all "more".
|
2023-09-13 06:35:27 +00:00
|
|
|
hpcols_lut = csv[[36
|
|
|
|
34, 136
|
|
|
|
34, 130, 136
|
|
|
|
34, 34, 130, 136
|
|
|
|
34, 34, 130, 130, 136]]
|
2023-09-13 05:49:01 +00:00
|
|
|
|
|
|
|
-- call after any change to maxhp
|
|
|
|
-- configures health gradient
|
|
|
|
function init_hpcols()
|
|
|
|
hpcols = hpcols_lut[min(primary_ship.maxhp,6)]
|
|
|
|
end
|
|
|
|
|
|
|
|
function wipe_level()
|
|
|
|
primary_ship = new_p1()
|
|
|
|
init_hpcols()
|
|
|
|
pships = {primary_ship}
|
|
|
|
eships = {}
|
|
|
|
pbullets = {}
|
|
|
|
ebullets = {}
|
|
|
|
intangibles_fg = {}
|
|
|
|
intangibles_bg = {}
|
|
|
|
events = {}
|
|
|
|
end
|
|
|
|
|
|
|
|
function _update60()
|
|
|
|
updategame()
|
|
|
|
end
|
|
|
|
|
|
|
|
function updategame()
|
|
|
|
leveldone = level_frame()
|
|
|
|
new_events = {}
|
|
|
|
local deaths = {}
|
|
|
|
for i, e in ipairs(events) do
|
|
|
|
if (e()) add(deaths, i)
|
|
|
|
end
|
|
|
|
bury_the_dead(events, deaths)
|
|
|
|
foreach(new_events, function(e)
|
|
|
|
add(events, e)
|
|
|
|
end)
|
|
|
|
deaths = {}
|
|
|
|
for i, x in ipairs(intangibles_bg) do
|
|
|
|
if (x:move()) add(deaths, i)
|
|
|
|
end
|
|
|
|
bury_the_dead(intangibles_bg, deaths)
|
|
|
|
for _, tbl in ipairs({pships, eships, pbullets, ebullets, intangibles}) do
|
|
|
|
local deaths = {}
|
|
|
|
for i, x in ipairs(tbl) do
|
|
|
|
if (x:move()) add(deaths, i)
|
|
|
|
end
|
|
|
|
bury_the_dead(tbl, deaths)
|
|
|
|
end
|
|
|
|
--then, calculate collisions
|
|
|
|
local pdeaths = {}
|
|
|
|
local edeaths = {}
|
|
|
|
local eskips = {}
|
|
|
|
-- todo: always use a collider,
|
|
|
|
-- it saves if pships is as low as 2s
|
|
|
|
-- pships usually contians 1 thing,
|
|
|
|
-- so don't bother with a bucket collider
|
|
|
|
for ip, ps in ipairs(pships) do
|
|
|
|
for ie, es in ipairs(eships) do
|
|
|
|
if not eskips[ie] then
|
|
|
|
if collides(hurtbox(ps), hurtbox(es)) then
|
|
|
|
if (es:hitship(ps)) then
|
|
|
|
add(edeaths, ie)
|
|
|
|
eskips[ie] = true
|
|
|
|
end
|
|
|
|
if ps:hitship(es) then
|
|
|
|
add(pdeaths, ip)
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
bury_the_dead(pships, pdeaths)
|
|
|
|
bury_the_dead(eships, edeaths)
|
|
|
|
pdeaths = {}
|
|
|
|
edeaths = {}
|
|
|
|
eskips = {}
|
|
|
|
for ip, ps in ipairs(pships) do
|
|
|
|
for ie, eb in ipairs(ebullets) do
|
|
|
|
if not eskips[ie] then
|
|
|
|
if collides(hurtbox(ps), hurtbox(eb)) then
|
|
|
|
local dead = false
|
|
|
|
if ps:hitbullet(eb) then
|
|
|
|
add(pdeaths, ip)
|
|
|
|
dead = true
|
|
|
|
end
|
|
|
|
if (eb:hitship(ps)) then
|
|
|
|
add(edeaths, ie)
|
|
|
|
eskips[ie] =true
|
|
|
|
end
|
|
|
|
if (dead) break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
bury_the_dead(pships, pdeaths)
|
|
|
|
bury_the_dead(ebullets, edeaths)
|
|
|
|
pdeaths = {}
|
|
|
|
edeaths = {}
|
|
|
|
-- many bullets and many enemy ships;
|
|
|
|
-- use bucket collider for efficiency
|
|
|
|
local pbullet_collider = new_collider()
|
|
|
|
for idx, pb in ipairs(pbullets) do
|
|
|
|
pb.___pbullets_idx = idx
|
|
|
|
pbullet_collider:insert(pb)
|
|
|
|
end
|
|
|
|
|
|
|
|
for es_idx, es in ipairs(eships) do
|
|
|
|
for pb in all(pbullet_collider:get_collisions(es)) do
|
|
|
|
local dead = false
|
|
|
|
if es:hitbullet(pb) then
|
|
|
|
add(edeaths, es_idx)
|
|
|
|
dead=true
|
|
|
|
end
|
|
|
|
if pb:hitship(es) then
|
|
|
|
add(pdeaths, pb.___pbullets_idx)
|
|
|
|
pbullet_collider:hide(pb)
|
|
|
|
end
|
|
|
|
if (dead) break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
bury_the_dead(eships, edeaths)
|
|
|
|
bury_the_dead(pbullets, pdeaths)
|
|
|
|
for i, x in ipairs(intangibles_fg) do
|
|
|
|
if (x:move()) add(deaths, i)
|
|
|
|
end
|
|
|
|
bury_the_dead(intangibles_fg, deaths)
|
|
|
|
|
|
|
|
if leveldone and ((#eships + #ebullets + #events) == 0) then
|
|
|
|
state = win
|
|
|
|
end
|
|
|
|
if #pships == 0 then
|
|
|
|
state = lose
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function _draw()
|
|
|
|
drawgame()
|
|
|
|
draw_debug()
|
|
|
|
if (state == game) fadelvl = -45
|
|
|
|
if (state == win) dropshadow("win",50,61,11)
|
|
|
|
if (state == lose) dropshadow("fail",48,61,8)
|
|
|
|
fadescreen()
|
|
|
|
end
|
|
|
|
|
2023-09-13 06:35:27 +00:00
|
|
|
fadetable=csv[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
|
|
|
1,1,129,129,129,129,129,129,129,129,0,0,0,0,0
|
|
|
|
2,2,2,130,130,130,130,130,128,128,128,128,128,0,0
|
|
|
|
3,3,3,131,131,131,131,129,129,129,129,129,0,0,0
|
|
|
|
4,4,132,132,132,132,132,132,130,128,128,128,128,0,0
|
|
|
|
5,5,133,133,133,133,130,130,128,128,128,128,128,0,0
|
|
|
|
6,6,134,13,13,13,141,5,5,5,133,130,128,128,0
|
|
|
|
7,6,6,6,134,134,134,134,5,5,5,133,130,128,0
|
|
|
|
8,8,136,136,136,136,132,132,132,130,128,128,128,128,0
|
|
|
|
9,9,9,4,4,4,4,132,132,132,128,128,128,128,0
|
|
|
|
10,10,138,138,138,4,4,4,132,132,133,128,128,128,0
|
|
|
|
11,139,139,139,139,3,3,3,3,129,129,129,0,0,0
|
|
|
|
12,12,12,140,140,140,140,131,131,131,1,129,129,129,0
|
|
|
|
13,13,141,141,5,5,5,133,133,130,129,129,128,128,0
|
|
|
|
14,14,14,134,134,141,141,2,2,133,130,130,128,128,0
|
|
|
|
15,143,143,134,134,134,134,5,5,5,133,133,128,128,0]]
|
2023-09-13 05:49:01 +00:00
|
|
|
|
|
|
|
function fadescreen()
|
|
|
|
fadelvl += 0.25
|
|
|
|
if fadelvl < 0 then
|
|
|
|
pal()
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local i = flr(fadelvl)
|
|
|
|
for c=0,15 do
|
|
|
|
if i+1>=16 then
|
|
|
|
pal(c,0,1)
|
|
|
|
else
|
|
|
|
pal(c,fadetable[c+1][i+1],1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function draw_debug()
|
|
|
|
cursor(0,0,7)
|
|
|
|
-- uncomment the followingh
|
|
|
|
-- to display object counts
|
|
|
|
--[[
|
|
|
|
print("es "..tostr(#eships))
|
|
|
|
print("eb "..tostr(#ebullets))
|
|
|
|
print("pb "..tostr(#pbullets))
|
|
|
|
print("ib "..tostr(#intangibles_bg))
|
|
|
|
print("if "..tostr(#intangibles_fg))
|
|
|
|
print("v "..tostr(#events))
|
|
|
|
]]
|
|
|
|
if (#debug==0) return
|
|
|
|
foreach(debug,print)
|
|
|
|
debug={}
|
|
|
|
end
|
|
|
|
|
|
|
|
function drawgame()
|
|
|
|
cls()
|
|
|
|
clip(0,0,112,128)
|
|
|
|
for tbl in all{intangibles_bg, pbullets, pships, eships, ebullets, intangibles_fg} do
|
|
|
|
for x in all(tbl) do
|
|
|
|
x:draw()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
clip(0,0,128,128)
|
|
|
|
drawhud()
|
|
|
|
end
|
|
|
|
|
2023-09-13 06:44:33 +00:00
|
|
|
powcols=split"170,154,153,148,68"
|
2023-09-13 05:49:01 +00:00
|
|
|
function drawhud()
|
|
|
|
-- 112-and-right is hud zone
|
|
|
|
rectfill(112, 0, 127, 127,0x56)
|
|
|
|
rect(112,0,127,127,7)
|
|
|
|
line(127,1,127,127,5)
|
|
|
|
line(113,127)
|
|
|
|
|
|
|
|
draw_gun_info("❎",1,116,3,primary_ship.main_gun)
|
|
|
|
draw_gun_info("🅾️",2,116,31,primary_ship.special_gun)
|
|
|
|
|
|
|
|
dropshadow("pwr",114,59,1)
|
|
|
|
inset(114,66,125,92)
|
|
|
|
fillp(0x5a5a)
|
2023-09-13 06:44:33 +00:00
|
|
|
vertmeter(115,67,124,91,primary_ship.power, primary_ship.max_power, powcols)
|
2023-09-13 05:49:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
dropshadow("h s",114,97,1)
|
|
|
|
inset(114,104,125,125)
|
|
|
|
line(119,105,119,124,119)
|
|
|
|
line(120,105,120,125,85)
|
|
|
|
vertmeter(115,105,118,124,primary_ship.hp, primary_ship.maxhp, hpcols)
|
|
|
|
vertmeter(121,105,124,124,primary_ship.shield, primary_ship.maxshield,{204,220,221})
|
|
|
|
fillp(0)
|
|
|
|
end
|
|
|
|
|
|
|
|
function draw_gun_info(lbl,fgc,x,y,gun)
|
|
|
|
dropshadow(lbl,x,y,fgc)
|
|
|
|
inset(114,y+7,125,y+18)
|
|
|
|
inset(114,y+20,125,y+24)
|
|
|
|
if(gun) then
|
|
|
|
spr(gun.icon,116,y+9,1,1)
|
|
|
|
--115 to 124 - ammo bar. round up
|
|
|
|
if gun.ammo == nil then
|
|
|
|
fillp(0xa5a5)
|
|
|
|
rectfill(115,y+21,124,y+23,0xea)
|
|
|
|
fillp(0)
|
|
|
|
elseif gun.ammo > 0 then
|
|
|
|
rectfill(
|
|
|
|
115,y+21,
|
|
|
|
115+flr(9*gun.ammo/gun.maxammo),
|
|
|
|
y+23,10)
|
|
|
|
else
|
|
|
|
line(118, y+22, 121, y+22, 2)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function vertmeter(x0,y0,x1,y1,val,maxval,cols)
|
|
|
|
if (val <= 0) return
|
|
|
|
local h = y1-y0
|
|
|
|
local px = -flr(-(h*val)\maxval)
|
|
|
|
local ncols = #cols
|
|
|
|
local firstcol = ((h-px)*ncols\h)+1
|
|
|
|
local lastbottom = y0+(h*firstcol\ncols)
|
|
|
|
rectfill(x0, y1-px, x1, lastbottom, cols[firstcol])
|
|
|
|
for i=firstcol+1,ncols do
|
|
|
|
local bottom = y0+h*i\ncols
|
|
|
|
rectfill(x0,lastbottom,x1,bottom,cols[i])
|
|
|
|
lastbottom = bottom
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function inset(x0,y0,x1,y1)
|
|
|
|
rectfill(x0,y0,x1,y1,0)
|
|
|
|
-- use "wide colors" to draw
|
|
|
|
-- monochrome regardless of
|
|
|
|
-- fillp
|
|
|
|
rect(x0,y0,x1,y1,119)
|
|
|
|
line(x1,y0,x0,y0,85)
|
|
|
|
line(x0,y1,85)
|
|
|
|
end
|
|
|
|
|
|
|
|
function dropshadow(str, x, y, col)
|
|
|
|
print(str, x+1, y+1, 5)
|
|
|
|
print(str, x, y, col)
|
|
|
|
end
|
|
|
|
|
|
|
|
function grab_p1_butts()
|
|
|
|
if state ~= game then
|
|
|
|
local r = {0,0,0,0,0}
|
|
|
|
r[0] = 0
|
|
|
|
return r
|
|
|
|
end
|
|
|
|
local b = btn()
|
|
|
|
return {
|
|
|
|
[0]=b&0x1,
|
|
|
|
[1]=(b&0x2)>>1,
|
|
|
|
[2]=(b&0x4)>>2,
|
|
|
|
[3]=(b&0x8)>>3,
|
|
|
|
[4]=(b&0x10)>>4,
|
|
|
|
[5]=(b&0x20)>>5
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
function bury_the_dead(tbl, dead)
|
|
|
|
if (#dead == 0) return
|
|
|
|
local tail = dead[1]
|
|
|
|
local head = tail + 1
|
|
|
|
local deaddex = 2
|
|
|
|
|
|
|
|
while head <= #tbl do
|
|
|
|
while deaddex <= #dead and head == dead[deaddex] do
|
|
|
|
deaddex += 1
|
|
|
|
head += 1
|
|
|
|
end
|
|
|
|
if (head > #tbl) break
|
|
|
|
tbl[tail] = tbl[head]
|
|
|
|
head += 1
|
|
|
|
tail += 1
|
|
|
|
end
|
|
|
|
|
|
|
|
for i=1,(head-tail) do
|
|
|
|
deli(tbl)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-->8
|
|
|
|
--ships, including player
|
|
|
|
|
|
|
|
function init_ship_mt()
|
|
|
|
setmetatable(player, ship_t)
|
|
|
|
setmetatable(frownie, ship_t)
|
|
|
|
setmetatable(blocky, frownie_t)
|
|
|
|
setmetatable(chasey, ship_t)
|
|
|
|
end
|
|
|
|
|
2023-09-13 06:52:14 +00:00
|
|
|
firespark = split"9, 8, 2, 5, 1"
|
|
|
|
smokespark = split"13, 13, 5, 5"
|
2023-09-13 05:49:01 +00:00
|
|
|
|
|
|
|
player = {
|
|
|
|
--shape
|
|
|
|
sprite = 1, --index of ship sprite
|
|
|
|
size = 1, --all ships are square; how many 8x8 sprites?
|
|
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
|
|
x_off = 3, -- upper left corner
|
|
|
|
y_off = 2, -- relative to ship ulc
|
|
|
|
width = 1,
|
|
|
|
height = 3
|
|
|
|
},
|
|
|
|
sparks = firespark, -- see tab 9
|
|
|
|
sparkodds = 2,
|
|
|
|
boss = true, -- dramatic special effects
|
|
|
|
|
|
|
|
-- health and power
|
|
|
|
hp = 3, -- current health, non-regenerating
|
|
|
|
maxhp = 3, -- player only; other ships never heal
|
|
|
|
shield = 2, -- regenerates, using power
|
|
|
|
maxshield = 2,
|
|
|
|
shieldcost = 300, -- power cost to refill shield
|
|
|
|
generator = 1.5, -- 1 feels too slow
|
|
|
|
|
|
|
|
-- gun
|
|
|
|
main_gun = nil, -- assign at spawn time
|
|
|
|
special_gun = nil,
|
|
|
|
fire_off_x = 4, -- offset where bullets come from
|
|
|
|
fire_off_y = 0,
|
|
|
|
|
|
|
|
-- position
|
|
|
|
x=52, -- x and y are for upper left corner
|
|
|
|
y=96,
|
|
|
|
xmomentum = 0,
|
|
|
|
ymomentum = 0,
|
|
|
|
maxspd = 2.5, -- momentum cap
|
|
|
|
thrust = 0.25, -- momentum added from button
|
|
|
|
drag = 0.125, -- momentum lost per frame
|
|
|
|
slip = false, -- does not slide down screen
|
|
|
|
grab_butts = function(self) -- fetch buttons
|
|
|
|
local butts = grab_p1_butts()
|
|
|
|
if butts[0] == butts[1] then
|
|
|
|
self.sprite = 1
|
|
|
|
elseif butts[0] > 0 then
|
|
|
|
self.sprite = 17
|
|
|
|
else
|
|
|
|
self.sprite = 18
|
|
|
|
end
|
|
|
|
return butts
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
player_t = {
|
|
|
|
__index = player
|
|
|
|
}
|
|
|
|
|
|
|
|
function new_p1()
|
|
|
|
p = {
|
|
|
|
main_gun = new_gun_of(zap_gun_t, false)
|
|
|
|
}
|
|
|
|
setmetatable(p, player_t)
|
|
|
|
return p
|
|
|
|
end
|
|
|
|
|
|
|
|
frownie = {
|
|
|
|
--shape
|
|
|
|
sprite = 3, --index of ship sprite
|
|
|
|
size = 1, --all ships are square; how many 8x8 sprites?
|
|
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
|
|
x_off = 0, -- upper left corner
|
|
|
|
y_off = 1, -- relative to ship ulc
|
|
|
|
width = 8,
|
|
|
|
height = 6
|
|
|
|
},
|
|
|
|
sparks = smokespark,
|
|
|
|
sparkodds = 8,
|
|
|
|
|
|
|
|
-- health and power
|
|
|
|
hp = 1, -- enemy ships need no max hp
|
|
|
|
|
|
|
|
-- position
|
|
|
|
x=60, -- x and y are for upper left corner
|
|
|
|
y=8,
|
|
|
|
xmomentum = 0,
|
|
|
|
ymomentum = 0,
|
|
|
|
maxspd = 2, -- momentum cap
|
|
|
|
thrust = 0.12, -- momentum added from button
|
|
|
|
drag = 0.07, -- momentum lost per frame
|
|
|
|
slip = true,
|
|
|
|
grab_butts = function(discard_self)
|
|
|
|
-- buttons are effectively analog
|
|
|
|
-- and negative buttons work just fine!
|
|
|
|
local butts = {}
|
|
|
|
local tstate = (1 + flr(4*t() + 0.5)) % 6
|
|
|
|
butts[0] = ((tstate==1 or tstate==2) and 1) or 0
|
|
|
|
butts[1] = ((tstate==4 or tstate==5) and 1) or 0
|
|
|
|
for b=2, 5 do
|
|
|
|
butts[b]=0
|
|
|
|
end
|
|
|
|
return butts
|
|
|
|
end, -- button fetch algorithm
|
|
|
|
}
|
|
|
|
frownie_t = {
|
|
|
|
__index = frownie
|
|
|
|
}
|
|
|
|
|
|
|
|
blocky = {
|
|
|
|
sprite = 10,
|
|
|
|
hp = 2,
|
|
|
|
hurt = {
|
|
|
|
x_off = 0,
|
|
|
|
y_off = 0,
|
|
|
|
width = 8,
|
|
|
|
height = 7
|
|
|
|
},
|
|
|
|
|
|
|
|
ow = function(self)
|
|
|
|
if self.hp <= 1 then
|
|
|
|
self.sprite = 11
|
|
|
|
else
|
|
|
|
self.sprite = 10
|
|
|
|
end
|
|
|
|
ship_t.__index.ow(self)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
blocky_t = {
|
|
|
|
__index = blocky
|
|
|
|
}
|
|
|
|
|
|
|
|
function spawn_spewy_at(x, y)
|
|
|
|
local spewy = {
|
|
|
|
x = x,
|
|
|
|
y = y,
|
|
|
|
sprite = 26,
|
|
|
|
power = -20,
|
|
|
|
hurt = {
|
|
|
|
x_off = 0,
|
|
|
|
y_off = 1,
|
|
|
|
width = 8,
|
|
|
|
height = 5
|
|
|
|
},
|
|
|
|
|
|
|
|
hp = 1,
|
|
|
|
maxpower = 70,
|
|
|
|
generator = 0.5,
|
|
|
|
main_gun = new_gun_of(protron_gun_t, true),
|
|
|
|
fire_off_x = 4,
|
|
|
|
fire_off_y = 7,
|
|
|
|
grab_butts = function()
|
|
|
|
local butts = frownie.grab_butts()
|
|
|
|
butts[5] = 1
|
|
|
|
return butts
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
setmetatable(spewy, frownie_t)
|
|
|
|
add(eships, spewy)
|
|
|
|
return spewy
|
|
|
|
end
|
|
|
|
|
|
|
|
chasey = {
|
|
|
|
sprite = 5,
|
|
|
|
size = 1,
|
|
|
|
hurt = {
|
|
|
|
x_off = 1,
|
|
|
|
y_off = 2,
|
|
|
|
width = 6,
|
|
|
|
height = 5,
|
|
|
|
},
|
|
|
|
sparks = smokespark,
|
|
|
|
sparkodds = 8,
|
|
|
|
hp = 2,
|
|
|
|
shield = 1,
|
|
|
|
maxshield = 1,
|
|
|
|
shieldcost = 180,
|
|
|
|
|
|
|
|
fire_off_x = 4,
|
|
|
|
fire_off_y = 7,
|
|
|
|
|
|
|
|
maxspd = 2,
|
|
|
|
thrust = 0.2,
|
|
|
|
drag = 0.075,
|
|
|
|
slip = true,
|
|
|
|
|
|
|
|
grab_butts = function(self)
|
|
|
|
local butts = {0,0,0,0,0}
|
|
|
|
butts[0] = 0
|
|
|
|
if (self.x < primary_ship.x) butts[1] = 1
|
|
|
|
if (self.x > primary_ship.x) butts[0] = 1
|
|
|
|
if (self.x - 16 < primary_ship.x and self.x + 16 > primary_ship.x) butts[5] = 1
|
|
|
|
return butts
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
chasey_t = {
|
|
|
|
__index = chasey
|
|
|
|
}
|
|
|
|
function spawn_chasey_at(x, y)
|
|
|
|
local c = {
|
|
|
|
x = x,
|
|
|
|
y = y,
|
|
|
|
main_gun = new_gun_of(zap_gun_t, true)
|
|
|
|
}
|
|
|
|
setmetatable(c, chasey_t)
|
|
|
|
add(eships, c)
|
|
|
|
return c
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_xl_chasey_at(x, y)
|
|
|
|
local c = {
|
|
|
|
x = x,
|
|
|
|
y = y,
|
|
|
|
size = 2,
|
|
|
|
maxspd = 1.25,
|
|
|
|
hurt = {
|
|
|
|
x_off = 2,
|
|
|
|
y_off = 4,
|
|
|
|
width = 12,
|
|
|
|
height = 10
|
|
|
|
},
|
|
|
|
hp = 20,
|
|
|
|
shield = 5,
|
|
|
|
boss = true,
|
|
|
|
slip = false,
|
|
|
|
main_gun = new_gun_of(zap_gun_t, true),
|
|
|
|
grab_butts = function(self)
|
|
|
|
local butts = chasey.grab_butts(self)
|
|
|
|
if (self.y < 4) butts[3] = 1
|
|
|
|
return butts
|
|
|
|
end,
|
|
|
|
draw = function(self)
|
|
|
|
if(self.fx_pal) pal(self.fx_pal)
|
|
|
|
sspr(40, 0, 8, 8, self.x, self.y, 16, 16)
|
|
|
|
pal()
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
setmetatable(c, chasey_t)
|
|
|
|
add(eships, c)
|
|
|
|
return c
|
|
|
|
end
|
|
|
|
-->8
|
|
|
|
--ship behavior
|
|
|
|
|
|
|
|
scrollrate = 0.25 --in px/frame
|
|
|
|
|
|
|
|
ship_m = {
|
|
|
|
|
|
|
|
-- ships have no shield by default
|
|
|
|
shield = 0,
|
|
|
|
maxshield = 0,
|
|
|
|
shieldcost = 32767.9,
|
|
|
|
shieldcooldown = 180,
|
|
|
|
|
|
|
|
-- default generator behavior:
|
|
|
|
-- 10 seconds for a full charge
|
|
|
|
max_power = 600,
|
|
|
|
power = 600,
|
|
|
|
generator = 1, -- power gen per frame
|
|
|
|
|
|
|
|
invincible_until = -32768,
|
|
|
|
|
|
|
|
slip = true, -- most enemies slide
|
|
|
|
|
|
|
|
xmomentum = 0,
|
|
|
|
ymomentum = 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
ship_t = {
|
|
|
|
__index = ship_m,
|
|
|
|
}
|
|
|
|
|
|
|
|
function ship_m.die(s)
|
|
|
|
s.dead = true
|
|
|
|
if (s.hp <= 0) boom(s.x+s.size*4, s.y+s.size*4,12*s.size, s.boss)
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m.move(ship)
|
|
|
|
ship:refresh_shield()
|
|
|
|
ship.power = min(ship.max_power, ship.power + ship.generator)
|
|
|
|
butt = ship:grab_butts()
|
|
|
|
if (butt[5] > 0) ship:maybe_shoot(ship.main_gun)
|
|
|
|
if (butt[4] > 0) ship:maybe_shoot(ship.special_gun)
|
|
|
|
if (butt[0]-butt[1] ~= 0 or butt[2]-butt[3] ~= 0) spark(ship.sparks, ship.x + 4*ship.size, ship.y + 4*ship.size, butt, ship.thrust, ship.sparkodds)
|
|
|
|
ship.xmomentum += (ship.thrust * butt[1]) - (ship.thrust * butt[0])
|
|
|
|
ship.ymomentum += (ship.thrust * butt[3]) - (ship.thrust * butt[2])
|
|
|
|
ship.xmomentum = mid(-ship.maxspd, ship.maxspd, ship.xmomentum)
|
|
|
|
ship.ymomentum = mid(-ship.maxspd, ship.maxspd, ship.ymomentum)
|
|
|
|
|
|
|
|
ship.x += ship.xmomentum
|
|
|
|
ship.y += ship.ymomentum
|
|
|
|
|
|
|
|
if ship == primary_ship then
|
|
|
|
ship.x = mid(0, 112 - 8 * ship.size, ship.x)
|
|
|
|
ship.y = mid(0, 128 - 8 * ship.size, ship.y)
|
|
|
|
end
|
|
|
|
|
|
|
|
--friction
|
|
|
|
local d = ship.drag
|
|
|
|
ship.xmomentum -= mid(d, -d, ship.xmomentum)
|
|
|
|
ship.ymomentum -= mid(d, -d, ship.ymomentum)
|
|
|
|
|
|
|
|
-- "scrolling" behavior
|
|
|
|
if ship.slip then
|
|
|
|
ship.y += scrollrate
|
|
|
|
if ship.y >= 128 then
|
|
|
|
ship:die()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m.draw(ship)
|
|
|
|
if(ship.fx_pal) pal(ship.fx_pal)
|
|
|
|
spr(ship.sprite, ship.x, ship.y, ship.size, ship.size)
|
|
|
|
pal()
|
|
|
|
end
|
|
|
|
|
|
|
|
function hurtbox(ship)
|
|
|
|
local h = ship.hurt
|
|
|
|
return {
|
|
|
|
x=ship.x + h.x_off,
|
|
|
|
y=ship.y + h.y_off,
|
|
|
|
width=h.width,
|
|
|
|
height=h.height
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m:maybe_shoot(gun)
|
|
|
|
if (not gun) return
|
|
|
|
if (self.power < gun.power) return
|
|
|
|
if (not gun:shoot(self.x + self.fire_off_x, self.y + self.fire_off_y)) return
|
|
|
|
self.power -= gun.power
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m:hitship(other)
|
|
|
|
return self:hitsomething(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m:hitbullet(b)
|
|
|
|
return self:hitsomething(b.damage)
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m:hitsomething(dmg)
|
|
|
|
if (dmg <= 0) return false
|
|
|
|
if (lframe < self.invincible_until) return false
|
|
|
|
self.shield_refresh_ready = lframe + self.shieldcooldown
|
|
|
|
if self.shield >= dmg then
|
|
|
|
self.shield -= dmg
|
|
|
|
self:ow(true)
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
dmg -= self.shield
|
|
|
|
self.shield = 0
|
|
|
|
self.hp -= dmg
|
|
|
|
if self.hp <= 0 then
|
|
|
|
self:die()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
self:ow(false)
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m:ow(shielded)
|
|
|
|
if (shielded) then
|
|
|
|
blip(self,12,3)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
blip(self, 7, 3)
|
|
|
|
end
|
|
|
|
|
|
|
|
function ship_m:refresh_shield()
|
|
|
|
if (self.shield >= self.maxshield) return
|
|
|
|
if (lframe < self.shield_refresh_ready) return
|
|
|
|
if (self.power < self.shieldcost) return
|
|
|
|
self.shield += 1
|
|
|
|
self.power -= self.shieldcost
|
|
|
|
self.shield_refresh_ready = lframe + self.shieldcooldown
|
|
|
|
end
|
|
|
|
-->8
|
|
|
|
-- collisions
|
|
|
|
|
|
|
|
-- box: x, y, width, height
|
|
|
|
|
|
|
|
function collides(box1, box2)
|
|
|
|
return not (
|
|
|
|
box1.x>box2.x+box2.width
|
|
|
|
or box1.y>box2.y+box2.height
|
|
|
|
or box1.x+box1.width<box2.x
|
|
|
|
or box1.y+box1.height<box2.y)
|
|
|
|
end
|
|
|
|
|
|
|
|
collider = { }
|
|
|
|
collider_t = {
|
|
|
|
__index = collider
|
|
|
|
}
|
|
|
|
|
|
|
|
function new_collider()
|
|
|
|
local c = { }
|
|
|
|
setmetatable(c, collider_t)
|
|
|
|
c.suppress = { }
|
|
|
|
return c
|
|
|
|
end
|
|
|
|
function collider_indexes(box)
|
|
|
|
local ret = {}
|
|
|
|
for x = box.x\8, (box.x+box.width)\8 do
|
|
|
|
for y = box.y\8, (box.y+box.height)\8 do
|
|
|
|
add(ret, x+256*y)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
|
|
|
function collider:insert(item)
|
|
|
|
-- todo: separate "big items" list?
|
|
|
|
local bdx = collider_indexes(hurtbox(item))
|
|
|
|
for i in all(bdx) do
|
|
|
|
local x = self[i]
|
|
|
|
if not x then
|
|
|
|
x = {}
|
|
|
|
self[i] = x
|
|
|
|
end
|
|
|
|
add(x, item)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function collider:hide(item)
|
|
|
|
self.suppress[item]=true
|
|
|
|
end
|
|
|
|
|
|
|
|
function collider:get_collisions(item)
|
|
|
|
local found = { }
|
|
|
|
local seen = { }
|
|
|
|
local box = hurtbox(item)
|
|
|
|
local bucket_ids = collider_indexes(box)
|
|
|
|
for b_idx in all(bucket_ids) do
|
|
|
|
local bucket = self[b_idx]
|
|
|
|
if bucket then
|
|
|
|
for candidate in all(bucket) do
|
|
|
|
if not (seen[candidate] or self.suppress[candidate]) then
|
|
|
|
seen[candidate] = true
|
|
|
|
if (collides(box, hurtbox(candidate))) add(found, candidate)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return found
|
|
|
|
end
|
|
|
|
-->8
|
|
|
|
-- level and event system
|
|
|
|
|
|
|
|
-- a level is a map from
|
|
|
|
-- effective frame number to
|
|
|
|
-- callback for that frame.
|
|
|
|
|
|
|
|
-- effective frame number stops
|
|
|
|
-- when freeze count is nonzero
|
|
|
|
|
|
|
|
-- a level is won when it hits
|
|
|
|
-- the end-of-level sentinel
|
|
|
|
-- and there are no more
|
|
|
|
-- tracked enemies.
|
|
|
|
-- lost when there are no
|
|
|
|
-- player ships left.
|
|
|
|
|
|
|
|
-- effective frame
|
|
|
|
distance = 0
|
|
|
|
-- actual frame count since
|
|
|
|
-- start of level
|
|
|
|
lframe = 0
|
|
|
|
|
|
|
|
-- do not advance distance when
|
|
|
|
-- nonzero
|
|
|
|
freeze = 0
|
|
|
|
|
|
|
|
eol = {}
|
|
|
|
|
|
|
|
function load_level(lvltbl)
|
|
|
|
distance = 0
|
|
|
|
lframe = 0
|
|
|
|
freeze = 0
|
|
|
|
current_level = {}
|
|
|
|
-- copy the level so we can
|
|
|
|
-- modify it dynamically
|
|
|
|
-- without losing the original
|
|
|
|
for frame, cb in pairs(lvltbl) do
|
|
|
|
current_level[frame] = cb
|
|
|
|
end
|
|
|
|
leveldone = false
|
|
|
|
end
|
|
|
|
|
|
|
|
function level_frame()
|
|
|
|
lframe += 1
|
|
|
|
if (current_level == nil) return true
|
|
|
|
if freeze == 0 then
|
|
|
|
distance += 1
|
|
|
|
local cb = current_level[distance]
|
|
|
|
if cb ~= nil then
|
|
|
|
if cb == eol then
|
|
|
|
current_level = nil
|
|
|
|
return true
|
|
|
|
else
|
|
|
|
cb()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
-->8
|
|
|
|
-- example level
|
|
|
|
|
|
|
|
function spawn_rnd_x(mt)
|
|
|
|
s = {
|
|
|
|
x = rnd(104),
|
|
|
|
y = -(mt.__index.size * 8 - 1)
|
|
|
|
}
|
|
|
|
setmetatable(s, mt)
|
|
|
|
add(eships, s)
|
|
|
|
return s
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_blocking_rnd_x(mt)
|
|
|
|
freeze += 1
|
|
|
|
s = {
|
|
|
|
x = rnd(104),
|
|
|
|
y = -7,
|
|
|
|
ice = 1,
|
|
|
|
die = function(self)
|
|
|
|
freeze -= self.ice
|
|
|
|
self.ice = 0
|
|
|
|
mt.__index.die(self)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
setmetatable(s, mt)
|
|
|
|
add(eships, s)
|
|
|
|
return s
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_frownie()
|
|
|
|
return spawn_rnd_x(frownie_t)
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_blocking_frownie()
|
|
|
|
spawn_blocking_rnd_x(frownie_t)
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_blocky()
|
|
|
|
spawn_rnd_x(blocky_t)
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_blocking_blocky()
|
|
|
|
spawn_blocking_rnd_x(blocky_t)
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_spewy()
|
|
|
|
return spawn_spewy_at(rnd(104), -7)
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_chasey()
|
|
|
|
return spawn_chasey_at(rnd(104), -7)
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_blocking_spewy()
|
|
|
|
freeze += 1
|
|
|
|
local s = spawn_spewy()
|
|
|
|
s.ice = 1
|
|
|
|
s.die = function(self)
|
|
|
|
freeze -= self.ice
|
|
|
|
self.ice = 0
|
|
|
|
frownie_t.__index.die(self)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_bonus_frownie()
|
|
|
|
local f = spawn_frownie()
|
|
|
|
f.sprite = 7
|
|
|
|
f.die = function(self)
|
|
|
|
spawn_repair_at(self.x+4, self.y+4)
|
|
|
|
frownie_t.__index.die(self)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_bonus_vulcan_chasey()
|
|
|
|
local c = spawn_chasey()
|
|
|
|
c.main_gun=new_gun_of(vulcan_gun_t, true)
|
|
|
|
c.die = function(self)
|
|
|
|
spawn_main_gun_at(self.x-1, self.y-1, vulcan_gun_t)
|
|
|
|
chasey.die(self)
|
|
|
|
end
|
|
|
|
c.sprite=4
|
|
|
|
return c
|
|
|
|
end
|
|
|
|
|
|
|
|
helpers = {
|
|
|
|
spawn_frownie,
|
|
|
|
spawn_frownie,
|
|
|
|
spawn_frownie,
|
|
|
|
spawn_blocky,
|
|
|
|
spawn_blocky,
|
|
|
|
spawn_chasey,
|
|
|
|
spawn_spewy,
|
|
|
|
}
|
|
|
|
|
|
|
|
function spawn_blocking_boss_chasey()
|
|
|
|
freeze += 1
|
|
|
|
local c = spawn_xl_chasey_at(44, -15)
|
|
|
|
c.ice = 1
|
|
|
|
c.die = function(self)
|
|
|
|
freeze -= self.ice
|
|
|
|
self.ice = 0
|
|
|
|
chasey_t.__index.die(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
local nextspawn = lframe + 120
|
|
|
|
add(events, function()
|
|
|
|
if lframe >= nextspawn then
|
|
|
|
helpers[flr(rnd(#helpers))+1]()
|
|
|
|
nextspawn += 60
|
|
|
|
end
|
|
|
|
return c.dead
|
|
|
|
end)
|
|
|
|
|
|
|
|
return c
|
|
|
|
end
|
|
|
|
|
|
|
|
example_level = {
|
|
|
|
[1]=spawn_frownie,
|
|
|
|
[60]=spawn_bonus_vulcan_chasey,
|
|
|
|
[61]=spawn_blocky,
|
|
|
|
[85]=spawn_spewy,
|
|
|
|
[100]=spawn_spewy,
|
|
|
|
[115]=spawn_spewy,
|
|
|
|
[130]=spawn_bonus_frownie,
|
|
|
|
[145]=spawn_spewy,
|
|
|
|
[200]=spawn_chasey,
|
|
|
|
[250]=spawn_blocking_blocky,
|
|
|
|
[285]=function()
|
|
|
|
spawn_spec_gun_at(35, -11, blast_gun_t)
|
|
|
|
end,
|
|
|
|
[310]=function()
|
|
|
|
spawn_blocking_blocky()
|
|
|
|
spawn_blocking_blocky()
|
|
|
|
spawn_blocking_blocky()
|
|
|
|
end,
|
|
|
|
[311]=spawn_frownie,
|
|
|
|
[350]=function()
|
|
|
|
spawn_main_gun_at(70, -11, protron_gun_t)
|
|
|
|
end,
|
|
|
|
[401]=spawn_frownie,
|
|
|
|
[420]=spawn_blocking_frownie,
|
|
|
|
[430]=spawn_bonus_vulcan_chasey,
|
|
|
|
[450]=spawn_frownie,
|
|
|
|
[465]=spawn_bonus_frownie,
|
|
|
|
[480]=spawn_chasey,
|
|
|
|
[500]=function()
|
|
|
|
local tnext = lframe
|
|
|
|
local remain = 20
|
|
|
|
add(events, function()
|
|
|
|
if (lframe < tnext) return false
|
|
|
|
spawn_blocking_blocky()
|
|
|
|
tnext = lframe + 12
|
|
|
|
remain -= 1
|
|
|
|
return (remain <= 0)
|
|
|
|
end)
|
|
|
|
end,
|
|
|
|
[501]=spawn_bonus_frownie,
|
|
|
|
[620]=spawn_blocking_blocky,
|
|
|
|
[700]=spawn_blocking_boss_chasey,
|
|
|
|
[701]=eol
|
|
|
|
}
|
|
|
|
-->8
|
|
|
|
-- bullets and guns
|
|
|
|
|
|
|
|
function init_bullet_mt()
|
|
|
|
setmetatable(zap, bullet_t)
|
|
|
|
setmetatable(zap_gun, gun_t)
|
|
|
|
setmetatable(blast, bullet_t)
|
|
|
|
setmetatable(blast_gun, gun_t)
|
|
|
|
setmetatable(protron, bullet_t)
|
|
|
|
setmetatable(protron_gun, gun_t)
|
|
|
|
setmetatable(vulcan, bullet_t)
|
|
|
|
setmetatable(vulcan_gun, gun_t)
|
|
|
|
end
|
|
|
|
|
|
|
|
function new_gun_of(mt, is_enemy)
|
|
|
|
local g = {
|
|
|
|
enemy = is_enemy
|
|
|
|
}
|
|
|
|
setmetatable(g, mt)
|
|
|
|
return g
|
|
|
|
end
|
|
|
|
|
|
|
|
zap = {
|
|
|
|
--shape
|
|
|
|
psprite = 8, --index of player ammo sprite
|
|
|
|
esprite = 9, -- index of enemy ammo sprite
|
|
|
|
width = 1, --in 8x8 blocks
|
|
|
|
height = 1,
|
|
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
|
|
x_off = 0, -- upper left corner
|
|
|
|
y_off = 0, -- relative to sprite
|
|
|
|
width = 2,
|
|
|
|
height = 8
|
|
|
|
},
|
|
|
|
center_x_off = 1, -- how to position by ship
|
|
|
|
bottom_y_off = 0,
|
|
|
|
top_y_off = 0,
|
|
|
|
|
|
|
|
damage = 1,
|
|
|
|
dx = 0, -- px/frame
|
|
|
|
dy = 8,
|
|
|
|
|
|
|
|
hitship = function(_, _)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
}
|
|
|
|
zap_t = {
|
|
|
|
__index = zap
|
|
|
|
}
|
|
|
|
|
|
|
|
zap_gun = {
|
|
|
|
enemy = false,
|
|
|
|
power = 20, -- power consumed per shot
|
|
|
|
cooldown = 10, -- frames between shots
|
|
|
|
ammo = nil, -- unlimited ammo - main gun
|
|
|
|
t = zap_t -- metatable of bullet to fire
|
|
|
|
}
|
|
|
|
|
|
|
|
zap_gun_t = {
|
|
|
|
__index = zap_gun
|
|
|
|
}
|
|
|
|
|
|
|
|
blast = {
|
|
|
|
--shape
|
|
|
|
psprite = 12, --index of player ammo sprite
|
|
|
|
esprite = 3, -- index of enemy ammo sprite
|
|
|
|
width = 1, --in 8x8 blocks
|
|
|
|
height = 1,
|
|
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
|
|
x_off = 1, -- upper left corner
|
|
|
|
y_off = 1, -- relative to sprite
|
|
|
|
width = 6,
|
|
|
|
height = 6
|
|
|
|
},
|
|
|
|
center_x_off = 4, -- how to position by ship
|
|
|
|
bottom_y_off = 0,
|
|
|
|
top_y_off = 0,
|
|
|
|
|
|
|
|
damage = 4,
|
|
|
|
dx = 0, -- px/frame
|
|
|
|
dy = 2,
|
|
|
|
|
|
|
|
-- disable damage for 2 frames
|
|
|
|
-- when hitting something
|
|
|
|
hitship = function(self, _)
|
|
|
|
self.damage = 0
|
|
|
|
local wait = 2
|
|
|
|
e = function()
|
|
|
|
wait -= 1
|
|
|
|
if wait <= 0 then
|
|
|
|
self.damage = 4
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
add(events, e)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
blast_t = {
|
|
|
|
__index = blast
|
|
|
|
}
|
|
|
|
|
|
|
|
blast_gun = {
|
|
|
|
icon = 13,
|
|
|
|
enemy = false,
|
|
|
|
power = 0, -- ammo, not power
|
|
|
|
cooldown = 30, -- frames between shots
|
|
|
|
ammo = 5,
|
|
|
|
maxammo = 5,
|
|
|
|
t = blast_t -- metatable of bullet to fire
|
|
|
|
}
|
|
|
|
|
|
|
|
blast_gun_t = {
|
|
|
|
__index = blast_gun
|
|
|
|
}
|
|
|
|
|
|
|
|
protron = {
|
|
|
|
--shape
|
|
|
|
psprite = 23, --index of player ammo sprite
|
|
|
|
esprite = 24, -- index of enemy ammo sprite
|
|
|
|
width = 1, --in 8x8 blocks
|
|
|
|
height = 1,
|
|
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
|
|
x_off = 1, -- upper left corner
|
|
|
|
y_off = 1, -- relative to sprite
|
|
|
|
width = 2,
|
|
|
|
height = 2
|
|
|
|
},
|
|
|
|
center_x_off = 1, -- how to position by ship
|
|
|
|
bottom_y_off = 4,
|
|
|
|
top_y_off = 0,
|
|
|
|
|
|
|
|
damage = 1,
|
|
|
|
dx = 0, -- px/frame
|
|
|
|
dy = 3,
|
|
|
|
}
|
|
|
|
protron_t = {
|
|
|
|
__index = protron
|
|
|
|
}
|
|
|
|
|
|
|
|
protron_gun = {
|
|
|
|
icon = 25,
|
|
|
|
enemy = false,
|
|
|
|
power = 35,
|
|
|
|
cooldown = 15, -- frames between shots
|
|
|
|
ammo = nil,
|
|
|
|
maxammo = nil,
|
|
|
|
actually_shoot = function(self, x, y)
|
|
|
|
local sprite = protron.psprite
|
|
|
|
if (self.enemy) sprite=protron.esprite
|
|
|
|
for i=1,3 do
|
|
|
|
local b = {
|
|
|
|
enemy=self.enemy,
|
|
|
|
sprite=sprite,
|
|
|
|
dx = i,
|
|
|
|
dy = 4-i
|
|
|
|
}
|
|
|
|
setmetatable(b, protron_t)
|
|
|
|
b:spawn_at(x,y)
|
|
|
|
local b2 = {
|
|
|
|
enemy=self.enemy,
|
|
|
|
sprite=sprite,
|
|
|
|
dx = -i,
|
|
|
|
dy = 4-i
|
|
|
|
}
|
|
|
|
setmetatable(b2, protron_t)
|
|
|
|
b2:spawn_at(x,y)
|
|
|
|
end
|
|
|
|
local bup = {
|
|
|
|
enemy=self.enemy,
|
|
|
|
sprite=sprite,
|
|
|
|
dy=4
|
|
|
|
}
|
|
|
|
setmetatable(bup, protron_t)
|
|
|
|
bup:spawn_at(x,y)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
protron_gun_t = {
|
|
|
|
__index = protron_gun
|
|
|
|
}
|
|
|
|
|
|
|
|
vulcan = {
|
|
|
|
--shape
|
|
|
|
psprite = 22, --index of player ammo sprite
|
|
|
|
esprite = 21, -- index of enemy ammo sprite
|
|
|
|
width = 1, --in 8x8 blocks
|
|
|
|
height = 1,
|
|
|
|
hurt = { -- hurtbox - where this ship can be hit
|
|
|
|
x_off = 0, -- upper left corner
|
|
|
|
y_off = 0, -- relative to sprite
|
|
|
|
width = 1,
|
|
|
|
height = 4
|
|
|
|
},
|
|
|
|
center_x_off = 0.5, -- how to position by ship
|
|
|
|
bottom_y_off = 4,
|
|
|
|
top_y_off = 0,
|
|
|
|
|
|
|
|
damage = 0.5,
|
|
|
|
dx = 0, -- px/frame
|
|
|
|
dy = 4,
|
|
|
|
}
|
|
|
|
vulcan_t = {
|
|
|
|
__index = vulcan
|
|
|
|
}
|
|
|
|
vulcan_gun = {
|
|
|
|
icon = 37,
|
|
|
|
enemy = false,
|
|
|
|
power = 8,
|
|
|
|
cooldown = 2, -- frames between shots
|
|
|
|
ammo = nil,
|
|
|
|
maxammo = nil,
|
|
|
|
dxs = {0.35, -0.35, -0.7, 0.7, 0.35, -0.35},
|
|
|
|
xoffs = {1, 0, -1, 1, 0, -1},
|
|
|
|
dxidx = 1,
|
|
|
|
actually_shoot = function(self, x, y)
|
|
|
|
local sprite = self.enemy and vulcan.esprite or vulcan.psprite
|
|
|
|
local b = {
|
|
|
|
enemy=self.enemy,
|
|
|
|
sprite=sprite,
|
|
|
|
dx = self.dxs[self.dxidx],
|
|
|
|
}
|
|
|
|
setmetatable(b, vulcan_t)
|
|
|
|
b:spawn_at(self.xoffs[self.dxidx]+x,y)
|
|
|
|
self.dxidx += 1
|
|
|
|
if (self.dxidx > #self.dxs) self.dxidx = 1
|
|
|
|
end
|
|
|
|
}
|
|
|
|
vulcan_gun_t = {
|
|
|
|
__index = vulcan_gun
|
|
|
|
}
|
|
|
|
|
|
|
|
-->8
|
|
|
|
-- bullet and gun behaviors
|
|
|
|
|
|
|
|
bullet_base = {
|
|
|
|
enemyspd = 0.5
|
|
|
|
}
|
|
|
|
|
|
|
|
bullet_t = {
|
|
|
|
__index = bullet_base
|
|
|
|
}
|
|
|
|
|
|
|
|
gun_base = {
|
|
|
|
shoot_ready = -32768,
|
|
|
|
|
|
|
|
icon = 20
|
|
|
|
}
|
|
|
|
|
|
|
|
gun_t = {
|
|
|
|
__index = gun_base
|
|
|
|
}
|
|
|
|
|
|
|
|
function bullet_base:hitship(_)
|
|
|
|
self:die()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function bullet_base:die()
|
|
|
|
end
|
|
|
|
|
|
|
|
function bullet_base:move()
|
|
|
|
self.x += self.dx
|
|
|
|
if self.enemy then
|
|
|
|
self.y += self.dy
|
|
|
|
if self.y > 128 then
|
|
|
|
self:die()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
else
|
|
|
|
self.y -= self.dy
|
|
|
|
if self.y < -8*self.height then
|
|
|
|
self:die()
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
function bullet_base:draw()
|
|
|
|
spr(self.sprite, self.x, self.y, self.width, self.height)
|
|
|
|
end
|
|
|
|
|
|
|
|
function bullet_base:spawn_at(x, y)
|
|
|
|
self.x = x - self.center_x_off
|
|
|
|
if self.enemy then
|
|
|
|
self.dx *= self.enemyspd
|
|
|
|
self.dy *= self.enemyspd
|
|
|
|
self.y = y + self.top_y_off
|
|
|
|
add(ebullets, self)
|
|
|
|
else
|
|
|
|
self.y = y - (8 * self.height) + self.bottom_y_off
|
|
|
|
add(pbullets, self)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function gun_base:shoot(x, y)
|
|
|
|
if (lframe < self.shoot_ready) return false
|
|
|
|
if self.ammo then
|
|
|
|
if (self.ammo <= 0) return false
|
|
|
|
self.ammo -= 1
|
|
|
|
end
|
|
|
|
self.shoot_ready = lframe + self.cooldown
|
|
|
|
self:actually_shoot(x, y)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
function gun_base:actually_shoot(x, y)
|
|
|
|
b = { }
|
|
|
|
setmetatable(b, self.t)
|
|
|
|
if self.enemy then
|
|
|
|
b.enemy = true
|
|
|
|
b.sprite = b.esprite
|
|
|
|
else
|
|
|
|
b.enemy = false
|
|
|
|
b.sprite = b.psprite
|
|
|
|
end
|
|
|
|
b:spawn_at(x, y)
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
-->8
|
|
|
|
-- readme.md
|
|
|
|
|
|
|
|
--[[
|
|
|
|
|
|
|
|
main loop sequence
|
|
|
|
==================
|
|
|
|
1. level_frame
|
|
|
|
2. events
|
|
|
|
3. merge new_events into events
|
|
|
|
4. update bg intangibles
|
|
|
|
5. move ships (player first)
|
|
|
|
6. move bullets (player first)
|
|
|
|
7. calculate collisions
|
|
|
|
1. pship on eship
|
|
|
|
2. ebullet on pship
|
|
|
|
3. pbullet on eship
|
|
|
|
8. update fg intangibles
|
|
|
|
9. check for end of level
|
|
|
|
|
|
|
|
draw order
|
|
|
|
----------
|
|
|
|
bottom to top:
|
|
|
|
1. intangibles_bg
|
|
|
|
2. player bullets
|
|
|
|
3. player ships
|
|
|
|
4. enemy ships
|
|
|
|
5. enemy bullets
|
|
|
|
6. intangibles_fg
|
|
|
|
|
|
|
|
notes
|
|
|
|
-----
|
|
|
|
intangibles_fg move()s after
|
|
|
|
all collisions and other moves
|
|
|
|
are processed. if an intangible
|
|
|
|
is added to the list as a result
|
|
|
|
of a collision or move, it will
|
|
|
|
itself be move()d before it is
|
|
|
|
drawn.
|
|
|
|
|
|
|
|
don't modify a list while it's
|
|
|
|
being iterated. ships that want
|
|
|
|
to create ships and bullets
|
|
|
|
that want to create bullets
|
|
|
|
need to create an event to
|
|
|
|
do this (which will run before
|
|
|
|
the ship and bullet phases of
|
|
|
|
the next frame). events that
|
|
|
|
want to create events add to
|
|
|
|
new_events, rather than events.
|
|
|
|
|
|
|
|
data-driven items
|
|
|
|
=================
|
|
|
|
guns and bullets both allow the most
|
|
|
|
common behaviors to be
|
|
|
|
expressed with data alone.
|
|
|
|
ships only need a movement
|
|
|
|
algorithm expressed.
|
|
|
|
|
|
|
|
guns
|
|
|
|
----
|
|
|
|
* power - cost in generator
|
|
|
|
power to fire. may be 0.
|
|
|
|
field directly read by ships;
|
|
|
|
required in all guns.
|
|
|
|
* t - metatable for bullet type.
|
|
|
|
fired once in the bullet's
|
|
|
|
default direction per shot.
|
|
|
|
* enemy - if true, fired bullets
|
|
|
|
are flagged as enemy bullets.
|
|
|
|
* icon - sprite index of an
|
|
|
|
8x8 sprite to display in the
|
|
|
|
hud when the player has this
|
|
|
|
gun. default is 20, a generic
|
|
|
|
crosshair bullseye thing.
|
|
|
|
* cooldown - min frames between
|
|
|
|
shots.
|
|
|
|
* ammo, maxammo - permitted
|
|
|
|
number of shots. 0 is empty
|
|
|
|
and unfireable. maxammo = 0
|
|
|
|
will cause a divide by zero
|
|
|
|
so don't do that. if nil,
|
|
|
|
ammo is infinite.
|
|
|
|
|
|
|
|
default guns manage ammo and
|
|
|
|
cooldown in shoot, then call
|
|
|
|
actually_shoot to create the
|
|
|
|
projectile. override only
|
|
|
|
actually_shoot to change
|
|
|
|
projectile logic while keeping
|
|
|
|
cooldown and ammo logic.
|
|
|
|
|
|
|
|
ships manage generator power
|
|
|
|
before asking the gun to shoot.
|
|
|
|
this behavior is in
|
|
|
|
ship_m:maybe_shoot.
|
|
|
|
|
|
|
|
bullets
|
|
|
|
-------
|
|
|
|
* dx, dy - movement per frame.
|
|
|
|
player bullets use -dy
|
|
|
|
instead.
|
|
|
|
* enemyspd - multiplier for dx
|
|
|
|
and dy on enemy bullets.
|
|
|
|
default is 0.5, making enemy
|
|
|
|
shots much easier to dodge
|
|
|
|
* damage - damage per hit;
|
|
|
|
used by ships
|
|
|
|
* psprite, esprite - index of
|
|
|
|
player or enemy sprite.
|
|
|
|
* center_off_x - the horizontal
|
|
|
|
centerpoint of the bullet,
|
|
|
|
for positioning when firing.
|
|
|
|
assume a pixel's coordinates
|
|
|
|
refer to the upper left corner
|
|
|
|
of the pixel; the center of
|
|
|
|
a 2-width bullet with an
|
|
|
|
upper left corner at 0 is 1,
|
|
|
|
not 0.5.
|
|
|
|
* top_off_y, bottom_off_y -
|
|
|
|
also for positioning when
|
|
|
|
firing. positive distance from
|
|
|
|
top or bottom edge to image.
|
|
|
|
top_off_y will usually be 0,
|
|
|
|
bottom_off_y will not be when
|
|
|
|
bullets are smaller than
|
|
|
|
the sprite box.
|
|
|
|
* width, height - measured in
|
|
|
|
full sprites (8x8 boxes), not
|
|
|
|
pixels. used for drawing.
|
|
|
|
|
|
|
|
bullets despawn when above or
|
|
|
|
below the screen (player or
|
|
|
|
enemy bullets, respectively).
|
|
|
|
|
|
|
|
by default, bullets despawn
|
|
|
|
when they hit something.
|
|
|
|
override hitship to change this.
|
|
|
|
|
|
|
|
ships
|
|
|
|
____
|
|
|
|
|
|
|
|
ships move by calculating
|
|
|
|
momentum, then offsetting their
|
|
|
|
position by that momentum, then
|
|
|
|
clamping their position to the
|
|
|
|
screen (horizontally only for
|
|
|
|
ships that autoscroll). ships
|
|
|
|
that autoscroll (slip==true)
|
|
|
|
then slide down by scrollspeed.
|
|
|
|
fractional coordinates are ok.
|
|
|
|
after movement, ships lose
|
|
|
|
momentum (ship.drag along each
|
|
|
|
axis). abs(momentum) can't
|
|
|
|
exceed ship.maxspeed.
|
|
|
|
|
|
|
|
ships gain momentum by acting
|
|
|
|
like a player pushing buttons.
|
|
|
|
the player ship actually reads
|
|
|
|
buttons for this.
|
|
|
|
|
|
|
|
grab_butts - ship thrust control
|
|
|
|
based on btn() api. returns a
|
|
|
|
table indexed from 0..5 with
|
|
|
|
0 to not push this button and 1
|
|
|
|
to push it. ships can use
|
|
|
|
fractional or out-of-range
|
|
|
|
numbers to get varying amounts
|
|
|
|
of thrust, including using
|
|
|
|
negative numbers for thrust in
|
|
|
|
the opposite direction. 4 and 5
|
|
|
|
just check for nonzeroness to
|
|
|
|
attempt to fire.
|
|
|
|
|
|
|
|
ships hitting another ship take
|
|
|
|
1 damage per frame of overlap.
|
|
|
|
ships hitting a bullet check
|
|
|
|
bullet.damage to find out how
|
|
|
|
much damage they take. damage
|
|
|
|
is applied to shields, then hp.
|
|
|
|
damaged ships flash briefly -
|
|
|
|
blue (12) if all damage was
|
|
|
|
shielded, white (7) if hp was
|
|
|
|
damaged. a ship that then has 0
|
|
|
|
or less hp calls self:die() and
|
|
|
|
tells the main game loop to
|
|
|
|
remove it.
|
|
|
|
|
|
|
|
ships have power, from 0 to
|
|
|
|
ship.maxpower, increasing by
|
|
|
|
ship.generator per frame.
|
|
|
|
in maybe_shoot, ships check that
|
|
|
|
they have power to fire before
|
|
|
|
trying to fire (the gun itself
|
|
|
|
checks ammo and cooldown), and
|
|
|
|
spend that power if they fire.
|
|
|
|
|
|
|
|
power is also used to restore
|
|
|
|
shields - ship.shieldcost per
|
|
|
|
point of shields. shieldcooldown
|
|
|
|
is the interval between
|
|
|
|
restoring shield points, which
|
|
|
|
is reset when a ship takes
|
|
|
|
damage (regardless of whether
|
|
|
|
that damage is stopped by the
|
|
|
|
shield or not).
|
|
|
|
|
|
|
|
therefore:
|
|
|
|
* damaged ships spend power
|
|
|
|
repairing shields, which may
|
|
|
|
affect ability to fire guns.
|
|
|
|
this looks like a slow firing
|
|
|
|
rate because the ship will
|
|
|
|
eventually recover enough
|
|
|
|
energy to fire.
|
|
|
|
* a ship firing nonstop will
|
|
|
|
typically be unable to recover
|
|
|
|
any shields because it will
|
|
|
|
not have energy to do so.
|
|
|
|
|
|
|
|
ships do not repair hp on their
|
|
|
|
own. negative-damage bullets
|
|
|
|
are treated as 0, but a bullet
|
|
|
|
can choose to repair the ship
|
|
|
|
it hits in its own hitship
|
|
|
|
method, or otherwise edit it
|
|
|
|
(changing weapons, refilling
|
|
|
|
weapon ammo). powerups are
|
|
|
|
therefore a kind of bullet.
|
|
|
|
|
|
|
|
levels
|
|
|
|
======
|
|
|
|
|
|
|
|
a level is a table mapping
|
|
|
|
effective frame number to
|
|
|
|
functions. when a level starts,
|
|
|
|
it sets lframe ("level frame")
|
|
|
|
and distance to 0.
|
|
|
|
|
|
|
|
every frame, level_frame
|
|
|
|
increments lframe. then if the
|
|
|
|
level is not frozen (more on
|
|
|
|
that later), it increments
|
|
|
|
distance and runs the function
|
|
|
|
in the level table for exactly
|
|
|
|
that frame number (if any).
|
|
|
|
distance is therefore "nonfrozen
|
|
|
|
frames", and is used to trigger
|
|
|
|
level progress. lframe always
|
|
|
|
increments. ships are encouraged
|
|
|
|
to use lframe to control
|
|
|
|
animation and movement, and may
|
|
|
|
use distance to react to level
|
|
|
|
progress separately from overall
|
|
|
|
time.
|
|
|
|
|
|
|
|
a special sentinel value, eol,
|
|
|
|
marks the end of the level.
|
|
|
|
(the level engine doesn't know
|
|
|
|
when it's out of events, so
|
|
|
|
without eol, the level will
|
|
|
|
simply have no events forever.)
|
|
|
|
when it finds eol, level_frame
|
|
|
|
throws away the current level
|
|
|
|
and tells the main loop that it
|
|
|
|
might be done. the main loop
|
|
|
|
agrees the level is over and the
|
|
|
|
player has won when the level
|
|
|
|
has reached eol and there are
|
|
|
|
no more enemy ships, enemy
|
|
|
|
bullets, or background events
|
|
|
|
remaining. player ships, player
|
|
|
|
bullets, and intangibles are
|
|
|
|
not counted.
|
|
|
|
|
|
|
|
level freezing
|
|
|
|
--------------
|
|
|
|
the level is frozen when the
|
|
|
|
global value freeze > 0.
|
|
|
|
generally, something intending
|
|
|
|
to block level progress (a
|
|
|
|
miniboss, a minigame, etc.)
|
|
|
|
increments freeze and prepares
|
|
|
|
some means of decrementing it
|
|
|
|
when it no longer wants to block
|
|
|
|
level progress.
|
|
|
|
|
|
|
|
most commonly, we want to block
|
|
|
|
until some specific ship or
|
|
|
|
group of ships has died. for
|
|
|
|
these ships, override ship:die
|
|
|
|
to decrement freeze. make sure
|
|
|
|
to set ship.dead in any new
|
|
|
|
ship:die method so anything else
|
|
|
|
looking at it can recognize
|
|
|
|
the ship as dead.
|
|
|
|
|
|
|
|
for anything else, you probably
|
|
|
|
want an event to figure out when
|
|
|
|
to unfreeze.
|
|
|
|
|
|
|
|
levels start at 1
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
distance is initialized to 0
|
|
|
|
but gets incremented before the
|
|
|
|
first time the engine looks for
|
|
|
|
events. therefore, the first
|
|
|
|
frame of the level executes
|
|
|
|
level[1]. since levelframe
|
|
|
|
executes before anything else,
|
|
|
|
level[1] sets up the first frame
|
|
|
|
drawn in the level. the player
|
|
|
|
does not see a blank world
|
|
|
|
before level[1] runs.
|
|
|
|
level[1] can therefore be used
|
|
|
|
to reconfigure the player ship,
|
|
|
|
set up backgrounds, start music,
|
|
|
|
kick off some kind of fade-in
|
|
|
|
animation, etc.
|
|
|
|
|
|
|
|
|
|
|
|
events
|
|
|
|
======
|
|
|
|
the global list "events" stores
|
|
|
|
0-argument functions which are
|
|
|
|
called every frame. if they
|
|
|
|
return true, they are removed
|
|
|
|
from the list and not run again;
|
|
|
|
if they return false, they stay
|
|
|
|
and will be called in later
|
|
|
|
frames. the level does not end
|
|
|
|
while the events table is
|
|
|
|
nonempty.
|
|
|
|
|
|
|
|
events are most commonly used
|
|
|
|
to set up something for later
|
|
|
|
(for example, blip uses an event
|
|
|
|
to remove the fx_pallete from
|
|
|
|
the flashing ship when the blip
|
|
|
|
expires), but can also be used
|
|
|
|
to implement a "level within a
|
|
|
|
level" that does something
|
|
|
|
complicated until it's done. if
|
|
|
|
you froze the level when
|
|
|
|
creating the event, remember
|
|
|
|
to thaw it (freeze -= 1) on all
|
|
|
|
paths that return true.
|
|
|
|
|
|
|
|
to do complex stuff in events,
|
|
|
|
use a closure or a metatable
|
|
|
|
that specifies __call.
|
|
|
|
|
|
|
|
to avoid editing the events
|
|
|
|
list while it is being iterated,
|
|
|
|
events that create new events
|
|
|
|
must add those events to
|
|
|
|
new_events rather than events.
|
|
|
|
new_events is only valid during
|
|
|
|
the "event execution" stage, so
|
|
|
|
events created at any other time
|
|
|
|
must go directly on events
|
|
|
|
without using new_events.
|
|
|
|
|
|
|
|
intangibles
|
|
|
|
===========
|
|
|
|
|
|
|
|
the intangibles_fg and
|
|
|
|
intangibles_bg lists contain
|
|
|
|
items with :move and :draw.
|
|
|
|
like ships and bullets, they
|
|
|
|
move during _update60 and
|
|
|
|
draw during _draw. they are
|
|
|
|
not checked for collisions.
|
|
|
|
|
|
|
|
intangibles_bg moves/draws
|
|
|
|
before anything else moves or
|
|
|
|
draws. intangibles_fg
|
|
|
|
moves/draws last. this controls
|
|
|
|
whether your intangible object
|
|
|
|
draws in front of or behind
|
|
|
|
other stuff. you probably want
|
|
|
|
intangibles_bg for decorative
|
|
|
|
elements and intangibles_fg
|
|
|
|
for explosions, score popups,
|
|
|
|
etc.
|
|
|
|
|
|
|
|
there's no scrolling background
|
|
|
|
engine but intangibles_bg could
|
|
|
|
be used to create one, including
|
|
|
|
using the map (otherwise unused
|
|
|
|
in this engine) for the purpose.
|
|
|
|
|
|
|
|
intangibles do not prevent the
|
|
|
|
level from ending. like bullets
|
|
|
|
and ships, if :move returns
|
|
|
|
true, they are dropped.
|
|
|
|
|
|
|
|
weird coding conventions
|
|
|
|
========================
|
|
|
|
|
|
|
|
* i am inconsistent between
|
|
|
|
including underscores or not
|
|
|
|
(sorry)
|
|
|
|
* a triple underscore prefix
|
|
|
|
is used for fields created
|
|
|
|
by invasive algorithms
|
|
|
|
(those algorithms that
|
|
|
|
modify the items they're
|
|
|
|
given to perform some kind
|
|
|
|
of bookkeeping)
|
|
|
|
|
|
|
|
]]
|
|
|
|
-->8
|
|
|
|
-- standard events
|
|
|
|
|
|
|
|
blip_fx = {
|
|
|
|
abort = function(self)
|
|
|
|
self.cancel = true
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
blip_fx_t = {
|
|
|
|
__index = blink_fx,
|
|
|
|
__call = function(self)
|
|
|
|
if (self.cancel) return true
|
|
|
|
self.frames -= 1
|
|
|
|
if self.frames < 0 then
|
|
|
|
self.obj.fx_pal = nil
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
function blip(obj, col, frames)
|
2023-09-13 06:52:14 +00:00
|
|
|
local p = {[0]=0}
|
|
|
|
obj.fx_pal = p
|
|
|
|
for i=1,15 do p[i]=col end
|
2023-09-13 05:49:01 +00:00
|
|
|
if (obj.___fx_pal_event) obj.___fx_pal_event:abort()
|
|
|
|
local e = {
|
|
|
|
frames = frames,
|
|
|
|
obj = obj
|
|
|
|
}
|
|
|
|
setmetatable(e, blip_fx_t)
|
|
|
|
add(events, e)
|
|
|
|
end
|
|
|
|
|
2023-09-13 06:52:14 +00:00
|
|
|
bossspark = split"7,7,10,10,9,9,9,8,8,8,2,2,5,5"
|
2023-09-13 05:49:01 +00:00
|
|
|
|
|
|
|
function boom(x,y,boominess,is_boss)
|
|
|
|
local sp = firespark
|
|
|
|
if is_boss then
|
|
|
|
boominess *= 10
|
|
|
|
sp = bossspark
|
|
|
|
end
|
|
|
|
local boombase = min(0.023 * boominess, 0.25)
|
|
|
|
local boombonus = min(0.05 * boominess, 1.25)
|
|
|
|
for _=1,boominess do
|
|
|
|
local angle = rnd(1)
|
|
|
|
local butts = {0, sin(angle), 0}
|
|
|
|
butts[0] = cos(angle)
|
|
|
|
spark(sp,x+4,y+4,butts,boombase+rnd(boombonus),1, true)
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
function spark(sprs, x, y, butts, thrust, odds, fg)
|
|
|
|
if (sprs==nil or flr(rnd(odds)) ~= 0) return
|
|
|
|
thrust *= 2.5
|
|
|
|
add(fg and intangibles_fg or intangibles_bg, {
|
|
|
|
x = x + rnd(4) - 2,
|
|
|
|
y = y + rnd(4) - 2,
|
|
|
|
sprs = sprs,
|
|
|
|
sidx = 1,
|
|
|
|
dx = (butts[0] - butts[1]) * thrust + rnd(2) - 1,
|
|
|
|
dy = (butts[2] - butts[3]) * thrust + rnd(2) - 1,
|
|
|
|
draw = function(self)
|
|
|
|
pset(self.x, self.y, self.sprs[self.sidx])
|
|
|
|
end,
|
|
|
|
move = function(self)
|
|
|
|
if (rnd(4) < 1) self.sidx += 1
|
|
|
|
if (self.sidx > #self.sprs) return true
|
|
|
|
self.x += self.dx
|
|
|
|
self.y += self.dy
|
|
|
|
self.dx -= mid(0.05,-0.05, self.dx)
|
|
|
|
self.dy -= mid(0.05,-0.05, self.dy)
|
|
|
|
end
|
|
|
|
})
|
|
|
|
end
|
|
|
|
-->8
|
|
|
|
-- powerups
|
|
|
|
function init_powerup_mt()
|
|
|
|
setmetatable(powerup, bullet_t)
|
|
|
|
setmetatable(gun_swap, powerup_t)
|
|
|
|
end
|
|
|
|
|
|
|
|
powerup = {
|
|
|
|
-- animated sprite array: "sprites"
|
|
|
|
-- to draw under or over anim,
|
|
|
|
-- override draw, draw the
|
|
|
|
-- under-part, call into
|
|
|
|
-- powerup.draw(self), then
|
|
|
|
-- draw the over-part
|
|
|
|
width = 1,
|
|
|
|
height = 1,
|
|
|
|
-- note: make hurtboxes larger
|
|
|
|
-- than sprite by 2px per side
|
|
|
|
-- since ship hitbox is tiny
|
|
|
|
-- but powerups should feel
|
|
|
|
-- easy to pick up
|
|
|
|
dx = 0,
|
|
|
|
dy = 1.5, -- 0.75 after enemyspd
|
|
|
|
enemy = true, -- collides with player ship
|
|
|
|
damage = 0,
|
|
|
|
|
|
|
|
anim_speed = 2,
|
|
|
|
loop_pause = 30 -- affected by animspeed
|
|
|
|
}
|
|
|
|
|
|
|
|
-- sprite indexes for "sheen" animation
|
2023-09-13 07:00:09 +00:00
|
|
|
sheen8x8 = split"2,54,55,56,57,58,59,60,61"
|
2023-09-13 05:49:01 +00:00
|
|
|
|
|
|
|
powerup_t = {
|
|
|
|
__index = powerup
|
|
|
|
}
|
|
|
|
|
|
|
|
-- todo: draw two sprites
|
|
|
|
-- on top of each other here
|
|
|
|
-- so all powerups can share
|
|
|
|
-- the "sheen" animation?
|
|
|
|
|
|
|
|
function powerup:draw()
|
|
|
|
spr(self.sprites[max(1,
|
|
|
|
(lframe\self.anim_speed)
|
|
|
|
%(#self.sprites+self.loop_pause)
|
|
|
|
-self.loop_pause
|
|
|
|
+1)],
|
|
|
|
self.x, self.y,
|
|
|
|
self.width, self.height)
|
|
|
|
end
|
|
|
|
|
|
|
|
function spawn_repair_at(x, y)
|
|
|
|
local repair = {
|
|
|
|
hurt = {
|
|
|
|
x_off = -2,
|
|
|
|
y_off = -2,
|
|
|
|
width = 12,
|
|
|
|
height = 12
|
|
|
|
},
|
|
|
|
center_x_off = 4,
|
|
|
|
top_y_off = 0,
|
|
|
|
bottom_y_off = 0,
|
|
|
|
sprites = sheen8x8,
|
|
|
|
hitship = function(self, ship)
|
|
|
|
if (ship ~= primary_ship) return false
|
|
|
|
primary_ship.hp = min(primary_ship.maxhp, primary_ship.hp + 1)
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
draw = function(self)
|
|
|
|
spr(53, self.x, self.y, self.width, self.height)
|
|
|
|
powerup.draw(self)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
setmetatable(repair, powerup_t)
|
|
|
|
repair:spawn_at(x, y)
|
|
|
|
end
|
|
|
|
|
|
|
|
gun_swap = {
|
|
|
|
hurt = {
|
|
|
|
x_off = -2,
|
|
|
|
y_off = -2,
|
|
|
|
width = 16,
|
|
|
|
height = 16
|
|
|
|
},
|
|
|
|
-- gun = new_gun_of(t, false)
|
|
|
|
center_x_off = 6,
|
|
|
|
top_y_off = 0,
|
|
|
|
bottom_y_off = 4,
|
|
|
|
width = 2,
|
|
|
|
height = 2,
|
|
|
|
sprites = {64, 66, 68, 70, 72, 74, 76, 78},
|
|
|
|
hitship = function(self, ship)
|
|
|
|
if (ship ~= primary_ship) return false
|
|
|
|
ship.main_gun = self.gun
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
draw = function(self)
|
|
|
|
powerup.draw(self)
|
|
|
|
spr(self.gun.icon, self.x+2, self.y+2, 1, 1)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
gun_swap_t = {
|
|
|
|
__index=gun_swap
|
|
|
|
}
|
|
|
|
|
|
|
|
function spawn_main_gun_at(x, y, mt)
|
|
|
|
local gun_p = {
|
|
|
|
gun = new_gun_of(mt, false)
|
|
|
|
}
|
|
|
|
setmetatable(gun_p, gun_swap_t)
|
|
|
|
gun_p:spawn_at(x, y)
|
|
|
|
end
|
|
|
|
|
|
|
|
spec_gun_pl = {
|
|
|
|
[1] = 2,
|
|
|
|
[14] = 6,
|
|
|
|
[2] = 14
|
|
|
|
}
|
|
|
|
|
|
|
|
function spawn_spec_gun_at(x, y, mt)
|
|
|
|
local gun_p = {
|
|
|
|
gun = new_gun_of(mt, false),
|
|
|
|
hitship = function(self, ship)
|
|
|
|
if (ship ~= primary_ship) return false
|
|
|
|
ship.special_gun = self.gun
|
|
|
|
return true
|
|
|
|
end,
|
|
|
|
draw = function(self)
|
|
|
|
pal(spec_gun_pl)
|
|
|
|
powerup.draw(self)
|
|
|
|
pal()
|
|
|
|
spr(self.gun.icon, self.x+2, self.y+2, 1, 1)
|
|
|
|
end
|
|
|
|
}
|
|
|
|
setmetatable(gun_p, gun_swap_t)
|
|
|
|
gun_p:spawn_at(x, y)
|
|
|
|
end
|
|
|
|
__gfx__
|
|
|
|
00000000000650000000000000000000bb0b50b59909209200cc0c00000000003b00000082000000e00e8002e00e800200333300002222000000000000000000
|
|
|
|
00000000006765000000000000cccc00b50b3055920940220c0000c000bbbb0037000000a2000000e0e8880240e8480403bbbb30028888200000000000000000
|
|
|
|
00700700006d6500000000000cddddd00b33335009444420c00c000c0b333330b7000000a8000000e88e2882e48e24823bbaabb3288aa8820000000000000000
|
|
|
|
00077000067c665000000000cdd10cd10b3dd350094dd42000c0000cb3350b35b7000000a8000000e88e2882484e24423ba77ab328a77a820000000000000000
|
|
|
|
00077000067d665000000000cd10cdd100b3350000944200c0000000b350b335b7000000a8000000e88e2882e84e28823ba77ab328a77a820000000000000000
|
|
|
|
0070070065666765000000000ddddd100b33355009444220c000000c03333350b7000000a800000008888820048488203bbaabb3288aa8820000000000000000
|
|
|
|
000000006506506500000000001111000b0b5050090920200c0000c00055550037000000a2000000008882000048420003bbbb30028888200000000000000000
|
|
|
|
00000000650000650000000000000000000b50000009200000c0cc00000000003b00000082000000000820000008200000333300002222000000000000000000
|
|
|
|
00000000000650000006500000000000b000000b80000000700000000bb0000008800000000000000009200000000000cccccccd000650000000000000000000
|
|
|
|
0000000000675000000765000000000000bbbb0080000000b0000000b76300008a920000000000009009200200000000c111111d006765000000000000000000
|
|
|
|
00000000006d6500006d6500000000000b0000b09000000030000000b663000089920000000550009994444200000000c111111d006d65000000000000000000
|
|
|
|
00000000067c6650067c6650000000000b0bb0b0a000000030000000033000000220000000576d009446544200000000c111111d067c66500000000000000000
|
|
|
|
00000000067d6650067d6650000000000b0bb0b00000000000000000000000000000000000566d009244442200000000c111111d067d66500000000000000000
|
|
|
|
000000005666657576667650000000000b0000b000000000000000000000000000000000000dd0009092220200000000c111111d656667650000000000000000
|
|
|
|
0000000056565066665656500000000000bbbb0000000000000000000000000000000000000000000090020000000000c111111d650650650000000000000000
|
|
|
|
00000000565000566500065000000000b000000b000000000000000000000000000000000000000000a00a0000000000cddddddd650000650000000000000000
|
|
|
|
000000000000000000000000000000000000000000a0008000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
00000000000000000000000000000000000000000090008000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
000000000000000000000000000000000000000000800a0000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
00000000000000000000000000000000000000000080090000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000000a080000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
00000000000000000000000000000000000000000009080000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
00000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
00000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000cccccccc77000000007700000000770000000077000000000000000000000000000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000c11ee11d70000000077000000007700000000770000000070000000000000000000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000c11ee11d00000000770000000077000000007700000000770000000700000000000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000ceeeeeed00000000700000000770000000077000000007700000007700000000000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000ceeeeeed00000000000000007700000000770000000077000000077000000007000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000c11ee11d00000000000000007000000007700000000770000000770000000077000000000000000000000000
|
|
|
|
0000000000000000000000000000000000000000c11ee11d00000000000000000000000077000000007700000007700000000770000000070000000000000000
|
|
|
|
0000000000000000000000000000000000000000cddddddd00000000000000000000000070000000077000000077000000007700000000770000000000000000
|
|
|
|
cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000cccccccccccc0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000ceee2222eeed0000c2221111222d0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c1ee2222ee1d0000ce22111122ed0000c2111111112d0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c11e2222e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111ee1111d0000c11ee22ee11d0000c1e221122e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
|
|
c1111111111d0000c1111ee1111d0000c111e22e111d0000c11e2112e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
|
|
c1111111111d0000c1111ee1111d0000c111e22e111d0000c11e2112e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111ee1111d0000c11ee22ee11d0000c1e221122e1d0000ce21111112ed0000c2111111112d0000c1111111111d0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c11e2222e11d0000c1e211112e1d0000ce21111112ed0000c2111111112d0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000c1ee2222ee1d0000ce22111122ed0000c2111111112d0000
|
|
|
|
c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c1111111111d0000c111eeee111d0000ceee2222eeed0000c2221111222d0000
|
|
|
|
cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000cddddddddddd0000
|
|
|
|
__label__
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007777777777777777
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666611111666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666115151166665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666111611156665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666115161156665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666611111556665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666665555566665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650b000000b0765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765000bbbb000765
|
|
|
|
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076500b0000b00765
|
|
|
|
00000000000000000000000000000000000000000000e00e800200000000000000000000000000000000000000000000000000000000000076500b0bb0b00765
|
|
|
|
00000000000000000000000050000000000000000000e0e8880200000000000000000000000000000000000000000000000000000000000076500b0bb0b00765
|
|
|
|
00000000000000000000000000000000000000000000e88e288200000000000000000000000000000000000000000000000000000000000076500b0000b00765
|
|
|
|
00000000000000000000000000000000000000000d00e88e2882000000000000000000000000000000000000000000000000000000000000765000bbbb000765
|
|
|
|
00000000000000000000000000000000000000000000e88e28820000000000000000000000000000000000000000000000000000000000007650b000000b0765
|
|
|
|
00000000000000000000000000000000000000000000088888200000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000000000000000000000000000000008882000000000000000000000000000000000000000000000000000000000000007657777777777765
|
|
|
|
00000000000000000000000000000000000000000000000820000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
|
|
0000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000000000000765aeaeaeaeae765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765eaeaeaeaea765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000765aeaeaeaeae765
|
|
|
|
00000000000000000000000000000000000000000000000000000009909209200000000000000000000000000000000000000000000000007657777777777765
|
|
|
|
00000000000000000000000000000000000000000000000000000009209402200000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000944442000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
0000000000000000000000000000000000000000000000000000000094dd42000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000094420000000000000000000000000000000000000000000000000007666622222666665
|
|
|
|
00000000000000000000000000000000000000000000000000500000944422000000000000000000000000000000000000000000000000007666225552266665
|
|
|
|
00000000000000000000000000000000000000000000000000000000909202000000000000000000000000000000000000000000000000007666225262256665
|
|
|
|
00000000000000000000000000000000000000000000000000000000009200000000000000000000000000000000000000000000000000007666225652256665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666622222556665
|
|
|
|
00000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666665555566665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000005000000009200000000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000050000000000000009009200200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
000000000000000000d0000009994444200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000000000009446544200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000000000009244442200000000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
0000000000000000000000000909222020000000000000000bbbb000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
000000000000000000000000000900200000000000000000b3333300000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
000000000000000000000000000a00a0000000000000000b3350b350000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000000000000000000000000000000000b350b3350000000000000000000000000000000000000000000000000000000007657777777777765
|
|
|
|
00000000000000000000000000000000000000000000000033333500000000000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000088000000000000005555000000000000000000000000000000000000000000000000000000000007655555555555565
|
|
|
|
000000000000000000000000000000058a9200000000000000000000000000000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
00000000000000000000000000000000899200000000000000000000008200000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
0000000000000000000000000000000002200000000000000000000000a200000000000000000000000000000000000000000000000000007650000000000765
|
|
|
|
0000000000000000000500000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007657777777777765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
0000000000000000000000000088000000000050000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
20000000000000000000000008a9200000000000000000000000000000a200000000000000000000000000000000000000000000000000007611161616111665
|
|
|
|
20000000000000000000000008992000000000000000000000000000008200000000000000000000000000000000000000000000000000007615151515151565
|
|
|
|
000000000000000000000000002200000d0000000000000000000000000000000000000000000000000000000000000000000000000000007611151515116565
|
|
|
|
0000000000000000000000000000000000000e00e800200000000000e00e80020000000000000000000000000000000000000000000000007615551115151665
|
|
|
|
0000000000000000000000000000000d00000e0e8880200000000000e0e888020000000000000000000000000000000000000000000000007615661115151565
|
|
|
|
0000000000000000000000000000000000d00e88e2882000000d0000e88e28820000000000000000000000000000000000000000000000007665666555656565
|
|
|
|
0000088000000000000880000000000000000e88e288200000000000e88e28820000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00008a9200000000008a92000000000000000e88e288200000000000e88e28820000000000000000000000000000000000000000000000007655555555555565
|
|
|
|
0000899200000000008992000000000000000088888200000000000008888820000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
|
|
0000022000000000000220000000000000000008882000000000000000888200000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
|
|
0000000000000000000000000000000000000000820000000000000000082000000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765aaaaaaaaaa765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765a9a9a9a9a9765
|
|
|
|
00000000000088000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659a9a9a9a9a765
|
|
|
|
000000000008a920000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000765a9a9a9a9a9765
|
|
|
|
00000000000899200000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000007659a9a9a9a9a765
|
|
|
|
0000000000002200000000000000000000008a92000000000000000000000000000000000000000000000000000000000000000000000000765a9a9a9a9a9765
|
|
|
|
00000000000000000000000000000000000089920000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
|
|
00000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659999999999765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654949494949765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659494949494765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654949494949765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007659494949494765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654949494949765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007654444444444765
|
|
|
|
00000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000007654444444444765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000007654444444444765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007657777777777765
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a800000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
0000000000000000000000000000000000000000000000000000000000a200000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000008200000000000000000000000000000000000000000000000000007616166666611665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007615156666165565
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007611156666111665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007615156666651565
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007615156666116565
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007665656666655665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000007666666666666665
|
|
|
|
0000000000000000000000000000000000000000000000000000000000000000008a920000000000000000000000000000000000000000007655555555555565
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000089920000000000000000000000000000000000000000007652222750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000007652222750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000006500000000000000000000000000000000000000000000000000007652222750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000067650000000000000000000000000000000000000000000000000007652222750000765
|
|
|
|
0000000000000000000000000000000000000000000000000000000006d650000000000000000000000000000000000000000000000000007652222750000765
|
|
|
|
0000000000000000000000000000000000000000000000000000000067c665000000000000000000000000000000000000000000000000007652222750000765
|
|
|
|
0000000000000000000000000000000000000000000000000000000067d665000000000000000000000000000000000000000000000000007652828750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000006566676500000000000000000000000000000000000000000000000007658282750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000006506506500000000000000000000000000000000000000000000000007652828750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000006500006500000000000000000000000000000000000000000000000007658282750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007652828750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658282750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007658888750000765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007657777757777765
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007666666666666665
|
|
|
|
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007555555555555555
|
|
|
|
|