zoukankan      html  css  js  c++  java
  • quick cocos2d-x重写消灭星星

        之前学习过c++在cocos2d-x游戏引擎上实现的消灭星星游戏,为了熟悉quick cocos2d-x以及Lua语言,我使用2.1.4版本的quick cocos2d-x重写了消灭星星,不过只是实现了其基本的消除,移动,计分以及过关等功能,一些文字漂移、粒子特效等功能有待以后完善。

        该游戏的界面非常简单,只有两个场景的切换,首先是一个开始场景,该场景下有一个背景图片以及一个按钮,点击该按钮可以进入到游戏场景界面。开始场景的主要实现代码如下:

     1 function MainScene:ctor()
     2     self.bg = display.newSprite("bg_menuscene.jpg", display.cx,display.cy)
     3     self:addChild(self.bg)
     4     local item ={}
     5     item[1]= ui.newImageMenuItem({image = "menu_start.png", imageSelected = "menu_start.png",
     6         listener = function()  
     7         game.enterGameScene() end , x = display.cx, y = display.cy})
     8     local menu = ui.newMenu(item)
     9     self:addChild(menu)
    10 end

    其中菜单按钮用table来实现,在Lua语言中没有其他的数据结构,只有table,利用table可以实现各种数据结构,下面讲解星星的消除算法的时候会详细介绍,这里的按钮事件是game.enterGameScene(),这是在game文件中实现的一个函数,用于进入游戏场景,在game文件中game被申明为一个全局的table变量,可以在其他的文件中使用。

       在游戏场景上面添加了一个层,该层用来实现星星矩阵的初始化显示,分数菜单的显示以及触摸事件。我们先看星星矩阵的初始化:

     1 local STAR_RES_LIST = {"blue.png","green.png",
     2 "orange.png","red.png","purple.png"}
     3 
     4 function MatrixStar:initMatrix()  
     5     --[[self.STAR[i][j]是一个表,其中i表示星星矩阵的行,j表示列,它包含四个元素
     6         self.STAR[i][j][1]表示星星精灵
     7         self.STAR[i][j][2]表示该精灵的颜色 
     8         self.STAR[i][j][3]表示该精灵是否被选中
     9         self.STAR[i][j][4]表示该精灵的x轴坐标
    10         self.STAR[i][j][5]表示该精灵的y轴坐标           
    11         ]]
    12     math.randomseed(os.time())    
    13     for row = 1, ROW do
    14         local y = (row-1) * STAR_HEIGHT + STAR_HEIGHT/2
    15         self.STAR[row] = {}
    16         for col = 1, COL do
    17             self.STAR[row][col] = {}
    18             local x = (col-1) * STAR_WIDTH + STAR_WIDTH/2
    19             local i=math.random(1,5)
    20             local star = display.newSprite(STAR_RES_LIST[i])
    21             self.STAR[row][col][1] = star
    22             self.STAR[row][col][2] = i
    23             self.STAR[row][col][3] = false
    24             star:setPosition(x,y)
    25             self.STAR[row][col][4] = x
    26             self.STAR[row][col][5] = y
    27             self:addChild(star)
    28         end
    29     end
    30 end
    这里利用随机函数,在for循环中生成了不同颜色的星星精灵表 STAR_RES_LIST记录了六种颜色的星星精灵,使用表self.STAR[i][j]
    记录了每一个星星的颜色、位置、是否被选中,这些信息用于后面对星星的消除算法,在C++中我们可以使用一个结构体来定义这些变量,而
    Lua中使用的是table. 分数的菜单使用了3个Label对象来实现的,分别记录了最高分数,目标分数以及当前分数,并且通过设置TAG来方便
    以后对该Label对象实现分数更新。
     1 HSCORETAG = 100
     2 LEVELTAG = 101
     3 CSCORETAG = 102
     4 
     5 function MatrixStar:setLabel(Hscore,Level,Goal,Cscore)
     6     local HscoreUI = ui.newTTFLabel({
     7         text = string.format("HighestScore: %s", tostring(Hscore)),
     8         x, y = display.left, display.top, 
     9     })
    10     HscoreUI:setScale(SCALE)
    11     HscoreUI:setPosition(display.right, display.cy)
    12     HscoreUI:setPosition(display.cx, display.top - SCALE * HscoreUI:getContentSize().height)
    13     self:addChild(HscoreUI)
    14     HscoreUI:setTag(HSCORETAG)
    15 
    16     local LevelUI = ui.newTTFLabel({
    17         text = string.format("Level: %s".." ".."Goal: %s", tostring(Level),tostring(Goal)),
    18         x, y = display.left, display.top, 
    19     })
    20     LevelUI:setScale(SCALE)
    21     LevelUI:setPosition(display.cx, display.top - SCALE * (HscoreUI:getContentSize().height + 
    22             LevelUI:getContentSize().height))
    23     self:addChild(LevelUI)
    24     LevelUI:setTag(LEVELTAG)
    25 
    26     local CscoreUI = ui.newTTFLabel({
    27         text = string.format("CurrentScore: %s", tostring(Cscore)),
    28         x, y = display.left, display.top, 
    29     })
    30     CscoreUI:setScale(SCALE)
    31     CscoreUI:setPosition(display.cx, display.top - SCALE * (HscoreUI:getContentSize().height + 
    32             LevelUI:getContentSize().height + CscoreUI:getContentSize().height))
    33     self:addChild(CscoreUI)
    34     CscoreUI:setTag(CSCORETAG)
    35 end

    接下来是实现触摸事件,在触摸事件中要将点中的星星和他周围与他颜色相同的星星消除,这里先用一个table记录选中的相同颜色星星个数,每次点击都要先将其设置为空。并且使用一个table来帮助选出周围与触摸星星颜色相同的星星,当触摸到一个星星后,将该星星插入到该表中,然后遍历它四周的星星是否与该星星相同,相同则插入表中。然后将表中的第一个元素从表中移除,接着对表中的元素进行上述操作,值到表为空为止。这个过程实际上就是利用队列来实现一个广度优先算法。具体代码如下:

     1     local travel = {}  --当作一个队列使用,用于选出周围与触摸星星颜色相同的星星
     2     if self.STAR[i][j][1] == nil then
     3         return
     4     end 
     5 
     6     table.insert(travel, {self.STAR[i][j][1], i, j})
     7     while #travel ~= 0 do
     8         if i + 1 <= ROW and self.STAR[i][j][3] ~= true and 
     9             self.STAR[i][j][2] == self.STAR[i + 1][j][2] then
    10             table.insert(travel, {self.STAR[i+1][j][1],i+1,j})
    11         end
    12 
    13         if i-1 >= 1 and self.STAR[i][j][3] ~= true and
    14             self.STAR[i][j][2] ==self.STAR[i-1][j][2] then
    15             table.insert(travel, {self.STAR[i-1][j][1],i-1,j})
    16         end
    17 
    18         if j+1 <= COL and self.STAR[i][j][3] ~= true and
    19             self.STAR[i][j][2] ==self.STAR[i][j+1][2] then
    20             table.insert(travel, {self.STAR[i][j+1][1],i,j+1}) 
    21         end
    22 
    23         if j-1 >= 1 and self.STAR[i][j][3] ~= true and
    24             self.STAR[i][j][2] ==self.STAR[i][j-1][2] then
    25             table.insert(travel, {self.STAR[i][j-1][1],i,j-1})
    26         end
    27         
    28         if self.STAR[i][j][3] ~= true then
    29            self.STAR[i][j][3] = true
    30            table.insert(self.SELECT_STAR,{self.STAR[i][j][1],i,j})
    31         end
    32 
    33         table.remove(travel,1)  --table没有类似双向队列的功能直接删除第一个元素
    34         if #travel ~= 0 then 
    35             i, j = travel[1][2], travel[1][3] --取出表的第一个元素
    36         end  
    37     end

     在C++的deque容器可以在O(1)的时间复杂度中将队头元素移除,而这里的table.remove的时间复杂度为O(n),不知道是否有更好的

     方法实现。当我们得到选中的星星后便可以更新分数,将选中的星星删除同时更新剩余星星的位置。位置的更新主要涉及垂直方向与水平方向。先看垂直方向,当我们删除部分星星时,这些星星上面的星星自然要掉下来,我们用掉下来的星星信息覆盖已删除星星的信息,并且将掉下来的星星信息设为nil。再看水平方向,当有一列的星星全部删除时,我们要求该列右边的星星能自动向左移动,实现过程与垂直方向类似,源代码如下:

     1 function MatrixStar:UpdateMatrix()
     2     for i = 1, ROW do
     3         for j = 1,COL do
     4             if self.STAR[i][j][1] == nil then 
     5                 local up = i
     6                 local dis = 0
     7                 while self.STAR[up][j][1] == nil do
     8                     dis = dis + 1
     9                     up = up + 1
    10                     if(up>ROW) then
    11                         break
    12                     end
    13                 end
    14 
    15                 for begin_i = i + dis, ROW do
    16                     if self.STAR[begin_i][j][1]~=nil then 
    17                         self.STAR[begin_i-dis][j][1]=self.STAR[begin_i][j][1]
    18                         self.STAR[begin_i-dis][j][2]=self.STAR[begin_i][j][2]
    19                         self.STAR[begin_i-dis][j][3]=self.STAR[begin_i][j][3]
    20                         local x = (j-1)*STAR_WIDTH + STAR_WIDTH/2  
    21                         local y = (begin_i-dis-1)*STAR_HEIGHT + STAR_HEIGHT/2 
    22                         self.STAR[begin_i-dis][j][4] = x
    23                         self.STAR[begin_i-dis][j][5] = y
    24                         self.STAR[begin_i][j][1] = nil
    25                         self.STAR[begin_i][j][2] = nil
    26                         self.STAR[begin_i][j][3] = nil
    27                         self.STAR[begin_i][j][4] = nil
    28                         self.STAR[begin_i][j][5] = nil
    29                     end
    30                 end
    31             end
    32         end
    33     end
    34 
    35     for j = 1, COL do
    36         if self.STAR[1][j][1] == nil then
    37             local des = 0 
    38             local right = j
    39             while self.STAR[1][right][1] == nil do
    40                 des = des + 1
    41                 right = right + 1
    42                 if right>COL then
    43                     break
    44                 end
    45             end
    46             for begin_i = ROW, 1,-1 do
    47                 for begin_j = j + des, COL do 
    48                     if self.STAR[begin_i][begin_j][1] ~= nil then
    49                         self.STAR[begin_i][begin_j-des][1]=self.STAR[begin_i][begin_j][1]
    50                         self.STAR[begin_i][begin_j-des][2]=self.STAR[begin_i][begin_j][2]
    51                         self.STAR[begin_i][begin_j-des][3]=self.STAR[begin_i][begin_j][3]
    52                         local x = (begin_j-des-1)*STAR_WIDTH + STAR_WIDTH/2  
    53                         local y = (begin_i-1)*STAR_HEIGHT + STAR_HEIGHT/2 
    54                         self.STAR[begin_i][begin_j-des][4] = x
    55                         self.STAR[begin_i][begin_j-des][5] = y
    56                         self.STAR[begin_i][begin_j][1] = nil
    57                         self.STAR[begin_i][begin_j][2] = nil
    58                         self.STAR[begin_i][begin_j][3] = nil
    59                         self.STAR[begin_i][begin_j][4] = nil
    60                         self.STAR[begin_i][begin_j][5] = nil
    61                     end
    62                 end
    63             end
    64         end
    65     end
    66 end

    星星的位置信息通过上述代码得到更新,我们通过设置Update事件,在每帧中更新星星的位置,为了有一个移动的效果,我们不是直接使用setPostion到目的位置,而是使用一个速度参数使其移动到目的位置。

     1 function MatrixStar:updatePos(posX,posY,i,j)
     2     if posY ~= self.STAR[i][j][5] then
     3         self.STAR[i][j][1]:setPositionY(self.STAR[i][j][5] - MOVESPEED)
     4         if self.STAR[i][j][1]:getPositionY() < self.STAR[i][j][5]  then
     5              self.STAR[i][j][1]:setPositionY(self.STAR[i][j][5])
     6              local x, y = self.STAR[i][j][1]:getPosition()
     7         end
     8     end
     9 
    10     if posX ~= self.STAR[i][j][4] then
    11         self.STAR[i][j][1]:setPositionX(self.STAR[i][j][4] - MOVESPEED)
    12         if self.STAR[i][j][1]:getPositionX() < self.STAR[i][j][4]  then
    13              self.STAR[i][j][1]:setPositionX(self.STAR[i][j][4])
    14         end
    15     end
    16 end

    整个游戏的基本代码就这些,代码写的比较乱,有待改进,但还是能跑起来,源代码地址:https://github.com/zhulong890816/xinxin

     
  • 相关阅读:
    js localtion.href 数据传输
    java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver 找不到jar包的问题,路径问题
    java 深度拷贝 复制 深度复制
    解决java在对MySQL插入数据时出现乱码问题
    python最大最小距离算法贴近度评价法
    java 连接数据库报错:Caused by: com.mysql.cj.exceptions.InvalidConnectionAttributeException: The server time zone value '
    java map 转 json 自编封装
    java 连接MySQL的代码
    在前端发起ajax遇到问题
    java map转json servlet response
  • 原文地址:https://www.cnblogs.com/zhulong890816/p/4688966.html
Copyright © 2011-2022 走看看