quick cocos2d-x重写消灭星星
2015-08-09 12:14
447 查看
之前学习过c++在cocos2d-x游戏引擎上实现的消灭星星游戏,为了熟悉quickcocos2d-x以及Lua语言,我使用2.1.4版本的quickcocos2d-x重写了消灭星星,不过只是实现了其基本的消除,移动,计分以及过关等功能,一些文字漂移、粒子特效等功能有待以后完善。
该游戏的界面非常简单,只有两个场景的切换,首先是一个开始场景,该场景下有一个背景图片以及一个按钮,点击该按钮可以进入到游戏场景界面。开始场景的主要实现代码如下:
其中菜单按钮用table来实现,在Lua语言中没有其他的数据结构,只有table,利用table可以实现各种数据结构,下面讲解星星的消除算法的时候会详细介绍,这里的按钮事件是game.enterGameScene(),这是在game文件中实现的一个函数,用于进入游戏场景,在game文件中game被申明为一个全局的table变量,可以在其他的文件中使用。
在游戏场景上面添加了一个层,该层用来实现星星矩阵的初始化显示,分数菜单的显示以及触摸事件。我们先看星星矩阵的初始化:
接下来是实现触摸事件,在触摸事件中要将点中的星星和他周围与他颜色相同的星星消除,这里先用一个table记录选中的相同颜色星星个数,每次点击都要先将其设置为空。并且使用一个table来帮助选出周围与触摸星星颜色相同的星星,当触摸到一个星星后,将该星星插入到该表中,然后遍历它四周的星星是否与该星星相同,相同则插入表中。然后将表中的第一个元素从表中移除,接着对表中的元素进行上述操作,值到表为空为止。这个过程实际上就是利用队列来实现一个广度优先算法。具体代码如下:
在C++的deque容器可以在O(1)的时间复杂度中将队头元素移除,而这里的table.remove的时间复杂度为O(n),不知道是否有更好的
方法实现。当我们得到选中的星星后便可以更新分数,将选中的星星删除同时更新剩余星星的位置。位置的更新主要涉及垂直方向与水平方向。先看垂直方向,当我们删除部分星星时,这些星星上面的星星自然要掉下来,我们用掉下来的星星信息覆盖已删除星星的信息,并且将掉下来的星星信息设为nil。再看水平方向,当有一列的星星全部删除时,我们要求该列右边的星星能自动向左移动,实现过程与垂直方向类似,源代码如下:
星星的位置信息通过上述代码得到更新,我们通过设置Update事件,在每帧中更新星星的位置,为了有一个移动的效果,我们不是直接使用setPostion到目的位置,而是使用一个速度参数使其移动到目的位置。
整个游戏的基本代码就这些,代码写的比较乱,有待改进,但还是能跑起来,源代码地址:https://github.com/zhulong890816/xinxin
该游戏的界面非常简单,只有两个场景的切换,首先是一个开始场景,该场景下有一个背景图片以及一个按钮,点击该按钮可以进入到游戏场景界面。开始场景的主要实现代码如下:
functionMainScene:ctor() self.bg=display.newSprite("bg_menuscene.jpg",display.cx,display.cy) self:addChild(self.bg) localitem={} item[1]=ui.newImageMenuItem({image="menu_start.png",imageSelected="menu_start.png", listener=function() game.enterGameScene()end,x=display.cx,y=display.cy}) localmenu=ui.newMenu(item) self:addChild(menu) end
其中菜单按钮用table来实现,在Lua语言中没有其他的数据结构,只有table,利用table可以实现各种数据结构,下面讲解星星的消除算法的时候会详细介绍,这里的按钮事件是game.enterGameScene(),这是在game文件中实现的一个函数,用于进入游戏场景,在game文件中game被申明为一个全局的table变量,可以在其他的文件中使用。
在游戏场景上面添加了一个层,该层用来实现星星矩阵的初始化显示,分数菜单的显示以及触摸事件。我们先看星星矩阵的初始化:
localSTAR_RES_LIST={"blue.png","green.png", "orange.png","red.png","purple.png"} functionMatrixStar:initMatrix() --[[self.STAR[i][j]是一个表,其中i表示星星矩阵的行,j表示列,它包含四个元素 self.STAR[i][j][1]表示星星精灵 self.STAR[i][j][2]表示该精灵的颜色 self.STAR[i][j][3]表示该精灵是否被选中 self.STAR[i][j][4]表示该精灵的x轴坐标 self.STAR[i][j][5]表示该精灵的y轴坐标 ]] math.randomseed(os.time()) forrow=1,ROWdo localy=(row-1)*STAR_HEIGHT+STAR_HEIGHT/2 self.STAR[row]={} forcol=1,COLdo self.STAR[row][col]={} localx=(col-1)*STAR_WIDTH+STAR_WIDTH/2 locali=math.random(1,5) localstar=display.newSprite(STAR_RES_LIST[i]) self.STAR[row][col][1]=star self.STAR[row][col][2]=i self.STAR[row][col][3]=false star:setPosition(x,y) self.STAR[row][col][4]=x self.STAR[row][col][5]=y self:addChild(star) end end end
这里利用随机函数,在for循环中生成了不同颜色的星星精灵表STAR_RES_LIST记录了六种颜色的星星精灵,使用表self.STAR[i][j] 记录了每一个星星的颜色、位置、是否被选中,这些信息用于后面对星星的消除算法,在C++中我们可以使用一个结构体来定义这些变量,而 Lua中使用的是table.分数的菜单使用了3个Label对象来实现的,分别记录了最高分数,目标分数以及当前分数,并且通过设置TAG来方便 以后对该Label对象实现分数更新。
HSCORETAG=100 LEVELTAG=101 CSCORETAG=102 functionMatrixStar:setLabel(Hscore,Level,Goal,Cscore) localHscoreUI=ui.newTTFLabel({ text=string.format("HighestScore:%s",tostring(Hscore)), x,y=display.left,display.top, }) HscoreUI:setScale(SCALE) HscoreUI:setPosition(display.right,display.cy) HscoreUI:setPosition(display.cx,display.top-SCALE*HscoreUI:getContentSize().height) self:addChild(HscoreUI) HscoreUI:setTag(HSCORETAG) localLevelUI=ui.newTTFLabel({ text=string.format("Level:%s".."".."Goal:%s",tostring(Level),tostring(Goal)), x,y=display.left,display.top, }) LevelUI:setScale(SCALE) LevelUI:setPosition(display.cx,display.top-SCALE*(HscoreUI:getContentSize().height+ LevelUI:getContentSize().height)) self:addChild(LevelUI) LevelUI:setTag(LEVELTAG) localCscoreUI=ui.newTTFLabel({ text=string.format("CurrentScore:%s",tostring(Cscore)), x,y=display.left,display.top, }) CscoreUI:setScale(SCALE) CscoreUI:setPosition(display.cx,display.top-SCALE*(HscoreUI:getContentSize().height+ LevelUI:getContentSize().height+CscoreUI:getContentSize().height)) self:addChild(CscoreUI) CscoreUI:setTag(CSCORETAG) end
接下来是实现触摸事件,在触摸事件中要将点中的星星和他周围与他颜色相同的星星消除,这里先用一个table记录选中的相同颜色星星个数,每次点击都要先将其设置为空。并且使用一个table来帮助选出周围与触摸星星颜色相同的星星,当触摸到一个星星后,将该星星插入到该表中,然后遍历它四周的星星是否与该星星相同,相同则插入表中。然后将表中的第一个元素从表中移除,接着对表中的元素进行上述操作,值到表为空为止。这个过程实际上就是利用队列来实现一个广度优先算法。具体代码如下:
localtravel={}--当作一个队列使用,用于选出周围与触摸星星颜色相同的星星 ifself.STAR[i][j][1]==nilthen return end table.insert(travel,{self.STAR[i][j][1],i,j}) while#travel~=0do ifi+1<=ROWandself.STAR[i][j][3]~=trueand self.STAR[i][j][2]==self.STAR[i+1][j][2]then table.insert(travel,{self.STAR[i+1][j][1],i+1,j}) end ifi-1>=1andself.STAR[i][j][3]~=trueand self.STAR[i][j][2]==self.STAR[i-1][j][2]then table.insert(travel,{self.STAR[i-1][j][1],i-1,j}) end ifj+1<=COLandself.STAR[i][j][3]~=trueand self.STAR[i][j][2]==self.STAR[i][j+1][2]then table.insert(travel,{self.STAR[i][j+1][1],i,j+1}) end ifj-1>=1andself.STAR[i][j][3]~=trueand self.STAR[i][j][2]==self.STAR[i][j-1][2]then table.insert(travel,{self.STAR[i][j-1][1],i,j-1}) end ifself.STAR[i][j][3]~=truethen self.STAR[i][j][3]=true table.insert(self.SELECT_STAR,{self.STAR[i][j][1],i,j}) end table.remove(travel,1)--table没有类似双向队列的功能直接删除第一个元素 if#travel~=0then i,j=travel[1][2],travel[1][3]--取出表的第一个元素 end end
在C++的deque容器可以在O(1)的时间复杂度中将队头元素移除,而这里的table.remove的时间复杂度为O(n),不知道是否有更好的
方法实现。当我们得到选中的星星后便可以更新分数,将选中的星星删除同时更新剩余星星的位置。位置的更新主要涉及垂直方向与水平方向。先看垂直方向,当我们删除部分星星时,这些星星上面的星星自然要掉下来,我们用掉下来的星星信息覆盖已删除星星的信息,并且将掉下来的星星信息设为nil。再看水平方向,当有一列的星星全部删除时,我们要求该列右边的星星能自动向左移动,实现过程与垂直方向类似,源代码如下:
functionMatrixStar:UpdateMatrix() fori=1,ROWdo forj=1,COLdo ifself.STAR[i][j][1]==nilthen localup=i localdis=0 whileself.STAR[up][j][1]==nildo dis=dis+1 up=up+1 if(up>ROW)then break end end forbegin_i=i+dis,ROWdo ifself.STAR[begin_i][j][1]~=nilthen self.STAR[begin_i-dis][j][1]=self.STAR[begin_i][j][1] self.STAR[begin_i-dis][j][2]=self.STAR[begin_i][j][2] self.STAR[begin_i-dis][j][3]=self.STAR[begin_i][j][3] localx=(j-1)*STAR_WIDTH+STAR_WIDTH/2 localy=(begin_i-dis-1)*STAR_HEIGHT+STAR_HEIGHT/2 self.STAR[begin_i-dis][j][4]=x self.STAR[begin_i-dis][j][5]=y self.STAR[begin_i][j][1]=nil self.STAR[begin_i][j][2]=nil self.STAR[begin_i][j][3]=nil self.STAR[begin_i][j][4]=nil self.STAR[begin_i][j][5]=nil end end end end end forj=1,COLdo ifself.STAR[1][j][1]==nilthen localdes=0 localright=j whileself.STAR[1][right][1]==nildo des=des+1 right=right+1 ifright>COLthen break end end forbegin_i=ROW,1,-1do forbegin_j=j+des,COLdo ifself.STAR[begin_i][begin_j][1]~=nilthen self.STAR[begin_i][begin_j-des][1]=self.STAR[begin_i][begin_j][1] self.STAR[begin_i][begin_j-des][2]=self.STAR[begin_i][begin_j][2] self.STAR[begin_i][begin_j-des][3]=self.STAR[begin_i][begin_j][3] localx=(begin_j-des-1)*STAR_WIDTH+STAR_WIDTH/2 localy=(begin_i-1)*STAR_HEIGHT+STAR_HEIGHT/2 self.STAR[begin_i][begin_j-des][4]=x self.STAR[begin_i][begin_j-des][5]=y self.STAR[begin_i][begin_j][1]=nil self.STAR[begin_i][begin_j][2]=nil self.STAR[begin_i][begin_j][3]=nil self.STAR[begin_i][begin_j][4]=nil self.STAR[begin_i][begin_j][5]=nil end end end end end end
星星的位置信息通过上述代码得到更新,我们通过设置Update事件,在每帧中更新星星的位置,为了有一个移动的效果,我们不是直接使用setPostion到目的位置,而是使用一个速度参数使其移动到目的位置。
functionMatrixStar:updatePos(posX,posY,i,j) ifposY~=self.STAR[i][j][5]then self.STAR[i][j][1]:setPositionY(self.STAR[i][j][5]-MOVESPEED) ifself.STAR[i][j][1]:getPositionY()<self.STAR[i][j][5]then self.STAR[i][j][1]:setPositionY(self.STAR[i][j][5]) localx,y=self.STAR[i][j][1]:getPosition() end end ifposX~=self.STAR[i][j][4]then self.STAR[i][j][1]:setPositionX(self.STAR[i][j][4]-MOVESPEED) ifself.STAR[i][j][1]:getPositionX()<self.STAR[i][j][4]then self.STAR[i][j][1]:setPositionX(self.STAR[i][j][4]) end end end
整个游戏的基本代码就这些,代码写的比较乱,有待改进,但还是能跑起来,源代码地址:
相关文章推荐
- cocos2dx tableview的实际应用
- Cocos2d-x学习笔记(五)—— 常见UI界面(未完全)
- cocos2dx-3.0(13)------SpriteBatchNode与SpriteFrameCache加快渲染
- cocos2dx3.6实现打字效果
- cocos2d-x综述(源自cocos2d-x中文网)
- Cocos2D游戏之旅(四):卡牌翻转效果的实现(下)
- cocos2dx-屏幕设置
- cocos2dx-粒子特效
- cocos2dx-音乐音效
- cocos2dx-多点触控
- cocos2dx-触屏事件
- cocos2dx-33种场景切换
- cocos2dx-24种基本特效
- cocos2dx-基本动画制作
- cocos2dx-CCScrollView的制作
- 【Cocos2d入门教程二】Cocos2d-x基础篇
- cocos2dx-Action动作
- cocos2dx-cpptest的结构
- cocos2d-x CCScale9Sprite实例
- Cocos2d-x学习笔记(四)—— 内存管理