射击事件,根据我不专业的看法可以分为两种实现,分为快速射击与慢速射击。
通常的射击游戏中,采用“快速射击”类型,也就是瞄准了物体点击射击就一定能射中。而慢速射击运用地比较少,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--;
}
}
这样一来就可以实现射中以后闪动一下的效果
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u013802033/article/details/48093531