制作一款打飞机游戏43:行为编辑
设计编辑器界面
首先,我们要设计一个更舒适的编辑器,以便开始在这个编辑器中编辑这些不同的行为。我们的目标是扩展我们的小编程语言中的命令集。现在,让我们加载大脑并开始看看有什么可以做的。
目前,我们的大脑编辑器中只有三个命令,但它已经滚动到屏幕的一边了。所以,我们可能需要为实际的大脑设计一个完全不同的布局。另外,我们看到屏幕上同时显示了两个大脑(大脑1和大脑2),但我们可能不希望同时编辑多个大脑,而是一次只看到一个大脑。
我想,在设计大脑编辑器的布局时,可以借鉴我们之前做精灵编辑的方式。在精灵编辑器中,我们有很多精灵,但我们不需要在大脑编辑器中也显示那么多。大脑编辑器可能看起来像这样:你可以切换不同的大脑,然后在这里添加命令。屏幕中央可能会显示一个预览,展示当这些命令被执行时是什么样子的。现在,让我们先来设计布局。
创建新模式和变量
我想创建一个新模式,叫做“绘制大脑”模式,然后还有“更新大脑”模式。此外,我们还需要创建一个UI标签,因为我们是基于模板新鲜创建的,而模板中没有UI标签。
接下来,我要创建一个变量,叫做cellBrain
,用来表示当前正在编辑的大脑。这样,我们就可以随时知道正在编辑哪个大脑了。
设计菜单
现在,让我们来设计菜单。在很多方面,它可能会类似于我们之前的精灵编辑器的布局。我们将创建一个新的菜单项,我会在后面解释它的用途。我想把这个菜单项叫做“设置”,并且用一个特殊的字符来表示它,比如一个钻石形状,表示这会打开一个新的菜单。
绘制大脑和命令
现在,我们要绘制大脑和命令了。我们会遍历所有的大脑,并为每个大脑绘制相应的命令和参数。每个命令都会有一个按钮,当点击这个按钮时,我们可以编辑该命令或参数。
添加新功能和优化布局
完成基本的布局后,我还想做一些优化。比如,我希望按钮的大小能够根据里面的数字自动调整。这样,无论数字多长,按钮都能完美显示它。
另外,我还想添加一些新功能,比如能够在不同的大脑之间切换,以及编辑单个命令或参数。当按下回车键时,我们需要根据当前编辑的是命令还是参数来执行不同的操作。
pico-8 cartridge // http://www.pico-8.com
version 41
__lua__--todo
-- -sanitize cmd input
-- -creating new brainsfunction _init()--- customize here ---#include shmup_brains.txtfile="shmup_brains.txt"arrname="brains"data=brains----------------------debug={}msg={}_drw=draw_brain_upd=update_brainmenuitem(1,"export",export)reload(0x0,0x0,0x2000,"cowshmup.p8")curx=1cury=1scrolly=0scrollx=0selbrain=1poke(0x5f2d, 1)
endfunction _draw()_drw()if #msg>0 thenbgprint(msg[1].txt,64-#msg[1].txt*2,80,14)msg[1].t-=1if msg[1].t<=0 thendeli(msg,1)end end-- debug --cursor(4,4)color(8)for txt in all(debug) doprint(txt)end
endfunction _update60()dokeys()mscroll=stat(36)_upd()
endfunction dokeys()if stat(30) thenkey=stat(31)if key=="p" thenpoke(0x5f30,1)endelsekey=nilendend
-->8
--drawfunction draw_brain()cls(13)drawmenu()endfunction draw_table()cls(2)--spr(0,0,0,16,16)drawmenu()--[[for i=1,#data dofor j=1,#data[i] dobgprint(data[i][j],2+18*j,2+8*i,7)endend]]
endfunction drawmenu()if menu thenfor i=1,#menu dofor j=1,#menu[i] dolocal mymnu=menu[i][j]local c=mymnu.c or 13if i==cury and j==curx thenc=7if _upd==upd_type thenc=0endendbgprint(mymnu.w,mymnu.x+scrollx,mymnu.y+scrolly,13) bgprint(mymnu.txt,mymnu.x+scrollx,mymnu.y+scrolly,c) endendendif _upd==upd_type thenlocal 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 thentxt_cur="\^i"..txt_cur.."\^-i"endlocal txt=txt_bef..txt_cur..txt_aftbgprint(txt,mymnu.x+scrollx,mymnu.y+scrolly,7)end
end-->8
--updatefunction update_brain()refresh_brain()if btnp(⬆️) thencury-=1endif btnp(⬇️) thencury+=1endcury=mid(1,cury,#menu)if cury==1 thenif btnp(⬅️) thenselbrain-=1endif btnp(➡️) thenselbrain+=1endselbrain=mid(1,selbrain,#data)elseif btnp(⬅️) thencurx-=1endif btnp(➡️) thencurx+=1endcurx=mid(1,curx,#menu[cury])endif btnp(❎) thenlocal mymnu=menu[cury][curx]if mymnu.cmd=="edit" then_upd=upd_typetypetxt=tostr(mymnu.txt)typecur=#typetxt+1callback=enter_brainelseif mymnu.cmd=="newline" thenadd(data[mymnu.cmdb],"wai")add(data[mymnu.cmdb],"0")add(data[mymnu.cmdb],"0") elseif mymnu.cmd=="setup" thenend endendfunction update_table()refresh_table()if btnp(⬆️) thencury-=1endif btnp(⬇️) thencury+=1endcury=(cury-1)%#menu+1cury-=mscrollcury=mid(1,cury,#menu)if btnp(⬅️) thencurx-=1endif btnp(➡️) thencurx+=1endif cury<#menu thencurx=(curx-2)%(#menu[cury]-1)+2elsecurx=1endlocal mymnu=menu[cury][curx]if mymnu.y+scrolly>110 thenscrolly-=4endif mymnu.y+scrolly<10 thenscrolly+=4endscrolly=min(0,scrolly)if mymnu.x+scrollx>110 thenscrollx-=2endif mymnu.x+scrollx<20 thenscrollx+=2endscrollx=min(0,scrollx)if btnp(❎) thenlocal mymnu=menu[cury][curx]if mymnu.cmd=="edit" then_upd=upd_typetypetxt=tostr(mymnu.txt)typecur=#typetxt+1callback=enter_tableelseif mymnu.cmd=="newline" thenadd(data,{0}) elseif mymnu.cmd=="newcell" thenadd(data[mymnu.cmdy],0)endend
endfunction upd_type()if key thenif key=="\r" then-- enterpoke(0x5f30,1)callback()returnelseif key=="\b" then--backspaceif typecur>1 thenif typecur>#typetxt thentypetxt=sub(typetxt,1,#typetxt-1)elselocal txt_bef=sub(typetxt,1,typecur-2)local txt_aft=sub(typetxt,typecur)typetxt=txt_bef..txt_aftendtypecur-=1endelseif typecur>#typetxt thentypetxt..=keyelselocal txt_bef=sub(typetxt,1,typecur-1)local txt_aft=sub(typetxt,typecur)typetxt=txt_bef..key..txt_aftendtypecur+=1endendif btnp(⬅️) thentypecur-=1endif btnp(➡️) thentypecur+=1endtypecur=mid(1,typecur,#typetxt+1)
end
-->8
--toolsfunction bgprint(txt,x,y,c)print("\#0"..txt,x,y,c)
endfunction split2d(s)local arr=split(s,"|",false)for k, v in pairs(arr) doarr[k] = split(v)endreturn arr
endfunction spacejam(n)local ret=""for i=1,n doret..=" "endreturn ret
end
-->8
--i/o
function export()local s=arrname.."=split2d\""for i=1,#data doif i>1 thens..="|"endfor j=1,#data[i] doif j>1 thens..=","ends..=data[i][j]endends..="\""printh(s,file,true)add(msg,{txt="exported!",t=120})--debug[1]="exported!"
end
-->8
--uifunction refresh_brain()menu={}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=19for i=1,#mybra,3 dolocal 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 dolocal 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+2endadd(menu,lne)ly+=8endadd(menu,{{txt="+",w=" ",cmd="newline",cmdb=selbrain,x=3,y=ly,c=13 }})endfunction refresh_table()menu={}for i=1,#data dolocal lne={}local linemax=#data[i]if i==cury thenlinemax+=1 endadd(lne,{txt=i,w=" ",cmd="",x=4,y=-4+8*i,c=2 })for j=1,linemax doif j==#data[i]+1 thenadd(lne,{txt="+",w=" ",cmd="newcell",cmdy=i,x=-10+14*(j+1),y=-4+8*i, })elseadd(lne,{txt=data[i][j],cmd="edit",cmdx=j,cmdy=i,x=-10+14*(j+1),y=-4+8*i,w=" "})endendadd(menu,lne)endadd(menu,{{txt=" + ",w=" ",cmd="newline",x=4,y=-4+8*(#data+1), }})
endfunction enter_table()local mymnu=menu[cury][curx]local typeval=typetxtif typeval==nil or typeval=="" thenif mymnu.cmdx==#data[mymnu.cmdy] and typetxt=="" then--delete celldeli(data[mymnu.cmdy],mymnu.cmdx)if mymnu.cmdx==1 thendeli(data,mymnu.cmdy)end_upd=update_tablereturnend typeval=0end data[mymnu.cmdy][mymnu.cmdx]=typeval_upd=update_table
endfunction enter_brain()_upd=update_brainlocal mymnu=menu[cury][curx]local typeval=typetxtif mymnu.cmdi%3==1 then--editing command entryif typeval=="" thendeli(data[mymnu.cmdb],mymnu.cmdi)deli(data[mymnu.cmdb],mymnu.cmdi)deli(data[mymnu.cmdb],mymnu.cmdi)returnendelse--editing parameterstypeval=tonum(typetxt)if typeval==nil thentypeval=0endtypeval=tostr(typeval)enddata[mymnu.cmdb][mymnu.cmdi]=typevalend
__gfx__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
0000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000