cocos2d-lua消除游戏实战(二)水果生成算法和消除算法

举报
鱼酱 发表于 2022/01/07 00:24:10 2022/01/07
【摘要】   效果是这样的: 代码如下:     FruitItem = import("app.scenes.FruitItem") local PlayScene = class("PlayScene", function() return display.newScene("PlayScene")...

 

效果是这样的:

代码如下:

 

 


  
  1. FruitItem = import("app.scenes.FruitItem")
  2. local PlayScene = class("PlayScene", function()
  3. return display.newScene("PlayScene")
  4. end)
  5. function PlayScene:ctor()
  6. -- init value
  7. self.highSorce = 0 -- 最高分数
  8. self.stage = 1 -- 当前关卡
  9. self.target = 123 -- 通关分数
  10. self.curSorce = 0 -- 当前分数
  11. self.xCount = 8 -- 水平方向水果数
  12. self.yCount = 8 -- 垂直方向水果数
  13. self.fruitGap = 0 -- 水果间距
  14. self.scoreStart = 5 -- 水果基分
  15. self.scoreStep = 10 -- 加成分数
  16. self.activeScore = 0 -- 当前高亮的水果得分
  17. self:initUI()
  18. -- 初始化随机数
  19. math.newrandomseed()
  20. -- 计算水果矩阵左下角的x、y坐标:以矩阵中点对齐屏幕中点来计算,然后再做Y轴修正。
  21. self.matrixLBX = (display.width - FruitItem.getWidth() * self.xCount - (self.yCount - 1) * self.fruitGap) / 2
  22. self.matrixLBY = (display.height - FruitItem.getWidth() * self.yCount - (self.xCount - 1) * self.fruitGap) / 2 - 30
  23. -- 等待转场特效结束后再加载矩阵
  24. self:addNodeEventListener(cc.NODE_EVENT, function(event)
  25. if event.name == "enterTransitionFinish" then
  26. self:initMartix()
  27. end
  28. end)
  29. end
  30. function PlayScene:initUI()
  31. -- 背景图片
  32. display.newSprite("playBG.png")
  33. :pos(display.cx, display.cy)
  34. :addTo(self)
  35. -- high sorce
  36. display.newSprite("#high_score.png")
  37. :align(display.LEFT_CENTER, display.left + 15, display.top - 30)
  38. :addTo(self)
  39. display.newSprite("#highscore_part.png")
  40. :align(display.LEFT_CENTER, display.cx + 10, display.top - 26)
  41. :addTo(self)
  42. self.highSorceLabel = display.newTTFLabel({text = tostring(self.highSorce), font = "font/earth38"})
  43. :align(display.CENTER, display.cx + 105, display.top - 24)
  44. :addTo(self)
  45. -- 声音
  46. display.newSprite("#sound.png")
  47. :align(display.CENTER, display.right - 60, display.top - 30)
  48. :addTo(self)
  49. -- stage
  50. display.newSprite("#stage.png")
  51. :align(display.LEFT_CENTER, display.left + 15, display.top - 80)
  52. :addTo(self)
  53. display.newSprite("#stage_part.png")
  54. :align(display.LEFT_CENTER, display.left + 170, display.top - 80)
  55. :addTo(self)
  56. self.highStageLabel = display.newTTFLabel({text = tostring(self.stage), font = "font/earth32"})
  57. :align(display.CENTER, display.left + 214, display.top - 78)
  58. :addTo(self)
  59. -- target
  60. display.newSprite("#tarcet.png")
  61. :align(display.LEFT_CENTER, display.cx - 50, display.top - 80)
  62. :addTo(self)
  63. display.newSprite("#tarcet_part.png")
  64. :align(display.LEFT_CENTER, display.cx + 130, display.top - 78)
  65. :addTo(self)
  66. self.highTargetLabel = display.newTTFLabel({text = tostring(self.target), font = "font/earth32"})
  67. :align(display.CENTER, display.cx + 195, display.top - 76)
  68. :addTo(self)
  69. -- current sorce
  70. display.newSprite("#score_now.png")
  71. :align(display.CENTER, display.cx, display.top - 150)
  72. :addTo(self)
  73. self.curSorceLabel = display.newTTFLabel({Utext = tostring(self.curSorce), font = "font/earth48"})
  74. :align(display.CENTER, display.cx, display.top - 150)
  75. :addTo(self)
  76. -- 选中水果分数
  77. self.activeScoreLabel = display.newTTFLabel({text = "", size = 30})
  78. :pos(display.width / 2, 120)
  79. :addTo(self)
  80. self.activeScoreLabel:setColor(display.COLOR_WHITE)
  81. end
  82. function PlayScene:initMartix()
  83. -- 创建空矩阵
  84. self.matrix = {}
  85. -- 高亮水果
  86. self.actives = {}
  87. for y = 1, self.yCount do
  88. for x = 1, self.xCount do
  89. if 1 == y and 2 == x then
  90. -- 确保有可消除的水果
  91. self:createAndDropFruit(x, y, self.matrix[1].fruitIndex)
  92. else
  93. self:createAndDropFruit(x, y)
  94. end
  95. end
  96. end
  97. end
  98. function PlayScene:createAndDropFruit(x, y, fruitIndex)
  99. local newFruit = FruitItem.new(x, y, fruitIndex)
  100. local endPosition = self:positionOfFruit(x, y)
  101. local startPosition = cc.p(endPosition.x, endPosition.y + display.height / 2)
  102. newFruit:setPosition(startPosition)
  103. local speed = startPosition.y / (2 * display.height)
  104. newFruit:runAction(cc.MoveTo:create(speed, endPosition))
  105. self.matrix[(y - 1) * self.xCount + x] = newFruit
  106. self:addChild(newFruit)
  107. -- 绑定触摸事件,此处3.7框架与3.6不太一样了 需要先绑定,后激活节点
  108. newFruit:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
  109. print( event.name)
  110. if event.name == "ended" then
  111. if newFruit.isActive then
  112. print("remove")
  113. self:removeActivedFruits()
  114. self:dropFruits()
  115. else
  116. self:inactive()
  117. self:activeNeighbor(newFruit)
  118. self:showActivesScore()
  119. end
  120. end
  121. if event.name == "began" then
  122. if newFruit.isActive then
  123. print("remove")
  124. self:removeActivedFruits()
  125. self:dropFruits()
  126. else
  127. self:inactive()
  128. self:activeNeighbor(newFruit)
  129. self:showActivesScore()
  130. end
  131. return true
  132. end
  133. end)
  134. newFruit:setTouchEnabled(true)
  135. end
  136. function PlayScene:removeActivedFruits()
  137. local fruitScore = self.scoreStart
  138. for _, fruit in pairs(self.actives) do
  139. if (fruit) then
  140. -- 从矩阵中移除
  141. self.matrix[(fruit.y - 1) * self.xCount + fruit.x] = nil
  142. -- 分数特效
  143. self:scorePopupEffect(fruitScore, fruit:getPosition())
  144. fruitScore = fruitScore + self.scoreStep
  145. fruit:removeFromParent()
  146. end
  147. end
  148. -- 清空高亮数组
  149. self.actives = {}
  150. -- 更新当前得分
  151. self.curSorce = self.curSorce + self.activeScore
  152. self.curSorceLabel:setString(tostring(self.curSorce))
  153. -- 清空高亮水果分数统计
  154. self.activeScoreLabel:setString("")
  155. self.activeScore = 0
  156. end
  157. function PlayScene:scorePopupEffect(score, px, py)
  158. print(scorePopupEffect)
  159. local labelScore = display.newTTFLabel({ text = tostring(score), font = "font/earth32"})
  160. local move = cc.MoveBy:create(0.8, cc.p(0, 80))
  161. local fadeOut = cc.FadeOut:create(0.8)
  162. local action = cc.Sequence:create(
  163. cc.Spawn:create(move,fadeOut),
  164. -- 动画结束移除 Label
  165. cc.CallFunc:create(function() labelScore:removeFromParent() end)
  166. )
  167. labelScore:pos(px, py)
  168. :addTo(self)
  169. :runAction(action)
  170. end
  171. function PlayScene:dropFruits()
  172. local emptyInfo = {}
  173. -- 1. 掉落已存在的水果
  174. -- 一列一列的处理
  175. for x = 1, self.xCount do
  176. local removedFruits = 0
  177. local newY = 0
  178. -- 从下往上处理
  179. for y = 1, self.yCount do
  180. local temp = self.matrix[(y - 1) * self.xCount + x]
  181. if temp == nil then
  182. -- 水果已被移除
  183. removedFruits = removedFruits + 1
  184. else
  185. -- 如果水果下有空缺,向下移动空缺个位置
  186. if removedFruits > 0 then
  187. newY = y - removedFruits
  188. self.matrix[(newY - 1) * self.xCount + x] = temp
  189. temp.y = newY
  190. self.matrix[(y - 1) * self.xCount + x] = nil
  191. local endPosition = self:positionOfFruit(x, newY)
  192. local speed = (temp:getPositionY() - endPosition.y) / display.height
  193. temp:stopAllActions() --停止之前的动画
  194. temp:runAction(cc.MoveTo:create(speed, endPosition))
  195. end
  196. end
  197. end
  198. -- 纪录本列最终空缺数
  199. emptyInfo[x] = removedFruits
  200. end
  201. -- 2. 掉落新水果补齐空缺
  202. for x = 1, self.xCount do
  203. for y = self.yCount - emptyInfo[x] + 1, self.yCount do
  204. self:createAndDropFruit(x, y)
  205. end
  206. end
  207. end
  208. function PlayScene:positionOfFruit(x, y)
  209. local px = self.matrixLBX + (FruitItem.getWidth() + self.fruitGap) * (x - 1) + FruitItem.getWidth() / 2
  210. local py = self.matrixLBY + (FruitItem.getWidth() + self.fruitGap) * (y - 1) + FruitItem.getWidth() / 2
  211. return cc.p(px, py)
  212. end
  213. function PlayScene:activeNeighbor(fruit)
  214. -- 高亮fruit
  215. if false == fruit.isActive then
  216. fruit:setActive(true)
  217. table.insert(self.actives, fruit)
  218. end
  219. -- 检查fruit左边的水果
  220. if (fruit.x - 1) >= 1 then
  221. local leftNeighbor = self.matrix[(fruit.y - 1) * self.xCount + fruit.x - 1]
  222. if (leftNeighbor.isActive == false) and (leftNeighbor.fruitIndex == fruit.fruitIndex) then
  223. leftNeighbor:setActive(true)
  224. table.insert(self.actives, leftNeighbor)
  225. self:activeNeighbor(leftNeighbor)
  226. end
  227. end
  228. -- 检查fruit右边的水果
  229. if (fruit.x + 1) <= self.xCount then
  230. local rightNeighbor = self.matrix[(fruit.y - 1) * self.xCount + fruit.x + 1]
  231. if (rightNeighbor.isActive == false) and (rightNeighbor.fruitIndex == fruit.fruitIndex) then
  232. rightNeighbor:setActive(true)
  233. table.insert(self.actives, rightNeighbor)
  234. self:activeNeighbor(rightNeighbor)
  235. end
  236. end
  237. -- 检查fruit上边的水果
  238. if (fruit.y + 1) <= self.yCount then
  239. local upNeighbor = self.matrix[fruit.y * self.xCount + fruit.x]
  240. if (upNeighbor.isActive == false) and (upNeighbor.fruitIndex == fruit.fruitIndex) then
  241. upNeighbor:setActive(true)
  242. table.insert(self.actives, upNeighbor)
  243. self:activeNeighbor(upNeighbor)
  244. end
  245. end
  246. -- 检查fruit下边的水果
  247. if (fruit.y - 1) >= 1 then
  248. local downNeighbor = self.matrix[(fruit.y - 2) * self.xCount + fruit.x]
  249. if (downNeighbor.isActive == false) and (downNeighbor.fruitIndex == fruit.fruitIndex) then
  250. downNeighbor:setActive(true)
  251. table.insert(self.actives, downNeighbor)
  252. self:activeNeighbor(downNeighbor)
  253. end
  254. end
  255. end
  256. function PlayScene:inactive()
  257. for _, fruit in pairs(self.actives) do
  258. if (fruit) then
  259. fruit:setActive(false)
  260. end
  261. end
  262. self.actives = {}
  263. end
  264. function PlayScene:showActivesScore()
  265. -- 只有一个高亮,取消高亮并返回
  266. if 1 == #self.actives then
  267. self:inactive()
  268. self.activeScoreLabel:setString("")
  269. self.activeScore = 0
  270. return
  271. end
  272. -- 水果分数依次为5、15、25、35... ,求它们的和
  273. self.activeScore = (self.scoreStart * 2 + self.scoreStep * (#self.actives - 1)) * #self.actives / 2
  274. self.activeScoreLabel:setString(string.format("%d 连消,得分 %d", #self.actives, self.activeScore))
  275. end
  276. function PlayScene:onEnter()
  277. end
  278. function PlayScene:onExit()
  279. end
  280. return PlayScene

 

 

 

 

 

文章来源: yujiang.blog.csdn.net,作者:鱼酱2333,版权归原作者所有,如需转载,请联系作者。

原文链接:yujiang.blog.csdn.net/article/details/78705965

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。