Moving in the direction of rotation?

Started by
23 comments, last by Carbon101 10 years, 4 months ago

I am confused at what the

this
keyword does in Java. From my understanding its similar to C++ reference operator (&) ? Is this correct?


Ein?? Wouldn't it by similar to the C++ `this' keyword?
Advertisement
Hello.
Firstly, I would suggest sticking to your first attempt: changing an angle and using that angle to determine the X and Y components to move your ship with.

Secondly, I believe your input logic is incorrect. You are checking each successive key only if the previous ones are not pressed. The keys in this case are depending on the state of the previous ones, and they usually shouldn't.

You should instead act separately on each key, or at least not chain them all in the same IF block:

boolean upKey	 =	input.isKeyDown( INPUT.KEY_UP )
boolean downKey	 =	input.isKeyDown( INPUT.KEY_DOWN )
boolean rightKey =	input.isKeyDown( INPUT.KEY_RIGHT )
boolean leftKey	 =	input.isKeyDown( INPUT.KEY_LEFT )

// Only work the "up" action if UP is pressed and DOWN is NOT pressed.
if( upKey && !downKey ) {
	
	shipX += ( float ) ( shipSpeed * Math.cos( Math.toRadians( angle ) ) )
	shipY += ( float ) ( shipSpeed * Math.sin( Math.toRadians( angle ) ) )

	 System.out.println( "X: " + shipX + " " + "Y: " + shipY );

} 

// Only work the "down" action if DOWN is pressed and UP is NOT pressed.
if( downKey && !upKey ) {

	// Note you still need the components in the same direction as the ship, only negated.
	shipX -= ( float ) ( shipSpeed * Math.cos( Math.toRadians( angle ) ) )
	shipY -= ( float ) ( shipSpeed * Math.sin( Math.toRadians( angle ) ) )

}

// Only work the "right" action if RIGHT is pressed and LEFT is NOT pressed.
if( rightKey && !leftKey ) {

	angle += rotation;

	Ship.setCenterOfRotation( Ship.getWidth() / 2, Ship.getHeight() / 2 );
	Ship.setRotation( ( float ) angle );

}

// Only work the "left" action if LEFT is pressed and RIGHT is NOT pressed.
if( leftKey && !rightKey ) {

	angle -= rotation;

	Ship.setCenterOfRotation( Ship.getWidth() / 2, Ship.getHeight() / 2 );
	Ship.setRotation( ( float ) angle );

}

Why not just split that up to two If/elses? It's the same logic, minus the redundant boolean checking.


if( rightKey ) 
{
}
// Only work the "left" action if LEFT is pressed and RIGHT is NOT pressed.
else if( leftKey )
{
}

EDIT: After having my coffee, it seems you just want to have it do nothing when both arrow keys are held down, which is mostly a non-concern, but if you really wanted a non-event to happen you can rearrange to be even cleaner;


float angle = 0.0f;
if( rightKey )
{
   angle += rotation;
}
if( leftKey )
{
   angle -= rotation;
}
if(angle != ApproximatelyZero )

{
    Ship.setCenterOfRotation( Ship.getWidth() / 2, Ship.getHeight() / 2 );
    Ship.setRotation( ( float ) angle );
}

if( rightKey )
{
   angle += rotation;
}
else if( leftKey )
{
   angle -= rotation;
}

Hello.
In this case I believe the right key would have dominance.
Consider the left key being pressed and the ship turning in the left direction. If the right key is then pressed, the ship will start turning to the right whether left is still pressed or not.
It is a particular behaviour that I don't like. Consequently, I prefer to remove it.

You can get around that by doing

if(right pressed) ang velocity += some amount;

if(left pressed) ang velocity -= some amount

newang = oldang + ang velocity

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley


if( rightKey )
{
   angle += rotation;
}
else if( leftKey )
{
   angle -= rotation;
}
Hello.
In this case I believe the right key would have dominance.
Consider the left key being pressed and the ship turning in the left direction. If the right key is then pressed, the ship will start turning to the right whether left is still pressed or not.
It is a particular behaviour that I don't like. Consequently, I prefer to remove it.

Yeah, sorry, half assed cut and paste job, lose the 'else' as the poster above outlined.

The nice part is that if you ever move to an analog stick or other fuzzy device, it's trivially easy to swap to.

I appreciate the reply's Kryzon and ferrous.

@Kryzon, I am curious on why you recommended the first attempt better because Paradigm Shifter recommended I use vectors, which is a good suggestions for future projects.

In terms of controls, I want my controls to be similar to the original asteroid where the UP arrow key is the only button that accelerates the ship right, left, up, down, left or right depending on the direction of rotation. I made a direction vector that had the ship coordinates:


 Vector2f Direction = new Vector2f(shipx, shipy);

then used the Direction vector to render the ship:


public void render(GameContainer gc, Graphics g)
{
  g.drawImage(Ship, Direction.x, Direction.y);
}

followed ferrous advice and normalized the Direction in the update method so I could use the vector to focus on the direction instead of the magnitude


public void update(GameContainer gc, int delta)
{
  
 
if(Pressed Key Up)
{
  Direction.normalize();
   Velocity.y += Direction.y + thrust;
}
 
}
 

when that didn't work I used the following method

Variables


static float shipx = 300f;
static float shipy = 300f;
static float posx = shipx;
static float posy = shipy;
static float speedx = 0.3f;
static float speedy = 0.3f;
Vector2f SpaceShip = new Vector(shipx, shipy);
Vector2f Direction = new Vector2f(posx, posy);
Vector2f Velocity = new Vector2f(speedx, speedy);
 
 

Render Method


public void render(GameContainer gc, Graphics g)
{
  g.drawImage(Ship, SpaceShip.x, SpaceShip.y);
}

Update Method


 
public void update(GameContainer gc, int delta)
{
   
  
  if(Pressed Key Up)
{
     Direction.normalize();
   SpaceShip.x += Velocity.x * Direction.x;
   SpaceShip.y += Velocity.y * Direction.y;
}
  
}
 

Pretty confused on how I should properly execute this?

@Kryzon, I am curious on why you recommended the first attempt better because Paradigm Shifter recommended I use vectors, which is a good suggestions for future projects.


Hello.
In my experience the first approach is simpler, so it works best when you're starting on this subject.
Note that it still uses vectors: Your position is a vector; the velocity that you are adding to this position is also a vector, one that was rotated (or transformed) based on the angle that the ship is facing.

In terms of controls, I want my controls to be similar to the original asteroid where the UP arrow key is the only button that accelerates the ship right, left, up, down, left or right depending on the direction of rotation.


I don't understand this statement very much.

I made a direction vector that had the ship coordinates:

Vector2f Direction = new Vector2f(shipx, shipy);
then used the Direction vector to render the ship:
public void render(GameContainer gc, Graphics g)
{
  g.drawImage(Ship, Direction.x, Direction.y);
}
followed ferrous advice and normalized the Direction in the update method so I could use the vector to focus on the direction instead of the magnitude
public void update(GameContainer gc, int delta)
{
  
 
if(Pressed Key Up)
{
  Direction.normalize();
   Velocity.y += Direction.y + thrust;
}
}


It's not working because every time the UP key is hit, you are normalizing the same vector that you're using to draw the ship. If the ship had started at the center of the screen, like [400, 300] in an 800x600 screen, the ship would then be placed at something like [0.8, 0.6] after the Direction vector is normalized. I also think you should name that Position, not Direction.

Pretty confused on how I should properly execute this?


I would do something along these lines. I don't know Java, so you'll have to interpret the following:
public class Ship {

	public float moveSpeed = 1.0f;
	public float turnSpeed = 1.5f;
	
	public float angle = 0f;
	public Vector2f position;

	public Sprite shipSprite;

	public Ship( posX, posY ) {
	
		position = new Vector2f( posX, posY );
		shipSprite = new Sprite( ..... );
	
	}

	public update( GameContainer gc, int delta ) {
			
		if( input.isKeyDown( INPUT.KEY_RIGHT ) {

			angle += turnSpeed;

		}

		if( input.isKeyDown( INPUT.KEY_LEFT ) {

			angle -= turnSpeed;

		}

		shipSprite.setCenterOfRotation( Ship.getWidth() / 2, Ship.getHeight() / 2 );
                shipSprite.setRotation( ( float ) angle );

		if( input.isKeyDown( INPUT.KEY_UP ) ) {
			
			position.x += moveSpeed * Math.cos( Math.toRadians( angle ) );
			position.y += moveSpeed * Math.sin( Math.toRadians( angle ) );

		}

	}

	public render( GameContainer gc, Graphics g ) {

		g.drawImage( shipSprite, position.x, position.y );

	}

}
You should post this sort of question in the Game Programming forum, where it will receive more attention.
Make sure to specify that you're using Java: http://www.gamedev.net/forum/11-game-programming/

@ferrous, thanks for the reply.

I am confused at what the


this
keyword does in Java. From my understanding its similar to C++ reference operator (&) ? Is this correct?

this keyword in Java refers to the given class of where the this keyword was written inside.

For example, if the this keyword was stated in the Dog class, the this keyword refers to the Dog class.

To make you understand how the this keyword works in Java, let's say you have an instance variable called life that is of type int in the Dog class.

you would write "this.life" in the Dog class to refer to the instance variable called life of that class called Dog.

this.life refers to the instance variable called life


public class Dog
{
 
// instance variable
private int life;
 
// life as a parameter of the Dog constructor
public Dog(life)
{
 
// parameter assigns to the instance variable
this.life = life;
 
}

Alternatively, you do not even need to write this.life to refer to the instance variable if and only if the instance variable and parameters are not the same name.

Thanks @warnexus, I have a better understanding of the

this
keyword.

This topic is closed to new replies.

Advertisement