制作一款打飞机游戏36:调度编辑器

我们正在创建一个调度编辑器。嗯,这个名字听起来可能有点奇怪,对吧?但如果你了解射击游戏中的"调度",那就是敌人出现的时间表。

你可能已经看到了,我们有一个可以滚动的关卡。现在,我想增加一些交互性,希望能够实际编辑这个调度。

创建新的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
相关推荐
二狗哈3 小时前
制作一款打飞机游戏28:编辑器完善鲁棒性
游戏
米芝鱼5 小时前
Unity URPShader:实现和PS一样的色相/饱和度调整参数效果(修复)
游戏·unity·游戏引擎·图形渲染·opengl·着色器
ricky_fan1 天前
LeetCode:55.跳跃游戏——局部最优并非全局最优!
算法·leetcode·游戏
Vacant Seat2 天前
贪心算法-跳跃游戏II
算法·游戏·贪心算法
李詹2 天前
游戏哪些接口会暴露源IP?_深度解析服务器通信安全隐患
游戏·游戏引擎·cocos2d·3dcoat
_李小白2 天前
【OSG学习笔记】Day 7: 材质与光照——让模型“活”起来
游戏·3d·材质
北冥没有鱼啊2 天前
UE 滚动提示条材质制作
游戏·ue5·游戏引擎·ue4·虚幻·材质
二狗哈3 天前
制作一款打飞机游戏26:精灵编辑器
游戏·编辑器