gavanwanggw

导航

解析cocos2d-lua项目中的Hello World

创建完cocos2d-x的lua项目后。打开项目的Resources目录,找到hello.lua。cocos2d-x的lua项目的測试样例主要就是由这个脚本文件运行的。

require "AudioEngine" --引入声音引擎文件

-- for CCLuaEngine traceback
function __G__TRACKBACK__(msg)
    print("----------------------------------------")
    print("LUA ERROR: " .. tostring(msg) .. "\n")--打印错误信息
    print(debug.traceback())--输出当前运行的traceback信息
    print("----------------------------------------")
end
--主函数
local function main()
    -- avoid memory leak
    -- 避免内存泄露
    --操作垃圾收集器
    collectgarbage("setpause", 100)
    collectgarbage("setstepmul", 5000)
    --定义日志输出函数
    local cclog = function(...)
        print(string.format(...))
    end
    --引入hello2脚本
    require "hello2"
    --调用hello2脚本中的myadd函数
    cclog("result is " .. myadd(3, 5))

    ---------------
    --获取屏幕的可视化大小
    local visibleSize = CCDirector:sharedDirector():getVisibleSize()
    --获取可视区域的起点坐标
    local origin = CCDirector:sharedDirector():getVisibleOrigin()

    -- add the moving dog
    --创建一个可移动的小狗
    local function creatDog()
        local frameWidth = 105
        local frameHeight = 95

        -- create dog animate
        --加入小狗的贴图到内存中
        local textureDog = CCTextureCache:sharedTextureCache():addImage("dog.png")
        --创建截取第一个小狗的精灵帧的矩形
        local rect = CCRectMake(0, 0, frameWidth, frameHeight)
        --创建一个小狗的精灵帧
        local frame0 = CCSpriteFrame:createWithTexture(textureDog, rect)
        --创建截取第二个小狗的精灵帧的矩形
        rect = CCRectMake(frameWidth, 0, frameWidth, frameHeight)
        --创建一个第二个小狗的精灵帧
        local frame1 = CCSpriteFrame:createWithTexture(textureDog, rect)

        --以小狗的第一个精灵帧创建一个小狗精灵
        local spriteDog = CCSprite:createWithSpriteFrame(frame0)
        --自己定义一个bool值的属性,标记为false
        spriteDog.isPaused = false
        --设置小狗的位置在 x:0, y:屏幕高度*0.75 处
        spriteDog:setPosition(origin.x, origin.y + visibleSize.height / 4 * 3)
        --创建一个用于存储精灵帧的数组
        local animFrames = CCArray:create()
        --把上面的两个精灵帧加入到数组中
        animFrames:addObject(frame0)
        animFrames:addObject(frame1)
        --以0.5秒的切换速度方式创建一个动画描写叙述
        local animation = CCAnimation:createWithSpriteFrames(animFrames, 0.5)
        --依据上面的动画描写叙述创建一个动画
        local animate = CCAnimate:create(animation);
        --运行该动画
        spriteDog:runAction(CCRepeatForever: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
        --运行定时器
        CCDirector:sharedDirector():getScheduler():scheduleScriptFunc(tick, 0, false)
        --返回创建的小狗
        return spriteDog
    end

    -- create farm
    --创建农田
    local function createLayerFarm()
        --创建一个农场层
        local layerFarm = CCLayer:create()

        -- add in farm background
        --创建一个背景精灵
        local bg = CCSprite: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 = CCSprite:create("land.png")
                spriteLand:setPosition(200 + j * 180 - i % 2 * 90, 10 + i * 95 / 2)
                layerFarm:addChild(spriteLand)
            end
        end

        -- add crop
        --创建农作物
        local frameCrop = CCSpriteFrame:create("crop.png", CCRectMake(0, 0, 105, 95))
        for i = 0, 3 do
            for j = 0, 1 do
                local spriteCrop = CCSprite:createWithSpriteFrame(frameCrop);
                spriteCrop:setPosition(10 + 200 + j * 180 - i % 2 * 90, 30 + 10 + i * 95 / 2)
                layerFarm:addChild(spriteCrop)
            end
        end

        -- add moving dog
        --创建一个会移动的小狗
        local spriteDog = creatDog()
        --将小狗加入到农场层中
        layerFarm:addChild(spriteDog)

        -- handing touch events
        --初始化触摸点
        local touchBeginPoint = nil
        --開始点击触摸屏
        local function onTouchBegan(x, y)
            --输出点击位置
            cclog("onTouchBegan: %0.2f, %0.2f", x, y)
            --将点击位置赋给触摸点
            touchBeginPoint = {x = x, y = y}
            --点击时小狗暂停移动
            spriteDog.isPaused = true
            -- CCTOUCHBEGAN event must return true
            return true
        end
        --滑动触摸屏
        local function onTouchMoved(x, y)
            --输出滑动位置
            cclog("onTouchMoved: %0.2f, %0.2f", x, y)
            --假设触摸点不为空
            if touchBeginPoint then
                --获取农场层的当前位置
                local cx, cy = layerFarm:getPosition()
                --移动农场层
                layerFarm:setPosition(cx + x - touchBeginPoint.x,
                                      cy + y - touchBeginPoint.y)
                --将滑动的位置赋给触摸点
                touchBeginPoint = {x = x, y = y}
            end
        end
        --离开触摸屏
        local function onTouchEnded(x, y)
            --输出离开屏幕时的位置
            cclog("onTouchEnded: %0.2f, %0.2f", x, y)
            --删除触摸点
            touchBeginPoint = nil
            --小狗又一次移动
            spriteDog.isPaused = false
        end
        --处理触摸状态
        local function onTouch(eventType, x, y)
            if eventType == "began" then   --点击屏幕状态
                return onTouchBegan(x, y)
            elseif eventType == "moved" then --滑动屏幕状态
                return onTouchMoved(x, y)
            else  --离开屏幕状态
                return onTouchEnded(x, y) 
            end
        end
        --注冊触摸事件
        layerFarm:registerScriptTouchHandler(onTouch)
        --开启触摸
        layerFarm:setTouchEnabled(true)
        --返回农场层
        return layerFarm
    end


    -- create menu
    --创建菜单
    local function createLayerMenu()
        --创建一个菜单层
        local layerMenu = CCLayer:create()
        --定义三个变量
        local menuPopup, menuTools, effectID
        --运行菜单项的回调函数
        local function menuCallbackClosePopup()
            -- stop test sound effect
            --停止音效的播放
            AudioEngine.stopEffect(effectID)
            --隐藏菜单
            menuPopup:setVisible(false)
        end
        --运行菜单项的回调函数
        local function menuCallbackOpenPopup()
            -- loop test sound effect
            --获取播放音效的路径
            local effectPath = CCFileUtils:sharedFileUtils():fullPathForFilename("effect1.wav")
            --播放音效
            effectID = AudioEngine.playEffect(effectPath)
            --显示菜单
            menuPopup:setVisible(true)
        end

        -- add a popup menu
        --创建一个菜单项
        local menuPopupItem = CCMenuItemImage:create("menu2.png", "menu2.png")
        --设置菜单项位置
        menuPopupItem:setPosition(0, 0)
        --设置运行该菜单项所相应的回调函数
        menuPopupItem:registerScriptTapHandler(menuCallbackClosePopup)
        --创建一个菜单
        menuPopup = CCMenu:createWithItem(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 = CCMenuItemImage:create("menu1.png", "menu1.png")
        --设置菜单项位置
        menuToolsItem:setPosition(0, 0)
        --设置运行该菜单项所相应的回调函数
        menuToolsItem:registerScriptTapHandler(menuCallbackOpenPopup)
        --创建一个菜单
        menuTools = CCMenu:createWithItem(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 = CCFileUtils:sharedFileUtils():fullPathForFilename("background.ogg")
    --获取背景音乐的文件路径
    local bgMusicPath = CCFileUtils:sharedFileUtils():fullPathForFilename("background.mp3")
    --播放背景音乐
    AudioEngine.playMusic(bgMusicPath, true)
    --获取音效的文件路径
    local effectPath = CCFileUtils:sharedFileUtils():fullPathForFilename("effect1.wav")
    --将音效缓存到内存中
    AudioEngine.preloadEffect(effectPath)

    -- run
    --创建一个场景
    local sceneGame = CCScene:create()
    --将农村层加入到该场景中
    sceneGame:addChild(createLayerFarm())
    --将菜单层加入到该场景中
    sceneGame:addChild(createLayerMenu())
    --运行该场景
    CCDirector:sharedDirector():runWithScene(sceneGame)
end
--保护模式下调用主函数,并制定错误处理函数句柄__G__TRACKBACK__
xpcall(main, __G__TRACKBACK__)

而这个脚本是在AppDelegate.cpp中被运行的。里面初始化了cocos2d-x解析lua的引擎。

bool AppDelegate::applicationDidFinishLaunching()
{
    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

    // turn on display FPS
    pDirector->setDisplayStats(true);

    // set FPS. the default value is 1.0/60 if you don't call this
    pDirector->setAnimationInterval(1.0 / 60);

    // register lua engine
	//初始化lua脚本引擎
    CCLuaEngine* pEngine = CCLuaEngine::defaultEngine();
	//将lua脚本引擎加入到脚本引擎管理器中
    CCScriptEngineManager::sharedManager()->setScriptEngine(pEngine);
	//取得lua的全局指针,全部的lua函数都须要使用这个指针来做为參数进行调用。  
    CCLuaStack *pStack = pEngine->getLuaStack();
	//获取lua_State
    lua_State *tolua_s = pStack->getLuaState();
	//开放扩展函数给lua调用
    tolua_extensions_ccb_open(tolua_s);
	//假设是ios、android、win32平台则开放WebSocket类给lua调用
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
    pStack = pEngine->getLuaStack();
    tolua_s = pStack->getLuaState();
    tolua_web_socket_open(tolua_s);
#endif
    
#if (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY)//黑莓平台,不清楚
    CCFileUtils::sharedFileUtils()->addSearchPath("script");
#endif
	//获取待运行的脚本路径
    std::string path = CCFileUtils::sharedFileUtils()->fullPathForFilename("hello.lua");
	//运行脚本
    pEngine->executeScriptFile(path.c_str());

    return true;
}

当中CCLuaEngine是继承自CCScriptEngineProtocl,这个协议定义了lua引擎的功能,当中CCScriptEngineManager用来管理当期的脚本文件(眼下没发现这个管理类有什么用)。

void CCScriptEngineManager::setScriptEngine(CCScriptEngineProtocol *pScriptEngine)
{
    removeScriptEngine();//移除上一个的脚本引擎
    m_pScriptEngine = pScriptEngine;//将当前的脚本引擎赋给m_pScriptEngine
}

void CCScriptEngineManager::removeScriptEngine(void)
{
    if (m_pScriptEngine)//假设脚本引擎的实例存在,则delete掉
    {
        delete m_pScriptEngine;
        m_pScriptEngine = NULL;
    }
}


posted on 2017-05-16 10:05  gavanwanggw  阅读(221)  评论(0编辑  收藏  举报