2dx-lua游戏震屏效果&简单的lua-binding
2016-05-20 12:14
330 查看
--1.首先要说的是,我这里震屏功能是在c++代码里写的,然后用lua掉用c++代码。其实用lua完全可以实现功能,这里贴上代码:(想看lua掉用c++的,直接看--4.之后)
--
-- Author: Evan
--
local ScreenShaker = class("ScreenShaker")
local scheduler = require("src.framework.scheduler")
function ScreenShaker:ctor(target, time)
self.init_x = 0 --[[初始位置x]]
self.init_y = 0 --[[初始位置y]]
self.diff_x = 0 --[[偏移量x]]
self.diff_y = 0 --[[偏移量y]]
self.diff_max = 8 --[[最大偏移量]]
self.interval = 0.01 --[[震动频率]]
self.totalTime = 0 --[[震动时间]]
self.time = 0 --[[计时器]]
self.target = target
self.init_x = target:getPositionX()
self.init_y = target:getPositionY()
self.totalTime = time
end
function ScreenShaker:run()
self.scheduler = scheduler.scheduleGlobal(function (ft)
self:shake(ft)
end, self.interval)
end
function ScreenShaker:shake(ft)
if self.time >= self.totalTime then
self:stop()
return
end
self.time = self.time+ft
self.diff_x = math.random(-self.diff_max, self.diff_max)*math.random()
self.diff_y = math.random(-self.diff_max, self.diff_max)*math.random()
self.target:setPosition(cc.p(self.init_x+self.diff_x, self.init_y+self.diff_y))
end
function ScreenShaker:stop()
self.time = 0
scheduler.unscheduleGlobal(self.scheduler)
self.target:setPosition(cc.p(self.init_x, self.init_y))
end
return ScreenShaker
--2.这样写的问题是游戏暂停的时候,屏幕还会继续震动,解决方法是将震屏类设置为一个变量,想震的时候掉用一下run()方法,并给震屏类添加标志暂停标志为,暂停的时候不走shake()方法。
--3.也可以在lua里继承cc.ActionInterval类,为2dx添加新的动作,这里代码省略:
local ScreenShakerA = class("ScreenShakerA", cc.ActionInterval)
--4.接下来说我用的lua掉用c++代码实现游戏震屏效果的方式:
c++代码:
-----1.添加ScreenShaker,因为同样是动作,所以代码我加到了2d/actions/cc.ActionInterval.h 里,写在了文件的最后:
/**
* @class ScreenShaker
* @EvanJobs
*/
class CC_DLL ScreenShaker :public
ActionInterval
{
public:
ScreenShaker();
// Create the action with a time and a strength (same in x and y)
static ScreenShaker* actionWithDuration(float dt,float strength );
// Create the action with a time and strengths (different in x and y)
static ScreenShaker* actionWithDuration(float dt,float strength_x,
float strength_y );
bool initWithDuration(float dt,float strength_x,
float strength_y );
virtual void startWithTarget(Node *pTarget);
virtual void update(float dt);
virtual
void stop(void);
protected:
// Initial position of the shake node
float _initial_x, _initial_y;
// Strength of the action
float _strength_x, _strength_y;
};
-----2.方法实现,代码添加到2d/actions/cc.ActionInterval.cpp 里:
//Not really used but added for completeness
ScreenShaker::ScreenShaker() : _strength_x(0),_strength_y(0),_initial_x(0),_initial_y(0)
{
}
ScreenShaker* ScreenShaker::actionWithDuration(float dt,
float strength )
{
// call other construction method with twice the same strength
return actionWithDuration( dt, strength, strength );
}
ScreenShaker* ScreenShaker::actionWithDuration(float dt,float strength_x,
float strength_y)
{
ScreenShaker *p_action =new
ScreenShaker();
p_action->initWithDuration(dt, strength_x, strength_y);
p_action->autorelease();
return p_action;
}
bool ScreenShaker::initWithDuration(float dt,float strength_x,
float strength_y)
{
if (ActionInterval::initWithDuration(dt))
{
_strength_x = strength_x;
_strength_y = strength_y;
return true;
}
return
false;
}
// Helper function. I included it here so that you can compile the whole file
// it returns a random value between min and max included
float fgRangeRand(
float min, float max )
{
float rnd = ((float)rand()/(float)RAND_MAX);
return rnd*(max-min)+min;
}
void ScreenShaker::update(float dt)
{
float randx =fgRangeRand( -_strength_x,_strength_x
);
float randy =fgRangeRand( -_strength_y,_strength_y
);
_target->setPosition(Vec2(_initial_x,_initial_y)
+ Vec2( randx, randy));
}
void ScreenShaker::startWithTarget(Node *pTarget)
{
ActionInterval::startWithTarget( pTarget );
// save the initial position
_initial_x = pTarget->getPosition().x;
_initial_y = pTarget->getPosition().y;
}
void ScreenShaker::stop(void)
{
// Action is done, reset clip position
_target->setPosition(Vec2(
_initial_x,_initial_y ) );
ActionInterval::stop();
}
-----3.接下来是注册lua掉用c++的方法,修改:lua_cocos2dx_auto.cpp。(这里顺便说一下,这里可以看到cocos2dx,lua掉用c++的所有基本类的方法,包括ref,node,sprite,touch,texture2D,action等等。该cpp快10w行代码了..)
-----4.frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/lua_cocos2dx_auto.hpp:
不用修改,该类就一句话:
int register_all_cocos2dx(lua_State* tolua_S);
-----5.frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/lua_cocos2dx_auto.cpp:(我把代码加到了MoveTo一系列方法后)
/*
*****************************************************************************************
*EvanJobs
*/
int lua_cocos2dx_Shaker_actionWithDuration(lua_State* tolua_S)
{
int argc = 0;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertable(tolua_S,1,"cc.ScreenShaker",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(tolua_S)-1;
do
{
if (argc == 2)
{
double arg0;
ok &= luaval_to_number(tolua_S, 2,&arg0, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
double arg1;
ok &= luaval_to_number(tolua_S, 3, &arg1, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
cocos2d::ScreenShaker* ret = cocos2d::ScreenShaker::actionWithDuration(arg0,
arg1);
object_to_luaval<cocos2d::ScreenShaker>(tolua_S, "cc.ScreenShaker",(cocos2d::ScreenShaker*)ret);
return 1;
}
} while (0);
ok = true;
do{
if (argc == 3) {
double arg0;
ok &= luaval_to_number(tolua_S, 2,&arg0, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
double arg1;
ok &= luaval_to_number(tolua_S, 3, &arg1, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
double arg2;
ok &= luaval_to_number(tolua_S, 3, &arg2, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
cocos2d::ScreenShaker* ret = cocos2d::ScreenShaker::actionWithDuration(arg0,
arg1, arg2);
object_to_luaval<cocos2d::ScreenShaker>(tolua_S, "cc.ScreenShaker",(cocos2d::ScreenShaker*)ret);
return 1;
}
}while (0);
ok = true;
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "cc.MoveTo:create",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_MoveTo_create'.",&tolua_err);
#endif
return 0;
}
int lua_register_cocos2dx_Shaker(lua_State* tolua_S)
{
tolua_usertype(tolua_S,"cc.ScreenShaker");
tolua_cclass(tolua_S,"ScreenShaker","cc.ScreenShaker","cc.ActionInterval",nullptr);
tolua_beginmodule(tolua_S,"ScreenShaker");
tolua_function(tolua_S,"actionWithDuration",lua_cocos2dx_Shaker_actionWithDuration);
tolua_endmodule(tolua_S);
std::string typeName = typeid(cocos2d::ScreenShaker).name();
g_luaType[typeName] = "cc.ScreenShaker";
g_typeCast["ScreenShaker"] = "cc.ScreenShaker";
return 1;
}
/*
*********************************************************************************************
*/
-----6.添加lua_register_cocos2dx_Shaker()
在 TOLUA_API int register_all_cocos2dx(lua_State*
tolua_S)方法中添加
lua_register_cocos2dx_Shaker(tolua_S);
我是添加在了MoveTo(toll_S);后面,你们随意。
-----7.lua掉用代码:
local ss = cc.ScreenShaker:actionWithDuration(0.5, 5)
self:runAction(ss)
--5.一些注意事项&遇到问题:
-----1.首先说下tolua_cclass(tolua_S,"ScreenShaker","cc.ScreenShaker","cc.ActionInterval",nullptr);
中的”cc.ScreenShaker“,这里最好是写成与c++的类名一致,避免出错。一开始我为了方便写的“cc.Shaker”,后来在lua中"cc.Shaker:actionWithDuration()"之后报错说找不到“cc.Shaker” 。
-----2.lua掉用c++后报参数错误
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertable(tolua_S,1,"cc.ScreenShaker",0,&tolua_err)) goto tolua_lerror;
#endif
中的tolua_isusertable要根据情况来改变,我这里是需要返回new之后的该类,所以用这个,我之前是复制的代码,用的tolua_isusertype这个,然后lua里会报参数错误。
-----3.这里只是非常简单的lua-binding,因为我把ScreenShaker C++的代码写到了之前已经存在的ActionInterval里,而且lua掉用c++的代码也是写在了lua_cocos2dx_auto.cpp中,省去了很多lua-binding的中间步骤,还是比较简单易懂的。对于想要在cocos2dx引擎上扩展一些相似功能的,或者是给一些类扩展一些方法的,这种做法足够了。
-----4.具体详细的lua-binding步骤还需要自己写一些类似lua_module_register()这种的方法,并且新建的文件也要做一些处理,这里不多做介绍,给上一个比较易懂的地址:
http://www.aichengxu.com/view/45851
--
-- Author: Evan
--
local ScreenShaker = class("ScreenShaker")
local scheduler = require("src.framework.scheduler")
function ScreenShaker:ctor(target, time)
self.init_x = 0 --[[初始位置x]]
self.init_y = 0 --[[初始位置y]]
self.diff_x = 0 --[[偏移量x]]
self.diff_y = 0 --[[偏移量y]]
self.diff_max = 8 --[[最大偏移量]]
self.interval = 0.01 --[[震动频率]]
self.totalTime = 0 --[[震动时间]]
self.time = 0 --[[计时器]]
self.target = target
self.init_x = target:getPositionX()
self.init_y = target:getPositionY()
self.totalTime = time
end
function ScreenShaker:run()
self.scheduler = scheduler.scheduleGlobal(function (ft)
self:shake(ft)
end, self.interval)
end
function ScreenShaker:shake(ft)
if self.time >= self.totalTime then
self:stop()
return
end
self.time = self.time+ft
self.diff_x = math.random(-self.diff_max, self.diff_max)*math.random()
self.diff_y = math.random(-self.diff_max, self.diff_max)*math.random()
self.target:setPosition(cc.p(self.init_x+self.diff_x, self.init_y+self.diff_y))
end
function ScreenShaker:stop()
self.time = 0
scheduler.unscheduleGlobal(self.scheduler)
self.target:setPosition(cc.p(self.init_x, self.init_y))
end
return ScreenShaker
--2.这样写的问题是游戏暂停的时候,屏幕还会继续震动,解决方法是将震屏类设置为一个变量,想震的时候掉用一下run()方法,并给震屏类添加标志暂停标志为,暂停的时候不走shake()方法。
--3.也可以在lua里继承cc.ActionInterval类,为2dx添加新的动作,这里代码省略:
local ScreenShakerA = class("ScreenShakerA", cc.ActionInterval)
--4.接下来说我用的lua掉用c++代码实现游戏震屏效果的方式:
c++代码:
-----1.添加ScreenShaker,因为同样是动作,所以代码我加到了2d/actions/cc.ActionInterval.h 里,写在了文件的最后:
/**
* @class ScreenShaker
* @EvanJobs
*/
class CC_DLL ScreenShaker :public
ActionInterval
{
public:
ScreenShaker();
// Create the action with a time and a strength (same in x and y)
static ScreenShaker* actionWithDuration(float dt,float strength );
// Create the action with a time and strengths (different in x and y)
static ScreenShaker* actionWithDuration(float dt,float strength_x,
float strength_y );
bool initWithDuration(float dt,float strength_x,
float strength_y );
virtual void startWithTarget(Node *pTarget);
virtual void update(float dt);
virtual
void stop(void);
protected:
// Initial position of the shake node
float _initial_x, _initial_y;
// Strength of the action
float _strength_x, _strength_y;
};
-----2.方法实现,代码添加到2d/actions/cc.ActionInterval.cpp 里:
//Not really used but added for completeness
ScreenShaker::ScreenShaker() : _strength_x(0),_strength_y(0),_initial_x(0),_initial_y(0)
{
}
ScreenShaker* ScreenShaker::actionWithDuration(float dt,
float strength )
{
// call other construction method with twice the same strength
return actionWithDuration( dt, strength, strength );
}
ScreenShaker* ScreenShaker::actionWithDuration(float dt,float strength_x,
float strength_y)
{
ScreenShaker *p_action =new
ScreenShaker();
p_action->initWithDuration(dt, strength_x, strength_y);
p_action->autorelease();
return p_action;
}
bool ScreenShaker::initWithDuration(float dt,float strength_x,
float strength_y)
{
if (ActionInterval::initWithDuration(dt))
{
_strength_x = strength_x;
_strength_y = strength_y;
return true;
}
return
false;
}
// Helper function. I included it here so that you can compile the whole file
// it returns a random value between min and max included
float fgRangeRand(
float min, float max )
{
float rnd = ((float)rand()/(float)RAND_MAX);
return rnd*(max-min)+min;
}
void ScreenShaker::update(float dt)
{
float randx =fgRangeRand( -_strength_x,_strength_x
);
float randy =fgRangeRand( -_strength_y,_strength_y
);
_target->setPosition(Vec2(_initial_x,_initial_y)
+ Vec2( randx, randy));
}
void ScreenShaker::startWithTarget(Node *pTarget)
{
ActionInterval::startWithTarget( pTarget );
// save the initial position
_initial_x = pTarget->getPosition().x;
_initial_y = pTarget->getPosition().y;
}
void ScreenShaker::stop(void)
{
// Action is done, reset clip position
_target->setPosition(Vec2(
_initial_x,_initial_y ) );
ActionInterval::stop();
}
-----3.接下来是注册lua掉用c++的方法,修改:lua_cocos2dx_auto.cpp。(这里顺便说一下,这里可以看到cocos2dx,lua掉用c++的所有基本类的方法,包括ref,node,sprite,touch,texture2D,action等等。该cpp快10w行代码了..)
-----4.frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/lua_cocos2dx_auto.hpp:
不用修改,该类就一句话:
int register_all_cocos2dx(lua_State* tolua_S);
-----5.frameworks/cocos2d-x/cocos/scripting/lua-bindings/auto/lua_cocos2dx_auto.cpp:(我把代码加到了MoveTo一系列方法后)
/*
*****************************************************************************************
*EvanJobs
*/
int lua_cocos2dx_Shaker_actionWithDuration(lua_State* tolua_S)
{
int argc = 0;
bool ok = true;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
#endif
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertable(tolua_S,1,"cc.ScreenShaker",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(tolua_S)-1;
do
{
if (argc == 2)
{
double arg0;
ok &= luaval_to_number(tolua_S, 2,&arg0, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
double arg1;
ok &= luaval_to_number(tolua_S, 3, &arg1, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
cocos2d::ScreenShaker* ret = cocos2d::ScreenShaker::actionWithDuration(arg0,
arg1);
object_to_luaval<cocos2d::ScreenShaker>(tolua_S, "cc.ScreenShaker",(cocos2d::ScreenShaker*)ret);
return 1;
}
} while (0);
ok = true;
do{
if (argc == 3) {
double arg0;
ok &= luaval_to_number(tolua_S, 2,&arg0, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
double arg1;
ok &= luaval_to_number(tolua_S, 3, &arg1, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
double arg2;
ok &= luaval_to_number(tolua_S, 3, &arg2, "cc.ScreenShaker:actionWithDuration");
if (!ok) { break; }
cocos2d::ScreenShaker* ret = cocos2d::ScreenShaker::actionWithDuration(arg0,
arg1, arg2);
object_to_luaval<cocos2d::ScreenShaker>(tolua_S, "cc.ScreenShaker",(cocos2d::ScreenShaker*)ret);
return 1;
}
}while (0);
ok = true;
luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "cc.MoveTo:create",argc, 2);
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'lua_cocos2dx_MoveTo_create'.",&tolua_err);
#endif
return 0;
}
int lua_register_cocos2dx_Shaker(lua_State* tolua_S)
{
tolua_usertype(tolua_S,"cc.ScreenShaker");
tolua_cclass(tolua_S,"ScreenShaker","cc.ScreenShaker","cc.ActionInterval",nullptr);
tolua_beginmodule(tolua_S,"ScreenShaker");
tolua_function(tolua_S,"actionWithDuration",lua_cocos2dx_Shaker_actionWithDuration);
tolua_endmodule(tolua_S);
std::string typeName = typeid(cocos2d::ScreenShaker).name();
g_luaType[typeName] = "cc.ScreenShaker";
g_typeCast["ScreenShaker"] = "cc.ScreenShaker";
return 1;
}
/*
*********************************************************************************************
*/
-----6.添加lua_register_cocos2dx_Shaker()
在 TOLUA_API int register_all_cocos2dx(lua_State*
tolua_S)方法中添加
lua_register_cocos2dx_Shaker(tolua_S);
我是添加在了MoveTo(toll_S);后面,你们随意。
-----7.lua掉用代码:
local ss = cc.ScreenShaker:actionWithDuration(0.5, 5)
self:runAction(ss)
--5.一些注意事项&遇到问题:
-----1.首先说下tolua_cclass(tolua_S,"ScreenShaker","cc.ScreenShaker","cc.ActionInterval",nullptr);
中的”cc.ScreenShaker“,这里最好是写成与c++的类名一致,避免出错。一开始我为了方便写的“cc.Shaker”,后来在lua中"cc.Shaker:actionWithDuration()"之后报错说找不到“cc.Shaker” 。
-----2.lua掉用c++后报参数错误
#if COCOS2D_DEBUG >= 1
if (!tolua_isusertable(tolua_S,1,"cc.ScreenShaker",0,&tolua_err)) goto tolua_lerror;
#endif
中的tolua_isusertable要根据情况来改变,我这里是需要返回new之后的该类,所以用这个,我之前是复制的代码,用的tolua_isusertype这个,然后lua里会报参数错误。
-----3.这里只是非常简单的lua-binding,因为我把ScreenShaker C++的代码写到了之前已经存在的ActionInterval里,而且lua掉用c++的代码也是写在了lua_cocos2dx_auto.cpp中,省去了很多lua-binding的中间步骤,还是比较简单易懂的。对于想要在cocos2dx引擎上扩展一些相似功能的,或者是给一些类扩展一些方法的,这种做法足够了。
-----4.具体详细的lua-binding步骤还需要自己写一些类似lua_module_register()这种的方法,并且新建的文件也要做一些处理,这里不多做介绍,给上一个比较易懂的地址:
http://www.aichengxu.com/view/45851
相关文章推荐
- WPF中数据绑定
- 用PS实现纹理浮雕效果代码
- 详解Lua中的表的概念及其相关操作方法
- Lua编程示例(二):面向对象、metatable对表进行扩展
- 用CSS实现的一张图完成的按钮效果
- 把Lua编译进nginx步骤方法
- Lua脚本自动生成APK包
- Lua中的元表(metatable)、元方法(metamethod)详解
- Lua中的metatable介绍
- Lua中ipair和pair的区别
- Lua中的函数精讲笔记
- 浅谈Lua的面向对象特性
- 详解Lua中的变量相关知识点
- Lua脚本语言入门笔记
- Lua脚本调用外部脚本
- 详解Lua中的if语句的使用方法
- Lua中调用函数使用点号和冒号的区别
- Lua中的闭合函数、非全局函数与函数的尾调用详解
- Lua中强大的元方法__index详解
- Lua中调用C++函数示例