第8章 创建敌方角色
本章讨论Drone Grid游戏中敌方角色的创建,包括Arena对象和坦克角色,其复杂程度也随之上升。为了理解敌方角色的行为,我们需要考查与有限状态机相关的基本概念及其相关类(由计算机控制的坦克角色)。随后,本章将探讨实现坦克角色的其他类。最后,我们还将通过示例展示相关类的应用方式。
8.1 创建Arena对象
Arena对象是一类简单的敌方角色对象,并可在重力网格区域内行进。此类角色在重力网格内以直线方式移动,直至到达网格边界或与玩家金字塔碰撞。在到达网格边界或与金字塔碰撞后,该对象将以相反的方向运动,并保持相同的速度。
ArenaObject3d类继承自Object3d类,如下所示。
public class ArenaObject3d extends Object3d
m_ArenaObjectID变量可加载一个字符串,用以标识游戏场景中的个体对象,如下所示。
private String m_ArenaObjectID = "None";
m_XmaxBoundary和m_XminBoundary变量分别加载游戏网格或游戏场景中沿x轴的最大和最小边界值,如下所示。
private float m_XMaxBoundary = 1;
private float m_XMinBoundary = 0;
m_ZmaxBoundary和m_ZminBoundary变量分别加载游戏场景中沿z轴的最大和最小边界值,如下所示。
private float m_ZMaxBoundary = 1;
private float m_ZMinBoundary = 0;
当Arena对象与地面碰撞时,m_HitGroundSFXIndex变量加载播放音效的句柄(如果存在),如下所示。
private int m_HitGroundSFXIndex = -1;
当Arena对象爆炸时,m_ExplosionSFXIndex变量加载播放音效的句柄,如下所示。
private int m_ExplosionSFXIndex = -1;
ArenaObject3d()构造函数调用Object3d类的构造函数,随后针对Arena对象设置游戏场景边界,如代码清单8.1所示。
代码清单8.1 ArenaObject3d()构造函数
ArenaObject3d(Context iContext, Mesh iMesh, MeshEx iMeshEx, Texture[] iTextures, Material iMaterial,Shader iShader, float XMaxBoundary,float XMinBoundary,float ZMaxBoundary,float ZMinBoundary)
{
super(iContext, iMesh, iMeshEx, iTextures, iMaterial, iShader);
m_XMaxBoundary = XMaxBoundary;
m_XMinBoundary = XMinBoundary;
m_ZMaxBoundary = ZMaxBoundary;
m_ZMinBoundary = ZMinBoundary;
}
通过创建声音的资源ID和加载该声音的声音池并调用Object3d类中的AddSound()函数,CreateExplosionSFX()函数创建一个新的爆炸音效。相应地,m_ExplosionSFXIndex变量加载新创建声音的索引,如代码清单8.2所示。
代码清单8.2 创建爆炸音效
void CreateExplosionSFX(SoundPool Pool, int ResourceID)
{
m_ExplosionSFXIndex = AddSound(Pool, ResourceID);
}
PlayExplosionSFX()函数播放爆炸的音效(如果存在),也就是说,利用爆炸音效索引调用Object3d类中的PlaySound()函数,如代码清单8.3所示。
代码清单8.3 播放爆炸音效
void PlayExplosionSFX()
{
if (m_ExplosionSFXIndex >= 0)
{
PlaySound(m_ExplosionSFXIndex);
}
}
通过音效的资源ID和该声音所存储的声音池并调用Object3d类中的AddSound()函数,CreateHitGroundSFX()函数创建一个新的音效。随后,新创建的声音索引被返回并被置于m_HitGroundSFXIndex中,如代码清单8.4所示。
代码清单8.4 创建撞击地面的音效
void CreateHitGroundSFX(SoundPool Pool, int ResourceID)
{
m_HitGroundSFXIndex = AddSound(Pool, ResourceID);
}
PlayHitGoundSFX()函数针对Arena对象撞击地面播放其音效,如代码清单8.5所示。
代码清单8.5 播放撞击地面的音效
void PlayHitGoundSFX()
{
if (m_HitGroundSFXIndex >= 0)
{
PlaySound(m_HitGroundSFXIndex);
}
}
RenderArenaObject()函数负责将Arena对象绘制至屏幕上。此外还测试对象是否刚好撞击地面。若是,则播放撞击地面的音效,并重置Physics类中的撞击地面的状态,如代码清单8.6所示。
代码清单8.6 渲染Arena对象
void RenderArenaObject(Camera Cam, PointLight light)
{
// Object hits ground
boolean ShakeCamera = GetObjectPhysics().GetHitGroundStatus();
if (ShakeCamera)
{
GetObjectPhysics().ClearHitGroundStatus();
PlayHitGoundSFX();
}
DrawObject(Cam, light);
}
UpdateArenaObject()函数负责更新Arena敌方角色对象,如代码清单8.7所示。
代码清单8.7 更新Arena对象
void UpdateArenaObject()
{
if (IsVisible() == true)
{
// Check Bounds for Z
if (m_Orientation.GetPosition().z >= m_ZMaxBoundary)
{
Vector3 v = GetObjectPhysics().GetVelocity();
if (v.z > 0)
{
v.z = -v.z;
}
}
else
if (m_Orientation.GetPosition().z <= m_ZMinBoundary)
{
Vector3 v = GetObjectPhysics().GetVelocity();
if (v.z < 0)
{
v.z = -v.z;
}
}
// Check bounds for X
if (m_Orientation.GetPosition().x >= m_XMaxBoundary)
{
Vector3 v = GetObjectPhysics().GetVelocity();
if (v.x > 0)
{
v.x = -v.x;
}
}
if (m_Orientation.GetPosition().x <= m_XMinBoundary)
{
Vector3 v = GetObjectPhysics().GetVelocity();
if (v.x < 0)
{
v.x = -v.x;
}
}
}
// Update Physics for this object
UpdateObject3d();
}
UpdateArenaObject()函数执行下列各项操作。
(1)如果对象处于可见状态,则UpdateArenaObject()函数持续更新操作;否则该函数将返回。
(2)检查最大z边界,以查看对象是否位于其外部,若是且远离边界,则逆置对象速度的z分量。随后检查最小z边界,以查看对象是否位于外部,若是且远离边界,则逆置对象速度的z分量。
(3)针对x边界,重复步骤(2),并逆置对象速度的x分量,而非z分量。
图8.1显示了当前Arena对象示例。另外,本章后续示例还将使用该对象。