Car rotation problem in top down

No, move is called when currentSpeed > 0 or < 0

Implementing this makes my coordinates go ‘wako’.

Rotation is functioning but is ‘choppy’ as I stated earlier. I would have thought there would be a better way then trial and error, but the rotation really doesn’t feel smooth. And well reverse is fixed but like I said, I’m sure there is a better way for doing it instead of rounding currentSpeed.

Oh yes that’s what I meant :stuck_out_tongue:
I was wondering if the calls to move() you showed us are the only ones or not.

How does this make your coordinates go ‘wako’? :stuck_out_tongue:

There really is no reason to round. If the car is not moving then the currentSpeed == 0. If the speed is between 0.0 and 0.5, your code will interpret that as stationary when you’re actually moving.

I also just noticed: Why do you subtract 1 from the ay after the Math.cos()?

  1. Yup move is only called within the update function, as this is the only class which has everything to do with the car.

  2. If I change the move method to integrate friction as Eli Delventhal mentioned giving


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

    x = Math.abs(x) < 0.01 ? 0 : x;
    y = Math.abs(y) < 0.01 ? 0 : y;
}

then the x and y coordinates seem to radically shift in one update loop. I don’t know if you understand what I mean, but I can post my whole class here if need be to illustrate? what is actually happening when I use friction. Note that it’s very possible I’m the one messing something up, since my math skills aren’t exactly up to par. ;D

As for not rounding… I know in a normal situation you probably wouldn’t need to, but if I consider not rounding inside my update function, the car still travels with minimal speed whether it be in forward or in reverse. :-\

And I multiply* but -1 so that my y coordinate travels in the proper direction, instead of going backwards (or in a car someone might think of it as going in reverse)

If you want, take a look to “Google Map Race”. It is a full top-down race prototype game in java 2d with sources. It can give you ideas.

I still don’t understand why you would apply the friction to the x and y! Friction is applied to acceleration! ;D

I should get some sleep cause my eyes can’t see properly :stuck_out_tongue:

Eli suggested doing that to the velocity, not the position (or the acceleration).

I think there are two problems which might explain your choppy rotation. First, you should just use the keyPressed()/keyReleased() functions to set/clear boolean variables leftPressed, upPressed, etc. Never put code that updates game objects in those functions. Move your ‘maths’ code into the move()/update() functions instead, and make it use leftPressed, etc.

Second, you’ve got a value deltaTime that you’re not using. I’m assuming from that that your game loop uses variable time steps, i.e., the time between calls to update() may be different each time. (You could try printing out the value of deltaTime to check this.) If so, you will need to multiply speeds and accelerations by (something proportional to) deltaTime to compensate. For example, if the car is moving at one metre per second, but the time between calls to update() is sometimes one second, sometimes ten seconds, you can see that the amount you need to move the car isn’t simply equal to the current speed.

Simon

You are essentially using vectors split out into components, that’s fine. You don’t want to add or subtract .1, you want to multiply by 0.9 or 0.95.

And friction is not applied to acceleration, it’s a separate force upon the object, so you apply it to the closest thing we have to cumulative force - velocity. Force is just velocity times mass, so we’re merely taking mass out of the picture as it’s rarely needed for simpler physics simulations like this. The car’s acceleration from its engine and the friction applied from the ground are separate forces (aka separate changes in velocity) so they are applied separately.

dishmoth has all good points, definitely try to implement what he’s talking about.

Yeah, for some reason I always interchange acceleration and velocity.
In my mind, I am visualizing the car’s velocity with 2 forces on it: acceleration and friction.

And multiplying the velocity by 0.9 or 0.95 instead of adding or subtract 0.1 is exponential, which is the closest to real life, rather than linear.

dishmoth’s ideas are the norm today, since I use them and I’m sure others do too.

Alright so I fixed up the code to use 4 booleans for the keys pressed and came out with this. I know the proportion isn’t included because I’m not sure to go about it. If anyone code share some thoughts on it I’d appreciate it! :slight_smile:


private void move(int deltaTime) {
	acceleration = .1;
	friction = 0.03;
	seconds += (deltaTime / 1000.0);		
		
	if (up) {
		if (currentSpeed < topspeed)
			currentSpeed += acceleration * seconds;
		else
			currentSpeed = topspeed;
	}
		
	if (down) {
		if (currentSpeed > -3)
			currentSpeed -= acceleration * seconds;
	}
		
	if (right) {
		carAngle += rotationStep * (currentSpeed/topspeed);
		currentSpeed -= .02;
	}
		
	if (left) {
		carAngle -= rotationStep * (currentSpeed/topspeed);
		currentSpeed -= .02;
	}
		
	currentSpeed *= (1-friction);
        currentSpeed = Math.abs(currentSpeed) < 0.03 ? 0 : currentSpeed;
	    
	double ax = Math.sin(Math.toRadians(carAngle)) * currentSpeed;
        double ay = Math.cos(Math.toRadians(carAngle)) * currentSpeed * -1;
	    
        x += ax;
        y += ay;

}

That whole thing with the seconds variable looks weird.
Multiplying acceleration (0.1) with seconds (which is likely to be less than 1) is going to output an even smaller number, causing your acceleration to be tiny.

deltaTime is the difference of time between the last iteration and this iteration of the call to move().
You should be checking to see if the deltaTime is different from the actual deltaTime you want, eg, 60 times a second or 16-17 milliseconds (preferably 16,667 nanoseconds)
Then have a scale variable to adjust accordingly.


double scale = (deltaTime/16667);
....
currentSpeed += acceleration*scale;
...
currentSpeed -= acceleration*scale;

That code looks pretty close to what I’d expect, except - as ra4king says - for the time stuff.

Things would be simpler if you had a ‘fixed frame rate’ game loop (so deltaTime is the same on every update, and on every machine) rather than a ‘variable’ one. But sticking with things as they are, I’d say that the function should look something like:


private void move(int deltaTime) {

  final double deltaSeconds = (deltaTime / 1000.0); // seconds since last update

  currentSpeed *= Math.max(0.0, (1 - friction*deltaSeconds));

  if ( Math.abs(currentSpeed) < tinySpeed ) currentSpeed = 0.0;
	    
  if (up) {
    currentSpeed += acceleration * deltaSeconds;
    if (currentSpeed > topspeed) currentSpeed = topspeed;
  }

  if (down) {
    currentSpeed -= acceleration * deltaSeconds;
    if (currentSpeed < bottomspeed) currentSpeed = bottomspeed;
  }

  if (right) {
    carAngle += rotationStep * (currentSpeed/topspeed) * deltaSeconds;
  }

  if (left) {
    carAngle -= rotationStep * (currentSpeed/topspeed) * deltaSeconds;
  }
		
  double ax = Math.sin(Math.toRadians(carAngle));
  double ay = -Math.cos(Math.toRadians(carAngle));

  x += ax * currentSpeed * deltaSeconds;
  y += ay * currentSpeed * deltaSeconds;

}

You’ll need to do some trial-and-error to find sensible values for the different constants. Start by setting friction to zero until everything else is working. I don’t know if it’s necessary to have the car always slow down when turning, but I’ve omitted that from the code above for simplicity.

Fingers crossed that’s the sort of thing you’re after.

Simon

So I’ve tried what you’ve mentioned dishmoth and it seems that with the seconds being used I need outrageous numbers in acceleration to be able to show motion for the car itself. I’ve reverted to the previous solution using the proportion ra4king proposed and now have motion with variables with are much smaller. I’m guessing this is due to the fact that in your solution - you base time on seconds; which I very much like and would prefer using. What I’m trying to do though, is implement something along the line of knowing only the acceleration for example 0-62mph or 0-100kph in 3.5 seconds for example. So we could say that acceleration = (62-0)/3.5 seconds seeing as the vehicle was at rest. The problem I seem to face when I try to implement this is beause deltaTime is such a low number, that acceleration must be very high; higher then ~17.71 for us to see adequate motion happening. Please note that I am using the base game code provided by Gudradain which has included desiredFPS. I might be totally wrong here, but that might have a huge roll to play in the operation of the move function. Anyway as I said, I’d very much like to use seconds so I can simulate real car physics with the notion that maybe 1px = 1mph? or 1kph? - still haven’t decided on either or, and either or will probably be fine seeing as doing conversions between is a peice of cake :smiley:

dishmoth is using seconds to divide the “per second” between the multiple calls to update() every second.
I was using scale to fix any deviation from the regular calls to update() since Thread.sleep() and javax.swing.Timer are not that accurate sometimes.

Ok so acceleration and friction are fully added every second, so you take a fraction of them every call to update();
Let’s say that when you press up, you add 1 to acceleration every second and subtract 1 when you press down (you can tweak this by testing).
So you would have:


double vx = 1.0;
double vy = 0.0;
double acceleration = 0.0;
double friction = 0.05

public void update(int deltaT) {
   double deltaSeconds = deltaT/1000.0;
   
   if(up)
      acceleration += 1.0*(deltaSeconds);
   if(down)
      acceleration -= 1.0*(deltaSeconds);
   if(right)
      carAngle += rotationStep * (vx/topVX) * deltaSeconds;
   if(left)
      carAngle -= rotationStep * (vx/topVX) * deltaSeconds;
   
   vx = Math.min((vx + (acceleration*deltaSeconds)) * (1-(friction*deltaSeconds)),topVX);
   vy = Math.min((vy + (acceleration*deltaSeconds)) * (1-(friction*deltaSeconds)),topVY);
   
   x += Math.sin(Math.toRadians(carAngle))*vx;
   y += -Math.cos(Math.toRadians(carAngle))*vy;
}

I usually don’t bother trying to convert everything into real-world values, and instead just measure everything in pixels per timestep. Therefore my delta becomes a scale of the “ideal” FPS (usually 60), so if we have a higher FPS than that we have a lower delta and vise versa.

Although these days I do almost everything with a fixed frame rate because I think it’s a lot easier to avoid mistakes (if you forget multiplying by delta anywhere then you’re not in trouble, because there is no delta) and it’s a lot better for networked situations and applying physics.

In my example, velocity has units of ‘pixels per second’, and acceleration has units of ‘pixels per second per second’. It doesn’t mean there’s a problem if the numbers are very big (or very small), that’s just how the units work out. But use whatever units you’re comfortable with.

[quote]Please note that I am using the base game code provided by Gudradain which has included desiredFPS.
[/quote]
Ah, okay, so if that code is working as advertised (I’ve not tried it, but it looks reasonable) then deltaTime should have roughly the same value every time, and it won’t hurt to just ignore it completely. That simplifies the physics code a lot, and means you can ignore just about everything I’ve said. :stuck_out_tongue:

Is your game actually running as you’d expect it to now? What happened to the choppy rotation?

Simon

dishmoth, I have come to an understanding that speed would be calculated in pixels / second since I guess converting to real world would probably cause way more headaches then solutions :). Also I did get kind of carried away by the resulting constant variables being either too high in one way or too low if implemented differently.

As for the game code, deltaTime does have roughly the same value every time, but I still wish to use it to ‘perfect’ if you wish the current movement. I’m not one to give up because the problem doesn’t necessarily have an easy solution :D, although sometimes it can be an annoyance ;D.

As far as for how the game is actually running, its still not exactly what I want, since like I said I was considering implementing acceleration in the form of 0-62 for matters sake (pixels/second) in 3.5 seconds, although ra4king has probably given me the solution ie (acceleration += (62/3.5) * deltaSeconds)?

As for choppy rotation, thats still is the case, but I’m starting to get to a point where it will be passable with more trial and error, because as some of you said, that would be the only way to go about it to calculate the rotation angle?

Oh and one last thing. Why do most of you ignore increasing friction while the vehicle is turning? or reducing velocity?

For simplicity. It makes sense to get the basic car physics working correctly before adding more complicated effects.

Also, there are lots of different ways that things like friction can be applied (e.g., pjt33’s post above) and you’re the only person who can decide what ‘feels’ right for your game.

Simon

Could you give us your current game code? I want to compile it and run it to better understand the rotation. Plus I work better with the code on hand :slight_smile:

Ya sure, no problem. I totally understand that, I also work better with code in front of me :D.

Please do note that it is somewhat messy, and probably not anywhere near professional level code, but I think it is easy to manage and get around. :stuck_out_tongue:

The source code is here http://rapidshare.com/files/449959015/ShootEm_UP.zip

EDIT: Note that this was built using eclipse, so it might be easier to just add the folder to your workspace and let eclipse handle the rest ;D

The car wouldn’t show up for some reason then, after 30 minutes of rummaging through the code, I found out that you use an image, which was not in the zip file so the getBounds().width and height on the Car would be -1. So I set those to 20 and the game runs fine! I don’t see any choppiness in the rotation. I moved the car around while shooting and everything works beautifully and smoothly. With some tweaking you could probably increase friction and acceleration a bit. Also, you need to fix the bounds checking. Other than that I found no other problems. Maybe the choppiness is caused by your computer?

Best of luck! ;D

BTW: Your code is quite complex for my taste. It could have been 20x simpler and with less classes and singletons. :wink: