码迷,mamicode.com
首页 > 其他好文 > 详细

Irrlicht 实现射击事件

时间:2015-08-30 01:08:42      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:游戏   irrlicht   

射击事件,根据我不专业的看法可以分为两种实现,分为快速射击与慢速射击。

  • 快速射击:子弹的飞行时间不计,所有距离都一瞬间到达。在按下射击的一瞬间判断由准心发出的射线与物体的相交情况,所交物体被击中。
  • 慢速射击:子弹速度有限。这时候子弹作为一个FPS对象,需要被实时跟踪,直到它与某个物体碰撞或者到达无穷远。被瞄准的对象可以躲开子弹。

通常的射击游戏中,采用“快速射击”类型,也就是瞄准了物体点击射击就一定能射中。而慢速射击运用地比较少,FPS对象的开销其实很不必要。

本文所说的是”快速射击“。效果是射中一个怪物后他会闪一下(掉血即视感,既高亮一小段时间)。如图

技术分享

首先,创建一个可以被射击的怪物

void  Game0::setUpMonster()
{
    scene::IAnimatedMeshSceneNode* yodanNode =
        smgr->addAnimatedMeshSceneNode(
        smgr->getMesh("../../media/yodan.mdl"),
        0,
        IDFlag_IsShootable //可被射击的标识
        );

    if (yodanNode)
    {
        scene::ISceneNodeAnimator* anim =
            smgr->createFlyStraightAnimator(core::vector3df(300,-50,20),
                                            core::vector3df(-300,-50,20), 5500, true);
        if (anim)
        {
            yodanNode->addAnimator(anim);
            anim->drop();
        }

        yodanNode->setMaterialFlag(video::EMF_LIGHTING, true); //使用光照

        yodanNode->setFrameLoop(0, 13);
        yodanNode->setAnimationSpeed(15);
        yodanNode->setRotation(core::vector3df(0,180,0));

        scene::ITriangleSelector* selector = smgr->createTriangleSelector(yodanNode);
        yodanNode->setTriangleSelector(selector);//增加三角选择器
        selector->drop();

    }
}

接下来,就是要在主循环中实时更新准心是否瞄准到了这个节点

while(device->run())
    {
        if (device->isWindowActive())
        {
            driver->beginScene(true, true, video::SColor(0,0,0,0));

            smgr->drawAll();

            this->unLight();
            //恢复光照,下面讲到


        //创建射线
            core::line3d<f32> ray;
            ray.start = camera->getPosition();
            ray.end = ray.start + (camera->getTarget() - ray.start).normalize() * 1000.0f;
            //交点位置
            core::vector3df intersection;
            //所交三角形
            core::triangle3df hitTriangle;

    //获取与ray所交三角形所属节点
            scene::ISceneNode * selectedSceneNode =
                collMan->getSceneNodeAndCollisionPointFromRay(
                    ray,
                    intersection,
                    hitTriangle);

            当前所交的节点
            this->currentSceneNode = NULL;

            if(selectedSceneNode)
            {
                if((selectedSceneNode->getID() & IDFlag_IsShootable) == IDFlag_IsShootable)
                //所交节点ID满足可被射击条件
                {
                    this->currentSceneNode = selectedSceneNode;
                }
            }

            driver->endScene();
      }
  }

这样一来,任何时候我们都可以知道瞄准的节点是否可以被射击(在本例中就是那个唯一的yodan节点)。接下来就是按下某个键调用的shoot函数了。

void  Game0::shoot()
{
    if(this->currentSceneNode)
    //此时瞄准了一个可被射击的节点
    {
           this->currentSceneNode->setMaterialFlag(video::EMF_LIGHTING, false);
           //关闭此节点的光照,让此节点高亮(按照模型原始的颜色渲染)
           LightedNode lnode(this->currentSceneNode,device->getTimer()->getTime()+100);
           //第二个参数是次节点该取消高亮的时间
           //可以看出高亮的时长为0.1s
           this->lightedNodes.push_back(lnode);
           //把这个节点加入到一个队列中,一段时间后取消高亮
    }
 }

这样一来上面提到的 unlight 函数就水到渠成了。它的作用就是判断当前的高亮队列中哪些节点高亮时间到了,取消其高亮

void Game0::unLight()
{
    u32 now = device->getTimer()->getTime();

    for (s32 i=0; i<(s32)this->lightedNodes.size(); ++i)
        if (now > lightedNodes[i].when )
        {
            lightedNodes[i].node->setMaterialFlag(video::EMF_LIGHTING, true);
            lightedNodes.erase(i);
            i--;
        }
}

这样一来就可以实现射中以后闪动一下的效果

版权声明:本文为博主原创文章,未经博主允许不得转载。

Irrlicht 实现射击事件

标签:游戏   irrlicht   

原文地址:http://blog.csdn.net/u013802033/article/details/48093531

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!