今天来介绍博主近期捣腾的一个小游戏[贪吃蛇],贪吃蛇这个游戏相信大家都不会感到陌生吧。今天博主将通过Love2D这款游戏引擎来为大家实现一个简单的贪吃蛇游戏,在本篇文章其中我们将会涉及到贪吃蛇的基本算法、Lua语言编程等主要的内容,希望能够对大家开发相似的游戏提供借鉴和思考,文章中如有不足之处,还希望大家能够谅解,由于博主的游戏开发基本就是这样慢慢摸索着学习。所以难免会有不足的地方。

游戏算法

我们首先来看看贪吃蛇是怎么移动的?

通过这四张图的演示,我们能够发现这样一个规律:

蛇的移动事实上是将蛇身体的最后一个元素移动到第一个元素的位置

那么完毕这样一个工作须要两个步骤:

1、将在蛇头位置插入一个新的元素

2、移除蛇尾位置的最后一个元素

好了。了解了蛇的移动后我们再来考虑一个问题,如何推断蛇吃到了食物?思路和蛇的移动相似,主要考虑在蛇头插入的这个元素和食物的关系,假设这个元素的坐标和食物的坐标是同样的,那么就能够觉得蛇吃到了食物,此时蛇的身体应该是变长的。所以仅仅要在蛇头位置插入一个元素就能够了。反之,假设蛇没有吃到食物。那么蛇应该是移动的。所以就能够依照移动的方法来处理了。那么在蛇头位置插入的这个元素该如何确定呢?我们来看以下这段程序:

--计算下一个目标点
function getNextPoint()
--计算下一个目标点
snake={}
if(dir==0) then
snake.x=snakes[1].x
snake.y=snakes[1].y-20
end
if(dir==1) then
snake.x=snakes[1].x
snake.y=snakes[1].y+20
end
if(dir==2) then
snake.x=snakes[1].x-20
snake.y=snakes[1].y
end
if(dir==3) then
snake.x=snakes[1].x+20
snake.y=snakes[1].y
end return snake
end

这里定义了getNextPoint()的方法,目的是计算在蛇头位置加入的下一个元素,这里我们注意到依据蛇的移动方向(dir)的不同,其中0表示上、1表示下、2表示左、3表示右,计算出下一个元素的位置,由于在这个游戏中网格大小是20,所以这里能够直接依据坐标来计算一个元素的位置。

snakes是一个table,保存的是当前的蛇的所有元素的坐标。通过维护这个table,我们就能够利用画图的函数绘制出蛇的身体,这样蛇就能够移动起来了。

我们来看看蛇是如何移动的:

--核心算法——蛇的移动
function SnakeUpdate()
--获取元素个数
local n=table.maxn(snakes)
if(table.maxn(snakes)>0) then
if(getNextPoint().x==foodX and getNextPoint().y==foodY) then
--将下一个目标点的位置插入表中
table.insert(snakes, 1, getNextPoint())
--将食物状态设置为BeEated
foodState="BeEated"
else
--将下一个目标点的位置插入表中
table.insert(snakes, 1, getNextPoint())
--移除最后一个元素
table.remove(snakes,n+1)
end
end
end

在这里我们定义了一个foodState变量以保存食物的状态。当食物的状态为BeEated的时候表示食物被蛇吃掉了,此时应该又一次生成一个食物的坐标。此时事物的状态将变成WaitToEat。食物的坐标保存在foodX和foodY这两个变量中。大家能够到完整的代码中去查看。

我们知道蛇碰到四周墙壁的时候就会死亡,此时游戏结束。

这个比較简单,仅仅要推断蛇头的坐标和屏幕的关系就能够了。

由于在这个游戏中屏幕的尺寸为640X640。所以推断游戏是否结束的代码能够这样写:

--推断游戏状态
if(snakes[1].x<=0 or snakes[1].x>=640 or snakes[1].y<=0 or snakes[1].y>=640) then
gameState=0
else
gameState=1
end

这里gameState为0表示游戏结束。gameState为1表示游戏正常进行。

在完毕了这些核心的算法以后,剩下的事情就交给Love2D引擎来绘制吧。最后给出完整的程序代码:

--定义窗体宽度和高度
local w=640
local h=640
--定义网格单元大小
local unitSize=20; --方块的初始位置
local initX=320
local initY=320 --移动方向
local dir=1 --贪吃蛇集合
local snakes={} --食物状态
--WaitToEat:绘制食物
--BeEated:随机生成食物
local foodState="WaitToEat" --游戏状态
--0:游戏结束
--1:游戏正常
local gameState=1 --食物的位置
local foodX=0
local foodY=0 --Love2D载入事件
function love.load()
--设置窗体标题
love.window.setTitle("Love2D-贪吃蛇游戏")
--设置窗体大小
love.window.setMode(w,h)
--定义字体
myFont=love.graphics.newFont(30)
--设置字体
love.graphics.setFont(myFont)
--设置背景色
love.graphics.setBackgroundColor(255,255,255,255)
--设置线条类型为平滑
love.graphics.setLineStyle("smooth")
--设置线宽
love.graphics.setLineWidth(0.1) --蛇的初始化(蛇的长度为5)
for i=1,5 do
snake={}
snake.x=initX +(i-1) * 20
snake.y=initY
snakes[i]=snake
end --食物初始化
foodX=love.math.random(32-1)*20
foodY=love.math.random(32-1)*20
end --Love2D绘制事件
function love.draw()
--绘制竖线
love.graphics.setColor(0,0,0,255)
for i=0,w,unitSize do
love.graphics.line(0,i,h,i)
end
--绘制横线
for j=0,h,unitSize do
love.graphics.line(j,0,j,w)
end --绘制蛇
for i=1,table.maxn(snakes) do
love.graphics.setColor(0,0,255,255)
love.graphics.rectangle("fill",snakes[i].x,snakes[i].y,20,20)
end --绘制食物
if(foodState=="WaitToEat") then
love.graphics.setColor(255,0,0,255)
love.graphics.rectangle("fill",foodX,foodY,20,20)
end --假设游戏结束则显示GameOver
if(gameState==0) then
love.graphics.setColor(255,0,0,255)
love.graphics.print("Game Over",250,300)
end
end --
function love.update(dt)
--推断游戏状态
if(snakes[1].x<=0 or snakes[1].x>=640 or snakes[1].y<=0 or snakes[1].y>=640) then
gameState=0
else
gameState=1
end --假设游戏状态为正常
if(gameState==1) then
SnakeUpdate()
FoodUpdate()
end
end --核心算法——蛇的移动
function SnakeUpdate()
--获取元素个数
local n=table.maxn(snakes)
if(table.maxn(snakes)>0) then
if(getNextPoint().x==foodX and getNextPoint().y==foodY) then
--将下一个目标点的位置插入表中
table.insert(snakes, 1, getNextPoint())
--将食物状态设置为BeEated
foodState="BeEated"
else
--将下一个目标点的位置插入表中
table.insert(snakes, 1, getNextPoint())
--移除最后一个元素
table.remove(snakes,n+1)
end
end
end --随机生成食物
function FoodUpdate()
--假设食物被蛇吃掉则又一次生成食物
if(foodState=="BeEated") then
foodX=love.math.random(32-1)*20
foodY=love.math.random(32-1)*20
foodState="WaitToEat"
end
end --依据玩家按下的键位定义不同的方向
function love.keypressed(key)
if(key=="a" and dir~=3) then
dir=2
end
if(key=="d" and dir~=2) then
dir=3
end
if(key=="w" and dir~=1) then
dir=0
end
if(key=="s" and dir~=0) then
dir=1
end
end function getNextPoint()
--计算下一个目标点
snake={}
if(dir==0) then
snake.x=snakes[1].x
snake.y=snakes[1].y-20
end
if(dir==1) then
snake.x=snakes[1].x
snake.y=snakes[1].y+20
end
if(dir==2) then
snake.x=snakes[1].x-20
snake.y=snakes[1].y
end
if(dir==3) then
snake.x=snakes[1].x+20
snake.y=snakes[1].y
end return snake
end

将代码压缩成.love文件后就能够执行了,我们来看看终于的效果:



Github

使用Love2D引擎开发贪吃蛇游戏的更多相关文章

  1. Love2D游戏引擎制作贪吃蛇游戏

    代码地址如下:http://www.demodashi.com/demo/15051.html Love2D游戏引擎制作贪吃蛇游戏 内附有linux下的makefile,windows下的生成方法请查 ...

  2. 用Java开发贪吃蛇游戏

    贪吃蛇游戏的设计步骤: Part 1: 设计游戏图纸 画出900*700的白色窗口 在窗口上添加画布 在画布上添加标题 在画布上添加黑色游戏区 Part 2: 放置静态的蛇:一个头.两个身体 加上开始 ...

  3. Android快乐贪吃蛇游戏实战项目开发教程-01项目概述与目录

    一.项目简介 贪吃蛇是一个很经典的游戏,也很适合用来学习.本教程将和大家一起做一个Android版的贪吃蛇游戏. 我已经将做好的案例上传到了应用宝,无病毒.无广告,大家可以放心下载下来把玩一下.应用宝 ...

  4. WebGL实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  5. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  6. H5实现的可自定义贪吃蛇游戏

    原创游戏,使用lufylegend.js开发 用canvas实现的贪吃蛇游戏,与一般的贪吃蛇游戏不同,图片经过美工设计,代码设计支持扩展和自定义. 游戏元素丰富,包括障碍物(仙人掌),金币(奖励),苹 ...

  7. Qt 学习之路 2(32):贪吃蛇游戏(2)

    Qt 学习之路 2(32):贪吃蛇游戏(2) 豆子 2012年12月27日 Qt 学习之路 2 55条评论 下面我们继续上一章的内容.在上一章中,我们已经完成了地图的设计,当然是相当简单的.在我们的游 ...

  8. Qt 学习之路 2(31):贪吃蛇游戏(1)

    Qt 学习之路 2(31):贪吃蛇游戏(1) 豆子 2012年12月18日 Qt 学习之路 2 41条评论 经过前面一段时间的学习,我们已经了解到有关 Qt 相当多的知识.现在,我们将把前面所讲过的知 ...

  9. 基于React的贪吃蛇游戏的设计与实现

    代码地址如下:http://www.demodashi.com/demo/11818.html 贪吃蛇小游戏(第二版) 一年半前层用react写过贪吃蛇小游戏https://github.com/ca ...

随机推荐

  1. HDU 4268 Alice and Bob(贪心+Multiset的应用)

     题意: Alice和Bob有n个长方形,有长度和宽度,一个矩形能够覆盖还有一个矩形的条件的是,本身长度大于等于还有一个矩形,且宽度大于等于还有一个矩形.矩形不可旋转.问你Alice最多能覆盖Bo ...

  2. hdu4870 Rating (高斯消元或者dp)

    Rating Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  3. jQuery取得循环列表的第一列值

    有例如以下的表格: <table class="list_tab" id="personalDetail"> <tr class=" ...

  4. c2

    #include <stdio.h> int main() { // 整型常量 ; // 实型常量(小数) // 单精度float / 双精度double // 注意: 默认情况下编写的小 ...

  5. 0x17 二叉堆

    优先队列太好用了手写啥呀 poj1456 经过贪心专题的洗礼以后这题根本就不叫题啊...按时间大到小排每次取最大就好 #include<cstdio> #include<iostre ...

  6. 2.Matlab数值数组及其运算

    2.1引导 2.2一维数组的创建与寻访 2.3二维数组的创建 2.4二维数组元素的标识 2.5二维数组的子数组寻访和赋值 2.6执行数组运算的常用函数 2.7数组运算和矩阵运算 2.8多项式的表达和创 ...

  7. pyCrypto python 3.5--转

    原文地址:https://gxnotes.com/article/198426.html 问题描述 我发现一些PyCrypto安装程序为Python 3.3和3.4,但没有任何Python 3.5. ...

  8. 洛谷P3358 最长k可重区间集问题(费用流)

    题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重 ...

  9. Photoshop保存文件时的选项

    以 JPEG 格式存储 您可以使用"存储为"命令以 JPEG (*.jpg) 格式存储 CMYK.RGB 和灰度图像.JPEG 通过有选择地扔掉数据来压缩文件大小.也可以使用&qu ...

  10. deploy springboot to tomcat

    1    在 Eclipse 中建立新的web项目[ABC],之后 转成Maven项目. 2   创建 class   Application 3  修改POM 4  修改web.xml 5  exp ...