Cocos2d-x-Lua 開發簡單的小遊戲(記數字踩白塊)
Cocos2d-x-Lua 開發簡單的小遊戲(記數字踩白塊)
本篇部落格來給大家介紹如何使用Lua這門語言來開發一個簡單的小遊戲—記數字踩白塊。
遊戲的流程是這樣的:在介面上產生5個數1~5字並顯示在隨機的位置上,點擊第一個數字,其他數字會顯示成白塊數字消失,玩家可以通過記住數位顯示的位置點擊按順序消除白塊,直到白塊消除完,遊戲成功。
如下:
先說明一下筆者的開發環境:
- Xcode 5.1(Mac系統下的蘋果開發工具)
- Cocos2d-x 3.1.1(Cocos2d-x遊戲引擎)
- LDT(Lua整合式開發環境)
首先你得建立一個Cocos2d-x項目,裡面會多個平台代碼,具體建立方法麻煩讀者參考筆者前面所寫的文章,如有疑問可以直接留言交流。
來看看我們項目結構:
》》AppDelegate.cpp
#include "AppDelegate.h"#include "CCLuaEngine.h"#include "SimpleAudioEngine.h"#include "cocos2d.h"using namespace CocosDenshion;USING_NS_CC;using namespace std;AppDelegate::AppDelegate(){}AppDelegate::~AppDelegate(){ SimpleAudioEngine::end();}bool AppDelegate::applicationDidFinishLaunching(){ // initialize director auto director = Director::getInstance();auto glview = director->getOpenGLView();if(!glview) { // 建立可視地區,位置(0,0)寬:900,高:640glview = GLView::createWithRect("記數字踩白塊", Rect(0,0,900,640));director->setOpenGLView(glview);} // 設定設計解析度 glview->setDesignResolutionSize(800, 480, ResolutionPolicy::SHOW_ALL); // turn on display FPS // 開啟顯示的FPS director->setDisplayStats(true); // set FPS. the default value is 1.0/60 if you don't call this director->setAnimationInterval(1.0 / 60); auto engine = LuaEngine::getInstance(); ScriptEngineManager::getInstance()->setScriptEngine(engine); // 執行src目錄下的main.lua指令檔 if (engine->executeScriptFile("src/main.lua")) { return false; } return true;}// This function will be called when the app is inactive. When comes a phone call,it's be invoked toovoid AppDelegate::applicationDidEnterBackground(){ Director::getInstance()->stopAnimation(); SimpleAudioEngine::getInstance()->pauseBackgroundMusic();}// this function will be called when the app is active againvoid AppDelegate::applicationWillEnterForeground(){ Director::getInstance()->startAnimation(); SimpleAudioEngine::getInstance()->resumeBackgroundMusic();}
我們主要在Lua檔案中實現我們的邏輯,如何開始呢,首先我們要想象一個情境6*10的方格,一共60個方格,每個方格一個卡片,我們要做的是如何在這60個方格裡放入我們的卡片,並且要隨機放上去的。
我們先定義卡片類》》card.lua
--[[卡片card.lua]]--function card(num) -- 建立一個精靈,代表一張卡片 local self = cc.Sprite:create() local txt,bg -- 卡片文本和背景 --初始化方法 local function init() self.num = num --設定內容尺寸 self:setContentSize( cc.size( 80, 80 ) ) --設定錨點 self:setAnchorPoint( cc.p( 0, 0 ) ) --設定顯示數位文本 txt = cc.Label:create() txt:setString( num ) txt:setSystemFontSize( 50 ) txt:setSystemFontName( "Courier" ) --設定文本顯示的位置,這裡是中間 txt:setPosition( cc.p( self:getContentSize().width / 2, self:getContentSize().height / 2 ) ) --添加到表 self:addChild(txt) --建立一個精靈,代表背景 bg = cc.Sprite:create() --顏色塊 bg:setTextureRect( cc.rect( 0, 0, 80, 80 ) ) --預設為白色,這裡設定為白色 bg:setColor( cc.c3b( 255, 255, 255 ) ) --bg:setPosition( cc.p(0, 0)) --設定錨點 bg:setAnchorPoint( cc.p( 0, 0 ) ) self:addChild(bg) --顯示文本 self:showTxt() end --定義顯示文本的方法 self.showTxt = function() txt:setVisible(true) bg:setVisible(false) end --定義顯示背景的方法 self.showBg = function() txt:setVisible(false) bg:setVisible(true) end init() return selfend
從卡片類我們可以知道,我們需要傳入一個數字,然後對卡片類進行初始化,顯示相應的數字,我們的卡片是一個Sprite(我們所說的精靈),我們要往Sprite添加數字(用Label來顯示),還要添加我們的背景(同樣也是一個Sprite)。
卡片類定義好之後,我們就要實現我們想要的效果了,定義我們的入口》》》main.lua
--[[記數字踩白塊小遊戲2014/6/22main.lua]]-- 引入card.lua檔案require( "src/card" )--主方法function Main() -- 建立一個情境 local self = cc.Scene:create() -- 聲明一個層 local layer local allPoints -- 儲存所有點 local allCards = {} -- 儲存所有卡片 local currentNum -- 當前數字 -- 產生可用點 local function genPoints() allPoints = {} -- 6行*10列 for i = 0, 9 do for j = 0, 5 do -- 插入點到allPoints數組當中 table.insert( allPoints, 1, cc.p( i * 80, j * 80 ) ) end end end -- 添加卡片 local function addCards() -- 設定隨機種子 math.randomseed( os.time() ) local c -- 卡片 local randNum -- 隨機數 local p -- 所在點 -- 添加5張卡片 for var = 1, 5 do c = card( var ) -- 產生一張卡片 layer:addChild( c ) -- 添加到層當中 -- 根據數組最大值產生隨機數 randNum = math.random( table.maxn(allPoints) ) p = table.remove( allPoints, randNum ) c:setPosition( p ) c:setAnchorPoint( cc.p( 0, 0 ) ) print("p.x:"..p.x..",p.y:"..p.y); -- 插入到卡片數組 table.insert( allCards, 1, c ) end end -- 開始遊戲 local function startGame() -- 初始值為1 currentNum = 1 -- 先產生可用點 genPoints() -- 然後添加卡片 addCards() end -- 顯示所有卡片背景 local function showAllCardsBg() for key, var in pairs(allCards) do var:showBg() end end -- 觸摸事件,第一個參數為事件類型,第二個參數為x座標,第二個為y座標 local function onTouch( type, x, y ) -- 根據x,y產生一個點 local p = cc.p(x,y) for key, var in pairs(allCards) do print(var:getPosition()) -- 判斷是否是點擊範圍 local pX,pY = var:getPosition() if (p.x < (pX + 80)) and (p.y < (pY + 80) and (p.x > pX) and (p.y > pY)) then --if var:getBoundingBox():containsPoint(p) then if currentNum == var.num then -- 如果是點擊的數字,則移除卡片 table.remove(allCards, key) layer:removeChild(var, true) -- 點擊了1之後,其他數字翻過背景 if currentNum == 1 then showAllCardsBg() end -- 當所有卡片都被順序點擊了,提示成功 if table.maxn( allCards ) <= 0 then print( "Success" ) end -- 每次增加1 currentNum = currentNum + 1 end end end end -- 初始化方法 local function init() -- 建立一個層 layer = cc.Layer:create() -- 將層添加到情境 self:addChild( layer ) -- 設定可點擊 layer:setTouchEnabled( true ) -- 註冊監聽事件 layer:registerScriptTouchHandler( onTouch ) -- 開始遊戲 startGame() -- self:addChild(layer) -- --測試代碼 -- local s = cc.Sprite:create("res/mn.jpg") -- s:setPosition(cc.p(0,0)) -- s:setAnchorPoint( cc.p( 0, 0 ) ) -- layer:addChild(s) -- -- layer:setTouchEnabled(true) -- layer:registerScriptTouchHandler( function (type,x,y) -- -- if s:getBoundingBox():containsPoint(cc.p(x,y)) then -- print("mn clicked") -- end -- print(type) -- return true -- end ) -- -- self:addChild(layer) end init() return selfend--入口方法local function _main() -- 獲得導演類執行個體 local dir = cc.Director:getInstance() -- 設定不顯示幀 dir:setDisplayStats(false) -- 運行情境 dir:runWithScene(Main())end-- 調用入口方法_main()
以上代碼已經很詳盡,筆者就不多做解釋,主要在這裡提一下,如果使用筆者的開發環境的話,需要注意以下幾個問題:1. XCode不能很好的支援Lua的編輯,所以我們使用LDT來進行編碼,但會遇到XCode運行程式沒有呈現最新效果,這時我們需要對XCode進行Clean,然後再編譯。這個過程很麻煩,筆者正在在尋求其他更好的解決方案。2. 因為Cocos2d-x版本的變化,使用Lua編寫C++邏輯代碼也發生了相應的變化,一些API被新版本拋棄,比如之前CCDirector會以cc.Director的形式呈現。筆者在網上也沒有找到相應的說明,只能通過查看Cocos2d-x提供的樣本程式尋找相關API的使用。