
我们正在创建一个调度编辑器。嗯,这个名字听起来可能有点奇怪,对吧?但如果你了解射击游戏中的"调度",那就是敌人出现的时间表。
你可能已经看到了,我们有一个可以滚动的关卡。现在,我想增加一些交互性,希望能够实际编辑这个调度。
创建新的UI模式
首先,我想为地图视图创建一个全新的UI模式。因为现在我们像是在这张表后面画图,但我们不想显示这张表,只想在地图上显示敌人。所以,我将引入一个新的UI模式。
我们将创建一个名为"draw map"的函数,这是地图模式。我想这将是游戏中唯一的模式。然后,我们将把整段代码复制过来放到这里。
接下来,我们需要一个更新函数来刷新地图。我们将在UI标签下创建一个新的函数,叫做"refresh map",把之前复制的代码放进去,但这次是用来刷新地图的。
现在,我们设置默认的更新和绘制函数为"draw map"和"update map",然后保存并运行。瞧,这就是编辑器,我们现在可以看到一切,没有额外的UI,这很好。
添加鼠标交互
现在,我想添加更多的元素。首先,我想在编辑器中实现基本的交互,比如点击某个地方创建一个敌人。所以,我想看到鼠标光标。
我们可以使用"stat"函数来检测鼠标的X和Y位置以及哪个按钮被按下了。在Pico-8的wiki上,你可以找到关于鼠标和键盘的详细信息。
我创建了一个名为"do mouse"的函数,用来处理鼠标事件。现在,我可以看到鼠标的位置了,这已经很酷了。
接下来,我想处理鼠标点击事件。我设置了一个变量"CLKL"来表示左键是否被按下,同样地,还有"CLKR"表示右键。我使用"btnp"来检测按钮是否在当前帧被按下,这样我们就可以实现点击效果了。
绘制鼠标光标
现在,我想在屏幕上看到一个鼠标光标。但因为我们正在使用整个精灵表来绘制地图,所以不能直接绘制光标。不过,我可以绘制一个简单的光标。
我画了一个白色的十字作为光标,并且让它可以根据鼠标位置移动。为了让光标更引人注目,我还让它随机闪烁红色和白色。
实现X轴滚动
接下来,我想实现X轴的滚动。这样,当我们移动鼠标时,地图也会跟着滚动。我复制了之前的滚动代码,并做了一些调整,使其基于鼠标位置进行滚动。
现在,当你移动鼠标时,地图会跟着左右滚动,这感觉很棒!
绘制敌人调度
现在,我想在地图上绘制敌人的调度点。我遍历了所有的调度,并在地图上绘制了它们。但因为没有导入精灵,所以我只能用红色矩形来表示。
我发现,这些矩形并没有随着地图的滚动而移动。所以,我调整了代码,将滚动值加到它们的Y位置上。现在,这些矩形会随着地图的滚动而移动了。
精确控制滚动值
为了更精确地控制滚动值,我添加了使用光标键来控制滚动的功能。这样,我们就可以更准确地滚动到想要的位置了。
调整调度显示
最后,我发现之前的调度显示没有考虑到敌人出现的时机。所以,我做了一些调整,使调度点能够正确地显示在地图上,反映敌人出现的时刻和位置。
pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
--show cursor
--move the cursor
--backspace
function _init()
--- customize here ---
#include shmup_sched.txt
file="shmup_sched.txt"
arrname="sched"
data=sched
#include shmup_mapsegs.txt
----------------------
debug={}
msg={}
_drw=draw_map
_upd=update_map
menuitem(1,"export",export)
reload(0x0,0x0,0x2000,"cowshmup.p8")
reload(0x1000, 0x1000, 0x2000, "cowshmup.p8")
curx=1
cury=1
scrolly=0
scrollx=0
scroll=0
xscroll=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()
domouse()
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
function domouse()
mousex=stat(32)
mousey=stat(33)
if stat(34)==0 then
clkwait=false
end
clkl=false
clkr=false
if not clkwait then
if stat(34)==1 then
clkl=true
clkwait=true
elseif stat(34)==2 then
clkl=true
clkwait=true
end
end
end
-->8
--draw
function draw_map()
cls(2)
for i=1,#mapsegs do
local segnum=mapsegs[i]
local sx=segnum\4*18
local sy=segnum%4*8
map(sx,sy,xscroll,scroll-((i-2)*64),18,8)
end
drawcur(mousex,mousey)
camera(-xscroll,0)
for sch in all(sched) do
local schx=sch[3]
local schy=sch[4]+scroll-sch[1]
rectfill(schx,schy,schx+16,schy+16,8)
end
camera()
debug[1]=scroll
end
function draw_table()
cls(2)
--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
--[[
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 drawcur(cx,cy)
local col=rnd({6,7})
line(cx,cy-1,cx,cy-2,col)
line(cx,cy+1,cx,cy+2,col)
line(cx-1,cy,cx-2,cy,col)
line(cx+1,cy,cx+2,cy,col)
end
-->8
--update
function update_map()
refresh_map()
scroll+=mscroll*8
xscroll=mid(0,(mousex-10)/108,1)\-0.0625
if btnp(⬇️) then
scroll-=1
end
if btnp(⬆️) then
scroll+=1
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
-->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_map()
menu={}
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