zoukankan      html  css  js  c++  java
  • Behavior脚本系统

    这周的前两天,研究xml小有成就,这周的后两天,我继续研究lua和cpp的结合。昨天小有成就,今天来给大家分享一下经验~

    先说一下效果,按照惯例,上一张图~

    这两天同组程序员"cc"研究了charcter controller,角色和场景的碰撞检测已经很完美了。
    所以目前的效果是:通过上下左右箭头,如同90坦克那样控制坦克在场景中移动,并且可以检测到楼梯上下。坦克的移动是个加速过程,速度从5-20,松开按键后归到5。

    而目前控制坦克逻辑已经完全交给了lua脚本!这个是昨天研究了一天的成果,相当舒服,而且对于cc(character controller)物体和非cc物体,都可以使用同一个behavior脚本控制(得益于gameobject的继承结构和override函数)。

    下面附上这一段控制的逻辑脚本

    Tank.lua
    1. --|-------------------------------------------
    2. --Private variables
    3. fSpeed = 10
    4. fMaxSpeed = 20
    5. fMinSpeed = 5
    6. fAccelaration = 10
    7.
    8. --|-------------------------------------------
    9. --System functions
    10. function Start ()
    11. local flag = true
    12. end
    13.
    14. function Update (fElapsedTime)
    15. -- move up. translate and rotate
    16. if (IsKey(KeyCode.VK_UP)) then
    17. fSpeed = fSpeed + fElapsedTime * fAccelaration
    18. if(fSpeed > fMaxSpeed) then fSpeed = fMaxSpeed end
    19. SetEuler(0,0,0)
    20. GlobalTranslate(0,0,1,fElapsedTime * fSpeed)
    21. end
    22. -- move left.
    23. if (IsKey(KeyCode.VK_LEFT)) then
    24. fSpeed = fSpeed + fElapsedTime * fAccelaration
    25. if(fSpeed > fMaxSpeed) then fSpeed = fMaxSpeed end
    26. SetEuler(0,-90,00)
    27. GlobalTranslate(-1,0,0,fElapsedTime * fSpeed)
    28. end
    29. -- move down.
    30. if (IsKey(KeyCode.VK_DOWN)) then
    31. fSpeed = fSpeed + fElapsedTime * fAccelaration
    32. if(fSpeed > fMaxSpeed) then fSpeed = fMaxSpeed end
    33. SetEuler(0,180,0)
    34. GlobalTranslate(0,0,-1,fElapsedTime * fSpeed)
    35. end
    36. -- move right.
    37. if (IsKey(KeyCode.VK_RIGHT)) then
    38. fSpeed = fSpeed + fElapsedTime * fAccelaration
    39. if(fSpeed > fMaxSpeed) then fSpeed = fMaxSpeed end
    40. SetEuler(0,90,0)
    41. GlobalTranslate(1,0,0,fElapsedTime * fSpeed)
    42. end
    43. -- if any key released.
    44. if ((not IsKey(KeyCode.VK_UP)) and (not IsKey(KeyCode.VK_LEFT)) and (not IsKey(KeyCode.VK_DOWN)) and (not IsKey(KeyCode.VK_RIGHT))) then
    45. fSpeed = fMinSpeed
    46. end
    47. end

    有过lua基础的同学应该很容易看懂。这段脚本其实和unity3d绑定在gameobject上的behavior异曲同工。
    哈哈,废话,我的设计思想多数是在模仿和借鉴unity3d。因为它的易用和易理解,现在很火。所以借鉴unity3d的结构一定能让程序更加易用。

    下面大概说一下具体的实现吧。

    先说设计思想。gameknife目前基本已经确定是以gameobject为中心的结构了,所以我考虑可以为每一个gameobject绑定一个behavior。这个behavior就是一个lua脚本。gameobject在绘制前会调用behavior的update() ,在每一次reset时(或者是create时)调用start(),为gameobject作初始化(是不是象极了unity?)。
    通过update()函数,反向的再调用c++中的函数,相当于把frameMove()做到外部可以动态改变,这样,便可以驱动游戏的逻辑了。

    那么现在的设计是这样的:

    C++代码
    代码
    1. void InitBehavior(const char* filename, bool uselib=false)
    2. {
    3. if (m_lsoBehavior->DoFile(filename) != 0)
    4. {
    5. OutputDebugString(L"===LuaScriptSystem> Behavior Script Init Error!\n");
    6. return;
    7. }
    8. m_bIsBehavior = true;
    9. if(uselib)
    10. m_lsoBehavior->OpenLibs();
    11. kLuaLinkFunctions();
    12. }
    13.
    14. void kLuaLinkFunctions()
    15. {
    16. if(m_lsoBehavior)
    17. {
    18. m_lsoBehavior->GetGlobals().RegisterDirect("IsKeyDown", *this, &kGameObject::luaIsKeyDown);
    19. m_lsoBehavior->GetGlobals().RegisterDirect("IsKeyUp", *this, &kGameObject::luaIsKeyUp);
    20. m_lsoBehavior->GetGlobals().RegisterDirect("IsKey", *this, &kGameObject::luaIsKey);
    21. m_lsoBehavior->GetGlobals().RegisterDirect("LocalTranslate", *this, &kGameObject::kLuaTranslateLocal);
    22. m_lsoBehavior->GetGlobals().RegisterDirect("GlobalTranslate", *this, &kGameObject::kLuaTranslateGlobal);
    23. m_lsoBehavior->GetGlobals().RegisterDirect("LocalRotate", *this, &kGameObject::kLuaRotateLocal);
    24. m_lsoBehavior->GetGlobals().RegisterDirect("GlobalRotate", *this, &kGameObject::kLuaRotateGlobal);
    25. m_lsoBehavior->GetGlobals().RegisterDirect("SetEuler", *this, &kGameObject::kLuaSetEuler);
    26. }
    27. }

    initBehavior是外部调用的,为gameobject绑定lua文件。
    然后链接Functions,把控制逻辑的函数链接进lua state

    C++代码
    代码
    1. void kLuaIntialize()
    2. {
    3. //获得名字为Start的函数指针
    4. LuaFunction<void> pStartFunc = m_lsoBehavior->GetGlobal("Start");
    5. pStartFunc();
    6. }
    7.
    8. void kLuaUpdate(float fElapsedTime)
    9. {
    10. //获得名字为Update的函数指针
    11. LuaFunction<float> pUpdateFunc = m_lsoBehavior->GetGlobal("Update");
    12. pUpdateFunc(fElapsedTime);
    13. }

    这里是start和update在c++中的体现,分别在create和framemove中调用即可。

    这样,就将lua脚本和c++执行的逻辑联系起来了。

    ps. 昨天做这个程序时,其实设计没花太多时间,大量时间放在那个register函数上了。
    luaplus中有相当多的register函数: register(xxx), registerDirect(xxx), registerFunc(...), registerObjectDirect(), registerObjectFunc()。选择上测试了好久。建议大家在做的时候先建一个tmain的小工程,测试,测试完成后直接移入大工程。我昨天深受其害,后来才意识到应该使用小工程测试,毕竟luaplus深入研究的文章不多,文档也写得...唉,毕竟是个人项目。那个Joshua C. Jensen确实太牛逼了,膜拜!

  • 相关阅读:
    C#学习之自定义类实现foreach
    C#学习之用迭代器实现枚举器
    silverlight学习之获取照片的路径
    Java语言基础基本数据类型与运算符
    Java语言基础数组
    Asp.Net 学习资源列表
    测试第一篇BLOG文,高亮代码
    当屌丝想看《蜀山剑侠传》[python屏幕抓取]
    jQuery数据显示插件整合
    腾讯面试题:50个阶梯,你一次可以上一阶或两阶,走上去,共有多少种走法【原】
  • 原文地址:https://www.cnblogs.com/gameknife/p/1832159.html
Copyright © 2011-2022 走看看