第四天:开火!
出自Ogre3D开放资源地带
目录 |
前言
经历了前面三天的学习,证明了你确实有毅力,但是不知道你有没有去论坛上面讨论一下bbs.ogre3d.cn。别害羞,提出意见或者问题我们都会来认真的回答和探讨(目前论坛冷冷清清啊~)。如果你之前看过类似的游戏源代码,你会发现我们教程中的过分简单,这是我们刻意保留的特点,尽量做到精简和直观。但如果你希望做一个漂亮和复杂的游戏,仍然有许多工作要做。所以希望你可以亲自参与到教程中来,对我们现在的原形进行一些修改和在加工,如果你心情不错的话更希望你发表在我们的论坛上。你会得到大家的赞许以及积极的反馈。
正文
好了,敌人——那个Ogre3D的头颅在我们上空盘旋。当我们正准备展开反击,却发现:我们忘带枪了,汗。
好吧没有枪炮,我们自己造。
Bullets.h
这里我们写了两个类,一个是子弹:
//3子弹类型
class Bullet
{
public:
Bullet(Ogre::SceneManager * sm);
~Bullet(void);
//3更新子弹
void update(void);
//3检查子弹是否被使用,返回true就是正在被使用中
bool active(void);
//3开火,第一个参数表示开火位置,第二个参数表明开火时的力量
void fire(const Ogre::Vector3 & pos,
const Ogre::Vector3 & force);
//3检查子弹是否射中物体
bool touch(void);
//3执行爆炸动作
void burst(void);
//3检查是否飞行中(激活且没有爆炸)
bool flying(void);
private:
Ogre::Vector3 _force;
Ogre::SceneNode * _node;
Ogre::Entity * _ent;
bool _active;
};
在这里,我们认为子弹有几个不同状态,未激活(在弹夹中)和激活状态,其中激活状态分为飞行中以及爆炸中。
//3子弹管理器
class BulletManager
{
typedef boost::shared_ptr<Bullet> BulletPtr;
typedef std::vector<BulletPtr> BulletPtrList;
public:
BulletManager(Ogre::SceneManager * sm, int n);
//3更新所有激活子弹
void update(void);
//3检查是否击中物体,如果击中,自动爆炸。
Bullet * touch(void);
~BulletManager(void);
//3开火,从已有子弹列表中选择一个没有激活的子弹,
//调用其fire函数,第一个参数表示开火位置,第二个参数表明开火时的力量
bool fire(const Ogre::Vector3 & pos, const Ogre::Vector3 & force);
private:
//子弹队列
BulletPtrList _bullets;
};
我们再提供一个子弹管理器(就当作弹夹的概念好了),在开始的时候里面放置n多没有被激活的子弹,当飞机调用fire时候,会在这些子弹中找到没有激活的子弹发射出去。
Bullets.cpp
Bullet::Bullet(Ogre::SceneManager * sm):
_force(),
_node(NULL),
_ent(NULL),
_active(false)
{
static int i = 0;
//3创建节点
_node = sm->getRootSceneNode()->createChildSceneNode();
//3这里临时用一个球体作为子弹模型,以后再美化
_ent = sm->createEntity(std::string("bullet") +
boost::lexical_cast<std::string>(i++), "sphere.mesh");
//3挂接模型实体
_node->attachObject(_ent);
//3缩放一下
_node->setScale(0.1f, 0.1f, 0.1f);
//3先隐藏着 备用
_ent->setVisible(false);
}
这里做了一些初始化操作,并把子弹的模型先隐藏了。
void Bullet::update(void)
{
//3进行一个位移,不是正确的物理模型,把力量当速度
_node->translate(_force);
}
每次更新的时候(仅当被激活时调用),子弹都匀速移动一个位移,我们可以根据游戏的不同修改这个函数,比如加入跟踪轨迹或者变速运动。
void Bullet::fire(const Ogre::Vector3 & pos, const Ogre::Vector3 & force)
{
_node->setPosition(pos);
_force = force;
_node->setVisible(true);
_active = true;
}
开火的时候我们给出两个向量:发射位置、发射力度。并把子弹状态设置为激活。
后面还有一些关于子弹管理器的代码:
BulletManager::BulletManager(Ogre::SceneManager * sm, int n)
{
//3先放置n个子弹
for(int i = 0; i< n; ++i)
{
_bullets.push_back(BulletPtr(new Bullet(sm)));
}
}
在构造函数里面,我们根据传入的数量构造n个子弹对象。
void BulletManager::update(void)
{
//3更新所有激活的子弹(包括飞行核爆炸)
for(BulletPtrList::iterator it = _bullets.begin();
it != _bullets.end();
++it)
{
if((*it)->active())
(*it)->update();
}
}
每次更新的时候,我们遍历所有子弹,只更新那些激活的实例。
Bullet * BulletManager::touch(void)
{
//3遍历所有 飞行的子弹,看看有没有击中的
for(BulletPtrList::iterator it = _bullets.begin();
it != _bullets.end();
++it)
{
if((*it)->flying())
if((*it)->touch())
{
(*it)->burst();
return (*it).get();
}
}
return NULL;
}
我们提供了一个方法给我们的主角战斗机使用,就是检查所有飞行的子弹,看看是否击中敌人,如果击中就返回子弹对象实例的指针。否则返回空指针。
bool BulletManager::fire(const Ogre::Vector3 & pos,
const Ogre::Vector3 & force)
{
//3开火,在没有激活的子弹中选择一个。如果没有子弹可用就返回false;
for(BulletPtrList::iterator it = _bullets.begin();
it != _bullets.end(); ++it)
{
if(!(*it)->active())
{
(*it)->fire(pos, force);
return true;
}
}
return false;
}
最后这里提供一个“开火”函数,从没有激活的子弹中选取一个发射。
没想到这么制造抢和子弹的代码这么平凡,害得我没办法多讲一些,不过还好,代码和注释就是最好的教程。
现在我们把枪支放置在战斗机上面吧。
其他文件修改
和战斗机对象以及敌人对象不同,我们现在的子弹类型是归属于战斗机拥有管理的。所以它需要修改下面两个战斗机相关的文件:
BattlePlane.h
//3子弹管理器 BulletManager _bulletManager;
在这里我们把子弹管理器对象实例直接作为成员变量使用。
BattlePlane.cpp
void BattlePlane::onKeyReleased(const KeyEvent & evt)
{
//这里省略前面的代码
if(evt.getKey() == KC_SPACE)//3如果释放空格键 发射子弹
_bulletManager.fire(
_node->getPosition(),
Ogre::Vector3(0.0f, 10.0f, 0.0f));
}
在释放键盘空格案件的时候,我们在飞机节点位置发射一颗子弹,其初始速度为(0,10,0)——既向y轴正方向10速度发射。
void BattlePlane::update(void)
{
//3更新子弹
_bulletManager.update();
//这里省略之前的代码
}
别忘了在每一frame中更新子弹位置。
好啦现在编译运行,你就能看到我们的勇猛的战斗机向敌人发射子弹。什么?打不到敌人?哦,我们还没有检测碰撞。没错,要检测子弹是否击中敌人。不过这需要一定量的工作。我们留给下一课吧。
课程结语
你别说我偷懒,把碰撞拿到下一课来实现。我告诉你,现在我偷偷送你一些好东西,咱们不告诉别人。
在BattlePlane.h以及BattlePlane.cpp中我们还有一些没有讲到的Ogre相关的代码。没错,这个就厉害了,他就是我们战斗机的喷射器。 不卖关子了,这是粒子系统。Ogre3D中巴粒子系统已经实现个八九不离十,我们只需要布置一下就好了。不过Ogre3D的讲解不是本教程的主要内容,所以就麻烦大家去ogre3d.cn看看,有什么问题也可以到bbs.ogre3d.cn去讨论。我们就不再这里废话了。
好的好的,今天课程到这里就结束了,虽然可能你仍然意犹未尽,但是我也要睡觉了,最近时间很紧张,你还是自己去看看粒子系统方面的文章吧。
