今天,我想重点介绍编辑器的实际用户界面(UI)。
关于Excel的讨论
很多人使用Excel来编辑他们程序的数据,因为大多数时候它都能很好地完成工作。Excel就像是一把瑞士军刀,可以修改各种数据。但是,在某些情况下,Excel并不能帮助我们太多。例如,我们现在正在创建一个用于编辑PICO 8精灵的编辑器,而Excel很难显示我们正在编辑的实际精灵。
编辑器的UI设计
我想要的是一个类似Axel的电子表格程序,但我也意识到这可能不是最明智的选择,因为我可以直接使用Excel。不过,由于我们的特殊需求,我们需要自己创建一个。
我的核心想法是,要有一些小黑盒子,里面写着文本。今天,我想继续完善这个想法,并做一些布局调整,让它们看起来更美观。同时,我想设置一个系统,让我可以通过光标移动来选择单元格。
UI系统的实现
我们计划基于底层数据直接绘制UI。这意味着我们会遍历数据,并根据数据在屏幕上绘制盒子。这种方法对于数据可视化来说很好,但对于UI来说可能有些困难,因为UI的其他元素可能并不完全基于数据。
为了解决这个问题,我计划使用一个中间菜单数组。这个数组将包含对象,每个对象代表一个小盒子,盒子里有文本和其他属性(如X和Y位置)。这样,我们可以基于这个菜单数组来绘制UI,而不是直接基于数据。
光标的实现
接下来,我想实现一个可以在UI菜单中移动的光标。我将创建两个变量:cursorX和cursorY,它们表示光标在UI中的位置。当绘制菜单元素时,如果当前元素的位置与光标位置匹配,我将改变其颜色以突出显示。
然后,我将使用方向键来移动光标,并添加边界限制,确保光标不会移出菜单系统的范围。同时,我还添加了滚动变量,以便在长表格中滚动查看内容。
编辑单元格
现在,我们可以移动光标并突出显示单元格,但还不能编辑它们。接下来,我想实现一个功能,让我们可以通过按键来增加或减少单元格中的数字。为此,我在每个UI对象中添加了两个属性:cmdX和cmdY,它们表示该单元格对应的数据在数组中的索引位置。
通过这些属性,我们可以轻松地访问和修改与单元格关联的数据。当我按下X按钮时,程序会找到当前光标所在的单元格,并增加其对应的数字值;当我按下O按钮时,数字值会减少。
键盘输入的实现
最后,我想实现一个功能,让我们可以直接在单元格中输入数字。由于PICO 8本身没有键盘输入功能,我将使用一个特殊的“def kit mode”(作弊模式)来启用键盘输入。通过调用stat函数并检查其返回值,我们可以检测到按键事件并获取按键值。
现在,我已经展示了如何检测按键事件,接下来我将实现一个系统,让我们在选中单元格并按下X按钮后,可以开始输入数字。
pico-8 cartridge // http://www.pico-8.com
version 41
__lua__function _init()--- customize here ---#include shmup_myspr.txtfile="shmup_myspr.txt"arrname="myspr"data=myspr----------------------debug={}_drw=draw_table_upd=update_tablemenuitem(1,"export",export)reload(0x0,0x0,0x2000,"cowshmup.p8")curx=1cury=1scrolly=0scrollx=0poke(0x5f2d, 1)debug[2]=""
endfunction _draw()_drw()-- debug --cursor(4,4)color(8)for txt in all(debug) doprint(txt)end
endfunction _update60()debug[1]=stat(30)if stat(30) thendebug[2]..=stat(31)end_upd()
end
-->8
--drawfunction draw_table()cls(2)--spr(0,0,0,16,16)if menu thenfor i=1,#menu dofor j=1,#menu[i] dolocal c=13if i==cury and j==curx thenc=7endlocal mymnu=menu[i][j]bgprint(mymnu.w,mymnu.x+scrollx,mymnu.y+scrolly,13) bgprint(mymnu.txt,mymnu.x+scrollx,mymnu.y+scrolly,c) endendend--[[for i=1,#data dofor j=1,#data[i] dobgprint(data[i][j],2+18*j,2+8*i,7)endend]]
endfunction refresh_table()--[[menu={{{txt="hello",cmd="say hello",x=2,y=2}}}]]--menu={}for i=1,#data dolocal lne={}for j=1,#data[i] doadd(lne,{txt=data[i][j],cmd="edit",cmdx=j,cmdy=i,x=-10+14*j,y=-4+8*i,w=" "})endadd(menu,lne)end
end
-->8
--updatefunction update_table()refresh_table()if btnp(⬆️) thencury-=1endif btnp(⬇️) thencury+=1endcury=mid(1,cury,#menu)if btnp(⬅️) thencurx-=1endif btnp(➡️) thencurx+=1endcurx=mid(1,curx,#menu[cury])local mymnu=menu[cury][curx]if mymnu.y+scrolly>110 thenscrolly-=1endif mymnu.y+scrolly<10 thenscrolly+=1endscrolly=min(0,scrolly)if mymnu.x+scrollx>110 thenscrollx-=1endif mymnu.x+scrollx<10 thenscrollx+=1endscrollx=min(0,scrollx)if btnp(❎) thenlocal mymnu=menu[cury][curx]if mymnu.cmd=="edit" thendata[mymnu.cmdy][mymnu.cmdx]+=1endendif btnp(🅾️) thenlocal mymnu=menu[cury][curx]if mymnu.cmd=="edit" thendata[mymnu.cmdy][mymnu.cmdx]-=1endend
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
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)debug[1]="exported!"
end
__gfx__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
0000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000