I'm able to move by boat sprite up, down, left, and right, as well as rotate it. However, instead of the boat always moving upwards when the 'up' key is pressed, I'd like the boat to move in the direction of its bow. I was thinking I could stick a vector2 variable somewhere in the update method which always points to the tip of the sprite, but I can't wrap my head around how to "hardcode" a coordinate on the sprite.
I'll post my ship class below, I think things are a bit messy, any suggestions on cleaning code up would be welcome as well.
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;
}
}
}
}
}
Here's the relevant draw method for my ship:
//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);
After a bit of tinkering I found a solution that worked for me.
Vector2 direction = new Vector2((float)Math.Cos(angle + 30),
(float)Math.Sin(angle + 30));
Then when the 'up' key is pressed, you can simply set the boat's position to its current position plus the angle of the boat. The sum of these two can be multiplied by delta time and the speed of the boat.
if(kstate.IsKeyDown(Keys.W))
{
position = position + direction * dt * speed;
}