接下來(lái)就像填充積木一樣慷彤,把GameScene里用到的東西一個(gè)個(gè)寫完~~
先來(lái)個(gè)最簡(jiǎn)單的娄蔼。GameBomb
一目了然
public class GameBomb : GameObject
{
public bool IsLive;
private int FrameIndex;
private int FrameMax;
private float FrameDelay;
private int FrameWidth;
private int FrameHeight;
private int FrameHalfWidth;
private int FrameHalfHeight;
private float time;
public GameBomb(Vector2 position, bool isBig, float duration)
{
this.Position = position;
this.FrameIndex = 0;
this.FrameMax = Config.BombSmallFrameMax;
this.FrameWidth = Config.BombSmallFrameWidth;
this.FrameHeight = Config.BombSmallFrameHeight;
this.FrameHalfWidth = this.FrameWidth / 2;
this.FrameHalfHeight = this.FrameHeight / 2;
this.FrameDelay = duration / (float)this.FrameMax;
this.IsLive = true;
}
public override void Update(float elapsedTime)
{
if ( IsLive == false )
{
return;
}
time += elapsedTime;
if ( time >= FrameDelay )
{
time -= FrameDelay;
FrameIndex++;
if ( FrameIndex >= FrameMax )
{
IsLive = false;
}
}
}
public override void Render(Graphics g)
{
if ( IsLive == false )
{
return;
}
g.DrawImage(Data.BombSource,
new Rectangle((int)Position.X - FrameHalfWidth, (int)Position.Y - FrameHalfHeight, FrameWidth, FrameHeight),
new Rectangle(FrameWidth * FrameIndex, 0, FrameWidth, FrameHeight),
GraphicsUnit.Pixel);
}
}
如果不熟悉的,估計(jì)是對(duì)2D類的精靈動(dòng)畫不太了解底哗。岁诉。可以百度了解下跋选。
或者簡(jiǎn)單講解涕癣,就是按照時(shí)間,不斷的繪制一樣圖片中不同位置的精靈~看起來(lái)就像動(dòng)態(tài)的了前标。
接下來(lái)是它的管理類GameBombManager
public static class GameBombManager
{
private static List<GameBomb> mBombs = new List<GameBomb>();
public static void AddBomb(Vector2 position, bool isBig, float duration)
{
mBombs.Add(new GameBomb(position, isBig, duration));
}
public static void Update(float elapsedTime)
{
for ( int i = 0; i < mBombs.Count; i++ )
{
mBombs[i].Update(elapsedTime);
if ( mBombs[i].IsLive == false )
{
mBombs.RemoveAt(i);
i--;
continue;
}
}
}
public static void Render(Graphics g)
{
foreach ( GameBomb bomb in mBombs )
{
bomb.Render(g);
}
}
}
這個(gè)看起來(lái)就比我們之前見過的簡(jiǎn)單多了坠韩。
好,這章就這么結(jié)束了:蛏同眯!貌似有點(diǎn)少啊。唯鸭。须蜗。
好吧,那接下來(lái)講一個(gè)與本游戲無(wú)關(guān)的目溉,粒子系統(tǒng)(其實(shí)粒子系統(tǒng)在游戲中很重要明肮,只是這個(gè)游戲很簡(jiǎn)單,沒有用到而已)
public struct GameParticle
{
/// <summary>
/// 粒子位置
/// </summary>
public Vector2 Position;
/// <summary>
/// 粒子速度
/// </summary>
public Vector2 Velocity;
/// <summary>
/// 重力加速度
/// </summary>
public float Gravity;
/// <summary>
/// 直線加速度(運(yùn)動(dòng)方向上的加速度)
/// </summary>
public float RadialAccel;
/// <summary>
/// 切線上的加速度(角速度)
/// </summary>
public float TangentialAccel;
/// <summary>
/// 粒子旋轉(zhuǎn)角度
/// </summary>
public float Spin;
/// <summary>
/// 粒子旋轉(zhuǎn)速度增量
/// </summary>
public float SpinDelta;
/// <summary>
/// 粒子大小
/// </summary>
public float Size;
/// <summary>
/// 粒子大小增量
/// </summary>
public float SizeDelta;
/// <summary>
/// 粒子生存時(shí)間
/// </summary>
public float Age;
/// <summary>
/// 粒子死亡時(shí)間
/// </summary>
public float TerminalAge;
}
/// <summary>
/// 粒子配置信息
/// </summary>
public struct GameParticleSystemInfo
{
/// <summary>
/// 粒子貼圖
/// </summary>
public Bitmap Texture;
/// <summary>
/// 每秒發(fā)射的粒子數(shù)量
/// </summary>
public int Emission;
/// <summary>
/// 生命周期
/// </summary>
public float LifeTime;
/// <summary>
/// 粒子生命周期范圍
/// </summary>
public Range ParticleLife;
/// <summary>
/// 方向
/// </summary>
public float Direction;
/// <summary>
/// 偏移角度
/// </summary>
public float Spread;
/// <summary>
/// 是否為絕對(duì)值(計(jì)算生成粒子的初始速度)
/// </summary>
public bool IsRelative;
/// <summary>
/// 速度范圍
/// </summary>
public Range Speed;
/// <summary>
/// 重力加速度范圍
/// </summary>
public Range Gravity;
/// <summary>
/// 直線加速度范圍
/// </summary>
public Range RadialAccel;
/// <summary>
/// 切線角加速度范圍
/// </summary>
public Range TangentialAccel;
/// <summary>
/// 起始大小
/// </summary>
public float SizeStart;
/// <summary>
/// 最終大小
/// </summary>
public float SizeEnd;
/// <summary>
/// 大小變化量
/// </summary>
public float SizeVar;
/// <summary>
/// 起始旋轉(zhuǎn)角度
/// </summary>
public float SpinStart;
/// <summary>
/// 最終旋轉(zhuǎn)角度
/// </summary>
public float SpinEnd;
/// <summary>
/// 角度變化值
/// </summary>
public float SpinVar;
}
/// <summary>
/// 粒子系統(tǒng)
/// </summary>
public class GameParticleSystem
{
/// <summary>
/// 粒子最大數(shù)量
/// </summary>
public const int MaxParticles = 512;
/// <summary>
/// 粒子系統(tǒng)未啟動(dòng)
/// </summary>
public const float Particle_System_Not_Start = -2.0f;
/// <summary>
/// 粒子發(fā)射器的配置信息
/// </summary>
public GameParticleSystemInfo Info;
private GameParticle[] mParticles; // 粒子集合
/// <summary>
/// 剩余時(shí)間
/// </summary>
private float Age;
/// <summary>
/// 剩余未發(fā)射粒子
/// </summary>
private float EmissionResidue;
private Vector2 PrevPosition; // 上一個(gè)位置
private Vector2 Position; // 當(dāng)前位置
private Vector2 Offset; // 偏移量
private float Scale; // 整體縮放系數(shù)
/// <summary>
/// 活動(dòng)粒子個(gè)數(shù)
/// </summary>
private int ParticlesAlive;
public GameParticleSystem(GameParticleSystemInfo info)
{
this.mParticles = new GameParticle[MaxParticles];
this.Info = info;
this.Position = new Vector2(0, 0);
this.PrevPosition = new Vector2(0, 0);
this.Offset = new Vector2(0, 0);
this.Scale = 1.0f;
this.EmissionResidue = 0;
this.ParticlesAlive = 0;
this.Age = Particle_System_Not_Start;
}
/// <summary>
/// 移動(dòng)粒子發(fā)射器到制動(dòng)位置
/// </summary>
/// <param name="x">橫坐標(biāo)</param>
/// <param name="y">縱坐標(biāo)</param>
/// <param name="moveParticles">是否移動(dòng)活動(dòng)粒子</param>
public void MoveTo(float x, float y, bool moveParticles)
{
float dx = 0;
float dy = 0;
if ( moveParticles )
{
dx = x - Position.X;
dy = y - Position.Y;
for ( int i = 0; i < ParticlesAlive; i++ )
{
mParticles[i].Position.X += dx;
mParticles[i].Position.Y += dy;
}
PrevPosition.X = PrevPosition.X + dx;
PrevPosition.Y = PrevPosition.Y + dy;
}
else
{
if ( Age == Particle_System_Not_Start )
{
PrevPosition.X = x;
PrevPosition.Y = y;
}
else
{
PrevPosition.X = Position.X;
PrevPosition.Y = Position.Y;
}
}
Position.X = x;
Position.Y = y;
}
/// <summary>
/// 啟動(dòng)粒子系統(tǒng)
/// </summary>
public void Start()
{
if ( Info.LifeTime == -1.0f )
{
Age = -1.0f;
}
else
{
Age = 0;
}
}
/// <summary>
/// 在指定位置啟動(dòng)粒子系統(tǒng)
/// </summary>
/// <param name="x">橫坐標(biāo)</param>
/// <param name="y">縱坐標(biāo)</param>
public void Start(float x, float y)
{
Stop(false);
MoveTo(x, y, false);
Start();
}
/// <summary>
/// 停止粒子系統(tǒng)
/// </summary>
/// <param name="killParticles">是否摧毀活動(dòng)粒子</param>
public void Stop(bool killParticles)
{
Age = Particle_System_Not_Start;
if ( killParticles )
{
ParticlesAlive = 0;
}
}
public float GetAge()
{
return Age;
}
public void Update(float elapsedTime)
{
float ang = 0;
Vector2 accel1;
Vector2 accel2;
if ( Age >= 0 )
{
Age += elapsedTime;
if ( Age >= Info.LifeTime )
{
Age = Particle_System_Not_Start;
}
}
for ( int i = 0; i < ParticlesAlive; i++ )
{
mParticles[i].Age += elapsedTime;
if ( mParticles[i].Age >= mParticles[i].TerminalAge )
{
ParticlesAlive--;
mParticles[i] = mParticles[ParticlesAlive];
i--;
continue;
}
// 計(jì)算粒子直線加速度
accel1 = mParticles[i].Position - Position;
accel1.Normalize();
accel2 = accel1;
accel1 = accel1 * mParticles[i].RadialAccel;
// 計(jì)算粒子切線加速度
ang = accel2.X;
accel2.X = -accel2.Y;
accel2.Y = ang;
accel2 = accel2 * mParticles[i].TangentialAccel;
// 計(jì)算粒子速度
mParticles[i].Velocity += (accel1 + accel2) * elapsedTime;
mParticles[i].Velocity.Y += mParticles[i].Gravity * elapsedTime;
mParticles[i].Position += mParticles[i].Velocity * elapsedTime;
mParticles[i].Spin += mParticles[i].SpinDelta;
mParticles[i].Size += mParticles[i].SizeDelta;
}
if ( Age != Particle_System_Not_Start )
{
// 計(jì)算需要生成的粒子數(shù)量
float ParticlesNeeded = Info.Emission * elapsedTime + EmissionResidue;
int ParticlesCreated = (int)((uint)ParticlesNeeded);
EmissionResidue = ParticlesNeeded - ParticlesCreated;
int n = ParticlesAlive;
for ( int i = n; i < n + ParticlesCreated; i++ )
{
if ( ParticlesAlive >= MaxParticles )
{
break;
}
mParticles[i].Age = 0;
mParticles[i].TerminalAge = Info.ParticleLife.Get();
mParticles[i].Position = PrevPosition + (Position - PrevPosition) * Helper.GetRandomFloat(0, 1);
mParticles[i].Position.X += Helper.GetRandomFloat(-2.0f, 2.0f);
mParticles[i].Position.Y += Helper.GetRandomFloat(-2.0f, 2.0f);
ang = Info.Direction - Data.TwoPI + Helper.GetRandomFloat(0, Info.Spread) - Info.Spread / 2.0f;
if ( Info.IsRelative )
{
ang += (PrevPosition - Position).Angle() + Data.TwoPI;
}
mParticles[i].Velocity.X = (float)Math.Cos(ang);
mParticles[i].Velocity.Y = (float)Math.Sin(ang);
mParticles[i].Velocity *= Info.Speed.Get();
mParticles[i].Gravity = Info.Gravity.Get();
mParticles[i].RadialAccel = Info.RadialAccel.Get();
mParticles[i].TangentialAccel = Info.TangentialAccel.Get();
mParticles[i].Size = Helper.GetRandomFloat(Info.SizeStart, Info.SizeStart + (Info.SizeEnd - Info.SizeStart) * Info.SizeVar);
mParticles[i].SizeDelta = (Info.SizeEnd - mParticles[i].Size) / mParticles[i].TerminalAge;
mParticles[i].Spin = Helper.GetRandomFloat(Info.SpinStart, Info.SpinStart + (Info.SpinEnd - Info.SpinStart) * Info.SpinVar);
mParticles[i].SpinDelta = (Info.SpinEnd - mParticles[i].Spin) / mParticles[i].TerminalAge;
ParticlesAlive++;
}
}
PrevPosition = Position;
}
public void Render(Graphics g)
{
for ( int i = 0; i < ParticlesAlive; i++ )
{
g.DrawImage(Data.BulletSource,
new Rectangle((int)(mParticles[i].Position.X * Scale + Offset.X),
(int)(mParticles[i].Position.Y * Scale + Offset.Y),
(int)(16.0f * Scale),
(int)(16.0f * Scale)),
new Rectangle(0, 0, 16, 16),
GraphicsUnit.Pixel);
}
}
}
/// <summary>
/// 粒子管理器
/// </summary>
public class GameParticleManager
{
/// <summary>
/// 粒子系統(tǒng)最大個(gè)數(shù)
/// </summary>
public const int MaxParticleSystem = 10;
private GameParticleSystem[] mPSList;
private int mPSCount;
private Vector2 mOffset;
public Vector2 Offset
{
get
{
return mOffset;
}
set
{
mOffset = value;
for ( int i = 0; i < mPSCount; i++ )
{
mPSList[i].MoveTo(mOffset.X, mOffset.Y, false);
}
}
}
public GameParticleManager()
{
mPSList = new GameParticleSystem[MaxParticleSystem];
mOffset = new Vector2(0, 0);
mPSCount = 0;
}
public void Spwan(float x, float y, GameParticleSystemInfo info)
{
if ( mPSCount >= MaxParticleSystem )
{
return;
}
mPSList[mPSCount] = new GameParticleSystem(info);
mPSList[mPSCount].Start(x, y);
mPSCount++;
}
public bool IsAlive(GameParticleSystem psi)
{
for ( int i = 0; i < mPSCount; i++ )
{
if ( mPSList[i] == psi )
{
return true;
}
}
return false;
}
public void Kill(GameParticleSystem psi)
{
for ( int i = 0; i < mPSCount; i++ )
{
if ( mPSList[i] == psi )
{
mPSList[i] = mPSList[mPSCount - 1];
mPSCount--;
return;
}
}
}
public void KillAll()
{
mPSCount = 0;
}
public void Update(float elapsedTime)
{
for ( int i = 0; i < mPSCount; i++ )
{
mPSList[i].Update(elapsedTime);
if ( mPSList[i].GetAge() == GameParticleSystem.Particle_System_Not_Start )
{
mPSList[i] = mPSList[mPSCount - 1];
mPSCount--;
i--;
}
}
}
public void Render(Graphics g)
{
for ( int i = 0; i < mPSCount; i++ )
{
mPSList[i].Render(g);
}
}
}