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

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

效果是这样的:

代码如下:


      FruitItem = import("app.scenes.FruitItem")
      local PlayScene = class("PlayScene", function()
      	return display.newScene("PlayScene")
      end)
      function PlayScene:ctor()
      	-- init value
      	self.highSorce = 0 -- 最高分数
      	self.stage = 1 -- 当前关卡
      	self.target = 123 -- 通关分数
      	self.curSorce = 0 -- 当前分数
      	self.xCount = 8 -- 水平方向水果数
      	self.yCount = 8 -- 垂直方向水果数
      	self.fruitGap = 0 -- 水果间距
      	self.scoreStart = 5 -- 水果基分
      	self.scoreStep = 10 -- 加成分数
      	self.activeScore = 0 -- 当前高亮的水果得分
      	self:initUI()
      	-- 初始化随机数
      	math.newrandomseed()
      	--  计算水果矩阵左下角的x、y坐标:以矩阵中点对齐屏幕中点来计算,然后再做Y轴修正。
      	self.matrixLBX = (display.width - FruitItem.getWidth() * self.xCount - (self.yCount - 1) * self.fruitGap) / 2
      	self.matrixLBY = (display.height - FruitItem.getWidth() * self.yCount - (self.xCount - 1) * self.fruitGap) / 2 - 30
      	-- 等待转场特效结束后再加载矩阵
      	self:addNodeEventListener(cc.NODE_EVENT, function(event)
      		if event.name == "enterTransitionFinish" then
      			self:initMartix()
      		end
      	end)
      end
      function PlayScene:initUI()
      	-- 背景图片
      	display.newSprite("playBG.png")
      		:pos(display.cx, display.cy)
      		:addTo(self)
      	-- high sorce
      	display.newSprite("#high_score.png")
      		:align(display.LEFT_CENTER, display.left + 15, display.top - 30)
      		:addTo(self)
      	display.newSprite("#highscore_part.png")
      		:align(display.LEFT_CENTER, display.cx + 10, display.top - 26)
      		:addTo(self)
      	self.highSorceLabel = display.newTTFLabel({text = tostring(self.highSorce), font = "font/earth38"})
      		:align(display.CENTER, display.cx + 105, display.top - 24)
      		:addTo(self)
      	-- 声音
      	display.newSprite("#sound.png")
      		:align(display.CENTER, display.right - 60, display.top - 30)
      		:addTo(self)
      		-- stage
      	display.newSprite("#stage.png")
      		:align(display.LEFT_CENTER, display.left + 15, display.top - 80)
      		:addTo(self)
      	display.newSprite("#stage_part.png")
      		:align(display.LEFT_CENTER, display.left + 170, display.top - 80)
      		:addTo(self)
      	self.highStageLabel = display.newTTFLabel({text = tostring(self.stage), font = "font/earth32"})
      		:align(display.CENTER, display.left + 214, display.top - 78)
              :addTo(self)
      	-- target
      	display.newSprite("#tarcet.png")
      		:align(display.LEFT_CENTER, display.cx - 50, display.top - 80)
      		:addTo(self)
      	display.newSprite("#tarcet_part.png")
      		:align(display.LEFT_CENTER, display.cx + 130, display.top - 78)
      		:addTo(self)
      	self.highTargetLabel = display.newTTFLabel({text = tostring(self.target), font = "font/earth32"})
      		:align(display.CENTER, display.cx + 195, display.top - 76)
              :addTo(self)
      	-- current sorce
      	display.newSprite("#score_now.png")
      		:align(display.CENTER, display.cx, display.top - 150)
      		:addTo(self)
      	self.curSorceLabel = display.newTTFLabel({Utext = tostring(self.curSorce), font = "font/earth48"})
      		:align(display.CENTER, display.cx, display.top - 150)
              :addTo(self)
      	-- 选中水果分数
      	self.activeScoreLabel = display.newTTFLabel({text = "", size = 30})
      		:pos(display.width / 2, 120)
      		:addTo(self)
      	self.activeScoreLabel:setColor(display.COLOR_WHITE)
      end
      function PlayScene:initMartix()
      	-- 创建空矩阵
      	self.matrix = {}
      	-- 高亮水果
      	self.actives = {}
      	for y = 1, self.yCount do
      		for x = 1, self.xCount do
      			if 1 == y and 2 == x then
                      -- 确保有可消除的水果
                      self:createAndDropFruit(x, y, self.matrix[1].fruitIndex)
                  else
                      self:createAndDropFruit(x, y)
      			end
      		end
      	end
      end
      function PlayScene:createAndDropFruit(x, y, fruitIndex)
          local newFruit = FruitItem.new(x, y, fruitIndex)
          local endPosition = self:positionOfFruit(x, y)
          local startPosition = cc.p(endPosition.x, endPosition.y + display.height / 2)
          newFruit:setPosition(startPosition)
          local speed = startPosition.y / (2 * display.height)
          newFruit:runAction(cc.MoveTo:create(speed, endPosition))
          self.matrix[(y - 1) * self.xCount + x] = newFruit
          self:addChild(newFruit)
      	-- 绑定触摸事件,此处3.7框架与3.6不太一样了 需要先绑定,后激活节点
      	newFruit:addNodeEventListener(cc.NODE_TOUCH_EVENT, function(event)
      		print( event.name)
      		if event.name == "ended" then
      			if newFruit.isActive then
      				print("remove")
      				self:removeActivedFruits()
      				self:dropFruits()
      			else
      				self:inactive()
      				self:activeNeighbor(newFruit)
      				self:showActivesScore()
      			end
      		end
      		if event.name == "began" then
      			if newFruit.isActive then
      				print("remove")
      				self:removeActivedFruits()
      				self:dropFruits()
      			else
      				self:inactive()
      				self:activeNeighbor(newFruit)
      				self:showActivesScore()
      			end
      			return true
      		end
      	end)
      	newFruit:setTouchEnabled(true)
      end
      function PlayScene:removeActivedFruits()
      	local fruitScore = self.scoreStart
      	for _, fruit in pairs(self.actives) do
      		if (fruit) then
      			-- 从矩阵中移除
      			self.matrix[(fruit.y - 1) * self.xCount + fruit.x] = nil
      			-- 分数特效
      			self:scorePopupEffect(fruitScore, fruit:getPosition())
      			fruitScore = fruitScore + self.scoreStep
      			fruit:removeFromParent()
      		end
      	end
      	-- 清空高亮数组
      	self.actives = {}
      	-- 更新当前得分
      	self.curSorce = self.curSorce + self.activeScore
      	self.curSorceLabel:setString(tostring(self.curSorce))
      	-- 清空高亮水果分数统计
      	self.activeScoreLabel:setString("")
      	self.activeScore = 0
      end
      function PlayScene:scorePopupEffect(score, px, py)
      	print(scorePopupEffect)
      	local labelScore = display.newTTFLabel({ text = tostring(score), font = "font/earth32"})
      	local move = cc.MoveBy:create(0.8, cc.p(0, 80))
      	local fadeOut = cc.FadeOut:create(0.8)
      	local action = cc.Sequence:create(
      		cc.Spawn:create(move,fadeOut),
      		-- 动画结束移除 Label
      		cc.CallFunc:create(function() labelScore:removeFromParent() end)
      	)
      	labelScore:pos(px, py)
      		:addTo(self)
      		:runAction(action)
      end
      function PlayScene:dropFruits()
      	local emptyInfo = {}
      	-- 1. 掉落已存在的水果
      	-- 一列一列的处理
      	for x = 1, self.xCount do
      		local removedFruits = 0
      		local newY = 0
      		-- 从下往上处理
      		for y = 1, self.yCount do
      			local temp = self.matrix[(y - 1) * self.xCount + x]
      			if temp == nil then
      				-- 水果已被移除
      				removedFruits = removedFruits + 1
      			else
      				-- 如果水果下有空缺,向下移动空缺个位置
      				if removedFruits > 0 then
      					newY = y - removedFruits
      					self.matrix[(newY - 1) * self.xCount + x] = temp
      					temp.y = newY
      					self.matrix[(y - 1) * self.xCount + x] = nil
      					local endPosition = self:positionOfFruit(x, newY)
      					local speed = (temp:getPositionY() - endPosition.y) / display.height
      					temp:stopAllActions() --停止之前的动画
      					temp:runAction(cc.MoveTo:create(speed, endPosition))
      				end
      			end
      		end
      		-- 纪录本列最终空缺数
      		emptyInfo[x] = removedFruits
      	end
      	-- 2. 掉落新水果补齐空缺
      	for x = 1, self.xCount do
      		for y = self.yCount - emptyInfo[x] + 1, self.yCount do
      			self:createAndDropFruit(x, y)
      		end
      	end
      end
      function PlayScene:positionOfFruit(x, y)
          local px = self.matrixLBX + (FruitItem.getWidth() + self.fruitGap) * (x - 1) + FruitItem.getWidth() / 2
          local py = self.matrixLBY + (FruitItem.getWidth() + self.fruitGap) * (y - 1) + FruitItem.getWidth() / 2
          return cc.p(px, py)
      end
      function PlayScene:activeNeighbor(fruit)
      	-- 高亮fruit
      	if false == fruit.isActive then
      		fruit:setActive(true)
      		table.insert(self.actives, fruit)
      	end
      	-- 检查fruit左边的水果
      	if (fruit.x - 1) >= 1 then
      		local leftNeighbor = self.matrix[(fruit.y - 1) * self.xCount + fruit.x - 1]
      		if (leftNeighbor.isActive == false) and (leftNeighbor.fruitIndex == fruit.fruitIndex) then
      			leftNeighbor:setActive(true)
      			table.insert(self.actives, leftNeighbor)
      			self:activeNeighbor(leftNeighbor)
      		end
      	end
      	-- 检查fruit右边的水果
      	if (fruit.x + 1) <= self.xCount then
      		local rightNeighbor = self.matrix[(fruit.y - 1) * self.xCount + fruit.x + 1]
      		if (rightNeighbor.isActive == false) and (rightNeighbor.fruitIndex == fruit.fruitIndex) then
      			rightNeighbor:setActive(true)
      			table.insert(self.actives, rightNeighbor)
      			self:activeNeighbor(rightNeighbor)
      		end
      	end
      	-- 检查fruit上边的水果
      	if (fruit.y + 1) <= self.yCount then
      		local upNeighbor = self.matrix[fruit.y * self.xCount + fruit.x]
      		if (upNeighbor.isActive == false) and (upNeighbor.fruitIndex == fruit.fruitIndex) then
      			upNeighbor:setActive(true)
      			table.insert(self.actives, upNeighbor)
      			self:activeNeighbor(upNeighbor)
      		end
      	end
      	-- 检查fruit下边的水果
      	if (fruit.y - 1) >= 1 then
      		local downNeighbor = self.matrix[(fruit.y - 2) * self.xCount + fruit.x]
      		if (downNeighbor.isActive == false) and (downNeighbor.fruitIndex == fruit.fruitIndex) then
      			downNeighbor:setActive(true)
      			table.insert(self.actives, downNeighbor)
      			self:activeNeighbor(downNeighbor)
      		end
      	end
      end
      function PlayScene:inactive()
          for _, fruit in pairs(self.actives) do
              if (fruit) then
                  fruit:setActive(false)
              end
          end
      	self.actives = {}
      end
      function PlayScene:showActivesScore()
      	-- 只有一个高亮,取消高亮并返回
      	if 1 == #self.actives then
      		self:inactive()
      		self.activeScoreLabel:setString("")
      		self.activeScore = 0
      		return
      	end
      	-- 水果分数依次为5、15、25、35... ,求它们的和
      	self.activeScore = (self.scoreStart * 2 + self.scoreStep * (#self.actives - 1)) * #self.actives / 2
      	self.activeScoreLabel:setString(string.format("%d 连消,得分 %d", #self.actives, self.activeScore))
      end
      function PlayScene:onEnter()
      end
      function PlayScene:onExit()
      end
      return PlayScene
  
 

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

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

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

作者其他文章

评论(0

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

    全部回复

    上滑加载中

    设置昵称

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

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

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