Cocos2d-X引擎+Lua語言俄羅斯方塊的製作及基本邏輯編寫(上)
阿新 • • 發佈:2019-02-13
一、遊戲區域準備
①首先解決格子到最終螢幕位置的轉換問題。
開啟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
}