使用Irrlicht构建游戏主角

原创 2015年07月07日 15:50:33

所谓游戏主角就是第三视角看到的在屏幕中间附近跑来跑去,然后周围景物随之变换的节点。

最终效果

实现的思路很简单,分为以下三步
1. 获取键盘输入
2. 移动主角,并且在需要的时候更改动画
3. 移动摄像机
这里的前提是周围环境相对世界坐标系不变。

那么使用Irrlicht怎么实现呢?一步一步来。

1. 获取键盘输入
自然就是重载我们的 IEventReceiver 类了,这部分大体思路可以参考教程 04.Movement 里面的实现:维护一个键位表,每个键值有两个状态(按下和没有按下),在键盘有信号时修改本表对应键值的状态,以便主渲染程序读取。


class MyEventReceiver : public IEventReceiver
{
public:

    MyEventReceiver()
    {
        for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
            KeyIsDown[i] = false;

        runContrlCounter = 0;
        pressKeyCounter = 0;
    }

    virtual bool OnEvent(const SEvent& event)
    {

        // 改变键位状态
        if (event.EventType == irr::EET_KEY_INPUT_EVENT){
            KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;

        }

        return false;
    }

    virtual bool IsKeyDown(EKEY_CODE keyCode) const
    {
        return KeyIsDown[keyCode];
    }

private:
    bool KeyIsDown[KEY_KEY_CODES_COUNT];
};

接下来第二步
2.移动角色并更改动画
本身这几个动作是比较简单的,但坑就坑在节点类 IAnimatedMeshSceneNode 居然是个抽象类,并且我没有找到合适的去继承它成为实体类的方法(如果有请告知)。那只能对这个类的系列操作封装在一个代理类 MyRoleDelegate 里面了。这个类里面有个 render() 函数用于从事件接收器中读取当前键盘状态并操作主节点。

有WASD操作的人物一共有八个方向,此时对应八种模型旋转变换(二维),也比较简单。附上代码

class MyRoleDelegate
{

public:

    MyRoleDelegate(IAnimatedMeshSceneNode* node_p, MyEventReceiver* receiver_p,
    IrrlichtDevice* device_p)
    :role(node_p), receiver(receiver_p), device(device_p)
    {
        init();

    }

    void init()
    {
        MOVEMENT_SPEED = 25.f;
        available = true;
        currentPosition = role->getPosition();
        setAnimationType(EMAT_STAND);
        //初始为站立动画
    }


    void setAnimationType(EMD2_ANIMATION_TYPE atype)
    {
        //避免重复设置同一个动作而造成卡顿
        if(currentAnimationType!=atype)
        {
            role->setMD2Animation(atype);
            currentAnimationType=atype;
        }
    }

    void render()
    {
        if(false)
        {
          //  setAnimationType(EMAT_STAND);
        }
        else
        {
            setAnimationType(EMAT_RUN);
            f32 frameDeltaTime = 0.1;

            currentPosition = role->getPosition();
            float move_distance = MOVEMENT_SPEED * frameDeltaTime;

            vector3df dir(0.0,-90,0); //角色的方向
            if(receiver->IsKeyDown(KEY_KEY_W))
            {
                dir.Y = -90;
                currentPosition.Z += move_distance*0.7;
                if(receiver->IsKeyDown(KEY_KEY_A))
                {   //WA 方向
                    dir.Y = -135;
                    currentPosition.X -= move_distance*0.7;
                }
                else if(receiver->IsKeyDown(KEY_KEY_D))
                {   //WD 方向
                    dir.Y = -45;
                    currentPosition.X += move_distance*0.7;
                }
                else
                {//W方向,以下类似
                    currentPosition.Z += move_distance*0.3;
                }
            }

            else if(receiver->IsKeyDown(KEY_KEY_S))
            {
                dir.Y = 90;
                currentPosition.Z -= move_distance*0.7;
                if(receiver->IsKeyDown(KEY_KEY_A))
                {
                    dir.Y = 135;
                    currentPosition.X -= move_distance*0.7;
                }
                else if(receiver->IsKeyDown(KEY_KEY_D))
                {
                    dir.Y = 45;
                    currentPosition.X += move_distance*0.7;
                }
                else
                {
                    currentPosition.Z -= move_distance*0.3;
                }
            }

            else if(receiver->IsKeyDown(KEY_KEY_A))
            {
                dir.Y = 180;
                currentPosition.X -= move_distance;
            }
            else if(receiver->IsKeyDown(KEY_KEY_D)){
                dir.Y = 360;
                currentPosition.X += move_distance;
            }
            else{
                dir = currentRotation;
                setAnimationType(EMAT_STAND);
            }

            if(dir != currentRotation){
                role->setRotation(dir);
                currentRotation = dir;
            }
            role->setPosition(currentPosition);
        }
    }


    vector3df getCameraPosition(){
        //设置此时相机应该处于的位置
        vector3df pos = currentPosition;
        pos.Y += 50;
        pos.Z -= 50;
        return pos;
    }

private:

    IrrlichtDevice* device; //主设备指针
    MyEventReceiver* receiver;//主类事件接收器
    IAnimatedMeshSceneNode* role;//所代理的节点指针

    bool available;
    EMD2_ANIMATION_TYPE currentAnimationType;
    vector3df currentPosition, currentRotation;;
    f32 MOVEMENT_SPEED;

};

另外,setAnimationType涉及更改动画的API,仅仅适用于MD2格式模型,如有其它需要请重载

第三步就最简单了,只需要在主渲染函数里面更改相机位置即可。

while(device->run())
{
    rDele->render(); //rDele 为主节点代理
    camera->setPosition(rDele->getCameraPosition());

    //其他渲染操作

当然,你还需要一个主Game类来初始化所有变量,载入模型,建立三角碎片选择器,加入碰撞检测与重力等等,就不在这里解释了。

最终的效果就是开头的那张动画。

基于Irrlicht引擎的3D游戏实例V0.1

最近研究Irrlicht引擎,做了个demon,包含如下功能: 1
  • xianyuxiaoqiang
  • xianyuxiaoqiang
  • 2014年07月22日 18:09
  • 544

Irrlicht游戏引擎 初探

Irrlicht引擎在Windows的安装和使用          我是Irrlicht引擎的初学者,在查阅了指导书和网络上的教程之后大概地了解了Irrlicht在Windows中的安装。      ...
  • qq_35040828
  • qq_35040828
  • 2017年03月02日 21:50
  • 99

Irrlicht学习笔记(1)--helloworld

声明: 想研究一下irrlicht引擎,所以先跟着手册和例子学习一下如何使用它. 本文为最基本的irrlicht程序.一个helloworld. 我的平台是win7,使用的是VS2013社区版 ...
  • gqkly
  • gqkly
  • 2016年04月21日 12:13
  • 1617

使用cocosstudio构建横版游戏主角2

昨天实现了从ccs中导出一个动画给2dx使用。不妨就把他当成游戏的主角。今天要实现另外一个基本元素————地图。 ccs提供了地图编辑器,但是做横版四方向游戏还是推荐使用tiled编辑器。他本身是一个...
  • yilagou
  • yilagou
  • 2014年02月26日 00:06
  • 593

3D游戏引擎剖析

原文作者:Jake Simpson 译者: 向海 Email:GameWorldChina@myway.com  第1部分: 游戏引擎介绍, 渲染和构造3D世界 介绍   自Doom游戏时代以来我们已...
  • yiyong0418
  • yiyong0418
  • 2006年09月16日 16:35
  • 2836

Irrlicht学习之创建GUI界面

Irrlicht游戏引擎自带了GUI模块,可以在三维的场景中创建二维的覆盖(Overlay),使得游戏中图标和文字的显示更为方便,配合游戏高效的三维渲染能力,相得益彰。 这一次我将尝...
  • jiangcaiyang123
  • jiangcaiyang123
  • 2013年11月10日 20:03
  • 3118

Irrlicht for android 学习之二: 再编译

文件夹如下: 就是把 Application.mk 拷贝到 jni文件夹下 把 ToRebuild 下的三个文件拷贝到jni 下 把文件夹 IrrlichtSdcard res src To...
  • xuhaiyan8825
  • xuhaiyan8825
  • 2012年12月27日 22:37
  • 2736

Irrlicht 移植到 Android

本文基于windows平台,首先,搭建Android NDK开发环境。这个就不多说了,网上教程有的是。有时间把自己的搭建环境的步骤整理下发上来。1.首先下载Irrlicht Android源码: h...
  • birdflyto206
  • birdflyto206
  • 2016年06月12日 23:51
  • 1523

Unity 2D游戏开发教程之精灵的死亡和重生

Unity 2D游戏开发教程之精灵的死亡和重生
  • u014621518
  • u014621518
  • 2015年09月07日 10:18
  • 899

Irrlicht引擎源码剖析——第二天

今天开始剖析代码,首先看include目录下的Irrlicht.h头文件。开始是关于该引擎的版权声明,然后是一长串预处理——各种头文件,因为这些头文件我们还没看过,所以先不添加,等以后看过了,在一一添...
  • iduosi
  • iduosi
  • 2012年07月25日 19:29
  • 3904
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用Irrlicht构建游戏主角
举报原因:
原因补充:

(最多只允许输入30个字)