当前位置: 首页 > news >正文

制作一款打飞机游戏42:敌人大脑

我们还有一个“敌人大脑”系统,

敌人行为系统的设计与实现

接下来,我们要谈谈如何设置一个系统,让敌人可以有不同的行为。这是一个复杂的问题,因为每个敌人行为都可能需要大量的代码。如果我们为每个敌人硬编码行为,那么很快就会用完标记。

因此,我计划创建一个脚本系统,通过数据来编码敌人的行为。每个敌人的大脑将是一个数组,包含一系列命令和参数。我们将编写一个解释器来读取这些命令并更新敌人的状态。

这样,我们就可以通过修改数据来轻松创建各种敌人行为,而无需编写大量的重复代码。我已经开始实现这个系统的基础部分,包括使用角度和速度来计算敌人的移动。

创建大脑数据库

首先,我们需要创建一个新的文本文件,我们将其命名为schmup brains。这个名字听起来很有趣,尽管你也可以称之为AI或行为。现在,我们在这个文件中定义brains,它应该是一个三维数组,因为每个大脑由多行组成,每行有多个条目。但是,处理三维数组有点复杂,所以我们决定将其简化为一个二维数组,其中每个大脑是一个长序列,每个命令及其参数连续存储。

编辑器的调整

我们的编辑器目前将所有输入都转换为数字,这不利于可读性。因此,我们需要对编辑器进行一些调整,以便当输入为nilnothing时,删除该单元格,否则保留输入内容。这样,我们就可以在大脑中输入可读的命令和参数了。

创建简单的大脑

接下来,我们创建了两个简单的大脑。每个大脑包含一条命令,例如head,后面跟着两个参数:角度和速度。这样,我们就可以控制敌人的移动方向和速度了。

将大脑集成到游戏中

现在,我们需要将这些大脑集成到我们的游戏中。当创建敌人时,我们从大脑数据库中选择一个大脑,并将其与敌人关联。然后,在游戏循环中,我们根据大脑中的命令和参数来更新敌人的行为。

扩展大脑功能

为了使大脑系统更加灵活,我们添加了一个新的命令wait,它允许敌人在执行下一条命令之前等待一段时间。为了实现这个功能,我们在敌人实体中添加了一个weight变量来记录等待时间,并在游戏循环中递减这个变量。当weight大于0时,敌人不会执行新的命令。

优化代码结构

为了使代码更加清晰和易于维护,我们将大脑相关的逻辑封装在一个doBrain函数中。这个函数负责从大脑中读取命令和参数,并更新敌人的状态。同时,我们还添加了一些调试信息,以便在开发过程中跟踪敌人的行为。

pico-8 cartridge // http://www.pico-8.com
version 41
__lua__
--show cursor
--move the cursor
--backspacefunction _init()--- customize here ---#include shmup_brains.txtfile="shmup_brains.txt"arrname="brains"data=brains----------------------debug={}msg={}_drw=draw_table_upd=update_tablemenuitem(1,"export",export)reload(0x0,0x0,0x2000,"cowshmup.p8")curx=1cury=1scrolly=0scrollx=0poke(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_table()cls(2)--spr(0,0,0,16,16)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--[[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={}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), }})
end
-->8
--updatefunction 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+1elseif 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-- enterlocal mymnu=menu[cury][curx]poke(0x5f30,1)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=0enddata[mymnu.cmdy][mymnu.cmdx]=typeval_upd=update_tablereturnelseif 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
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
__gfx__
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00077000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00700700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
0000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

相关文章:

  • Unity3D实现Render Streaming推送视频流的解决方案
  • 【网络编程】四、守护进程实现 前后台作业 会话与进程组
  • 【强化学习】强化学习算法 - 马尔可夫决策过程
  • 可再生能源中的隔离栅极驱动器:光伏逆变器的游戏规则改变者
  • 数据防泄漏的解决方案
  • Java学习手册:单体架构到微服务演进
  • CSS vertical-align
  • SPN技术介绍
  • HunyuanCustom, 腾讯混元开源的多模态定制视频生成框架
  • RuntimeError: expected scalar type ComplexDouble but found Float
  • 经过多年发展,中国机械工业已经具备了独特的国际比较优势
  • 一文了解氨基酸的分类、代谢和应用
  • WorkManager与Kotlin后台任务调度指南
  • springboot 加载 tomcat 源码追踪
  • 《 指针变量的创建:初探内存世界的钥匙》
  • 水印云:AI赋能,让图像处理变得简单高效
  • zst-2001 历年真题 UML
  • Babylon.js学习之路《二、开发环境搭建与第一个Hello World》
  • 在Mac M1/M2上使用Hugging Face Transformers进行中文文本分类(完整指南)
  • JavaSE核心知识点02面向对象编程02-04(包和导入)
  • 上海交大:关注到对教师邵某的网络举报,已成立专班开展调查
  • 硅料巨亏后弘元绿能割肉求生:逾12亿元内蒙古公司股权转让协鑫
  • 上海充电桩调研:须全盘考量、分步实现车网互动规模化
  • 特色业务多点开花,苏州银行擦亮金融为民底色
  • 联想发布超级智能体矩阵,杨元庆:美国关税影响反映在产品定价上,未来不确定性很大
  • 明天起,沪苏湖高铁、杭温高铁推出13款新型票制产品