很多时候在学习或者尝试做游戏的时候总是会无疾而终,现在把自己的收获和做出来的示例记下来给自己一个督促吧。

平台环境: cocos2dx(3.8)+lua vs2012

关于三消游戏的认识

基础的三消游戏是在一个二维空间上,放置不同的元素,通过滑动消除相邻的几个相同元素,来获得积分或过关。当然完整的上线项目会有很多玩法,像是一次消除多个会产生一个炸弹,或者地图上有各种的障碍,甚至有的游戏像best friends是通过连接临近相同元素来进行消除。

期望的效果

这次的一个小尝试期望做出的效果只是在一个二维的空间中,随机几种不同颜色的元素进行填充,接受玩家的滑动操作,能够检测相邻三个以上的相同元素进行消除,并且判断当无法有滑动消除的情况时,会随机交换几个元素的位置重新继续。暂时不包含其他的玩法。

系统设计

需要的对象

  1. 二维界面中的元素,我命名为对象SXBlock,本身存储有所处的行和列,拥有一个sprite,并且实现了sprite需要的各个动画效果;
  2. 游戏世界,在cocos2dx中我以一个layer实现,存储了二维的数组存储所有SXBlock,同时监听玩家的输入,控制游戏状态的转换,同时游戏的大部分算法都在这里实现。

游戏中的各个状态

我把整个三消流程分为四个状态:

  1. 填充:当二维数组有空位时,其他的元素往下移,同时从上方随机出新的元素掉落进行填充。
  2. 检测是否满足消除条件并消除。
  3. 接受玩家输入,并表现输入动画:只有在此状态下玩家的操作才有效果。
  4. 检测是否无法再消除,是的话随机交换几个元素的位置。

状态之间的转换如下图示:

算法需求

在实现过程中,考虑到的一些核心的算法总共有三个:

1. 当前玩家滑动操作是否有效

根据玩家输入获得的两个相邻元素,判断交换位置后是否能够达到消除条件,lua代码实现如下:

function UIMainLayer:FunGetRowSameBlocks( row, col )local ltabBlocks = {}local block = self:FunGetBlock( row, col )if not block then return {} endtable.insert( ltabBlocks, block )for i = col - 1, 1, -1 doif block:FunSameType( self:FunGetBlock( row, i ) ) thentable.insert( ltabBlocks, self:FunGetBlock( row, i ) )elsebreakendendfor i = col + 1, NUM_COL doif block:FunSameType( self:FunGetBlock( row, i ) ) thentable.insert( ltabBlocks, self:FunGetBlock( row, i ) )elsebreakendendreturn ltabBlocks
endfunction UIMainLayer:FunGetColSameBlocks( row, col )local ltabBlocks = {}local block = self:FunGetBlock( row, col )if not block then return {} endtable.insert( ltabBlocks, block )for i = row - 1, 1, -1 doif block:FunSameType( self:FunGetBlock( i, col ) ) thentable.insert( ltabBlocks, self:FunGetBlock( i, col ) )elsebreakendendfor i = row + 1, NUM_ROW doif block:FunSameType( self:FunGetBlock( i, col ) ) thentable.insert( ltabBlocks, self:FunGetBlock( i, col ) )elsebreakendendreturn ltabBlocks
end-- 判断local ltabRowSame1 = self:FunGetRowSameBlocks( block1.mvarRow, block1.mvarCol )local ltabRowSame2 = self:FunGetRowSameBlocks( block2.mvarRow, block2.mvarCol )local ltabColSame1 = self:FunGetColSameBlocks( block1.mvarRow, block1.mvarCol )local ltabColSame2 = self:FunGetColSameBlocks( block2.mvarRow, block2.mvarCol )if #ltabRowSame1 >= 3 or #ltabRowSame2 >= 3 or #ltabColSame1 >= 3 or #ltabColSame2 >= 3 then-- 达到条件可以交换else-- 未达到end

2. 空间填满元素后是否结束,即无法再消除;

符合的条件如下所示,当如下相邻位置元素类型一样时,可以消除

判断逻辑如下:

function UIMainLayer:FunCheckIsFixCon3R2C( row, col )-- 5 6-- 3 4-- 1 2local ltabType = {}for r = row, row + 2 dofor c = col, col + 1 dotable.insert( ltabType, self:FunGetBlock( r, c ):FunGetType() )endendif not (ltabType[1] == ltabType[3] and ltabType[1] == ltabType[6]) thenif not (ltabType[1] == ltabType[4] and ltabType[1] == ltabType[5]) thenif not (ltabType[2] == ltabType[3] and ltabType[2] == ltabType[5]) thenif not (ltabType[1] == ltabType[4] and ltabType[1] == ltabType[6]) thenif not (ltabType[2] == ltabType[3] and ltabType[2] == ltabType[6]) thenif not (ltabType[2] == ltabType[4] and ltabType[2] == ltabType[5]) thenreturn falseendendendendendendreturn true
endfunction UIMainLayer:FunCheckIsFixCon2R3C( row, col )-- 4  5  6-- 1  2  3local ltabType = {}for r = row, row + 1 dofor c = col, col + 2 dotable.insert( ltabType, self:FunGetBlock( r, c ):FunGetType() )endendif not (ltabType[3] == ltabType[4] and ltabType[3] == ltabType[5]) thenif not (ltabType[2] == ltabType[4] and ltabType[2] == ltabType[6]) thenif not (ltabType[1] == ltabType[5] and ltabType[1] == ltabType[6]) thenif not (ltabType[2] == ltabType[3] and ltabType[2] == ltabType[4]) thenif not (ltabType[1] == ltabType[3] and ltabType[1] == ltabType[5]) thenif not (ltabType[1] == ltabType[2] and ltabType[1] == ltabType[6]) thenreturn falseendendendendendendreturn true
endfunction UIMainLayer:FunCheckIsEnd()for r = 1, NUM_ROW - 2 dofor c = 1, NUM_COL - 1 doif self:FunCheckIsFixCon3R2C( r, c ) thenreturn falseendendendfor r = 1, NUM_ROW - 1 dofor c = 1, NUM_COL - 2 doif self:FunCheckIsFixCon2R3C( r, c ) thenreturn falseendendendreturn true
end

3. 无法消除时,随机交换几个元素位置达能够继续消除。

代码如下示:

function UIMainLayer:FunGetRandomGroups()local lvarNum = MAX_RANDOM_GROUP_WHEN_END * 2local ltabIndex = {}while(#ltabIndex<lvarNum) dolocal lvarIndex = math.random(1, NUM_ROW*NUM_COL)local lvarIsIn = falsefor k, v in pairs( ltabIndex ) doif v == lvarIndex thenlvarIsIn = truebreakendendif not lvarIsIn thentable.insert( ltabIndex, lvarIndex )endendlocal ltabBlocks = {}for k, v in pairs( ltabIndex ) dotable.insert( ltabBlocks, self.mtabBlocks[math.floor((v-1)/NUM_COL)+1][(v-1)%NUM_COL+1])endreturn ltabBlocks
endfunction UIMainLayer:FunRandomSwap()local function SwapGroup( ltabBlocks, lvarCover )for i = 1, MAX_RANDOM_GROUP_WHEN_END dolocal block1 = ltabBlocks[i*2 - 1]local block2 = ltabBlocks[i*2]self.mtabBlocks[block2.mvarRow][block2.mvarCol] = lvarCover and block2 or block1self.mtabBlocks[block1.mvarRow][block1.mvarCol] = lvarCover and block1 or block2endendlocal ltabRandomBlocks = self:FunGetRandomGroups()SwapGroup( ltabRandomBlocks, false )if not self:FunCheckIsEnd() then-- 交换位置returnelse-- 仍然不符合SwapGroup( ltabRandomBlocks, true ) end
end

总结

这几天的尝试,实现了这个简单的三消demo,但是在玩法上并没有什么乐趣…

还有一个可能出现的问题如果总行,列比较少会造成如何随机都不能消除的bug,导致一直卡在第四个状态。

暂时到这里吧,有进一步完善的话后续添加。

完整的可玩demo和lua代码在此下载 。

cocos2dx 制作一个简单的三消游戏相关推荐

  1. 使用PlayCanvas制作一个简单的小游戏(四)

    原文: 足球 足球是掂球游戏的焦点.它响应玩家的输入,响应环境(如重力),发出声音等.它也许是游戏中最复杂的部分.幸运的是,我们会尽可能的深入浅出. ball.js pc.script.attribu ...

  2. 使用PlayCanvas制作一个简单的小游戏(二)

    原文:http://developer.playcanvas.com/zh/tutorials/beginner/keepyup-part-two/ 设置材质 在这个游戏中,我们尽可能的使用了简单的图 ...

  3. 使用PlayCanvas制作一个简单的小游戏(一)

    我们使用PlayCanvas做了一个"掂球"的小游戏,在这个小游戏中玩家需要点击落下的足球使之停留在空中. 本教程包含如下主题: 1 场景(Scene)和层级(Hierarchy) ...

  4. 使用PlayCanvas制作一个简单的小游戏(三)

    原文:http://developer.playcanvas.com/zh/tutorials/beginner/keepyup-part-three/ 游戏脚本和输入 在场景的根实体Game上绑定了 ...

  5. 用turtle库制作一个简单的小游戏《鸡子大战篮球》

    刚上大学,学习python不到两月半,连简单的字典.元组数据类型都还没有捂熟.这不刚好python小组作业是用turtle库画自己喜欢的图案吗,在我们小组的努力下我们画好了5只小只因,于是我就大胆的进 ...

  6. Java制作一个简单地小游戏

    package 代码部分; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import jav ...

  7. 如何使用cocos2d-x 3.0来做一个简单的iphone游戏教程(第一部分)

    游戏截图: cocos2d-x 是一个支持多平台的开源框架,用于构建游戏.应用程序和其他图形界面交互应用.Cocos2d-x项目可以很容易地建立和运行在iOS,Android的三星Bada,黑莓Bla ...

  8. 如何制作一个基于Tile的游戏 2 Cocos2d-x 2 0 4

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 在第一篇 ...

  9. Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)

    懒骨头(http://blog.csdn.net/iamlazybone  QQ124774397 青岛 ) 或许有天 我们羡慕和崇拜的人 因为我们的努力 也会来了解我们 说不定 还会成为好友 骨头喜 ...

  10. Cocos2dx游戏开发系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)...

    2019独角兽企业重金招聘Python工程师标准>>> 或许有天 我们羡慕和崇拜的人 因为我们的努力 也会来了解我们 说不定 还会成为好友 骨头喜欢这样与哲哲共勉 多少个夜晚 一张长 ...

最新文章

  1. 三类常见软件质量(Quality Attribute)属性的通俗解释
  2. 第一篇T语言实例开发(版本5.3),带错误检测的加减乘除运算器
  3. 批处理停止php服务,通过批处理启动和停止MSSQL+IIS
  4. 在C#中利用DirectX实现声音播放
  5. python_基础知识回顾总结
  6. css3中的transform,渐变,rgba
  7. UOJRoundPLUS+
  8. 酒店预订管理小系统c语言,酒店管理系统有些问题,求c语言大佬帮忙
  9. UWB定位系统场景的分析
  10. 三极管工作原理_PNP型三极管基础知识解析
  11. 汇总了25个FPGA开源网站和前10大FPGA论坛
  12. 使用计算机拍摄 制作电视和电影,视频制作毕业论文: 影视制作
  13. python求极限中有算术平方根如何表达_Python求算数平方根和约数的方法汇总
  14. 使用excel进行数据挖掘(4)---- 突出显示异常值
  15. 模型基础——模型与材质
  16. 爱快ikuai软路由远程维护用户名
  17. 小程序中商家入驻提醒、新订单提醒
  18. Python 编辑器哪个好用
  19. 简单教你贴-iPhone新一代超薄卡贴
  20. Lytro光场相机的原理,科普,简单地进行了解

热门文章

  1. 常见蛋白质种类_蛋白粉有哪些种类?都有什么作用?常见的6种蛋白粉
  2. 海外观看2022卡塔尔世界杯中文直播攻略大全
  3. python统计元音字母个数_python统计并输出字符串中小写元音字母的个数?
  4. nuvoton ADC采集
  5. 百度服务器状态异常,百度抓取异常连接超时是什么意思
  6. 数据清洗第六章—课后操作题
  7. C#里的InputBox
  8. 【C语言】之实现大小写字母转换
  9. Spring Cloud Alibaba Sentinel(七)受权规则 黑白名单
  10. R中五种常用的统计分析方法