我知道为什么每次调用Update_Animation(Point sheetSize,TimeSpan frameInterval,GameTime gameTime)函数时,精灵动画的速度变得更快。它是否由gameTime引起?怎么解决?感谢。
class Character
{
#region Field
// Character file
System.Xml.Linq.XDocument doc;
// The texture with animation frames
Texture2D animationTexture_Stand;
Texture2D animationTexture_Run;
Texture2D animationTexture_Hit;
// The size of single frame inside the animationTexture
public Point frameSize_Stand;
public Point frameSize_Run;
public Point frameSize_Hit;
// The size and structure of whole frames sheet in animationTexture. The animationTexture could
// hold animaton sequence organized in multiple rows and multiple columns.
Point sheetSize_Stand;
Point sheetSize_Run;
Point sheetSize_Hit;
// Amount of time between frames
TimeSpan frameInterval_Stand;
TimeSpan frameInterval_Run;
TimeSpan frameInterval_Hit;
#endregion
#region Initialization
/// <summary>
/// Constructor of a character class
/// </summary>
/// <param name="characterName">the name of the xml file of the character without .xml</param>
/// <param name="content">ContentManager instance</param>
public Character(String characterName, ContentManager content)
{
doc = System.Xml.Linq.XDocument.Load("Content/" + "Player/" + characterName + ".xml");
// Get the first sprite info from the XML definition
var stand = doc.Root.Element("stand");
var run = doc.Root.Element("run");
var hit = doc.Root.Element("hit");
animationTexture_Stand = content.Load<Texture2D>(stand.Attribute("SheetName").Value);
animationTexture_Run = content.Load<Texture2D>(run.Attribute("SheetName").Value);
animationTexture_Hit = content.Load<Texture2D>(hit.Attribute("SheetName").Value);
frameSize_Stand = new Point();
frameSize_Stand.X = int.Parse(stand.Attribute("FrameWidth").Value, NumberStyles.Integer);
frameSize_Stand.Y = int.Parse(stand.Attribute("FrameHeight").Value, NumberStyles.Integer);
frameSize_Run = new Point();
frameSize_Run.X = int.Parse(run.Attribute("FrameWidth").Value, NumberStyles.Integer);
frameSize_Run.Y = int.Parse(run.Attribute("FrameHeight").Value, NumberStyles.Integer);
frameSize_Hit = new Point();
frameSize_Hit.X = int.Parse(hit.Attribute("FrameWidth").Value, NumberStyles.Integer);
frameSize_Hit.Y = int.Parse(hit.Attribute("FrameHeight").Value, NumberStyles.Integer);
sheetSize_Stand = new Point();
sheetSize_Stand.X = int.Parse(stand.Attribute("SheetColumns").Value, NumberStyles.Integer);
sheetSize_Stand.Y = int.Parse(stand.Attribute("SheetRows").Value, NumberStyles.Integer);
sheetSize_Run = new Point();
sheetSize_Run.X = int.Parse(run.Attribute("SheetColumns").Value, NumberStyles.Integer);
sheetSize_Run.Y = int.Parse(run.Attribute("SheetRows").Value, NumberStyles.Integer);
sheetSize_Hit = new Point();
sheetSize_Hit.X = int.Parse(hit.Attribute("SheetColumns").Value, NumberStyles.Integer);
sheetSize_Hit.Y = int.Parse(hit.Attribute("SheetRows").Value, NumberStyles.Integer);
frameInterval_Stand = TimeSpan.FromSeconds(1.0f / int.Parse(stand.Attribute("Speed").Value, NumberStyles.Integer));
frameInterval_Run = TimeSpan.FromSeconds(1.0f / int.Parse(run.Attribute("Speed").Value, NumberStyles.Integer));
frameInterval_Hit = TimeSpan.FromSeconds(1.0f / int.Parse(hit.Attribute("Speed").Value, NumberStyles.Integer));
}
#endregion
#region Update Animation
TimeSpan nextFrame;
Point currentFrame;
public void Update_Animation(Point sheetSize, TimeSpan frameInterval, GameTime gameTime)
{
if (nextFrame >= frameInterval)
{
currentFrame.X++;
if (currentFrame.X >= sheetSize.X)
{
currentFrame.X = 0;
currentFrame.Y++;
}
if (currentFrame.Y >= sheetSize.Y)
currentFrame.Y = 0;
nextFrame = TimeSpan.Zero;
}
else
{
nextFrame += gameTime.ElapsedGameTime;
}
}
#endregion
#region Update Control
KeyboardState mPreviousKeyboardState;
String action;
SpriteEffects effect = SpriteEffects.FlipHorizontally;
Vector2 feetPosition = new Vector2(0, 450);
Vector2 mSpeed = Vector2.Zero;
Vector2 mDirection = Vector2.Zero;
Vector2 mStartingPosition = Vector2.Zero;
int CHARACTER_SPEED = 50;
int MOVE_LEFT = -5;
int MOVE_RIGHT = 5;
int MOVE_UP = -5;
int MOVE_DOWN = 5;
enum State
{
Walking,
Jumping,
Hitting,
}
State mCurrentState = State.Walking;
public void UpdateControl(GameTime gameTime)
{
KeyboardState aCurrentKeyboardState = Keyboard.GetState();
feetPosition += mDirection * mSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds;
UpdateMovement(aCurrentKeyboardState, gameTime);
UpdateJump(aCurrentKeyboardState, gameTime);
mPreviousKeyboardState = aCurrentKeyboardState;
}
private void UpdateMovement(KeyboardState aCurrentKeyboardState, GameTime gameTime)
{
if (mCurrentState == State.Walking)
{
action = "stand";
Update_Animation(sheetSize_Stand, frameInterval_Stand, gameTime);
mSpeed = Vector2.Zero;
mDirection = Vector2.Zero;
if (aCurrentKeyboardState.IsKeyDown(Keys.Left) && !aCurrentKeyboardState.IsKeyDown(Keys.Right))
{
action = "run";
effect = SpriteEffects.None;
mSpeed.X = CHARACTER_SPEED;
mDirection.X = MOVE_LEFT;
Update_Animation(sheetSize_Run, frameInterval_Run, gameTime);
}
else if (aCurrentKeyboardState.IsKeyDown(Keys.Right) && !aCurrentKeyboardState.IsKeyDown(Keys.Left))
{
action = "run";
effect = SpriteEffects.FlipHorizontally;
mSpeed.X = CHARACTER_SPEED;
mDirection.X = MOVE_RIGHT;
Update_Animation(sheetSize_Run, frameInterval_Run, gameTime);
}
if (aCurrentKeyboardState.IsKeyDown(Keys.Z) && mPreviousKeyboardState.IsKeyUp(Keys.Z))
{
mCurrentState = State.Hitting;
}
}
if (mCurrentState == State.Hitting)
{
action = "hit";
Update_Animation(sheetSize_Hit, frameInterval_Hit, gameTime);
mCurrentState = State.Walking;
}
}
private void UpdateJump(KeyboardState aCurrentKeyboardState, GameTime gameTime)
{
if (mCurrentState == State.Walking)
{
if (aCurrentKeyboardState.IsKeyDown(Keys.Up) && mPreviousKeyboardState.IsKeyUp(Keys.Up))
Jump();
}
if (mCurrentState == State.Jumping)
{
if (mStartingPosition.Y - feetPosition.Y > 150)
mDirection.Y = MOVE_DOWN;
if (feetPosition.Y > mStartingPosition.Y)
{
feetPosition.Y = mStartingPosition.Y;
mCurrentState = State.Walking;
mDirection = Vector2.Zero;
}
}
}
private void Jump()
{
if (mCurrentState != State.Jumping)
{
mCurrentState = State.Jumping;
mStartingPosition = feetPosition;
mDirection.Y = MOVE_UP;
mSpeed = new Vector2(CHARACTER_SPEED, CHARACTER_SPEED);
}
}
#endregion
#region Draw Animation
Texture2D animationTexture;
Point frameSize;
/// <summary>
/// Rendering of the animation
/// </summary>
/// <param name="spriteBatch">SpriteBatch in which current frame will be rendered</param>
/// <param name="position">The position of the current frame</param>
/// <param name="scale">Scale factor to apply on the current frame</param>
/// <param name="spriteEffect">SpriteEffect to apply on the current frame</param>
public void Draw_Animation(SpriteBatch spriteBatch)
{
if (action == "stand")
{
Assign_Sprite(animationTexture_Stand, frameSize_Stand);
Draw_Action(spriteBatch, feetPosition, 1.0f, effect);
}
else if (action == "run")
{
Assign_Sprite(animationTexture_Run, frameSize_Run);
Draw_Action(spriteBatch, feetPosition, 1.0f, effect);
}
else if (action == "hit")
{
Assign_Sprite(animationTexture_Hit, frameSize_Hit);
Draw_Action(spriteBatch, feetPosition, 1.0f, effect);
}
}
private void Assign_Sprite(Texture2D assignAnimationTexture, Point assignFrameSize)
{
animationTexture = assignAnimationTexture;
//currentFrame = AssignCurrentFrame;
frameSize = assignFrameSize;
}
private void Draw_Action(SpriteBatch spriteBatch, Vector2 position, float scale, SpriteEffects spriteEffect)
{
spriteBatch.Draw(animationTexture, position - new Vector2(0, frameSize.Y), new Rectangle(
frameSize.X * currentFrame.X,
frameSize.Y * currentFrame.Y,
frameSize.X,
frameSize.Y),
Color.White, 0f, Vector2.Zero, scale, spriteEffect, 0);
}
#endregion
}
答案 0 :(得分:1)
我不确定这是不是问题,但这段代码关注我:
if (nextFrame >= frameInterval)
{
//Blah blah
nextFrame = TimeSpan.Zero;
}
如果gameTime.ElapsedGameTime
不常规(如果您的游戏出现性能问题),则此方法将无法正确计时。相反,你应该尝试:
while (nextFrame >= frameInterval)
{
//Blah blah
nextFrame -= frameInterval;
}
因此nextFrame
会有一些时间“遗留”,所以下一个动画会在正确的时间出现。
但是,由于你的问题不是很清楚,我不确定这是否能真正解决你的问题。