LUAT游戏第一弹---贪吃蛇

前言

开个新系列,基于LUAT制作小游戏

准备工作

硬件准备

1,准备724,724等能运行luat的开发版
2,矩阵键盘

软件准备

首先呢,准备几个需要用到的图片,例如这样的

0

开始制作

游戏制作

好了,图片准备完了,开始做吧,我使用的是ST7899的LCD做的,1.54寸屏幕上分辨率 240*240,画面细腻有弹性

所以最先准备的是LCD驱动,直接使用

0

有屏幕了,还需要按键呀,矩阵按键走起

module(..., package.seeall)


--[[
sta:按键状态,IDLE表示空闲状态,PRESSED表示已按下状态,LONGPRESSED表示已经长按下状态
longprd:长按键判断时长,默认3秒;按下大于等于3秒再弹起判定为长按键;按下后,在3秒内弹起,判定为短按键
longcb:长按键处理函数
shortcb:短按键处理函数
]]
local sta,longprd = "IDLE",1500

local function longtimercb()
 log.info("keypad.longtimercb")
 sta = "LONGPRESSED"
end

local lcd_out = pins.setup(pio.P0_7,1)--GPIO7配置为输出

local function keyMsg(msg)
 --msg.key_matrix_row:行
 --msg.key_matrix_col:列
 --msg.pressed:true表示按下,false表示弹起
 --log.info("keyMsg",msg.key_matrix_row,msg.key_matrix_col,msg.pressed)
 if msg.pressed then
 disp.sleep(0)
 lcd_out(1)
 if msg.key_matrix_row == 2 then
 if msg.key_matrix_col == 1 then
 sys.publish("key","key_up")
 elseif msg.key_matrix_col == 2 then
 sys.publish("key","key_back")
 elseif msg.key_matrix_col == 3 then
 end
 elseif msg.key_matrix_row == 3 then
 if msg.key_matrix_col == 1 then
 sys.publish("key","key_down")
 elseif msg.key_matrix_col == 2 then
 end
 elseif msg.key_matrix_row == 4 then
 if msg.key_matrix_col == 1 then
 sys.publish("key","key_left")
 elseif msg.key_matrix_col == 2 then
 sys.publish("key","key_right")
 end
 elseif msg.key_matrix_row == 255 then
 if msg.key_matrix_col == 255 then
 sta = "PRESSED"
 sys.timerStart(longtimercb,longprd)
 end
 end
 else
 sys.timerStop(longtimercb)
 if sta=="PRESSED" then
 sys.publish("key","key_ok")
 elseif sta=="LONGPRESSED" then
 rtos.poweroff()
 end
 sta = "IDLE"
 end
end

--注册按键消息处理函数
rtos.on(rtos.MSG_KEYPAD,keyMsg)
--初始化键盘阵列
--第一个参数:固定为rtos.MOD_KEYPAD,表示键盘
--第二个参数:目前无意义,固定为0
--第三个参数:表示键盘阵列keyin标记,例如使用了keyin0、keyin1、keyin2、keyin3,则第三个参数为1<<0|1<<1|1<<2|1<<3 = 0x0F
--第四个参数:表示键盘阵列keyout标记,例如使用了keyout0、keyout1、keyout2、keyout3,则第四个参数为1<<0|1<<1|1<<2|1<<3 = 0x0F
rtos.init_module(rtos.MOD_KEYPAD,0,0x1C,0x0E)

这样就可以通过消息机制得到按键事件了,加了长按关机

按键有了,屏幕有了,接下来开始愉快的掉头发吧

首先创建一个协程作为入口,然后加个游戏图标

disp.setbkcolor(0x0000)
 disp.clear()
 lcd.setcolor(0x00FF)
 disp.setfontheight(24)
 disp.puttext(common.utf8ToGb2312("贪吃蛇"),(lcd.HEIGHT-string.utf8Len("贪吃蛇")*24)/2,170)
 disp.putimage("/lua/snake.png",90,90)
 disp.update()
 disp.setfontheight(16)
 sys.wait(2000)

好,接下来开始做蛇:

我们知道,对象由属性和方法组成。LUA中最基本的结构是table,所以需要用table来描述对象的属性。

lua 中的 function 可以用来表示方法。那么LUA中的类可以通过 table + function 模拟出来。

至于继承,可以通过 metetable 模拟出来,所以有了我们的蛇:

local sk = {}
sk.__index = sk
local function snake()
 return setmetatable({
 x = 20+2*20,
 y = 40+0,
 body = {{20+2*20,40+0},{40,40},{20,40}},
 body_len = 3,
 direction = "right",
 food = {},
 run = false,
    }, sk)
end

可以看到属性有蛇头的初始坐标,蛇身坐标,长度,蛇头方向,食物坐标,蛇的状态,接下来我们使用snake1=snake()即可创建一条蛇的对象,

然后放蛇!!!!不对,界面是不是很丑?没有围墙跑出去咬人咋整,哈哈哈,随后初始化游戏环境:

local function snake_init()
 disp.clear()
 disp.puttext(common.utf8ToGb2312("得分:"),10,2)
 disp.puttext(common.utf8ToGb2312(score),55,2)
 for i = 0, LCD_WIDTH-20, 20 do
 disp.putimage("/lua/wall.png",i,20)
 end
 for i = 0, LCD_WIDTH-20, 20 do
 disp.putimage("/lua/wall.png",i,LCD_WIDTH-20)
 end
 for i = 20, LCD_HEIGHT-20, 20 do
 disp.putimage("/lua/wall.png",0,i)
 end
 for i = 20, LCD_HEIGHT-20, 20 do
 disp.putimage("/lua/wall.png",LCD_HEIGHT-20,i)
 end
 if snake1.direction=="left" then
 disp.putimage("/lua/snake_l.png",snake1.x,snake1.y)
 elseif snake1.direction=="right" then
 disp.putimage("/lua/snake_r.png",snake1.x,snake1.y)
 elseif snake1.direction=="up" then
 disp.putimage("/lua/snake_u.png",snake1.x,snake1.y)
 elseif snake1.direction=="down" then
 disp.putimage("/lua/snake_d.png",snake1.x,snake1.y)
 end
 for k,v in pairs(snake1.body) do
 if k==1 then
 -- body
 else
 disp.putimage("/lua/snake_body.png",v[1],v[2])
 end
 end
 disp.putimage("/lua/start.png",40,100)
 disp.update()
end

可以看到我们放了墙,和墙,之后呢?按开始进入游戏入口

while true do
   local result, data = sys.waitUntil("key",20)
   if result == true then
     if data == "key_ok" then
       game_thread()
     end
   end
 end

游戏里做一个协程吧,死了或者退出就break出来,nice

local function game_thread()
 snake1.run = true
 snake1:putfood()
 while true do
 snake1:draw()
 disp.putimage("/lua/food.png",snake1.food[1],snake1.food[2])
 disp.update()
 local result, data = sys.waitUntil("key",500 - score*4)
 if result == true then
 if data == "key_left" then
 snake1.direction="left"
 elseif data == "key_right" then
 snake1.direction="right"
 elseif data == "key_up" then
 snake1.direction="up"
 elseif data == "key_down" then
 snake1.direction="down"
 elseif data == "key_back" then
 snake1.run = false
 elseif data == "key_ok" then
 disp.putimage("/lua/start.png",40,100)
 disp.update()
 while true do
 local result, data = sys.waitUntil("key",500 - score*4)
 if result == true then
 if data == "key_ok" then
 break
 end
 end
 end
 end
 end
 if snake1.run == false then
 snake1:kill()
 snake_init()
 break
 end
 end
end

可以看到,进去之后让蛇的状态为存活,投食,之后循环画蛇画食物,通过按键改变蛇方向状态,如果死了或者退出就break出去,得分越高,速度越快,那我们还缺什么呢?对哦,投食和画蛇

那么投食来了

function sk:putfood()
 local state
 local x
 local y
 repeat
 x = math.random(1,10)*20
 y = math.random(2,10)*20
 state = 0
 for k,v in pairs(self.body) do
 if x == v[1] and y == v[2] then
 state = 1
 break
 end
 end
 until( state == 0 )
 self.food[1]=x
 self.food[2]=y
end

很简单,做两个墙以内的,不在蛇身上的随机数来放食物,之后画蛇:

function sk:draw()
 disp.drawrect(20,40,220,220,0x0000)
 if self.direction=="left" then
 self.x = self.x - 20
 disp.putimage("/lua/snake_l.png",self.x,self.y)
 elseif self.direction=="right" then
 self.x = self.x + 20
 disp.putimage("/lua/snake_r.png",self.x,self.y)
 elseif self.direction=="up" then
 self.y = self.y - 20
 disp.putimage("/lua/snake_u.png",self.x,self.y)
 elseif self.direction=="down" then
 self.y = self.y + 20
 disp.putimage("/lua/snake_d.png",self.x,self.y)
 end

 for k,v in pairs(self.body) do
 if self.x == v[1]and self.y == v[2]then
 self.run = false
 break
 end
 end

 if self.x>LCD_WIDTH-20-20 or self.x<20 or self.y>LCD_HEIGHT-20-20 or self.y<20+20 then
 self.run = false
 table.insert(self.body,1,{self.x,self.y})
 table.remove (self.body)
 elseif self.x ==self.food[1] and self.y==self.food[2] then
 disp.drawrect(0,0,240,19,0x0000)
 score=score+1
 disp.puttext(common.utf8ToGb2312("得分:"),10,2)
 disp.puttext(common.utf8ToGb2312(score),55,2)
 table.insert(self.body,1,{self.x,self.y})
 self:putfood()
 else
 table.insert(self.body,1,{self.x,self.y})
 table.remove (self.body)
 end
 for k,v in pairs(self.body) do
 if k == 1 then
 -- body
 else
 disp.putimage("/lua/snake_body.png",v[1],v[2])
 end
 end
end

也很好理解,就是不断地加蛇身坐标,删除蛇尾坐标,如果吃到食物就不删除蛇尾,吃自己或者撞墙就死掉

大功告成,还差点什么?????对喽,B G M

0

local function game_thread() audio.play(0,"FILE","/lua/bgm.mp3",1,nil,true)

在入口处加上,OK,开玩!!!

0

好了,一起来玩好玩的贪吃蛇吧

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值