粒子系统修复
首先,我们要加载cow(可能是某个项目或资源),然后直接处理粒子系统。你们看到在粒子系统中,我们仍然有X滚动。这现在已经没什么意义了,因为我们正在使用一个奇怪的新系统。所以我们实际上不再需要这个了。我们可以用为玩家创建的新对象来替代它,即PSPR的X和Y。PSPR是一个功能或特性,它将粒子锁定在玩家的位置上,这样我们就可以将东西附加到玩家上。但我们现在不需要这么做了。顺便说一句,这也可以是PY,这样可以稍微节省一些标记。
编辑器边界问题
在编辑器中,我们可以将敌人移动到负滚动值或当前滚动值之前,这显然是不合理的。我添加了一些检查来确保敌人只能在合理的滚动值范围内生成。
Brain Editor元数据设置
接下来,我们开始为Brain Editor设置元数据。我们的目标是创建一个设置菜单,允许用户为每个Brain设置预览参数,如动画、动画速度、生成位置等。我创建了一个元数据表,并将其导出到一个文件中。然后,我在编辑器中实现了这个设置菜单,允许用户编辑和查看元数据。
pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
--todo
-- - meta brain data
-- - -ui
-- - -create meta on brain create
-- - -delete meta on brain delete
-- - more commands
function _init()
--- customize here ---
#include shmup_brains.txt
#include shmup_brains_meta.txt
file="shmup_brains.txt"
filem="shmup_brains_meta.txt"
arrname="brains"
data=brains
#include shmup_myspr.txt
#include shmup_enlib.txt
#include shmup_anilib.txt
----------------------
debug={}
msg={}
_drw=draw_brain
_upd=update_brain
menuitem(1,"export",export)
reload(0x0,0x0,0x2000,"cowshmup.p8")
curx=1
cury=1
scrolly=0
scrollx=0
selbrain=1
cmdlist={
"hed",
"wai"
}
enemies={}
poke(0x5f2d, 1)
end
function _draw()
_drw()
if #msg>0 then
bgprint(msg[1].txt,64-#msg[1].txt*2,80,14)
msg[1].t-=1
if msg[1].t<=0 then
deli(msg,1)
end
end
-- debug --
cursor(4,4)
color(8)
for txt in all(debug) do
print(txt)
end
end
function _update60()
dokeys()
mscroll=stat(36)
_upd()
end
function dokeys()
if stat(30) then
key=stat(31)
if key=="p" then
poke(0x5f30,1)
end
else
key=nil
end
end
-->8
--draw
function draw_brain()
cls(13)
for e in all(enemies) do
drawobj(e)
end
drawmenu()
end
function draw_table()
cls(2)
--spr(0,0,0,16,16)
drawmenu()
--[[
for i=1,#data do
for j=1,#data[i] do
bgprint(data[i][j],2+18*j,2+8*i,7)
end
end
]]
end
function drawmenu()
if menu then
for i=1,#menu do
for j=1,#menu[i] do
local mymnu=menu[i][j]
local c=mymnu.c or 13
if i==cury and j==curx then
c=7
if _upd==upd_type then
c=0
end
end
bgprint(mymnu.w,mymnu.x+scrollx,mymnu.y+scrolly,13)
bgprint(mymnu.txt,mymnu.x+scrollx,mymnu.y+scrolly,c)
end
end
end
if _upd==upd_type then
local mymnu=menu[cury][curx]
local txt_bef=sub(typetxt,1,typecur-1)
local txt_cur=sub(typetxt,typecur,typecur)
local txt_aft=sub(typetxt,typecur+1)
txt_cur=txt_cur=="" and " " or txt_cur
if (time()*2)%1<0.5 then
txt_cur="\^i"..txt_cur.."\^-i"
end
local txt=txt_bef..txt_cur..txt_aft
bgprint(txt,mymnu.x+scrollx,mymnu.y+scrolly,7)
end
end
-->8
--update
function update_setup()
refresh_setup()
if btnp(⬆️) then
cury-=1
end
if btnp(⬇️) then
cury+=1
end
cury=mid(2,cury,#menu)
curx=2
if btnp(❎) then
local mymnu=menu[cury][curx]
if mymnu.cmd=="meta" then
_upd=upd_type
typetxt=tostr(mymnu.txt)
typecur=#typetxt+1
callback=enter_meta
end
end
if btnp(🅾️) then
_upd=update_brain
refresh_brain()
return
end
if data[selbrain] then
if #enemies==0 then
local selmeta=meta[selbrain]
if enlib[selmeta[1]]!=nil then
spawnen(selmeta[1],selmeta[2],selmeta[3])
end
end
doenemies()
else
enemies={}
end
end
function update_brain()
refresh_brain()
if btnp(⬆️) then
cury-=1
end
if btnp(⬇️) then
cury+=1
end
cury=mid(1,cury,#menu)
if cury==1 then
if btnp(⬅️) then
selbrain-=1
enemies={}
end
if btnp(➡️) then
selbrain+=1
enemies={}
end
selbrain=mid(1,selbrain,#data+1)
else
if btnp(⬅️) then
curx-=1
end
if btnp(➡️) then
curx+=1
end
curx=mid(1,curx,#menu[cury])
end
if btnp(❎) then
local mymnu=menu[cury][curx]
if mymnu.cmd=="edit" then
_upd=upd_type
typetxt=tostr(mymnu.txt)
typecur=#typetxt+1
callback=enter_brain
elseif mymnu.cmd=="newline" then
add(data[mymnu.cmdb],"wai")
add(data[mymnu.cmdb],"0")
add(data[mymnu.cmdb],"0")
elseif mymnu.cmd=="setup" then
refresh_setup()
_upd=update_setup
return
elseif mymnu.cmd=="newbrain" then
add(data,{
"wai",0,0
})
end
return
end
if data[selbrain] then
if #enemies==0 then
local selmeta=meta[selbrain]
if enlib[selmeta[1]]!=nil then
spawnen(selmeta[1],selmeta[2],selmeta[3])
end
end
doenemies()
else
enemies={}
end
end
function update_table()
refresh_table()
if btnp(⬆️) then
cury-=1
end
if btnp(⬇️) then
cury+=1
end
cury=(cury-1)%#menu+1
cury-=mscroll
cury=mid(1,cury,#menu)
if btnp(⬅️) then
curx-=1
end
if btnp(➡️) then
curx+=1
end
if cury<#menu then
curx=(curx-2)%(#menu[cury]-1)+2
else
curx=1
end
local mymnu=menu[cury][curx]
if mymnu.y+scrolly>110 then
scrolly-=4
end
if mymnu.y+scrolly<10 then
scrolly+=4
end
scrolly=min(0,scrolly)
if mymnu.x+scrollx>110 then
scrollx-=2
end
if mymnu.x+scrollx<20 then
scrollx+=2
end
scrollx=min(0,scrollx)
if btnp(❎) then
local mymnu=menu[cury][curx]
if mymnu.cmd=="edit" then
_upd=upd_type
typetxt=tostr(mymnu.txt)
typecur=#typetxt+1
callback=enter_table
elseif mymnu.cmd=="newline" then
add(data,{0})
elseif mymnu.cmd=="newcell" then
add(data[mymnu.cmdy],0)
end
end
end
function upd_type()
if key then
if key=="\r" then
-- enter
poke(0x5f30,1)
callback()
return
elseif key=="\b" then
--backspace
if typecur>1 then
if typecur>#typetxt then
typetxt=sub(typetxt,1,#typetxt-1)
else
local txt_bef=sub(typetxt,1,typecur-2)
local txt_aft=sub(typetxt,typecur)
typetxt=txt_bef..txt_aft
end
typecur-=1
end
else
if typecur>#typetxt then
typetxt..=key
else
local txt_bef=sub(typetxt,1,typecur-1)
local txt_aft=sub(typetxt,typecur)
typetxt=txt_bef..key..txt_aft
end
typecur+=1
end
end
if btnp(⬅️) then
typecur-=1
end
if btnp(➡️) then
typecur+=1
end
typecur=mid(1,typecur,#typetxt+1)
end
-->8
--tools
function bgprint(txt,x,y,c)
print("\#0"..txt,x,y,c)
end
function split2d(s)
local arr=split(s,"|",false)
for k, v in pairs(arr) do
arr[k] = split(v)
end
return arr
end
function spacejam(n)
local ret=""
for i=1,n do
ret..=" "
end
return ret
end
function mspr(si,sx,sy)
local _x,_y,_w,_h,_ox,_oy,_fx,_nx=unpack(myspr[si])
sspr(_x,_y,_w,_h,sx-_ox,sy-_oy,_w,_h,_fx==1)
if _fx==2 then
sspr(_x,_y,_w,_h,sx-_ox+_w,sy-_oy,_w,_h,true)
end
if _nx then
mspr(_nx,sx,sy)
end
end
function cyc(age,arr,anis)
local anis=anis or 1
return arr[(age\anis-1)%#arr+1]
end
function drawobj(obj)
mspr(cyc(obj.age,obj.ani,obj.anis),obj.x,obj.y)
--★
if coldebug and obj.col then
msprc(obj.col,obj.x,obj.y)
end
end
function onscreen(obj)
if obj.x<-8 then return false end
if obj.y<-8 then return false end
if obj.x>136 then return false end
if obj.y>136 then return false end
return true
end
-->8
--i/o
function export()
local s=arrname.."=split2d\""
for i=1,#data do
if i>1 then
s..="|"
end
for j=1,#data[i] do
if j>1 then
s..=","
end
s..=data[i][j]
end
end
s..="\""
printh(s,file,true)
local s="meta=split2d\""
for i=1,#meta do
if i>1 then
s..="|"
end
for j=1,#meta[i] do
if j>1 then
s..=","
end
s..=meta[i][j]
end
end
s..="\""
printh(s,filem,true)
add(msg,{txt="exported!",t=120})
--debug[1]="exported!"
end
-->8
--ui
function refresh_setup()
menu={}
add(menu,{{
txt="brain "..selbrain,
w=" ",
cmd="",
x=3,
y=3,
c=13
}})
local cap={"en:"," x:"," y:"}
local selmeta=meta[selbrain]
for i=1,3 do
local lne={}
add(lne,{
txt=cap[i],
w=" ",
cmd="",
x=3,
y=3+i*6+2,
c=13
})
add(lne,{
txt=selmeta[i],
w=" ",
cmd="meta",
cmdy=i,
x=3+12,
y=3+i*6+2,
c=13
})
add(menu,lne)
end
end
function refresh_brain()
menu={}
if selbrain>#data then
--empty brain slot
add(menu,{{
txt="< new brain ",
w=" ",
cmd="newbrain",
x=3,
y=3,
c=13
}})
return
end
add(menu,{{
txt="< brain "..selbrain.." >",
w=" ",
cmd="head",
x=3,
y=3,
c=13
}})
add(menu,{{
txt="◆setup",
w=" ",
cmd="setup",
x=3,
y=3+8,
c=13
}})
local mybra=brains[selbrain]
local ly=19
for i=1,#mybra,3 do
local lne={}
add(lne,{
txt=mybra[i],
w=" ",
cmd="edit",
cmdi=i,
cmdb=selbrain,
x=3,
y=ly,
c=13
})
local lx=3+14
for j=1,2 do
local mytxt=tostr(mybra[i+j])
add(lne,{
txt=mytxt,
w=spacejam(#mytxt),
cmd="edit",
cmdi=i+j,
cmdb=selbrain,
x=lx,
y=ly,
c=13
})
lx+=#mytxt*4+2
end
add(menu,lne)
ly+=8
end
add(menu,{{
txt="+",
w=" ",
cmd="newline",
cmdb=selbrain,
x=3,
y=ly,
c=13
}})
end
function refresh_table()
menu={}
for i=1,#data do
local lne={}
local linemax=#data[i]
if i==cury then
linemax+=1
end
add(lne,{
txt=i,
w=" ",
cmd="",
x=4,
y=-4+8*i,
c=2
})
for j=1,linemax do
if j==#data[i]+1 then
add(lne,{
txt="+",
w=" ",
cmd="newcell",
cmdy=i,
x=-10+14*(j+1),
y=-4+8*i,
})
else
add(lne,{
txt=data[i][j],
cmd="edit",
cmdx=j,
cmdy=i,
x=-10+14*(j+1),
y=-4+8*i,
w=" "
})
end
end
add(menu,lne)
end
add(menu,{{
txt=" + ",
w=" ",
cmd="newline",
x=4,
y=-4+8*(#data+1),
}})
end
function enter_table()
local mymnu=menu[cury][curx]
local typeval=typetxt
if typeval==nil or typeval=="" then
if mymnu.cmdx==#data[mymnu.cmdy] and typetxt=="" then
--delete cell
deli(data[mymnu.cmdy],mymnu.cmdx)
if mymnu.cmdx==1 then
deli(data,mymnu.cmdy)
end
_upd=update_table
return
end
typeval=0
end
data[mymnu.cmdy][mymnu.cmdx]=typeval
_upd=update_table
end
function enter_brain()
_upd=update_brain
local mymnu=menu[cury][curx]
local typeval=typetxt
enemies={}
if mymnu.cmdi%3==1 then
--editing command entry
if typeval=="" then
deli(data[mymnu.cmdb],mymnu.cmdi)
deli(data[mymnu.cmdb],mymnu.cmdi)
deli(data[mymnu.cmdb],mymnu.cmdi)
if #data[mymnu.cmdb]==0 then
deli(data,mymnu.cmdb)
add(msg,{txt="brain deleted!",t=120})
end
return
else
local found=false
for c in all(cmdlist) do
if typeval==c then
found=true
end
end
if not found then
typeval="wai"
end
end
else
--editing parameters
typeval=tonum(typetxt)
if typeval==nil then
typeval=0
end
end
data[mymnu.cmdb][mymnu.cmdi]=typeval
end
function enter_meta()
_upd=update_setup
local mymnu=menu[cury][curx]
local typeval=tonum(typetxt)
enemies={}
if typeval==nil then
typeval=0
end
meta[selbrain][mymnu.cmdy]=typeval
end
-->8
--enemy
function dobrain(e)
local mybra=brains[e.brain]
local quit=false
if e.bri<#mybra then
local cmd=mybra[e.bri]
local par1=mybra[e.bri+1]
local par2=mybra[e.bri+2]
if cmd=="hed" then
--set heading / speed
e.ang=par1
e.spd=par2
elseif cmd=="wai" then
--wait x frames
e.wait=par1
quit=true
end
e.bri+=3
if quit then return end
dobrain(e)
end
end
function doenemies()
for e in all(enemies) do
if e.wait>0 then
e.wait-=1
else
dobrain(e)
end
e.sx=sin(e.ang)*e.spd
e.sy=cos(e.ang)*e.spd
e.x+=e.sx
e.y+=e.sy
e.age+=1
if not onscreen(e) then
del(enemies,e)
end
end
end
function spawnen(eni,enx,eny)
local en=enlib[eni]
add(enemies,{
x=enx,
y=eny,
ani=anilib[en[1]],
anis=en[2],
sx=0,
sy=0,
ang=0,
spd=0,
brain=selbrain,
bri=1,
age=0,
flash=0,
hp=en[4],
col=en[5],
wait=0
})
end
__gfx__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
0000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000