📄 worldobject.cs
字号:
DuckCycle.EndCell = int.Parse((string)dr["DuckEndCell"],
CultureInfo.InvariantCulture);
x = float.Parse((string)dr["DuckBoundsX"],
CultureInfo.InvariantCulture);
y = float.Parse((string)dr["DuckBoundsY"],
CultureInfo.InvariantCulture);
r = float.Parse((string)dr["DuckBoundsRadius"],
CultureInfo.InvariantCulture);
DuckCycle.Bounds = new Bounds(x, y, r);
// Death
DeathCycle.AnimationRate = int.Parse(
(string)dr["DeathAnimationRate"],
CultureInfo.InvariantCulture);
DeathCycle.StartCell = int.Parse((string)dr["DeathStartCell"],
CultureInfo.InvariantCulture);
DeathCycle.EndCell = int.Parse((string)dr["DeathEndCell"],
CultureInfo.InvariantCulture);
// General info
worldXValue = float.Parse((string)dr["X"],
CultureInfo.InvariantCulture);
worldYValue = float.Parse((string)dr["Y"],
CultureInfo.InvariantCulture);
activateDistance = float.Parse((string)dr["ActivateDistance"],
CultureInfo.InvariantCulture);
collidableValue = bool.Parse((string)dr["Collidable"]);
// Animation
int animationId = int.Parse((string)dr["AnimationId"],
CultureInfo.InvariantCulture);
Debug.Assert(animationId >= 0 &&
animationId < lev.AnimationList.Count,
"WorldObject.WorldObject: Animatin ID out of range");
animationValue = new Animation(
(Animation)lev.AnimationList[animationId], 0, 0);
Debug.Assert(animationValue != null && animationValue.Init,
"WorldObject.WorldObject: Failed to initialize animation");
// AI
int aiId = int.Parse((string)dr["AIId"],
CultureInfo.InvariantCulture);
if (aiId >= 0)
{
Debug.Assert(aiId < lev.AIList.Count,
"WorldObject.WorldObject: AI Id out of range");
AILogic = AIHandler.Create((AI)lev.AIList[aiId]);
AILogic.Init(this, lev);
}
// Draw options
if (bool.Parse((string)dr["Transparency"]))
{
DrawOptions = DrawOptions.BlitKeyedTransparency;
}
// Shot, if one exists
int numShots = 0;
if (!dr.IsNull("Shot2AnimationId"))
numShots = 2;
else if (!dr.IsNull("Shot1AnimationId"))
numShots = 1;
if (numShots > 0)
{
shotInfoValue = new ShotInfo[numShots];
for (int i = 0; i < shotInfoValue.Length; i++)
{
shotInfoValue[i] = new ShotInfo(dr, i + 1);
ShotInfo shot = shotInfoValue[i];
Debug.Assert(shot != null,
"WorldObject.WorldObject: Failed to allocate " +
"shot info");
}
}
ResetCollidable = collidableValue;
ResetWorldX = worldXValue;
ResetWorldY = worldYValue;
}
/// <summary>
/// Initialize a world object based on the given animation. This
/// method is provided for creating dynamic objects that are not
/// defined in the level data file.
/// </summary>
/// <param name="animation">Source animation</param>
/// <param name="animRate">Animation rate</param>
public WorldObject(Animation animation, int animationRate)
{
dynamicValue = true;
activeValue = true;
collidableValue = true;
curState = AnimationState.Static;
this.animationValue = new Animation(animation, 0, animationRate);
}
/// <summary>
/// Called when the level is reset, this method resets the world
/// object.
/// </summary>
/// <param name="lev">Current level</param>
virtual public void Reset(Level lev)
{
if (AILogic != null)
{
AILogic.Reset();
AILogic.Init(this, lev);
}
if (animationValue != null)
animationValue.SetCycle(0, animationValue.NumberCells - 1, 0);
activeValue = false;
collidableValue = ResetCollidable;
worldXValue = ResetWorldX;
worldYValue = ResetWorldY;
velocityXValue = 0.0F;
velocityYValue = 0.0F;
curState = AnimationState.None;
if (GetShotInfo() != null)
{
foreach (ShotInfo si in GetShotInfo())
{
si.Reset();
}
}
DrawOptions &= ~DrawOptions.BlitMirrorLeftRight;
}
/// <summary>
/// Kill this object. If a death animation exists then it is
/// initiated.
/// </summary>
public void Die()
{
collidableValue = false;
if (dynamicValue)
{
activeValue = false;
removeMeValue = true;
}
else
{
animationValue.SetCycle(DeathCycle.EndCell, DeathCycle.EndCell, 0);
animationValue.StartOneShot(DeathCycle.StartCell,
DeathCycle.EndCell, DeathCycle.AnimationRate);
curState |= AnimationState.Dead;
collidableValue = false;
}
}
/// <summary>
/// Set or clear the transparency data for this object.
/// </summary>
/// <param name="set">Set transparency if true, otherwise clear
/// it</param>
public void SetTransparency(bool set)
{
if (set)
{
DrawOptions |= DrawOptions.BlitKeyedTransparency;
}
else
{
DrawOptions &= ~DrawOptions.BlitKeyedTransparency;
}
}
/// <summary>
/// Update this world object.
/// </summary>
/// <param name="gi">Input instance</param>
/// <param name="lev">Current level</param>
/// <returns>true if the object should be removed, false otherwise
/// </returns>
virtual public bool Update(Input gi, Level lev)
{
// If the object is not active then check the activation distance
if (!activeValue)
{
if (Math.Abs(lev.Player.WorldX - worldXValue) <=
activateDistance)
activeValue = true;
else
return false;
}
// If the object is in a death animation then check if it has
// finished
if ((curState & AnimationState.Dead) != 0)
{
if (animationValue.Done)
{
activeValue = false;
}
animationValue.Update(GameMain.SecondsPerFrame);
return false;
}
// If the object is attacking then check the shot data
if ((curState & AnimationState.Attack) != 0)
{
// If the object has a shot...
if (GetShotInfo() != null)
{
// Check all shots...
foreach (ShotInfo shot in GetShotInfo())
{
// If the shot is not already fired and the animation
// is in the proper shooting cell then fire it
if (!shot.Fired && animationValue.CurCell == shot.ShootCell)
{
WorldDir dir = WorldDir.Left;
if ((DrawOptions &
DrawOptions.BlitMirrorLeftRight) != 0)
dir = WorldDir.Right;
FireShot(lev, shot, dir, 1.0F, 1.0F);
}
// If the animation is done the reset it
if (animationValue.Done)
{
shot.Fired = false;
Stand();
}
}
}
}
// If the object has AI then update it
if (AILogic != null)
AILogic.Update(this, lev);
// Update the object's world position
worldXValue += GameMain.SecondsPerFrame * velocityXValue;
worldYValue += GameMain.SecondsPerFrame * velocityYValue;
// If the object is dynamic then check if it is off-screen
if (dynamicValue)
{
if (worldXValue > lev.Player.WorldX + 1.5F * lev.ViewWidth ||
worldXValue < lev.WorldX - 1.5F * lev.ViewWidth)
{
return true;
}
}
// Update the animation
animationValue.Update(GameMain.SecondsPerFrame);
// Do not remove this object
return false;
}
/// <summary>
/// Returns the object's draw location relative to the screen.
/// </summary>
/// <param name="lev">Current level</param>
/// <returns>X coordinate of the draw</returns>
public float DrawX(Level lev)
{
return (int)lev.DrawX + (int)worldXValue -
(int)lev.WorldX - (animationValue.CellWidth >> 1);
}
/// <summary>
/// Returns the object's draw location relative to the screen.
/// </summary>
/// <param name="lev">Current level</param>
/// <returns>Y coordinate of the draw</returns>
public float DrawY(Level lev)
{
return (int)lev.DrawY + (int)worldYValue -
(int)lev.WorldY - (animationValue.CellHeight >> 1);
}
/// <summary>
/// Draw the world object on the back buffer.
/// </summary>
/// <param name="graphics">Graphics instance</param>
/// <param name="lev">Current level</param>
public void Draw(IGraphics graphics, Level lev)
{
if (!activeValue)
return;
graphics.SetDrawOptions(DrawOptions);
int drawX = (int)lev.DrawX + (int)worldXValue -
(int)lev.WorldX - (animationValue.CellWidth >> 1);
int drawY = (int)lev.DrawY + (int)worldYValue -
(int)lev.WorldY - (animationValue.CellHeight >> 1);
graphics.DrawAnimation(drawX, drawY, animationValue);
graphics.ClearDrawOptions(DrawOptions);
}
/// <summary>
/// Start the object walk animation.
/// </summary>
public void Walk()
{
if (curState == AnimationState.Walk)
return;
animationValue.SetCycle(WalkCycle.StartCell, WalkCycle.EndCell,
WalkCycle.AnimationRate);
curState = AnimationState.Walk;
}
/// <summary>
/// Start the object duck animation.
/// </summary>
public void Duck()
{
if (curState == AnimationState.Duck)
return;
animationValue.SetCycle(DuckCycle.EndCell, DuckCycle.EndCell, 0);
animationValue.StartOneShot(DuckCycle.StartCell, DuckCycle.EndCell,
DuckCycle.AnimationRate);
curState = AnimationState.Duck;
}
/// <summary>
/// Start the object stand animation (stationary walk).
/// </summary>
public void Stand()
{
if (curState == AnimationState.Stop)
return;
animationValue.SetCycle(WalkCycle.StartCell, WalkCycle.EndCell, 0);
curState = AnimationState.Stop;
}
/// <summary>
/// Fire a shot from the object's current location.
/// </summary>
/// <param name="lev">Current level</param>
/// <param name="shot">Information regarding shot to be fired</param>
/// <param name="dir">Direction to fire shot</param>
/// <param name="xMultiplier">Velocity x multiplier</param>
/// <param name="yMultiplier">Velocity y multiplier</param>
protected void FireShot(Level lev, ShotInfo shot, WorldDir dir,
float xMultiplier, float yMultiplier)
{
shot.Fired = true;
WorldObject wo = new WorldObject(
(Animation)lev.AnimationList[shot.AnimationId], shot.AnimationRate);
Debug.Assert(wo != null,
"Player.Update: Failed to create player bullet");
float velX = shot.VelocityX * xMultiplier;
float offsetX = shot.XOffset;
if (dir == WorldDir.Left)
{
velX = -velX;
offsetX = -offsetX;
}
wo.VelocityX = velX;
wo.VelocityY = shot.VelocityY * yMultiplier;
wo.WorldX = worldXValue + offsetX;
wo.WorldY = worldYValue + shot.YOffset;
wo.SetTransparency(shot.UseTransparency);
wo.staticBounds = new Bounds(0.0F, 0.0F, shot.Radius);
wo.parentValue = this;
if (shot.UseGravity)
{
wo.AILogic = AIHandler.Create(AI.AIType.ShotArc);
}
lev.WorldObjects.Add(wo);
}
/// <summary>
/// Start the object attack animation (stationary walk).
/// </summary>
public void Attack()
{
if (curState == AnimationState.Attack)
return;
animationValue.SetCycle(WalkCycle.StartCell, WalkCycle.EndCell, 0);
animationValue.StartOneShot(AttackCycle.StartCell, AttackCycle.EndCell,
AttackCycle.AnimationRate);
curState = AnimationState.Attack;
}
/// <summary>
/// Flip the object draw about the x axis.
/// </summary>
public void FlipX()
{
DrawOptions |= DrawOptions.BlitMirrorLeftRight;
}
/// <summary>
/// UnFlip the object draw about the x axis.
/// </summary>
public void UnflipX()
{
DrawOptions &= ~DrawOptions.BlitMirrorLeftRight;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -