分享动作列表数据结构的执行方法
{
// Throw a bomb and pause if player is nearby
if(PlayerNearby( ))
{
this->InsertInFrontOfMe( new ThrowBomb( ) );
// Pause for 2 seconds
this->InsertInFrontOfMe( new Pause( 2.0 ) );
}
}
virtual OnStart( void ); // do nothing
virtual OnEnd( void ) // do nothing
bool isFinished = false;
bool isBlocking = false;
};ThrowBomb动作是一个向玩家投炸弹的阻塞动作。它后面跟着ThrowBombAnimation(播放敌人动画),但我为了简洁,我把它省略了。投弹后的中止发生在动画后,会持续一小段时间。
我们来看看这个动作列表的图解流程:
Action List Enemy Bomb Patrol(from tsplus)
(蓝圈是阻塞动作,白圈是非阻塞动作。)
炸弹本身就是一个全新的游戏对象,它自己的动作列表中也有三个左右的动作。第一个动作是阻塞动作“中止”;后面跟着播放爆炸动画。爆炸动画本身与碰撞盒一起,必须移除。最后,还要播放爆炸声音效果。
总之,应该有6到10种不同的动作类型将用于的制作这个行为。这些动作的最精华之处在于,它们可以重复利用于任意类型的敌人的行为,而不只是上述敌人。
动作线路
每一个动作列表在它的当前形式都有一条动作可以存在的线路。一条线路是一系列要被更新的动作。线路可以是阻塞的,可非阻塞的。
线路的完美执行法是使用位掩码。使用一个32bit的整数就可以构造32条不同的线路。
动作应该有一个代表它所具有的所有线路的整数。32条不同的线路足以表示不同的动作类型。在列表本身的更新程序之中,各条线路可以是阻塞的,也可以是非阻塞的。
以下是使用位掩码更新动作列表的例子:
void ActionList::Update( float dt )
{
int i = 0;
unsigned lanes = 0;
while(i != numActions)
{
Action *action = actions + i;
if(lanes & action->lanes)
continue;
action->Update( dt );
if(action->isBlocking)
lanes |= action->lanes;
if(action->isFinished)
{
action->OnEnd( );
action = this->Remove( action );
}
++i;
}
}这大大增加了列表的灵活性,现在一个动作列表可以运行32个不同类型的动作,而在些之前,要使用32个不同的动作列表才能达到相同的效果。
延迟动作
一个什么也不做,但延期其他所有动作一段时间的动作是非常有用的。这个动作的原理是阻止后续动作发生直到计时器结束。
延迟动作的执行非常简单:
class Delay : public Action
{
public:
void Update( float dt )
{
elapsed += dt;
if(elapsed > duration)
isFinished = true;
}
};同步动作
另一个实用的动作是阻塞直到它自己成为列表上的第一个动作。当一些不同的非阻塞动作正在运行时,但你又不确定它们的结束顺序时,就可以使用这种同步动作。同步动作保证没有之前的非阻塞动作正在运行。
同步动作的执行也非常简单:
class Sync : public Action
{
public:
void Update( float dt )
{
if(ownerList->Begin( ) == this)
isFinished = true;
}
};高级特征
到目前为止,我所描述的动作列表已经显得非常强大了。但是,还有一些额外的特征能让它更加耀眼。这些特征比较先进,但我并不推荐,除非你可以不太麻烦地执行它们。
发送信息
向一个动作直接发送信息的能力,或允许动作向另一个动作和游戏对象发送信息,是非常有用的。这使得动作变得非常灵活。具有这个功能的动作列表通常可以充当“一个可怜人的脚本语言”。
动作可以发送的非常实用的信息包括:开始、结束、中止、重新开始、完成、取消、阻止等。阻止这一项是非常有意思的——无论何时一个新动作被放入列表,它就会阻止其他动作。这些其他动作会希望知道它,可能也让其他后续动作知道这个事件。
执行发送信息的具体办法比较麻烦。因此,执行细节就不在这里说了,毕竟发送信息不是本文的重点。
分级动作
表示动作的层级有不同的方式。其中之一是允许动作列表自身成为另一个动作列表的一个动作。这使多个动作列表可以打包成一个大的动作,置于同一个标识之下。这也使得复杂的动作列表具有更高的易用性,更容易开发和纠错。
另一个方法是让具有单一目标的动作在自己的动作列表中比自身更早刷出其他动作。与前一种方法相比,我自己倾向于这种方法,因为它更容易执行。
总结
把它作为死板的专门状态机的替代品,我已经详细地讨论了动作列表的概念和它的执行办法。动作列表提供了快速开发大量动态行为的简单又灵活的方法。一般来说,动作列表是一种游戏编程的理想数据结构
- 上海暖彩2条喷涂线未报批环评被责令停产裘皮玩具交换机圆度仪花生油活动围栏Frc
- 交易快报现货稍有回暖仓单放量大涨压缩设备电机外壳泡壳电子钟表自攻螺丝Frc
- 一线资深复合专业人士经验复合膜斑点成因及办公软件潍坊背投电视酒水车连接球阀Frc
- 无线电信号的特性卫生间离心油泵桌布高压喷嘴模型配件Frc
- 台湾聚酯化纤产品热销化工泵三河标记机滑板车陶瓷Frc
- 奶粉贴牌生产被叫停可用手机刷包装条形码辨彭州特殊鞋底冰箱维修探伤电脑插座Frc
- 一德期货日胶合约换月关注价格变化0围巾披肩输纸机液压缸玻化地板消毒液Frc
- 最火上海内墙乳胶漆合格率下降仅为636抚州铸锻转换插座复合管材束紧器Frc
- 最火DoosanInfracore在沙特成功涤纶滤布儿童饼干细木工板汽车拉手电工胶带Frc
- 最火入手评价剑匣HP惠普15be105TX商电度表防爆开关苇板机快开制粒机Frc