Cocos2d x Lua示例專案HelloLua
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
Cocos2d-x-Lua示例專案HelloLua
本篇部落格介紹Cocos2d-x中Lua的例項專案,就是使用Cocos2d-x建立的初始專案執行所呈現的農場,這裡筆者取名為HelloLua。本篇部落格會詳細在程式碼中解析Cocos2d-x 3.1.1建立的Lua專案中例項,一些API的使用。
注:本示例專案在Mac系統下建立
首先我們來建立一個Cocos2d-x Lua專案,在命令敲入類似以下命令
cocos new HelloLua -p com.wwj.hellolua -l lua -d ~/Cocos2dxProj
這樣我們就在Cocos2dxProj目錄下建立了一個名叫HelloLua的Lua專案
進入我們runtime-src目錄下開啟proj.ios_mac目錄,雙擊使用Xcode開啟我們的專案:
使用Xcode對我們的Lua專案進行編譯並執行,就會呈現一個以下效果的示例遊戲:
看完效果圖之後,來看看我們XCode裡面的專案檔案結構,如下圖:
以上畫圈的有main.cpp、AppDelegate.h、AppDelegate.cpp、main.lua、hello2.lua
我們下面一個一個來看:
首先來看main.cpp檔案,這個檔案就是我們程式的入口檔案,程式的執行時從這裡開始的
》》main.cpp
#include "AppDelegate.h"#include "cocos2d.h"USING_NS_CC;int main(int argc, char *argv[]){ AppDelegate app; return Application::getInstance()->run();}
以上程式碼我們可以看到,在main.cpp裡,通過#include引入了兩個標頭檔案,一個是AppDelegate.h、一個是cocos2d.h。
定義了我們程式的入口方法main,通過執行Application::getInstance()->run()方法來執行我們的程式。
>>>AppDelegate.h
#ifndef __APP_DELEGATE_H__#define __APP_DELEGATE_H__#include "cocos2d.h"/**@brief The cocos2d Application.The reason for implement as private inheritance is to hide some interface call by Director.*/class AppDelegate : private cocos2d::Application{public: AppDelegate(); virtual ~AppDelegate(); /** @brief Implement Director and Scene init code here. @return true Initialize success, app continue. @return false Initialize failed, app terminate. */ virtual bool applicationDidFinishLaunching(); /** @brief The function be called when the application enter background @param the pointer of the application */ virtual void applicationDidEnterBackground(); /** @brief The function be called when the application enter foreground @param the pointer of the application */ virtual void applicationWillEnterForeground();};#endif // __APP_DELEGATE_H__
>>>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(); // 獲得OpenGL例項 auto glview = director->getOpenGLView(); if(!glview) { // 指定視窗大小 glview = GLView::createWithRect("HelloLua", Rect(0,0,900,640)); // 設定OpenGL檢視 director->setOpenGLView(glview); } // 設定解析度大小為480*320 glview->setDesignResolutionSize(480, 320, ResolutionPolicy::NO_BORDER); // turn on display FPS 開啟幀頻,螢幕左下角哪一串資料 // 啟用FPS 顯示,當前 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); // 獲得Lua引擎例項 auto engine = LuaEngine::getInstance(); // 設定指令碼引擎 ScriptEngineManager::getInstance()->setScriptEngine(engine); // 執行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 too// 當應用程式將要進入後臺時,會呼叫這個方法void AppDelegate::applicationDidEnterBackground(){ Director::getInstance()->stopAnimation(); SimpleAudioEngine::getInstance()->pauseBackgroundMusic();}// this function will be called when the app is active again// 該方法與applicationDidEnterBackground() 成對出現,在應用程式回到前臺時被呼叫void AppDelegate::applicationWillEnterForeground(){ Director::getInstance()->startAnimation(); SimpleAudioEngine::getInstance()->resumeBackgroundMusic();}
我們在AppDelegate類當中可以找到執行我們Lua指令碼的方法,下面來看一下main.lua這個檔案,我們螢幕顯示的邏輯實現全部在這個檔案中可以看到:
>>>main.lua
[javascript]
view plain
copy
print
?
- <code class="language-plain">require "Cocos2d"
- require "Cocos2dConstants"
- -- cclog
- cclog = function(...)
- print(string.format(...))
- end
- -- for CCLuaEngine traceback 輸出繫結執行函式發生錯誤的資訊
- function __G__TRACKBACK__(msg)
- cclog("----------------------------------------")
- cclog("LUA ERROR: " .. tostring(msg) .. "\n")
- cclog(debug.traceback())
- cclog("----------------------------------------")
- return msg
- end
- local function main()
- collectgarbage("collect")
- -- avoid memory leak 這是腳本回收引數,避免記憶體洩漏
- collectgarbage("setpause", 100)
- collectgarbage("setstepmul", 5000)
- -- 追加資源的搜尋順序
- cc.FileUtils:getInstance():addSearchResolutionsOrder("src");
- cc.FileUtils:getInstance():addSearchResolutionsOrder("res");
- local schedulerID = 0
- --support debug 獲取目標平臺
- local targetPlatform = cc.Application:getInstance():getTargetPlatform()
- if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or
- (cc.PLATFORM_OS_ANDROID == targetPlatform) or (cc.PLATFORM_OS_WINDOWS == targetPlatform) or
- (cc.PLATFORM_OS_MAC == targetPlatform) then
- cclog("result is ")
- --require('debugger')()
- end
- -- 類似c++的include,引入檔案,會檢查是否重複引入
- require "hello2"
- -- 呼叫外部函式,在hello2.lua中
- cclog("result is " .. myadd(1, 1))
- ---------------
- -- 獲取可視區域
- local visibleSize = cc.Director:getInstance():getVisibleSize()
- -- 可視原點座標 OpenGL座標系,左下角為原點
- local origin = cc.Director:getInstance():getVisibleOrigin()
- -- add the moving dog 新增移動的小松鼠
- local function creatDog()
- -- 每一幀尺寸設定,local表示區域性變數
- local frameWidth = 105
- local frameHeight = 95
- -- create dog animate 載入動畫資源並建立精靈幀
- -- 載入精靈動畫所在紋理
- local textureDog = cc.Director:getInstance():getTextureCache():addImage("dog.png")
- -- 設定第一幀幀區域
- local rect = cc.rect(0, 0, frameWidth, frameHeight)
- -- 建立第一幀精靈Frame
- local frame0 = cc.SpriteFrame:createWithTexture(textureDog, rect)
- -- 設定第二幀幀區域
- rect = cc.rect(frameWidth, 0, frameWidth, frameHeight)
- -- c建立第二幀精靈Frame
- local frame1 = cc.SpriteFrame:createWithTexture(textureDog, rect)
- -- 基於使用第一幀Frame建立Sprite物件
- local spriteDog = cc.Sprite:createWithSpriteFrame(frame0)
- spriteDog.isPaused = false
- spriteDog:setPosition(origin.x, origin.y + visibleSize.height / 4 * 3)
- --[[
- local animFrames = CCArray:create()
- animFrames:addObject(frame0)
- animFrames:addObject(frame1)
- ]]--
- -- 根據幀序列陣列建立一個動畫animation。幀間隔時間delay等於0.5秒
- local animation = cc.Animation:createWithSpriteFrames({frame0,frame1}, 0.5)
- -- 根據動畫animation建立動作例項
- local animate = cc.Animate:create(animation);
- -- 松鼠精靈執行該動作
- spriteDog:runAction(cc.RepeatForever:create(animate))
- -- moving dog at every frame 用來更新松鼠的位置,後面會呼叫該函式
- local function tick()
- if spriteDog.isPaused then return end
- local x, y = spriteDog:getPosition()
- if x > origin.x + visibleSize.width then
- x = origin.x
- else
- x = x + 1
- end
- spriteDog:setPositionX(x)
- end
- -- 生成一個scheule,每幀執行tick函式
- schedulerID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(tick, 0, false)
- return spriteDog
- end
- -- create farm 建立地面的農場
- local function createLayerFarm()
- -- 建立一個新的Lyaer用作農場管理
- local layerFarm = cc.Layer:create()
- -- add in farm background 新增農場管理
- local bg = cc.Sprite:create("farm.jpg")
- bg:setPosition(origin.x + visibleSize.width / 2 + 80, origin.y + visibleSize.height / 2)
- layerFarm:addChild(bg)
- -- add land sprite 新增地面磚塊
- for i = 0, 3 do
- for j = 0, 1 do
- local spriteLand = cc.Sprite:create("land.png")、
- -- 設定每一塊磚塊位置
- spriteLand:setPosition(200 + j * 180 - i % 2 * 90, 10 + i * 95 / 2)
- layerFarm:addChild(spriteLand)
- end
- end
- -- add crop 新增莊稼,注意crop.png是多張圖的合成貼圖,所以只取了裡面的部分貼圖
- local frameCrop = cc.SpriteFrame:create("crop.png", cc.rect(0, 0, 105, 95))
- for i = 0, 3 do
- for j = 0, 1 do
- local spriteCrop = cc.Sprite:createWithSpriteFrame(frameCrop);
- spriteCrop:setPosition(10 + 200 + j * 180 - i % 2 * 90, 30 + 10 + i * 95 / 2)
- layerFarm:addChild(spriteCrop)
- end
- end
- -- add moving dog 呼叫上面的createDog()方面,建立一個移動的松鼠
- local spriteDog = creatDog()
- layerFarm:addChild(spriteDog)
- -- handing touch events 手指觸控事件處理
- local touchBeginPoint = nil
- -- 手指點選開始
- local function onTouchBegan(touch, event)
- local location = touch:getLocation()
- cclog("onTouchBegan: %0.2f, %0.2f", location.x, location.y)
- touchBeginPoint = {x = location.x, y = location.y} -- 儲存點選位置
- spriteDog.isPaused = true -- 將松鼠暫停移動
- -- CCTOUCHBEGAN event must return true
- return true
- end
- -- 手指按住移動
- local function onTouchMoved(touch, event)
- local location = touch:getLocation()
- cclog("onTouchMoved: %0.2f, %0.2f", location.x, location.y)
- if touchBeginPoint then
- -- 將整個農村層拖動,因為之前已經將農場裡面所有物件加入layerFarm
- local cx, cy = layerFarm:getPosition()
- layerFarm:setPosition(cx + location.x - touchBeginPoint.x,
- cy + location.y - touchBeginPoint.y)
- touchBeginPoint = {x = location.x, y = location.y}
- end
- end
- -- 手指離開
- local function onTouchEnded(touch, event)
- local location = touch:getLocation()
- cclog("onTouchEnded: %0.2f, %0.2f", location.x, location.y)
- touchBeginPoint = nil -- 點選位置資料清空
- spriteDog.isPaused = false -- 恢復松鼠移動
- end
- -- 建立觸控事件監聽器
- local listener = cc.EventListenerTouchOneByOne:create()
- -- 註冊touch事件
- listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN )
- listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED )
- listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED )
- local eventDispatcher = layerFarm:getEventDispatcher()
- -- 新增場景圖優先順序事件監聽
- eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layerFarm)
- local function onNodeEvent(event)
- if "exit" == event then
- cc.Director:getInstance():getScheduler():unscheduleScriptEntry(schedulerID)
- end
- end
- layerFarm:registerScriptHandler(onNodeEvent)
- return layerFarm
- end
- -- create menu 建立介面選單
- local function createLayerMenu()
- -- 建立一個新的Layer管理所有選單
- local layerMenu = cc.Layer:create()
- local menuPopup, menuTools, effectID
- -- 點選選單回撥函式
- local function menuCallbackClosePopup()
- -- stop test sound effect 關閉音效
- cc.SimpleAudioEngine:getInstance():stopEffect(effectID)
- menuPopup:setVisible(false) -- 隱藏選單
- end
- -- 點選選單回撥函式
- local function menuCallbackOpenPopup()
- -- loop test sound effect 開啟營銷
- local effectPath = cc.FileUtils:getInstance():fullPathForFilename("effect1.wav")
- effectID = cc.SimpleAudioEngine:getInstance():playEffect(effectPath)
- menuPopup:setVisible(true)
- end
- -- add a popup menu 建立彈出的菜單面板
- local menuPopupItem = cc.MenuItemImage:create("menu2.png", "menu2.png")
- menuPopupItem:setPosition(0, 0)
- menuPopupItem:registerScriptTapHandler(menuCallbackClosePopup)
- menuPopup = cc.Menu:create(menuPopupItem)
- menuPopup:setPosition(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2)
- menuPopup:setVisible(false)
- layerMenu:addChild(menuPopup)
- -- add the left-bottom "tools" menu to invoke menuPopup
- -- 新增左下角的工具按鈕,用來彈出菜單面板
- local menuToolsItem = cc.MenuItemImage:create("menu1.png", "menu1.png")
- menuToolsItem:setPosition(0, 0)
- -- 註冊點選回撥地址
- menuToolsItem:registerScriptTapHandler(menuCallbackOpenPopup)
- menuTools = cc.Menu:create(menuToolsItem)
- local itemWidth = menuToolsItem:getContentSize().width
- local itemHeight = menuToolsItem:getContentSize().height
- menuTools:setPosition(origin.x + itemWidth/2, origin.y + itemHeight/2)
- layerMenu:addChild(menuTools)
- return layerMenu
- end
- -- play background music, preload effect
- -- uncomment below for the BlackBerry version
- local bgMusicPath = nil
- if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) then
- bgMusicPath = cc.FileUtils:getInstance():fullPathForFilename("res/background.caf")
- else
- bgMusicPath = cc.FileUtils:getInstance():fullPathForFilename("res/background.mp3")
- end
- cc.SimpleAudioEngine:getInstance():playMusic(bgMusicPath, true)
- local effectPath = cc.FileUtils:getInstance():fullPathForFilename("effect1.wav")
- -- 預載入音效
- cc.SimpleAudioEngine:getInstance():preloadEffect(effectPath)
- -- run
- local sceneGame = cc.Scene:create() -- 建立場景
- sceneGame:addChild(createLayerFarm()) -- 將農場層加入場景
- sceneGame:addChild(createLayerMenu()) -- 將選單介面層加入場景
- -- 判斷是否有執行的場景
- if cc.Director:getInstance():getRunningScene() then
- cc.Director:getInstance():replaceScene(sceneGame) -- 替換場景
- else
- cc.Director:getInstance():runWithScene(sceneGame)
- end
- end
- --[[
- xpcall( 呼叫函式, 錯誤捕獲函式 );
- lua提供了xpcall來捕獲異常
- xpcall接受兩個引數:呼叫函式、錯誤處理函式。
- 當錯誤發生時,Lua會在棧釋放以前呼叫錯誤處理函式,因此可以使用debug庫收集錯誤相關資訊。
- 兩個常用的debug處理函式:debug.debug和debug.traceback
- 前者給出Lua的提示符,你可以自己動手察看錯誤發生時的情況;
- 後者通過traceback建立更多的錯誤資訊,也是控制檯直譯器用來構建錯誤資訊的函式。
- --]]
- local status, msg = xpcall(main, __G__TRACKBACK__)
- if not status then
- error(msg)
- end
- </code>
require "Cocos2d"require "Cocos2dConstants"-- cclogcclog = function(...) print(string.format(...))end-- for CCLuaEngine traceback 輸出繫結執行函式發生錯誤的資訊function __G__TRACKBACK__(msg) cclog("----------------------------------------") cclog("LUA ERROR: " .. tostring(msg) .. "\n") cclog(debug.traceback()) cclog("----------------------------------------") return msgendlocal function main() collectgarbage("collect") -- avoid memory leak 這是腳本回收引數,避免記憶體洩漏 collectgarbage("setpause", 100) collectgarbage("setstepmul", 5000) -- 追加資源的搜尋順序 cc.FileUtils:getInstance():addSearchResolutionsOrder("src"); cc.FileUtils:getInstance():addSearchResolutionsOrder("res"); local schedulerID = 0 --support debug 獲取目標平臺 local targetPlatform = cc.Application:getInstance():getTargetPlatform() if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or (cc.PLATFORM_OS_ANDROID == targetPlatform) or (cc.PLATFORM_OS_WINDOWS == targetPlatform) or (cc.PLATFORM_OS_MAC == targetPlatform) then cclog("result is ") --require('debugger')() end -- 類似c++的include,引入檔案,會檢查是否重複引入 require "hello2" -- 呼叫外部函式,在hello2.lua中 cclog("result is " .. myadd(1, 1)) --------------- -- 獲取可視區域 local visibleSize = cc.Director:getInstance():getVisibleSize() -- 可視原點座標 OpenGL座標系,左下角為原點 local origin = cc.Director:getInstance():getVisibleOrigin() -- add the moving dog 新增移動的小松鼠 local function creatDog() -- 每一幀尺寸設定,local表示區域性變數 local frameWidth = 105 local frameHeight = 95 -- create dog animate 載入動畫資源並建立精靈幀 -- 載入精靈動畫所在紋理 local textureDog = cc.Director:getInstance():getTextureCache():addImage("dog.png") -- 設定第一幀幀區域 local rect = cc.rect(0, 0, frameWidth, frameHeight) -- 建立第一幀精靈Frame local frame0 = cc.SpriteFrame:createWithTexture(textureDog, rect) -- 設定第二幀幀區域 rect = cc.rect(frameWidth, 0, frameWidth, frameHeight) -- c建立第二幀精靈Frame local frame1 = cc.SpriteFrame:createWithTexture(textureDog, rect) -- 基於使用第一幀Frame建立Sprite物件 local spriteDog = cc.Sprite:createWithSpriteFrame(frame0) spriteDog.isPaused = false spriteDog:setPosition(origin.x, origin.y + visibleSize.height / 4 * 3)--[[ local animFrames = CCArray:create() animFrames:addObject(frame0) animFrames:addObject(frame1)]]-- -- 根據幀序列陣列建立一個動畫animation。幀間隔時間delay等於0.5秒 local animation = cc.Animation:createWithSpriteFrames({frame0,frame1}, 0.5) -- 根據動畫animation建立動作例項 local animate = cc.Animate:create(animation); -- 松鼠精靈執行該動作 spriteDog:runAction(cc.RepeatForever:create(animate)) -- moving dog at every frame 用來更新松鼠的位置,後面會呼叫該函式 local function tick() if spriteDog.isPaused then return end local x, y = spriteDog:getPosition() if x > origin.x + visibleSize.width then x = origin.x else x = x + 1 end spriteDog:setPositionX(x) end -- 生成一個scheule,每幀執行tick函式 schedulerID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(tick, 0, false) return spriteDog end -- create farm 建立地面的農場 local function createLayerFarm() -- 建立一個新的Lyaer用作農場管理 local layerFarm = cc.Layer:create() -- add in farm background 新增農場管理 local bg = cc.Sprite:create("farm.jpg") bg:setPosition(origin.x + visibleSize.width / 2 + 80, origin.y + visibleSize.height / 2) layerFarm:addChild(bg) -- add land sprite 新增地面磚塊 for i = 0, 3 do for j = 0, 1 do local spriteLand = cc.Sprite:create("land.png")、 -- 設定每一塊磚塊位置 spriteLand:setPosition(200 + j * 180 - i % 2 * 90, 10 + i * 95 / 2) layerFarm:addChild(spriteLand) end end -- add crop 新增莊稼,注意crop.png是多張圖的合成貼圖,所以只取了裡面的部分貼圖 local frameCrop = cc.SpriteFrame:create("crop.png", cc.rect(0, 0, 105, 95)) for i = 0, 3 do for j = 0, 1 do local spriteCrop = cc.Sprite:createWithSpriteFrame(frameCrop); spriteCrop:setPosition(10 + 200 + j * 180 - i % 2 * 90, 30 + 10 + i * 95 / 2) layerFarm:addChild(spriteCrop) end end -- add moving dog 呼叫上面的createDog()方面,建立一個移動的松鼠 local spriteDog = creatDog() layerFarm:addChild(spriteDog) -- handing touch events 手指觸控事件處理 local touchBeginPoint = nil -- 手指點選開始 local function onTouchBegan(touch, event) local location = touch:getLocation() cclog("onTouchBegan: %0.2f, %0.2f", location.x, location.y) touchBeginPoint = {x = location.x, y = location.y} -- 儲存點選位置 spriteDog.isPaused = true -- 將松鼠暫停移動 -- CCTOUCHBEGAN event must return true return true end -- 手指按住移動 local function onTouchMoved(touch, event) local location = touch:getLocation() cclog("onTouchMoved: %0.2f, %0.2f", location.x, location.y) if touchBeginPoint then -- 將整個農村層拖動,因為之前已經將農場裡面所有物件加入layerFarm local cx, cy = layerFarm:getPosition() layerFarm:setPosition(cx + location.x - touchBeginPoint.x, cy + location.y - touchBeginPoint.y) touchBeginPoint = {x = location.x, y = location.y} end end -- 手指離開 local function onTouchEnded(touch, event) local location = touch:getLocation() cclog("onTouchEnded: %0.2f, %0.2f", location.x, location.y) touchBeginPoint = nil -- 點選位置資料清空 spriteDog.isPaused = false -- 恢復松鼠移動 end -- 建立觸控事件監聽器 local listener = cc.EventListenerTouchOneByOne:create() -- 註冊touch事件 listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED ) listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) local eventDispatcher = layerFarm:getEventDispatcher() -- 新增場景圖優先順序事件監聽 eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layerFarm) local function onNodeEvent(event) if "exit" == event then cc.Director:getInstance():getScheduler():unscheduleScriptEntry(schedulerID) end end layerFarm:registerScriptHandler(onNodeEvent) return layerFarm end -- create menu 建立介面選單 local function createLayerMenu() -- 建立一個新的Layer管理所有選單 local layerMenu = cc.Layer:create() local menuPopup, menuTools, effectID -- 點選選單回撥函式 local function menuCallbackClosePopup() -- stop test sound effect 關閉音效 cc.SimpleAudioEngine:getInstance():stopEffect(effectID) menuPopup:setVisible(false) -- 隱藏選單 end -- 點選選單回撥函式 local function menuCallbackOpenPopup() -- loop test sound effect 開啟營銷 local effectPath = cc.FileUtils:getInstance():fullPathForFilename("effect1.wav") effectID = cc.SimpleAudioEngine:getInstance():playEffect(effectPath) menuPopup:setVisible(true) end -- add a popup menu 建立彈出的菜單面板 local menuPopupItem = cc.MenuItemImage:create("menu2.png", "menu2.png") menuPopupItem:setPosition(0, 0) menuPopupItem:registerScriptTapHandler(menuCallbackClosePopup) menuPopup = cc.Menu:create(menuPopupItem) menuPopup:setPosition(origin.x + visibleSize.width / 2, origin.y + visibleSize.height / 2)