我正在制作和RPG,并为精灵编码了动作和动画。当我运行项目时,精灵将向下或向右移动。按下右箭头键时,精灵将向右移动,但不会停止。按下向下键时,精灵将向下移动,并在释放按键时停止。但是,按下向下或向右键后按另一个箭头键时,精灵图像不会改变方向。此外,按下新箭头键时,精灵图像不会改变。为什么会这样?任何帮助表示赞赏。
Game.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace RPG
{
/// <summary>
/// Default Project Template
/// </summary>
public class Game1 : Game
{
#region Fields
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Vector2 aPosition = new Vector2(250, 100);
MageChar mageSprite;
#endregion
#region Initialization
public Game1 ()
{
graphics = new GraphicsDeviceManager (this);
Content.RootDirectory = "Content";
graphics.IsFullScreen = false;
}
/// <summary>
/// Overridden from the base Game.Initialize. Once the GraphicsDevice is setup,
/// we'll use the viewport to initialize some values.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
mageSprite = new MageChar();
base.Initialize();
}
/// <summary>
/// Load your graphics content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
mageSprite.LoadContent(this.Content);
}
#endregion
#region Update and Draw
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
// game exits id back button is pressed
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
// TODO: Add your update logic here
//calls update method of MageChar class
mageSprite.Update(gameTime);
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
spriteBatch.Begin();
//calls draw method of MageChar class
mageSprite.Draw(this.spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
#endregion
}
}
CharMovement.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace RPG
{
public class CharMovement
{
//The asset name for the Sprite's Texture
public string charSprite;
//The Size of the Sprite (with scale applied)
public Rectangle Size;
//The amount to increase/decrease the size of the original sprite.
private float mScale = 1.0f;
//The current position of the Sprite
public Vector2 Position = new Vector2(0, 0);
//The texture object used when drawing the sprite
private Texture2D charTexture;
//Load the texture for the sprite using the Content Pipeline
public void LoadContent(ContentManager theContentManager, string theCharSprite)
{
//loads the image of the sprite
charTexture = theContentManager.Load<Texture2D>(theCharSprite);
theCharSprite = charSprite;
//creates a new rectangle the size of the sprite
Size = new Rectangle(0, 0, (int)(charTexture.Width * mScale), (int)(charTexture.Height * mScale));
}
//Update the Sprite and change it's position based on the set speed, direction and elapsed time.
public void Update(GameTime theGameTime, Vector2 theSpeed, Vector2 theDirection)
{
//calculates the position of the sprite using the speed and direction from the MageChar class
Position += theDirection * theSpeed * (float)theGameTime.ElapsedGameTime.TotalSeconds;
if (Position.X < 0)
{
Position.X = 0;
}
if (Position.Y < 0)
{
Position.Y = 0;
}
}
//Draw the sprite to the screen
public void Draw(SpriteBatch theSpriteBatch)
{
//draw the sprite to the screen inside a rectangle
theSpriteBatch.Draw(charTexture, Position,
new Rectangle(0, 0, charTexture.Width, charTexture.Height),
Color.White, 0.0f, Vector2.Zero, mScale, SpriteEffects.None, 0);
}
}
}
MageChar.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace RPG
{
public class MageChar : CharMovement
{
//variable where sprite file name is stored
string MageAssetName = "WalkingFront";
//starting x position
const int StartPositionX = 0;
//starting y position
const int StartPositionY = 0;
//speed that the sprite will move on screen
const int MageSpeed = 160;
//move sprite 1 up/down when the arrow key is pressed
const int MoveUp = 1;
const int MoveDown = 1;
const int MoveLeft = 1;
const int MoveRight = 1;
//used to store the current state of the sprite
enum State
{
WalkingLeft,
WalkingRight,
WalkingFront,
WalkingBack
}
//set to current state of the sprite. initally set to walking
State CurrentState = State.WalkingFront;
//stores direction of sprite
Vector2 Direction = Vector2.Zero;
//stores speed of sprite
Vector2 Speed = Vector2.Zero;
//stores previous state of keyboard
KeyboardState PreviousKeyboardState;
public void LoadContent(ContentManager theContentManager)
{
//sets position to the top left corner of the screen
Position = new Vector2(StartPositionX, StartPositionY);
//calls the load content method of the CharMovement class, passing in the content manager, and the name of the sprite image
base.LoadContent(theContentManager, MageAssetName);
}
//checks state of the keyboard
private void Update(KeyboardState aCurrentKeyboardState)
{
//run if the sprite is walking
if (CurrentState == State.WalkingFront)
{
//sets direction and speed to zero
Speed = Vector2.Zero;
Direction = Vector2.Zero;
//if left key is pressed, move left
if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true)
{
CurrentState = State.WalkingLeft;
MageAssetName = "WalkingLeft";
//speed of sprite movement
Speed.X -= MageSpeed;
//moves the sprite left
Direction.X -= MoveLeft;
}
//if right key is pressed, move right
else if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true)
{
CurrentState = State.WalkingRight;
MageAssetName = "WalkingRight";
//speed of sprite movement
Speed.X += MageSpeed;
//moves the sprite right
Direction.X += MoveRight;
}
//if up key is pressed, move up
if (aCurrentKeyboardState.IsKeyDown(Keys.Up) == true)
{
CurrentState = State.WalkingBack;
MageAssetName = "WalkingBack";
//speed of sprite movement
Speed.Y += MageSpeed;
//moves sprite up
Direction.Y += MoveUp;
}
//if down key is pressed, move down
else if (aCurrentKeyboardState.IsKeyDown(Keys.Down) == true)
{
CurrentState = State.WalkingFront;
MageAssetName = "WalkingFront";
//speed of sprite movement
Speed.Y -= MageSpeed;
//moves sprite down
Direction.Y -= MoveDown;
}
}
}
public void Update(GameTime theGameTime)
{
//obtains current state of the keyboard
KeyboardState aCurrentKeyboardState = Keyboard.GetState();
//calls in UpdateMovement and passes in current keyboard state
Update(aCurrentKeyboardState);
//set previous state to current state
PreviousKeyboardState = aCurrentKeyboardState;
//call update method of the charMovement class, passing in the gametime, speed and direction of the sprite
base.Update(theGameTime, Speed, Direction);
}
}
}
答案 0 :(得分:0)
要控制Left
和Down
键,请减少Speed
:
Speed.X -= MageSpeed; // Keys.Left
Speed.Y -= MageSpeed; // Keys.Down
基于Speed
的常规用法,这似乎不正确。例如,如果玩家向右移动并且速度为5.然后向左移动将取消此速度并将其设置为0.因此玩家不会移动。
所以在所有4个案例中,Speed
都应该递增(+ =)。
Speed.X += MageSpeed; // Keys.Left
Speed.Y += MageSpeed; // Keys.Down
如果播放器没有按任何方向键,我建议使用else
条件。在此,您可以将角色MageChar
设置为继续朝向与上次移动方向相同的方向,并将Speed
设置为0.
MageChar
中移动的代码存在潜在问题:
根据用户输入,您将CurrentState
设置为State.WalkingLeft
或State.WalkingRight
。接下来检查向上和向下键。如果同时按下其中任何一个,则CurrentState
和MageAssetName
将被覆盖,如果它们已被分配到左/右代码块中。
这与你在问题中所述的内容一致:
按下向下键时,精灵将向下移动,并在释放该键时停止。但是,按下向下或向右键后按另一个箭头键时,精灵图像不会改变方向。此外,按下新箭头键时,精灵图像不会改变。
我建议先行动一下。我建议对每个移动方向/键执行独立检查。目前,如果玩家按下左键,则右键码完全被忽略,上下键分别相同。
当您递增和递减时,您的Direction
值应该是正确的。然而,直观地说,按下左右两个,或者向上和向下按压都会取消彼此的移动。如果您同意,四个独立的运动检查将解决此问题。
当您修复此问题时,您可能需要考虑一些事情,我希望您这样做。在玩家沿对角线移动的情况下,将向上或向下以及向左或向右移动。在这里你可能会注意到玩家在对角线移动时移动得更快。这可以用毕达哥拉斯定理来解释* a ^ 2 + b ^ 2 = c ^ 2.
因此,如果玩家向右移动4,则向上移动4.结果速度为5.65。
(4 ^ 2 + 4 ^ 2 = 32) - &gt; sqrt(32)= 5.65。要解决此问题,再次使用4,您将需要Normalize
此变量。如果需要,我可以详细介绍。
*毕达哥拉斯定理解释:Pythagaros Theorem Wikipedia Article