📄 player.cs
字号:
DrawOptions = DrawOptions.BlitKeyedTransparency;
}
ResetCollidable = Collidable;
ResetWorldX = WorldX;
ResetWorldY = WorldY;
}
/// <summary>
/// Maps the player buttons. Each element in the array is an index
/// into Input's HardwareKeys list. The index of each element
/// corresponds to a Buttons enum value. For example, to access the
/// key value for resetting the level, the code would be:
/// gi.HardwareKeys[buttonMapValue[Buttons.ResetLevel]]
/// where gi is an instance of Input.
/// </summary>
public static int[] ButtonMap()
{
return buttonMapValue;
}
/// <summary>
/// Called when the level is reset. Resets the player state and
/// position.
/// </summary>
/// <param name="lev">Current level</param>
public override void Reset(Level lev)
{
// Reset the base world object data
base.Reset(lev);
// Start with the walk cycle
Animation.SetCycle(WalkCycle.StartCell, WalkCycle.EndCell, 0);
curCycle = WalkCycle;
prevState = AnimationState.Stop | AnimationState.Walk;
// Reset player specific information
Active = true;
Collidable = true;
shotStarted = false;
shotTime = 0.0F;
misfireValue = false;
}
/// <summary>
/// Force the player to walk to the right with the scrolling
/// world. This occurs when the player bumps against the left
/// edge of the screen.
/// </summary>
/// <param name="lev">Current level</param>
/// <param name="src">Animation state that spawned this</param>
private void ForceRight(Level lev, AnimationState src)
{
// If not attacking and we were not being forced right in the
// previous update then reset the walk cycle
if ((State & AnimationState.Attack) == 0 && (State |
AnimationState.ForceRight) != prevState)
{
Animation.SetCycle(curCycle.StartCell, curCycle.EndCell,
curCycle.ForceAnimationRate);
Animation.CurCell = 1;
}
// If not previously attacking then face the direction of the
// source that spawned this walk
if ((prevState & AnimationState.Attack) == 0)
{
if (src == AnimationState.Left)
DrawOptions |= DrawOptions.BlitMirrorLeftRight;
else
DrawOptions &= ~DrawOptions.BlitMirrorLeftRight;
}
// Update the world position
WorldX = lev.WorldX + lev.ScreenEdgeBuffer +
(curCycle.Bounds.Radius);
// Set the state
State |= AnimationState.ForceRight;
}
/// <summary>
/// Attempt to walk to the left.
/// </summary>
/// <param name="lev">Current world</param>
private void WalkLeft(Level lev)
{
// Calculate the new world location
float resultX = WorldX - GameMain.SecondsPerFrame *
(curCycle.MoveRate - lev.ScrollRate);
// If the world location is off the screen to the left then
// force the player to walk right
if (resultX - (curCycle.Bounds.Radius) < lev.WorldX +
lev.ScreenEdgeBuffer)
{
ForceRight(lev, AnimationState.Left);
return;
}
// If not attacking and not previously walking left then reset the
// animation
if ((State & AnimationState.Attack) == 0 && (State |
AnimationState.Left) != prevState)
{
Animation.SetCycle(curCycle.StartCell, curCycle.EndCell,
curCycle.AnimationRate);
Animation.CurCell = 1;
DrawOptions |= DrawOptions.BlitMirrorLeftRight;
}
// Set the new world position
WorldX = resultX;
// Set the state
State |= AnimationState.Left;
}
/// <summary>
/// Attempt to walk to the right.
/// </summary>
/// <param name="lev">Current level</param>
private void WalkRight(Level lev)
{
// If not attacking and not previously walking to the right then
// reset the animation
if ((State & AnimationState.Attack) == 0 && (State |
AnimationState.Right) != prevState)
{
int curCell = 1;
if (State == AnimationState.ForceRight)
curCell = Animation.CurCell;
Animation.SetCycle(curCycle.StartCell, curCycle.EndCell,
curCycle.AnimationRate);
Animation.CurCell = curCell;
DrawOptions &= ~DrawOptions.BlitMirrorLeftRight;
}
// Update the animation rate and world position
Animation.AnimationRate = curCycle.AnimationRate;
WorldX += GameMain.SecondsPerFrame * (curCycle.MoveRate +
lev.ScrollRate);
// Validate the new world location
if (WorldX + (curCycle.Bounds.Radius) > lev.WorldX +
lev.ViewWidth - lev.ScreenEdgeBuffer)
{
WorldX = lev.WorldX + lev.ViewWidth -
lev.ScreenEdgeBuffer - (curCycle.Bounds.Radius);
Animation.AnimationRate = curCycle.ForceAnimationRate;
}
// Update the animation state
State |= AnimationState.Right;
}
/// <summary>
/// Stop walking.
/// </summary>
/// <param name="lev">Current level</param>
private void Stop(Level lev)
{
// If the world scrolls past the player then force the player
// to walk right
if (WorldX - (curCycle.Bounds.Radius) < lev.WorldX +
lev.ScreenEdgeBuffer)
{
ForceRight(lev, AnimationState.Stop);
return;
}
// If not attacking and not previously stopped then reset
// the animation cycle
if ((State & AnimationState.Attack) == 0 && (State |
AnimationState.Stop) != prevState)
{
Animation.SetCycle(curCycle.StartCell, curCycle.EndCell, 0);
}
// Set the animation state
State |= AnimationState.Stop;
}
/// <summary>
/// Update the player.
/// </summary>
/// <param name="gi">Input instance</param>
/// <param name="lev">Current level</param>
/// <returns>Always false</returns>
public override bool Update(Input gi, Level lev)
{
// Assume there is no misfire this frame
misfireValue = false;
// If a shot is charging then update the time
if (shotStarted)
shotTime += GameMain.SecondsPerFrame;
// If the player is not dead then update it
if ((State & AnimationState.Dead) == 0)
{
// clear out the current direction but leave the animation
// state
State = prevState & AnimationState.AnimationMask;
// If attacking then update the shot state
if ((State & AnimationState.Attack) != 0)
{
// If the shot is not already fired and the current
// animation cell is the one where the player shoots
// then launch a shot
if (!GetShotInfo()[0].Fired &&
Animation.CurCell == GetShotInfo()[0].ShootCell)
{
// Determine the direction of the shot
WorldDir dir = WorldDir.Left;
if ((DrawOptions & DrawOptions.BlitMirrorLeftRight)
== 0)
dir = WorldDir.Right;
// Velocity multipliers
float shotVelXMultiplier;
float shotVelYMultiplier;
// Determine the chance of a misfire based on the shot
// bar charge (min to max)
float misfireChance =
shotMisfireMax - CurrentShotBarPercent *
(shotMisfireMax - shotMisfireMin);
if (GameMain.Random() < misfireChance)
{
// A misfire occurred so set the flag and
// update the velocity multipliers accordingly
misfireValue = true;
shotVelXMultiplier = shotMisfireVelocityXMin +
GameMain.Random() *
(shotVelocityXMax - shotVelocityXMin);
shotVelYMultiplier = shotMisfireVelocityYMin +
GameMain.Random() *
(shotVelocityYMax - shotVelocityYMin);
}
else
{
// No misfire, so the velocities are set
// relative to the bar charge percentage
shotVelXMultiplier = shotVelocityXMin +
CurrentShotBarPercent *
(shotVelocityXMax - shotVelocityXMin);
shotVelYMultiplier = shotVelocityYMax -
CurrentShotBarPercent *
(shotVelocityYMax - shotVelocityYMin);
}
// Fire a shot and reset the charge time
shotTime = 0.0F;
FireShot(lev, GetShotInfo()[0], dir,
shotVelXMultiplier, shotVelYMultiplier);
}
else if (Animation.Done)
{
// If the shot animation is done then reset shot info
GetShotInfo()[0].Fired = false;
State = AnimationState.Walk;
curCycle = WalkCycle;
}
}
else if (gi.KeyPressed((int)Keys.Down))
{
// If pressing down then attempt to crawl.
State = AnimationState.Duck;
curCycle = DuckCycle;
}
else if (gi.KeyPressed((int)Keys.Up))
{
// If pressing up then stand up
State = AnimationState.Walk;
curCycle = WalkCycle;
}
else if (!shotStarted && gi.KeyDown(
(int)gi.HardwareKeys[buttonMapValue[
(int)Buttons.FireShot]]))
{
// If the fire button is pressed then start charging
// the bar
shotStarted = true;
shotTime = 0.0F;
}
else if (shotStarted && gi.KeyReleased(
(int)gi.HardwareKeys[buttonMapValue[
(int)Buttons.FireShot]]))
{
// If the fire button is released then start the shot
// animation
curCycle = AttackCycle;
State |= AnimationState.Attack;
Animation.SetCycle(WalkCycle.StartCell,
WalkCycle.EndCell, WalkCycle.AnimationRate);
Animation.StartOneShot(AttackCycle.StartCell,
AttackCycle.EndCell, AttackCycle.AnimationRate);
shotStarted = false;
}
Debug.Assert(curCycle != null,
"Player.Update: Invalid animation sequence");
Debug.Assert((State & AnimationState.AnimationMask) != 0,
"Player.Update: Invalid animation state determined");
// Attempt to walk in the direction the user is pressing
if (gi.KeyDown((int)Keys.Left))
WalkLeft(lev);
else if (gi.KeyDown((int)Keys.Right))
WalkRight(lev);
else
Stop(lev);
Debug.Assert((State & AnimationState.DirectionMask) != 0 &&
(State & AnimationState.AnimationMask) != 0,
"Player.Update: Invalid movement state determined");
}
// Update the animation
Animation.Update(GameMain.SecondsPerFrame);
// Set the previous state
prevState = State;
// The player always returns false
return false;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -