在2d游戏中,如何对不需要的动画子画面进行自动隐藏或删除?例如,当一个爆炸子画面的帧动画结束后,需要对此子画面进行删除操作。另外对此前的游戏引擎中,除了对边界动作为BA_DIE的子画面可以对其删除外,还没有提供一个在一些特定时刻需对子画面对象进行删除操作的方法,比如碰撞时需要删除互相碰撞的两个子画面。
首先向Sprite.h中添加2个成员变量。
- BOOL m_bDying; //标记一个子画面是否删除
- BOOL m_bOneCycle; //标记是否显示所有帧之后删除子画面
Sprite()构造函数对其初始化
- m_bDying = FALSE;
- m_bOneCycle = FALSE;
给出一个访问方法,这个方法是删除任何子画面的一种简单有效的方法。
- void Kill() { m_bDying = TRUE; }; //任何子画面对象调用此方法,都会对删除该子画面做好准备
- //Sprite.cpp
- SPRITEACTION Sprite::Update()
- {
- // 查看是否需要删除子画面
- if (m_bDying)
- return SA_KILL;
- // Update the frame
- UpdateFrame();
- ...
- }
在对子画面进行更新时,若子画面已经调用过Kill()方法,则返回子画面的SA_KILL行为,在GameEngine.cpp中会做出相应的删除子画面操作,该操作已经在前面的引擎中给出,这里不再赘述。
另外一种情况是子画面在一次循环绘制帧动画后自动消失。修改代码如下:
- //Sprite.h
- inline void Sprite::UpdateFrame()
- {
- if ((m_iFrameDelay >= 0) && (--m_iFrameTrigger <= 0))
- {
- // Reset the frame trigger;
- m_iFrameTrigger = m_iFrameDelay;
- // Increment the frame
- if (++m_iCurFrame >= m_iNumFrames)
- {
- // If it's a one-cycle frame animation, kill the sprite
- if (m_bOneCycle)
- m_bDying = TRUE;
- else
- m_iCurFrame = 0;
- }
- }
- }
成员变量m_bOneCycle在SetNumFrames()方法中设置
- //Sprite.h
- inline void Sprite::SetNumFrames(int iNumFrames, BOOL bOneCycle)
- {
- ...
- m_bOneCycle = bOneCycle;
- ...
- }
该方法的声明修改如下:
- void SetNumFrames(int iNumFrames, BOOL bOneCycle = FALSE);
对其余须设置帧数的方法没有影响,只对需要一次循环后消失的子画面有效,传入的第2个参数为TRUE即可。
最后新增1个游戏函数:
- //GameEngine.h
- void SpriteDying(Sprite* pSpriteDying); //新增游戏函数
在对子画面删除前调用它,为什么要这样做呢?可以看作是破坏子画面的后果。比如当导弹子画面撞上行星子画面,行星子画面消失后会产生爆炸声及爆炸子画面,所以在这个函数中就可以进行这些操作。
以下是调用:
- //GameEngine.cpp
- void GameEngine::UpdateSprites()
- {
- ...
- if (saSpriteAction & SA_KILL)
- {
- // Notify the game that the sprite is dying
- SpriteDying(*siSprite);
- // Kill the sprite
- delete (*siSprite);
- m_vSprites.erase(siSprite);
- siSprite--;
- continue;
- }
- ...
- }
定义该函数的操作在特定的游戏代码中。