2D car turning & collisisions

Monkey Forums/Monkey Beginners/2D car turning & collisisions

sionco(Posted 2014) [#1]
I'm trying to create a simple top-down 2D racing game. (like micromachines)

Currently, I've got a tile based track, created from a basic track editor, that I created along with checkpoints that are there to provide a path around the circuit, as well as to work out positions and laps (which I've done successfully)

I've also got the movement for the player controlled working, but I'm having problems with the computer controlled cars.

I want them to travel from one check point to another, checkpoints are just a list of x and y coordinates. The cars move forwards, but currently I'm only setting the angle of the computer cars to the difference between the angle of the cars current position and the angle of the next checkpoint (as shown below) so the movement is sudden and erratic:



So I'm wondering, how to turn gradually, and ideally to know whether the amount the car has to turn is greater than the maximum steering amount of the car (called steeramount=0.2, which works well with the player's turning)

JFYI, I check to see whether the car has reached the next checkpoint like this (nxtX and nxtY are the coordinates of the next checkpoint the car has to go to.):


I'm still learning monkey and programming so any help will be greatly appreciated.


Gerry Quinn(Posted 2014) [#2]
One way you could do it would be to plot a curve (could be a Bezier, a circular arc, or a simple quadratic) inside the 'dog-leg' angle that your path from checkpoint1 - checkpoint2 - checkpoint3 makes, and have your car go along that.

A circular arc looks nice in that you could set it up to have a consistent turning radius (which can be a function of car speed) regardless of the acuteness of the corner. If the angle is very acute and the turning radius is large, the car will have to slow down or crash.

It doesn't seem too hard. If rad is your turning radius, I think the points at which you start and finish turning are rad/tan( theta/2) from the corner of the straight line (dogleg) route, and the centre of the turning circle will be rad away from these points in a perpendicular direction to the straight lines. [theta is the angle between the lines of the dogleg.]

You're just fitting a circle of radius rad into the angle between the straight lines.

That's what I'd try first anyway, though I haven't done this.


MikeHart(Posted 2014) [#3]
A method I find very good is to have way- or checkpoints but also a rabbit. The rabbit travels along these waypoints in a linear movement. The cars chase this rabbit. They ajust their heading by driving towards the rabbit. On straights, the rabbit can travel further away form the car. In curves, it has to be closer. I saw this method inside a Unity racing game dev course. Very effective.

http://www.youtube.com/watch?v=XbPciCHPdTw


sionco(Posted 2014) [#4]
Thanks Gerry and Mike for the ideas, they are both interesting approaches, I'll have a look into them both, and report back .-)


sionco(Posted 2014) [#5]
In the end, I've decided to make my own version, which
tests whether the angle to the next checkpoint, is greater than the max turn of the car in the amount of time it'll take to get there.
Currently, the cars don't follow the exact same line around, as they all have different weights, acceleration and grip. This will change once I add things such as overtaking.

But one thing that I'm stuck on is very basic collisions

My idea, but I'm not sure if it's right

If two cars are in the same part of the track then:
test if they are colliding,
by checking their widths and lengths, rotated. (not sure how to programme

if they are colliding, something like this?
x=x+ (Sin(move_angle))*(half the xvelocity of the othercar?)
y=y+(Cos(move_angle))*(half the xvelocity of the othercar?)




Gerry Quinn(Posted 2014) [#6]
There would be something to be said for using Box2D here.

You can make home-made collisions too, basically by iteratively pushing cars that intersect apart, until no cars do. Calculate the 'push-apart' vectors, and add them to the velocity of the cars.

Of course, what happens when there are three cars colliding? Middle one gets pushed right by left car... then gets pushed left by right car, maybe even harder! So you have to iterate and be very careful that your solutions don't blow up.


sionco(Posted 2014) [#7]
Thanks for the idea, I didn't realize box2d, was included in the monkey modules until just searching for it now.


I've never used it, so will have to find some tutorials and start learning it then, thanks again for the advice!


sionco(Posted 2014) [#8]
oops


sionco(Posted 2014) [#9]
I think I'll have to think of something else, as I really can't understand the monkeybox2d demo.


skid(Posted 2014) [#10]
you do need to be a little prepared for a learning curve when it comes to physics, try this thread where hardcoal posts some nice code samples on second page I think.


Volker(Posted 2014) [#11]
More to get started with box2d:
http://www.monkeycoder.co.nz/Community/posts.php?topic=3106&page=1
http://www.monkeycoder.co.nz/Community/posts.php?topic=1764&post=20694


Gerry Quinn(Posted 2014) [#12]
Physics is tough. It's possible to hack something together, but don't expect everything you try to work well. And you still need geometry even if your physics is very fake.

One possibility might be to sort the cars from front to back, and move them an increment in that order. If a car tries to enter the space occupied by another car, it is blocked (it just moves as far as it can). You might consider making the calculations more fine-grained with multiple updates per render cycle.

I can't be sure that would work well, but it's a non-physics solution that might turn out okay IMO.


sionco(Posted 2014) [#13]
ok thank you all for giving me some of your time.

I've been looking at the links, the one skid posted a link is at least a lot more understandable than the demo, with all the imports.

I'll have another look at box2d.
Because, yes, thinking about it, doing something basic on my own, might work ok for some collisions, but as you said, there are many different possibilities.
And even though I'm just trying to make a basic racing game, I've already learned a lot, getting to this point, so I might as well add basic box2d to my little repertoire.

I'll post my findings for future reference for anyone else, once I've got somewhere.


sionco(Posted 2014) [#14]
Ok, I've playing with some small demos of box2d and the collisions are really cool, and even works well with android!

but now my existing movement code didn't fit in with box2d, and it's better if box2d handles all the physics,
but I'm struggling to add movement to the cars from input. here are some failed attempts, I think i'm doing this completely wrong.

Self.body.SetAngularVelocity(0)

If TURN_LEFT Then Self.body.ApplyTorque(-15)
If TURN_RIGHT Then Self.body.ApplyTorque(15)

Local r:Float	= RadToDeg(Self.body.GetAngle())
			
If drivers[id].power > 0 Then
	Self.body.ApplyForce(New b2Vec2(Sin(r)*velocityX,(Cos(r)*velocityY),(Self.body.GetWorldCenter()))
	'Self.body.ApplyForce(New b2Vec2(0,power),(Self.body.GetWorldCenter()))
End



muddy_shoes(Posted 2014) [#15]
https://www.iforce2d.net/b2dtut/top-down-car


sionco(Posted 2014) [#16]
Thanks,
Yes, I've tried following that, but I'm trying to do something more simple with just a main body

and I couldn't get these working in monkey, as some of the functions don't exist and I'm not sure how to do it

b2Vec2 getLateralVelocity() {
      b2Vec2 currentRightNormal = m_body->GetWorldVector( b2Vec2(1,0) );
      return b2Dot( currentRightNormal, m_body->GetLinearVelocity() ) * currentRightNormal;
  }

void updateFriction() {
      b2Vec2 impulse = m_body->GetMass() * -getLateralVelocity();
      m_body->ApplyLinearImpulse( impulse, m_body->GetWorldCenter() );
  }



muddy_shoes(Posted 2014) [#17]
They all exist, either on b2Body or in b2Math.

You haven't provided any runnable code and you don't say exactly what happens with what you've tried that is wrong. I'm not about to set up a test case so it's difficult to provide a solution. Your force calculation looks decidedly odd though. I'm guessing you actually mean to do this:

Local angle:Float = Self.body.GetAngle()
Local carDirection:b2Vec2 = New b2Vec2( Sinr(angle), Cosr(angle) )
carDirection.Multiply( Self.body.GetLinearVelocity().Length() )


...but applying that as a force doesn't make much sense either as the force should be the turn and engine acceleration components, not the velocity. If you really just want box cars rotating about their centre then you may as well just set the velocities directly rather than attempt to use forces to accelerate, i.e.

Self.body.SetLinearVelocity(carDirection)