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

 
时间: 2024-10-11 21:22:52

quick cocos2d-x重写消灭星星的相关文章

Cocos2d JS 之消灭星星(九) 处理星星类之——移动和消灭星星

1 /* 2 * 本层拥有处理星星的实例化以及对星星的操作 3 * 1/排列星星 4 * 2/移动和删除星星 5 */ 6 var GameStarLayout = ccui.Layout.extend( 7 { 8 size:null, 9 starArr:[],//存放点击与被点击状态的星星资源 10 starObjArr:[],//存放游戏中星星的二位数组 11 firstTouchStar:null,//第一次选择的星星,用于判断两次选择的星星颜色是否一致 12 isSelected:f

Cocos2d JS 之消灭星星(六) 创建星星类

1 /* 2 * 创建星星类(所有的星星都在这里创建,星星拥有的所有性都在这里实现) 3 */ 4 var GameCreateStar = ccui.ImageView.extend( 5 { 6 type:0,//星星的类型(不同数字代表不同颜色的星星); 7 isSelected:false,//是否选中 8 col:null,//水平方向排列位置(0-9) 9 row:null,//竖直方向排列位置(0-9) 10 normal:null,//通常状态图片纹理 11 selected:n

Cocos2d JS 之消灭星星(七) 处理星星类之——排列星星

1 /* 2 * 本层拥有处理星星的实例化以及对星星的操作 3 */ 4 var GameStarLayout = ccui.Layout.extend( 5 { 6 size:null, 7 starArr:[],//存放点击与被点击状态的星星资源 8 starObjArr:[],//存放游戏中星星的二位数组 9 ctor:function() 10 { 11 this._super(); 12 this.zinit(); 13 this.layoutStar(); 14 }, 15 //将星

Cocos2d JS 之消灭星星(五) 游戏主场景

1 /* 2 * 游戏主场景 3 */ 4 var GameMainScene = ccui.Layout.extend( 5 { 6 ctor:function() 7 { 8 this._super(); 9 this.zinit(); 10 this.setTopInfor(); 11 this.addStarLayout(); 12 }, 13 //游戏主场景顶部显示信息 14 setTopInfor:function() 15 { 16 var gameTopInfo = new Ga

Cocos2d JS 之消灭星星(十) 关卡配置

关卡配置,包括每个关卡的通关分数和当前关卡的星星数量 1 /* 2 * 关卡配置 3 * 每一关的通过分数和星星数量配置档 4 */ 5 var levelData = 6 [ 7 {level:1, standards:1000, starNumber:4}, 8 {level:2, standards:3000, starNumber:4}, 9 {level:3, standards:5000, starNumber:4}, 10 {level:4, standards:7000, sta

Cocos2d JS 之消灭星星(三) 进入游戏过渡场景

1 /* 2 * 游戏过渡场景,主要作用是在每次进入游戏或者进入下一关卡时进行过渡,显示当前的关卡以及通过该关卡要达到的分数; 3 */ 4 var TransitionScene = ccui.Layout.extend( 5 { 6 size:null, 7 ctor:function() 8 { 9 this._super(); 10 this.zinit(); 11 this.setLabel(); 12 this.gotoGameMainScene(); 13 }, 14 //设置显示

Cocos2d JS 之消灭星星(四) 游戏主场景顶部显示

1 /* 2 * 游戏主场景顶部显示信息 3 */ 4 var GameTopInformation = ccui.Layout.extend( 5 { 6 size:null, 7 isPause:false,//是否暂停游戏 8 maxScoreLabel:null,//最高纪录 9 getScoreNum:null,//当前得分 10 currentLevel:null,//当前关卡 11 ctor:function() 12 { 13 this._super(); 14 this.zin

Cocos2d JS 之消灭星星(十一) 本地保存玩家信息

当玩家退去游戏后,下次进入游戏可以接着上一次的游戏进度继续游戏; 1 /* 2 * win7下本地存储玩家的数据 3 */ 4 var PlayerLocalData = {}; 5 /* 6 * 玩家数据结构 7 */ 8 var playerData = function() 9 { 10 var playerD = [ 11 { 12 currentLevel:1, //玩家关卡 13 gameScore:0, //游戏得分 14 maxScore:0 //游戏最高得分 15 }]; 16

Cocos2d JS 之消灭星星(十二) 游戏帮助

前面游戏的各个部分都完善了,游戏共一百关,后面还有使用粒子系统的部分,给游戏添加特效:写得有点粗糙 1 /* 2 * @游戏帮助说明 3 */ 4 var GameHelpLayout = ccui.Layout.extend( 5 { 6 ctor:function() 7 { 8 this._super(); 9 this.zinit(); 10 this.setBackButton(); 11 }, 12 //还回按钮 13 setBackButton:function() 14 { 15