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和AppDelegate.cpp,这里两个文件用于 控制整个游戏的生命周期

>>>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*320glview->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

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
endlocal 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) thencclog("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 = 105local frameHeight = 95-- create dog animate 加载动画资源并创建精灵帧-- 加载精灵动画所在纹理local textureDog = cc.Director:getInstance():getTextureCache():addImage("dog.png")-- 设置第一帧帧区域local rect = cc.rect(0, 0, frameWidth, frameHeight)-- 创建第一帧精灵Framelocal frame0 = cc.SpriteFrame:createWithTexture(textureDog, rect)-- 设置第二帧帧区域rect = cc.rect(frameWidth, 0, frameWidth, frameHeight)-- c创建第二帧精灵Framelocal frame1 = cc.SpriteFrame:createWithTexture(textureDog, rect)-- 基于使用第一帧Frame创建Sprite对象local spriteDog = cc.Sprite:createWithSpriteFrame(frame0)spriteDog.isPaused = falsespriteDog: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 endlocal x, y = spriteDog:getPosition()if x > origin.x + visibleSize.width thenx = origin.xelsex = x + 1endspriteDog:setPositionX(x)end-- 生成一个scheule,每帧执行tick函数schedulerID = cc.Director:getInstance():getScheduler():scheduleScriptFunc(tick, 0, false)return spriteDogend-- 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 dofor j = 0, 1 dolocal spriteLand = cc.Sprite:create("land.png")、-- 设定每一块砖块位置spriteLand:setPosition(200 + j * 180 - i % 2 * 90, 10 + i * 95 / 2)layerFarm:addChild(spriteLand)endend-- add crop 添加庄稼,注意crop.png是多张图的合成贴图,所以只取了里面的部分贴图local frameCrop = cc.SpriteFrame:create("crop.png", cc.rect(0, 0, 105, 95))for i = 0, 3 dofor j = 0, 1 dolocal spriteCrop = cc.Sprite:createWithSpriteFrame(frameCrop);spriteCrop:setPosition(10 + 200 + j * 180 - i % 2 * 90, 30 + 10 + i * 95 / 2)layerFarm:addChild(spriteCrop)endend-- 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 truereturn trueend-- 手指按住移动local function onTouchMoved(touch, event)local location = touch:getLocation()cclog("onTouchMoved: %0.2f, %0.2f", location.x, location.y)if touchBeginPoint then-- 将整个农村层拖动,因为之前已经将农场里面所有对象加入layerFarmlocal cx, cy = layerFarm:getPosition()layerFarm:setPosition(cx + location.x - touchBeginPoint.x,cy + location.y - touchBeginPoint.y)touchBeginPoint = {x = location.x, y = location.y}endend-- 手指离开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 thencc.Director:getInstance():getScheduler():unscheduleScriptEntry(schedulerID)endendlayerFarm:registerScriptHandler(onNodeEvent)return layerFarmend-- 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().widthlocal itemHeight = menuToolsItem:getContentSize().heightmenuTools:setPosition(origin.x + itemWidth/2, origin.y + itemHeight/2)layerMenu:addChild(menuTools)return layerMenuend-- play background music, preload effect-- uncomment below for the BlackBerry versionlocal bgMusicPath = nil if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) thenbgMusicPath = cc.FileUtils:getInstance():fullPathForFilename("res/background.caf")elsebgMusicPath = cc.FileUtils:getInstance():fullPathForFilename("res/background.mp3")endcc.SimpleAudioEngine:getInstance():playMusic(bgMusicPath, true)local effectPath = cc.FileUtils:getInstance():fullPathForFilename("effect1.wav")-- 预加载音效cc.SimpleAudioEngine:getInstance():preloadEffect(effectPath)-- runlocal sceneGame = cc.Scene:create() -- 创建场景sceneGame:addChild(createLayerFarm())    -- 将农场层加入场景sceneGame:addChild(createLayerMenu())    -- 将菜单界面层加入场景-- 判断是否有运行的场景if cc.Director:getInstance():getRunningScene() thencc.Director:getInstance():replaceScene(sceneGame) -- 替换场景elsecc.Director:getInstance():runWithScene(sceneGame)endend--[[
xpcall( 调用函数, 错误捕获函数 );
lua提供了xpcall来捕获异常
xpcall接受两个参数:调用函数、错误处理函数。
当错误发生时,Lua会在栈释放以前调用错误处理函数,因此可以使用debug库收集错误相关信息。
两个常用的debug处理函数:debug.debug和debug.traceback
前者给出Lua的提示符,你可以自己动手察看错误发生时的情况;
后者通过traceback创建更多的错误信息,也是控制台解释器用来构建错误信息的函数。
--]]
local status, msg = xpcall(main, __G__TRACKBACK__)
if not status thenerror(msg)
end

这是Cocos2d-x 3.1.1所使用的代码,代码中的注释已经很详细了,笔者在这里就不多说,希望大家能认真阅读,跟笔者一起尽快入门Lua在Cocos2dx中的使用。

Cocos2d-x-Lua示例项目HelloLua相关推荐

  1. 【Android 性能优化】应用启动优化 ( 方法追踪代码模板 | 示例项目 | SD 卡访问权限 | 示例代码 | 获取 Trace 文件 | Android Studio 查看文件)

    文章目录 一. 方法追踪代码模板 二. 追踪 Launch 页面的 onCreate 方法执行情况 1. 示例项目 2. SD 卡访问权限问题 ( 动态权限申请 ) 3. MainActivity o ...

  2. Meteor创建示例项目 Simple-todos

    2019独角兽企业重金招聘Python工程师标准>>> 本笔记,基于Windows环境. 1.Meteor提供了一些示例项目供开发者参考,打开命令行,输入meteor create ...

  3. jboss项目导入idea_如何导入任何JBoss BRMS示例项目

    jboss项目导入idea 在过去几周内,JBoss BRMS演示的用户反复询问我以下内容时,会给您这些提示和技巧: "如何将与各种JBoss BRMS演示项目相关的项目导入到我自己的现有安 ...

  4. 如何导入任何JBoss BRMS示例项目

    在过去几周内,JBoss BRMS演示的用户反复询问我以下内容时,会给您这些提示和技巧: "如何将与各种JBoss BRMS演示项目相关的项目导入到我自己的现有安装中?" 这意味着 ...

  5. 使用aws跑深度学习_RNN示例项目从开发到部署(三):在AWS上部署深度学习模型...

    虽然我很喜欢为自己建立数据科学和编程项目,但我同样乐于与世界上的任何人在线分享它.幸好,我们以使用AWS(Amazon Web Services),这样我们可以在几分钟内免费将Python Web应用 ...

  6. vant 项目_基于 vue3.x+vant3.x 搭建示例项目

    今天给大家分享一些如何使用Vue3.0+Vant3搭建demo项目. 目前市面上有关vue3的项目并不多,vue3的UI组件库有ant-design-vue和vant-ui. 接下来讲解下使用vue3 ...

  7. 微软SQLServer官方示例项目部署-数据引擎和分析服务部分

    微软SQLServer每个版本都会带有相应的示例项目,从2000时的Foodmart到2005之后的Adventure Works,里面的设计方法和规范都有很多我们值得学习的地方.不仅是做普通的开发, ...

  8. struts2 log4j_Struts2和Log4j集成示例项目

    struts2 log4j Sometime back I wrote an article about using log4j in web application and we utilized ...

  9. kotterKnife+dagger2+otto+okhttp+picasso+retrofit+rxjava示例项目,使用kotlin编写。

    kotterKnife+dagger2+otto+okhttp+picasso+retrofit+rxjava示例项目,使用kotlin编写. 链接:https://github.com/zengzh ...

最新文章

  1. 生产者与消费者(三)---BlockingQueue
  2. [转载]jQuery.extend 函数详解
  3. 青年歌手大奖赛_评委会打分
  4. 关于团队发展的若干想法(欢迎讨论)
  5. CQRS简单入门(Golang)
  6. 计算机主机内有哪些部件常用的,智慧职教: 计算机系统由什么组成?计算机主机内有哪些部件?常用的计算机外设有哪些...
  7. 安装ie9提示未能完成安装_Windows 7下安装IE 11失败,提示:Internet Explorer未能完成安装...
  8. 高并发、高访问量如何计算【测试评估】
  9. android 模仿今日头条ViewPager+TabLayout
  10. 项目管理概论【项目管理基础-第一章 项目与项目管理】
  11. HiJson修改版,修改为按json字符串默认字段顺序格式化
  12. 在Ubuntu 18.04中安装ROS操作系统
  13. 开源了一个私人云盘——蓝眼云盘
  14. H3CNE GB0-191最新题库 加解释四份材料
  15. 裕太微递交招股书上会稿:拟募资13亿元,哈勃投资、小米等为股东
  16. 眼睛血管分割matlab版本
  17. Colliding Mice碰撞老鼠工程分析
  18. 推荐 6 个火爆 GitHub 的开源项目
  19. Android客户端访问服务器保持SESSION会话的实现
  20. 在Virtual Box中安装Windows7 64位虚拟机系统

热门文章

  1. 设置允许从网络访问计算机的用户账户(加入guest组),没法访问 您可能没有权限使用网络资源...
  2. 技术人员和非技术人员如何写出优质博客?-涵子的个人想法
  3. 常用的一维时间序列滤波方法
  4. 视频教程-华为路由交换精讲系列20:OSPF技术精讲 [肖哥]视频课程-华为认证
  5. System.ComponentModel.Win32Exception解决方案
  6. MYSQL如何让主键使用BTREE索引
  7. 2021电赛预测押题:基于互联网的多人音频会议系统
  8. ubuntu18.04安装x11vnc远程登录并设置开机自启
  9. java模拟atm_Java项目实现模拟ATM机
  10. 基于STM32的环境监测系统设计与实现