1. 程式人生 > >Cocos2d-X引擎+Lua語言俄羅斯方塊的製作及基本邏輯編寫(上)

Cocos2d-X引擎+Lua語言俄羅斯方塊的製作及基本邏輯編寫(上)

一、遊戲區域準備

①首先解決格子到最終螢幕位置的轉換問題。

開啟src->app目錄下新建一個Common.lua檔案。用notepad++開啟,編碼格式轉為UTF-8無編碼格式。下面為Common.lua具體程式碼

cGridSize = 32 --每個方塊是32個畫素

cScenWidth = 8 + 2  --場景的寬度,單位是格子,

cScenHeight = 18 --場景的高度,

function Grid2Pos(x,y)  --把格子轉成最終渲染的位置函式

   local visibleSize = cc.Direct:getInstance():getVisibleSize()

   local
origin = cc.Director:getInstance():getVisibleOrigin() local finalX = origin.x + visibleSize.width*0.5 + x*cGridSize - cScenWidth/2*cGridSize local finalY = origin.y + visibleSize.height*0.5 + y*cGridSize - cScenHeight/2*cGridSize return finalX,finalY end

②遊戲場景

同樣開啟src->app目錄下新建一個Scene.lua檔案。用notepad++開啟,編碼格式轉為UTF-8無編碼格式。下面為Scene.lua具體程式碼

require "app.Common" x,y

-- 8 * 18

local Scene = class("Scene")

local function makeKey(x,y) 
return x*1000 + y
end

function Scene:ctor(node) --Scene的建構函式

  self.map = {}

  for x = 0,cSceneWidth -1 do

    for y = 0,cSceneHight -1 do

       local posX,posY = Grid2Pos(x,y) 
       local sp = cc.Sprite:create
("box.png") --沒有圖片 sp:setPosition(posX,posY) node:addChild(sp) local visible = (x == 0 or x==cSceneWidth-1)or y==0 sp:setVisible(visible) self.map[makeKey(x,y)]=sp --一維陣列通過製造key,把它變成線性的座標 end end end function Scene:ClearLine(y) for x = 1,cSceneWidth -2 do self:Set(x,y,false) end end function Scene:Clear() for y = 1,cSceneHight - 1 do self:ClearLine(y) end end function Scene:Set(x,y,value) local sp = self.map[makeKey(x,y)] if sp == nil then return end sp:setVisible(value) end function Scene:Get(x,y) local sp = self.map[makeKey(x,y)] if sp == nil then return end return sp:isVisible() end

③主邏輯場景

引用之前寫好的Scene


local Scene = require "app.Scene"

local MainScene = class("MainScene",function()
    return display.newScene("Scene")
end)

function MainScene():ctor

end

function MainScene:onEnter()

   self.scene = Scene.new(self)

end

function MainScene:onExit()

end

return MainScene

④資料化方塊

搭建好了遊戲場景,現在開始資料化方塊。俄羅斯方塊有很多形狀,每個形狀還會旋轉。這裡我們用一個4*4的陣列,正好以(2,2)這個點旋轉。
舉以下兩個例子。(其他的自己完善~)這裡我們設定一個變數innitoffset,因為其他型方塊第一行都是有1的,如果把方塊放在底部的時候它會吸住底部,直線型方塊第一行是空白的,為了讓它不那麼怪異,就讓它這個方塊偏轉一下吸住底部。後面的邏輯就是操作這一堆資料。

local cBlockArray = {
  {
     initoffset =1,
    {
      {1,1,1,0}, --1表示有,0表示有 
      {0,1,0,0},-- ***
      {0,0,0,0},--  *
      {0,0,0,0},    
    },

    {
      {0,1,0,0}, --1表示有,0表示有
      {1,1,0,0},-- *
      {0,1,0,0},--**
      {0,0,0,0},-- *
    },
 }

⑤方塊變形

申明方塊類

local Block = class("Block")

每個方塊的初始偏移整個螢幕寬度的一半-3

local InitXOffset = cSceneWidth/2 - 3

編寫Block的建構函式,傳入scene,index是選哪個方塊

function Block:ctor(scene,index)  

  self.x = InitXOffset
  self.y = cSceneHeight

  local offset = cBlockArray[index].initOffset

  if offset then
    self.y = self.y + offset --lua 無自加符
  end

  self.scene = scene
  self.index = index
  self.trans = 1

end

遍歷方塊函式

local function IterateBlock(index,trans,callback) 

local transArray = cBlockArray[index] --取一種形狀
local eachBlock = transArray[trans] --變化

for y=1,#eachBlock do

 local xdata = eachBlock[y]

for x=1,#data do  --# 字串取長度,table取數量

  local data = xdata[x]

  if not callback(x,y,data~=0)then 
  return false
  end

end

end

return true
end 

放置方塊到遊戲場景

function RawPlace(index,trans,scene,newX,newY) --放置方塊到遊戲場景

  local result = {}

  if IterateBlock(index,trans,function(x,y,b))

     if b then

        local finalX = newX + x
        local finalY = newY - y

        if scene:Get(finalX,finalY)then --在場景中找能否放這個方塊,如果不能就返回false
           return false
        end

        table.insert(result,{x=finalX,y=finalY})

    end

    return true
  end )then

  for k,v in ipairs(result) do
     scene:Set(v.x,v.y,true)
  end

  return true

end

方塊移動

function Block:Move(deltaX,deltaY) --方塊移動

    self:Clear()

    local x = self.x + deltaX
    local y = self.y + deltaY

    if RawPlace(self.index,self.trans,self.scene,x,y) then
       self.x = x
       self.y = y
       return true

    else
      self.Place()
      return false

    end

end

方塊變形–旋轉

function Block:Rotate() --方塊變形,旋轉

  local offset = cBlockArray[self.index].initOffset --剔除不符合條件
  if offset and self.y == 0 then
    return
  end

  self.Clear()

  local transArray = cBlockArray[self.index]

  local trans = self.trans + 1

  if trans >#transArray then 
    trans = 1
  end

  if RawPlace(self.index,trans,self.scene,self.x,self.y)then
     self.trans = trans

  else
    self:Place()
  end

end

把方塊直接放上去

function Block:Place()

   return RawPlace(self.index,self.trans,self.scene,self.x,self.y)

end  

function Block:Clear()

  IterateBlock(self.index,self.trans,function(x,y,b))
    local finalX = self.x + x
    local finalY = self.y +    if b then
      self.scene:Set(finalX,finalY,false)
   end

   ren true
   end)

end

調節解析度,寬960,高640,固定高

CC_DESIGN_RESOLUTION = {
    width = 960,
    height = 640,
    autoscale = "FIXED_HEIGHT",
    callback = function(framesize)
        local ratio = framesize.width / framesize.height
        if ratio <= 1.34 then
            -- iPad 768*1024(1536*2048) is 4:3 screen
            return {autoscale = "FIXED_WIDTH"}
        end
    end
}

(注:因為實驗室專案開發,本人也還在學習中,本文為imooc徐波老師課程筆記)