{
// 执行我方战机的循环Tick函数 if( m_pMyFighter )
m_pMyFighter->OnFire( fDeltaTime );
}
6、但是我们子弹要发射子弹只有当空格键按下设置CMyFighter的m_bCanFire值为
true。在OnKeyDown方法中添加如下代码;
// 游戏进行中,按下空格发射子弹
if( KEY_SPACE == iKey && NULL != m_pMyFighter ) m_pMyFighter->SetCanFire( true );
7、同理在OnKeyUp中设置m_bCanFire值为false。
实验三 敌方战机
【实验内容】
1、创建一个敌方战机类CEnemyFighter;
2、战机以编辑器中HorizontalSprite_Template精灵为模板; 3、每隔5秒创建一架敌方战机; 4、敌方战机每隔1秒发射一发子弹; 5、敌方战机飞行中上下浮动;
【实验思路】
运用面向对象知识,创建CEnemyFighter类。该类具有点方战机的属性,战机隔一定的事件被复制出来,然后上下浮动,开始向我方战机发射子弹,这样有助于增加敌方战机的杀伤力,也增加了游戏的趣味性。 【实验指导】
1、仿照方便的方法创建CEnemyFighter类,其继承与CSprite类,修改其构造函数。 2、为类增添两个静态变量,一个表示表示创建敌机的数量,一个表示创建敌机的时间;
static floatm_fCreateTime;// 创建敌机的时间间隔
static intm_iCreatedSpriteCount;//表示创建战机数量
并在LessonX.cpp文件最后进行初始化: float CEnemyFighter::m_fCreateTime = 0.f; int CEnemyFighter:: m_iCreatedSpriteCount = 0;
3、为CEnemyFighter类添加一个创建敌方战机的静态方法ClassTick(float fDeltaTime)。
1)在EnemyFighter类中添加函数的声明: void static ClassTick( float fDeltaTime );
2)其参数为游戏的时间间隔。当创建战机的时间间隔递减为0时,创建战机。并重新设置时间间隔时间为5到10秒。
void CEnemyFighter::ClassTick( float fDeltaTime ) //创建敌方战机 {
// 是否到时间创建
m_fCreateTime -= fDeltaTime; if( m_fCreateTime <= 0.f ) {
// 随机一个时间,作为下次出生的时间
8
上海锐格软件有限公司
m_fCreateTime=(float)CSystem::RandomRange( 1, 3 ); //在以下添加创建一架敌方战机的代码 } }
2)创建战机时,只需要战机不显示在世界边界之外就可以,即Y轴坐标在比世界边界的上下边界稍微大一点的范围之间,在此我们设置比世界边界大10个世界坐标单位。在ClassTick方法的if( m_fCreateTime <= 0.f )判断中添加以下代码:
IntiPosBase=CSystem::RandomRange((int)CSystem::GetScreenTop()+10,(int)CSystem::GetScreenBottom() - 10);
2)然后声明一个CEnemyFighter类对象。然后设置敌方飞机X轴和Y轴的坐标,再
次设置速度,设置世界边界碰撞属性,走后设置其碰撞模式以及初始化其成员变量的值。
charszName[MAX_NAME_LEN];
sprintf(szName,\给新建的敌方战机起名 m_iCreatedSpriteCount++;
CEnemyFighter *pSprite=new CEnemyFighter( szName );
pSprite->CloneSprite( \ //克隆模板 intiRandom=CSystem::RandomRange( iPosBase - 10, iPosBase + 10 ); floatfPosX=(int)CSystem::GetScreenRight() + 20.f; pSprite->SetSpritePosition( fPosX, (float)iRandom ); pSprite->SetSpriteLinearVelocityX( -10.f ); pSprite->SetSpriteWorldLimit(WORLD_LIMIT_KILL,
CSystem::GetScreenLeft()-10.f,CSystem::GetScreenTop(),CSystem::GetScreenRight() + 200.f, CSystem::GetScreenBottom() );
pSprite->SetSpriteCollisionActive(true,true);
pSprite->SetHp(300); pSprite->SetScore(100); pSprite->SetType(1);
这里用到sprintf函数,所以应该在EnemyFighter.cpp中包含头文件: #include
4、在添加CEnemyFighter类中添加LoopTick方法,实现在游戏循环时,战机发射子弹
和上下浮动飞行的功能。其参数为,游戏的时间间隔。
1)添加一个成员变量,表示战机创建之后,隔多久才可以开始发射子弹。确保飞机已经被看见,才会发射子弹。
float m_fCanFireAfterCreated;
2)再添加三个成员变量,分别表示子弹的发射间隔,战机飞行时上下浮动的时间
间隔,战机飞行时是上浮还是下浮。
float m_fBulletCreateTime; float m_fFloatTime; bool m_bFloatUp;
注意把这这些变量在构造函数中初始化。
9
3)然后在EnemyFighter.h中声明函数:
void LoopTick( float fDeltaTime );
在EnemyFighter.cpp中对函数进行实现:
void CEnemyFighter::LoopTick( float fDeltaTime ) { }
4)在函数中添加代码,当表示战机创建之后,隔多久才可以开始发射子弹的变量
递减到小于等于0时,开始可以创建子弹,然后开始递减子弹的发射间隔变量,当递减到小于等于0时,战机发射子弹。
m_fCanFireAfterCreated -= fDeltaTime; if( m_fCanFireAfterCreated <= 0.f ) {
m_fBulletCreateTime -= fDeltaTime; if( m_fBulletCreateTime <= 0.f ) {
m_fBulletCreateTime = 1.f;
g_GameMain.CreateBullet(GetSpritePositionX(), GetSpritePositionY()); } }
这里用到g_GameMain这个全局对象,所以应该在EnemyFighter.cpp中包含头文件: #include\
5)添加战机上下浮动的代码。当战机浮动时,首先累计浮动的时间,当浮动时间大于1和小于0时,修改上浮还是下浮的变量值。然后获得战机此时的Y轴坐标,我们设置上下浮动的速度为6,这样就可以计算出浮动后的Y轴坐标。
if( m_bFloatUp ) {
m_fFloatTime += fDeltaTime; if( m_fFloatTime >= 1.f ) {
m_bFloatUp = false; }
floatfPosY=GetSpritePositionY(); fPosY+=6.f * fDeltaTime; SetSpritePositionY( fPosY ); } else {
m_fFloatTime -= fDeltaTime; if( m_fFloatTime <= 0.f ) {
m_bFloatUp = true; }
floatfPosY=GetSpritePositionY();
10
上海锐格软件有限公司 fPosY-=6.f * fDeltaTime; SetSpritePositionY( fPosY ); }
5、在CGameRun中,调用CEnemyFighter类的静态方法ClassTick,让游戏不停的创建敌
方战机。
CEnemyFighter::ClassTick( fDeltaTime );
实验四 敌方战机发射子弹
【实验内容】
1、创建一个精灵链接类;
2、将生成的战机添加到链表中;
【实验思路】
为了便于对各种精灵的管理,我们使用链表来对这些精灵管理,比如精灵发生碰撞之后,我们可以通过遍历链表来判断是链表中的那个精灵发生了碰撞,同样删除操作使用链表也非常的便利。
【实验指导】
1、为CBullet添加一个表示该子弹是谁发射的变量。
intm_iType;
2、在CBullet类构造函数中为此变量赋值,更改构造函数为三个参数:
CBullet::CBullet(const int iType, const char *szName) : CSprite( szName )
{
m_iType = iType; }
3、修改CGameMain类的CreateBullet方法,注意同时修改函数声明。
void CGameMain::CreateBullet( int iType, const float fPosX, const float fPosY ) {
……
if( 1 == iType ) //如果iType值为1,则说明子弹为敌方战机反射。 {
pBullet->SetSpriteLinearVelocityX( -30 ); }
else//其他情况说明为我方战机反射 {
pBullet->SetSpriteFlipX( true ); pBullet->SetSpriteLinearVelocityX( 60 ); }
pBullet->SetScore(100); pBullet->SetDamage(100); pBullet->SetHp(10); pBullet->SetType(iType);
pBullet->SetSpriteCollisionActive(true,true);
11