如何在旋转后沿它所面对的方向移动精灵?
How do I move a sprite in the direction it is facing after being rotated?
我可以让小船精灵上下左右移动,也可以旋转它。但是,当按下 'up' 键时,船不是总是向上移动,而是希望船向船头的方向移动。我在想我可以在更新方法中的某处放置一个 vector2 变量,它始终指向精灵的尖端,但我无法思考如何 "hardcode" 精灵上的坐标。
我会 post 我的船 class 下面,我觉得事情有点乱,也欢迎任何关于清理代码的建议。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
//width = 62 pixels
//height = 179 pixels
namespace my_first_game
{
class Ship
{
private Vector2 position = new Vector2(300, 300);
private int radius = 50;
private bool ismoving = false;
private Dir direction = Dir.down;
private int health = 3;
private float speed = 100;
public float angle = 0;
public double turntime = .5d;
private float velocity = 10f;
private float drifttime = 0f;
// Constructor for the ship class
public Ship(int shiphealth)
{
shiphealth = health;
}
//getter/setter for angle
public float Get_angle
{
get { return angle; }
set { value = angle; }
}
//get and set health
public int Health
{
get { return health; }
set { value = health; }
}
// get and set the ship's position
public Vector2 Position
{
get{ return position; }
set { value = position; }
}
public void SetAngle (float f)
{
angle = MathHelper.ToDegrees(f);
}
//update loop for the ship's state
public void update_ship(GameTime gameTime)
{
KeyboardState kstate = Keyboard.GetState();
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
float rotation = 0.02f;
//Vector2 Direction = new Vector2((float)Math.Cos(angle + 45), (float)Math.Sin(angle));
//Direction.Normalize();
//if keys are pressed, the ship moves until the keys are unpressed
if (kstate.IsKeyDown(Keys.W))
{
direction = Dir.up;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.A))
{
direction = Dir.left;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.D))
{
direction = Dir.right;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.S))
{
direction = Dir.down;
ismoving = true;
}
if(kstate.IsKeyDown(Keys.W) && kstate.IsKeyDown(Keys.D))
{ direction = Dir.up_right;
ismoving = true;
}
if(kstate.IsKeyDown(Keys.W) && kstate.IsKeyDown(Keys.A))
{
direction = Dir.up_left;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.S) && kstate.IsKeyDown(Keys.D))
{ direction = Dir.down_right;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.S) && kstate.IsKeyDown(Keys.A))
{
direction = Dir.down_left;
ismoving = true;
}
//"ismoving" is used as a flag to move the ship if keys are held
//angle also rotates the boat when "A" and "D" are pressed
if (ismoving) {
switch (direction)
{
case Dir.up:
position.Y -= speed * dt;
ismoving = false;
break;
case Dir.down:
position.Y += speed * dt;
ismoving = false;
break;
case Dir.left:
angle -= rotation;
ismoving = false;
break;
case Dir.right:
angle += rotation;
ismoving = false;
break;
case Dir.up_right:
position.Y -= speed * dt;
position.X += speed * (float)turntime * dt;
angle += rotation;
ismoving = false;
break;
case Dir.up_left:
position.Y -= speed * dt;
position.X -= speed * (float)turntime * dt;
angle -= rotation;
ismoving = false;
break;
case Dir.down_right:
position.Y += speed * dt;
position.X += speed * (float)turntime * dt;
angle += rotation;
ismoving = false;
break;
case Dir.down_left:
position.Y += speed * dt;
position.X -= speed * (float)turntime * dt;
angle -= rotation;
ismoving = false;
break;
default: break;
}
}
}
}
}
这是我的船的相关绘制方法:
//create a new rectangle around the ship_sprite
Rectangle ship_rectangle = new Rectangle(0, 0, ship_sprite.Width,
ship_sprite.Height);
Vector2 origin = new Vector2(31, 160);
spriteBatch.Draw(ship_sprite, ship.Position, ship_rectangle,
Color.White, ship.angle, origin, 1.0f, SpriteEffects.None, 1);
我怀疑这个问题只有一个 "Right" 答案,但我会做的是使用你的 "angle" 属性 来确定按下向上按钮时的移动。
我在沿着三角线思考 - 你的半径就是船速。然后你会按照(伪代码!)的方式做一些事情:
x += (cos(angle) * speed);
y += (sin(angle) * speed);
这假设角度 = 0 对应于法线平面图上 0 度的标准解释(因此面向右侧)。如果不是这种情况,您需要相应地进行调整。
警告:我自己没有编写过这样的代码,所以这只是我对实现方式的估计。我鼓励您进行实验,看看不同的方法是如何工作的。
经过一番修改后,我找到了适合我的解决方案。
Vector2 direction = new Vector2((float)Math.Cos(angle + 30),
(float)Math.Sin(angle + 30));
然后当按下'up'键时,您可以简单地将船的位置设置为其当前位置加上船的角度。这两者的总和可以乘以增量时间和船速。
if(kstate.IsKeyDown(Keys.W))
{
position = position + direction * dt * speed;
}
我可以让小船精灵上下左右移动,也可以旋转它。但是,当按下 'up' 键时,船不是总是向上移动,而是希望船向船头的方向移动。我在想我可以在更新方法中的某处放置一个 vector2 变量,它始终指向精灵的尖端,但我无法思考如何 "hardcode" 精灵上的坐标。
我会 post 我的船 class 下面,我觉得事情有点乱,也欢迎任何关于清理代码的建议。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
//width = 62 pixels
//height = 179 pixels
namespace my_first_game
{
class Ship
{
private Vector2 position = new Vector2(300, 300);
private int radius = 50;
private bool ismoving = false;
private Dir direction = Dir.down;
private int health = 3;
private float speed = 100;
public float angle = 0;
public double turntime = .5d;
private float velocity = 10f;
private float drifttime = 0f;
// Constructor for the ship class
public Ship(int shiphealth)
{
shiphealth = health;
}
//getter/setter for angle
public float Get_angle
{
get { return angle; }
set { value = angle; }
}
//get and set health
public int Health
{
get { return health; }
set { value = health; }
}
// get and set the ship's position
public Vector2 Position
{
get{ return position; }
set { value = position; }
}
public void SetAngle (float f)
{
angle = MathHelper.ToDegrees(f);
}
//update loop for the ship's state
public void update_ship(GameTime gameTime)
{
KeyboardState kstate = Keyboard.GetState();
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
float rotation = 0.02f;
//Vector2 Direction = new Vector2((float)Math.Cos(angle + 45), (float)Math.Sin(angle));
//Direction.Normalize();
//if keys are pressed, the ship moves until the keys are unpressed
if (kstate.IsKeyDown(Keys.W))
{
direction = Dir.up;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.A))
{
direction = Dir.left;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.D))
{
direction = Dir.right;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.S))
{
direction = Dir.down;
ismoving = true;
}
if(kstate.IsKeyDown(Keys.W) && kstate.IsKeyDown(Keys.D))
{ direction = Dir.up_right;
ismoving = true;
}
if(kstate.IsKeyDown(Keys.W) && kstate.IsKeyDown(Keys.A))
{
direction = Dir.up_left;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.S) && kstate.IsKeyDown(Keys.D))
{ direction = Dir.down_right;
ismoving = true;
}
if (kstate.IsKeyDown(Keys.S) && kstate.IsKeyDown(Keys.A))
{
direction = Dir.down_left;
ismoving = true;
}
//"ismoving" is used as a flag to move the ship if keys are held
//angle also rotates the boat when "A" and "D" are pressed
if (ismoving) {
switch (direction)
{
case Dir.up:
position.Y -= speed * dt;
ismoving = false;
break;
case Dir.down:
position.Y += speed * dt;
ismoving = false;
break;
case Dir.left:
angle -= rotation;
ismoving = false;
break;
case Dir.right:
angle += rotation;
ismoving = false;
break;
case Dir.up_right:
position.Y -= speed * dt;
position.X += speed * (float)turntime * dt;
angle += rotation;
ismoving = false;
break;
case Dir.up_left:
position.Y -= speed * dt;
position.X -= speed * (float)turntime * dt;
angle -= rotation;
ismoving = false;
break;
case Dir.down_right:
position.Y += speed * dt;
position.X += speed * (float)turntime * dt;
angle += rotation;
ismoving = false;
break;
case Dir.down_left:
position.Y += speed * dt;
position.X -= speed * (float)turntime * dt;
angle -= rotation;
ismoving = false;
break;
default: break;
}
}
}
}
}
这是我的船的相关绘制方法:
//create a new rectangle around the ship_sprite
Rectangle ship_rectangle = new Rectangle(0, 0, ship_sprite.Width,
ship_sprite.Height);
Vector2 origin = new Vector2(31, 160);
spriteBatch.Draw(ship_sprite, ship.Position, ship_rectangle,
Color.White, ship.angle, origin, 1.0f, SpriteEffects.None, 1);
我怀疑这个问题只有一个 "Right" 答案,但我会做的是使用你的 "angle" 属性 来确定按下向上按钮时的移动。
我在沿着三角线思考 - 你的半径就是船速。然后你会按照(伪代码!)的方式做一些事情:
x += (cos(angle) * speed);
y += (sin(angle) * speed);
这假设角度 = 0 对应于法线平面图上 0 度的标准解释(因此面向右侧)。如果不是这种情况,您需要相应地进行调整。
警告:我自己没有编写过这样的代码,所以这只是我对实现方式的估计。我鼓励您进行实验,看看不同的方法是如何工作的。
经过一番修改后,我找到了适合我的解决方案。
Vector2 direction = new Vector2((float)Math.Cos(angle + 30),
(float)Math.Sin(angle + 30));
然后当按下'up'键时,您可以简单地将船的位置设置为其当前位置加上船的角度。这两者的总和可以乘以增量时间和船速。
if(kstate.IsKeyDown(Keys.W))
{
position = position + direction * dt * speed;
}