Irrlicht 实现射击事件

3 篇文章 0 订阅

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

  • 快速射击:子弹的飞行时间不计,所有距离都一瞬间到达。在按下射击的一瞬间判断由准心发出的射线与物体的相交情况,所交物体被击中。
  • 慢速射击:子弹速度有限。这时候子弹作为一个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--;
        }
}

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值