Car rotation problem in top down

Hi everyone,
First off let me say that I’ve been browsing this forum as a guest for a while now, and the community really seems to be friendly compared to some places I’ve seen in the past and I hope that I can contribute as much as I’ve seen people do. It really is a pleasure not seeing anyone being flamed because of the level of intellect they may or may not have :slight_smile:

Moving on to business then. As much as I’ve scoured the internet in search of information concerning Java game programming, I’ve found that this forum in addition to some other sources are close enough to the best you can be lead to. I’ve got a problem with positioning and rotation in a top down car game I’m building and all the resources I’ve seen so far do not go through as much detail as I would hope concerning certain aspects.

The following code is what I have presently, and it would be of great help if someone could point me in the right direction or tell me what is actually being done wrong.

This is where I render my drawing from the game loop.

	
public void render(Graphics2D g) {
        ...
	g.rotate(rotation,x,y);
	g.drawImage(carImage, x, y, null);
		
	g.setColor(Color.GRAY);
	g.drawRect(getBounds().x, getBounds().y, getBounds().width, getBounds().height);
}

This is where i update the drawing for the render process


public void update(int deltaTime) {
	if ((Map.getGameArea().contains(getBounds()))) {
		if (speed >= 0) {
			if (slowdown)
				speed -= .1;
				
		        move();
		}			
	}

        ...

This is when keys are pressed


public void keyPressed(KeyEvent evt) {
	slowdown = false;
		
	if (evt.getKeyCode() == KeyEvent.VK_UP) {
		speed += acceleration;
	}
	if (evt.getKeyCode() == KeyEvent.VK_DOWN) {
		speed -= acceleration;
	}
	if (evt.getKeyCode() == KeyEvent.VK_RIGHT) {
		rotation += rotationStep * (speed/TOPSPEED);
	}
	if (evt.getKeyCode() == KeyEvent.VK_LEFT) {
		rotation -= rotationStep * (speed/TOPSPEED);
	}
}

These are variables that are used to determine the angle

private double rotation = 0;
private double rotationStep = 1.1;

And finally the most important? method to actually change the coordinates

	
private void move() {	
	double ax = Math.sin(rotation * (Math.PI/180)) * speed;
	double ay = Math.cos(rotation * (Math.PI/180)) * speed * -1;
	x += ax;
	y += ay;
}

The variables for speed and acceleration are initialized with 0 and .3 respectively

The actual problem seems the lie in the move method as the x constantly remains 0, and in all honesty I don’t understand why.
Thanks for your time!

What primitive type is X? int or double?

x and y are both int’s seeing as you can’t have a pixel being a double or float or even at that matter a long :slight_smile:

Well there is your problem :smiley:
If you keep adding a double to an int, the decimal part gets chopped off. So if you start out with 0, you add 0.5 to it, x is still 0!
Change x and y to double then in your render() method, use (int)Math.round(x) and (int)Math.round(y) in your drawImage() method :slight_smile:

Ahhhh! that seems to have fixed the problem somewhat, but I believe there is still a problem relating with the rotation of the image in the render? In addition to that, it the movement for the rotation doesn’t feel smooth, and I think the problem for that is because it doesn’t move in the direction the sprite is headed towards. Can you think of any idea why?
BTW, I should have thought of changing the x and y variables then typecasting them to integers inside my render but I’ve been on this problem for quite a while, at least a week and I couldn’t figure out why! so I guess a second pair of eyes really do help! :slight_smile:

By the looks of it, the rotation is dependent on the speed. The faster you go, the more you rotate; the slower you go, the less you rotate.
Try making the rotation constant.

Hahaha the problem was indeed the rotation!, but if you notice my call to the rotation function in the graphics2d class used degrees instead of radians, which required a simple solution Math.toRadians(rotation) and voila the trick is done. Everything seems to be fine for now, I’ll just run a few tests a see what gives!

Thanks a bunch!

You could also call Math.toRadians(rotation) in your move method :smiley:

Glad to help!

You’ll probably find that the movement feels very strange at the moment, because you’re using a one-dimensional speed which rotates with the car. I don’t have any worthwhile experience with car games, but I would guess that you’ll want to use a full vectorial speed and then add a friction component to damp speed perpendicular to the facing of the car so that you corner in a way which feels right.

Actually movement on the level of acceleration in any angle feels relatively smooth, but the actual problem is while steering the car left or right. It feels choppy and I think thats due to the rotation step, but I don’t know how to calculate a smooth rotation other then trial and error. Any ideas?

EDIT: Also forgot to mention something about handling acceleration and reverse for the car. I think this is probably a bad way to handle things but here it is anyway. If you also have any ideas how to handle this any better, please share :slight_smile:


if (Math.round(currentSpeed) > 0) {
	if (slowdown)
		currentSpeed -= .1;
		
	move();
}
if (Math.round(currentSpeed) < 0) {
	if (slowdown)
		currentSpeed += .1;
				
	move();
}

First if statement used when accelerating, and second is reverse. I need to round the currentSpeed seeing as it will either keep accelerating or in reverse if the speed is > or < without rounding.

It seems that trial and error is the best way here. Try lowering the rotation step and analyzing the output.

Why the slowdown boolean variable?

When I release my key, I want it to decelerate to 0, thus the slowdown variable, although I could just shove the speed -= acceleration in the keyreleased which would probably increase performance… hmmm, well good eye! :slight_smile:

EDIT: Actually removing the variable wouldn’t work because there would be no deceleration and I can’t just currentSpeed -= .1 inside keyReleased since the action is only being done once.

You don’t want -=, you want *=, as per usual with friction. Then set it to 0 if it gets too low.

ex.


public void moveCar()
{
    double friction = 0.05;
    car.velocity.x *= (1 - friction);
    car.velocity.y *= (1 - friction);
    car.velocity.x += acceleration.x;
    car.velocity.y += acceleration.y;

    // dampen velocity so that objects will actually be at rest eventually
    car.velocity.x = Math.abs(car.velocity.x) < 0.01 ? 0 : car.velocity.x;
    car.velocity.y = Math.abs(car.velocity.y) < 0.01 ? 0 : car.velocity.y;
}

The best to do this is to have an update() method that is called at a regular interval. Then when a user presses a key, you set the rotation and acceleration accordingly so they would be updated next time udpate() is called. When a user releases a key, you set it so next time update() is called, you start decelerating.

Don’t you mean:


    acceleration.x *= (1 - friction);
    acceleration.y *= (1 - friction);

:smiley:

Conceptually I disagree with you. In my opinion, friction should be applied at all times, given that it is in fact friction. Even when you are accelerating you are under the effect of a small amount of friction (like 0.05). When you are decelerating, you would be increasing the friction (you’re hitting the brakes), but that doesn’t change that friction should always be applied.

No, I don’t, that wouldn’t work. Friction does not affect the acceleration applied by the engine, friction is a separate source of force, so it affects velocity. http://en.wikipedia.org/wiki/Friction

Also just thinking purely in a “what will work” approach, if you are constantly reducing the acceleration then the vehicle will still never stop, because nothing is curbing the velocity.

Yes, in the update() method, you would apply friction and all the other variables.

Would friction affect the acceleration, which in turn would be added to the velocity?
Or am I so sleepy that I am misunderstanding this whole thing? :smiley:

I’m starting to think I did it the wrong way since I’m not using vectors… adding the friction messes it up if I multiply it instead of subtracting it. I don’t understand what is wrong.

Would you mind explaining what isn’t correct about having these two functions?


private void move() {	
    double ax = Math.sin(Math.toRadians(carAngle)) * currentSpeed;
    double ay = Math.cos(Math.toRadians(carAngle)) * currentSpeed * -1;
    x += ax;
    y += ay;
}

and


public void update(int deltaTime) {
	if ((Map.getGameArea().contains(getBounds()))) {
		if (Math.round(currentSpeed) > 0) {
			if (slowdown)
				currentSpeed -= .1;
			
			move();
		}
		if (Math.round(currentSpeed) < 0) {
			if (slowdown)
			        currentSpeed += .1;
				
			move();
		}
	}
        ...

I know using Math.round(currentSpeed) is probably not the smartest thing, but its what halts my vehicle once the speed gets near 0. In addition, what would be the proper way of implementing friction, should I change to use vectors? I’m sure that would simplify the process, but would that work without using a grid?

  1. Do you only call move() when you start slowing down?
  2. Friction is best implemented by taking a tiny percentage off the currentSpeed, eg. currentSpeed *= 0.95;
  3. Let us focus on what is malfunctioning. Is the rotation still not working?