虽然我们基本上已经重建了Axel编辑器,但我不想直接使用它。我想创建一个真正适合我们当前目的的编辑器,那就是编辑精灵(sprites)。这将是今天的一个大目标------创建一个基于模板的编辑器,用它作为我们实际编辑器的起点。
细节调整
在开始之前,有一些小细节我想修复。比如,滚动功能现在不太灵敏,尤其是在屏幕左侧边缘。我们需要让滚动对左侧边缘更敏感一些。通过调整滚动X的值,我们现在已经解决了这个问题,使得滚动更加顺畅。
消息系统优化
另一个我不喜欢的地方是,当我们导出时,它只使用一个调试系统来显示消息。我希望有一个内置的更正式的消息系统,消息可以格式化并在一段时间后自动消失。因此,我决定添加一个MSG对象来处理这些消息,并在屏幕上显示它们,每条消息显示两秒钟后自动消失。
编辑器界面优化
我注意到,当列表项很多时,滚动到底部会变得非常繁琐。因此,我决定添加鼠标滚轮滚动功能,这样可以更快速地滚动列表。通过调整状态变量m_scroll
,我们已经实现了这一功能。
创建精灵编辑器
现在,我想基于之前的编辑器模板,创建一个专门用于编辑精灵的编辑器。我将其命名为"Sprite Edit"。在这个编辑器中,我将保留表格视图,但同时创建一个新的视图来编辑精灵。这个新视图将被称为"列表视图"。
列表视图实现
在列表视图中,我将显示所有精灵的列表,每个精灵占据一行。用户可以通过滚动快速浏览所有精灵,并通过选择某个精灵来编辑它。我已经实现了刷新列表和绘制列表的功能,现在用户可以看到一个简洁的精灵列表。
显示精灵预览
为了让用户能够直观地看到他们正在编辑的精灵,我决定在列表视图中添加精灵预览功能。当用户选择某个精灵时,程序将在屏幕上绘制该精灵的预览图。为了实现这一点,我使用了mspr
函数来从精灵表中获取精灵数据,并在屏幕上绘制它们。
中心点标记
为了让用户更清楚地了解精灵的中心点位置,我决定在精灵预览图上添加中心点标记。我使用了一个小红点来表示精灵的中心点,并通过闪烁来引起用户的注意。此外,我还绘制了从屏幕中心到精灵中心点的虚线,以帮助用户更准确地定位精灵。

新增精灵功能
接下来,我实现了新增精灵的功能。用户可以通过点击底部的"+"按钮来创建一个新的精灵条目。为了确保新创建的精灵条目是有效的,我添加了足够的默认数据(如位置、宽度、高度和偏移量)。
编辑精灵模式
最后,我创建了一个编辑精灵的模式。在这个模式下,用户可以选择一个精灵并进入编辑状态。我将编辑精灵的UI设计为一个包含多个编辑框和按钮的菜单,用户可以通过这些控件来修改精灵的属性。
pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
function _init()
--- customize here ---
#include shmup_myspr.txt
file="shmup_myspr.txt"
arrname="myspr"
data=myspr
----------------------
debug={}
msg={}
_drw=draw_list
_upd=update_list
menuitem(1,"export",export)
reload(0x0,0x0,0x2000,"cowshmup.p8")
curx=1
cury=1
scrolly=0
scrollx=0
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_edit()
fillp(0b11001100001100111100110000110011)
rectfill(0,0,127,127,33)
fillp(▒)
line(63,0,63,127,13)
line(0,63,127,63,13)
fillp()
draw_menu()
if selspr then
mspr(selspr,63,63)
end
if (time()*2)%1<0.5 then
pset(63,63,rnd({8,13,7,15}))
end
end
function draw_list()
fillp(0b11001100001100111100110000110011)
rectfill(0,0,127,127,33)
fillp(▒)
line(63,0,63,127,13)
line(0,63,127,63,13)
fillp()
draw_menu()
local mymnu=menu[cury][curx]
if mymnu.cmdy then
mspr(mymnu.cmdy,63,63)
end
if (time()*2)%1<0.5 then
pset(63,63,rnd({8,13,7,15}))
end
end
function draw_table()
cls(2)
draw_menu()
end
function draw_menu()
--spr(0,0,0,16,16)
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_edit()
refresh_edit()
end
function update_list()
refresh_list()
if btnp(⬆️) then
cury-=1
end
if btnp(⬇️) then
cury+=1
end
cury=(cury-1)%#menu+1
cury-=mscroll
cury=mid(1,cury,#menu)
curx=1
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=="newline" then
add(data,{0,0,0,0,0,0})
elseif mymnu.cmd=="editspr" then
selspr=mymnu.cmdy
_upd=update_edit
_drw=draw_edit
end
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
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
local mymnu=menu[cury][curx]
poke(0x5f30,1)
local typeval=tonum(typetxt)
if typeval==nil 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
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 mspr(si,sx,sy)
local ms=myspr[si]
sspr(ms[1],ms[2],ms[3],ms[4],sx-ms[5],sy-ms[6],ms[3],ms[4],ms[7]==1)
if ms[7]==2 then
sspr(ms[1],ms[2],ms[3],ms[4],sx-ms[5]+ms[3],sy-ms[6],ms[3],ms[4],true)
end
if ms[8] then
mspr(ms[8],sx,sy)
end
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)
add(msg,{txt="exported!",t=120})
--debug[1]="exported!"
end
-->8
--ui
function refresh_edit()
menu={}
end
function refresh_list()
menu={}
for i=1,#data do
local lne={}
local linemax=#data[i]
if i==cury then
linemax+=1
end
add(lne,{
txt="spr "..i,
w="",
cmd="editspr",
cmdy=i,
x=2,
y=-4+6*i
})
add(menu,lne)
end
add(menu,{{
txt=" + ",
w=" ",
cmd="newline",
x=2,
y=-4+6*(#data+1)+2,
}})
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
__gfx__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
0000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000