newbies flight sim game (collisions)

I’d like help to make a flight sim game

I want it to just have a plane that moves by physics and forces, according to it’s rotation and thrust
(but im not good at understanding the physics engine yet)

using “real” physics on airplanes is difficult since calculation the air flowing around the wings and the plane istself is VERY cpu-heavy and impossible to do in runtime. you can fallback on a simplified model like flightgear does. they are using JSBSim which might be intresting for you,too. http://jsbsim.sourceforge.net/

if this is still too difficult for you you can write your own functions in python which defines the plane’s mocement. it’s not that hard and the result can be quite nice,too. most flight-sim games have their own simple math. :slight_smile: it can be done using some vector-math, i guess there should be some stuff on the net about it.
feel free to ask further :slight_smile:

greetings
ThomasEgi

Calculating the real physics on an airplane in a game in real time is just impossible. Aerodynamics are too complex.
So all you can do is calculate the physics for a special case.

That is, you know your plane can fly, you know that the wings of your plane will have a lift that only depends on the speed and the altitude.
So basically you’re going down to simple vector math in this special case. Which means you won’t need a physics engine at all.
Ater all you can only apply forces, and forces are vectors.

I dont want aerodynamics; i meant applying simple forces to the plane, as in thrust and then it turns with Hpr changes (i was looking at the physics engine in the manual)

[edit] i finally got it (somewhat) working
Now, i need help figuring out changing direction, esp relative to the plane, as in pressing left, instead of rotating by global axis, rotates the plane by its axes
or, to make the plane turn like a normal plane

also, how can you change a force, ie. change the thrust

After lots of time trying over a gain, this is about what i got:
(not including basic loading stuff)

def joystick_check(task):
    throt = 0
    for event in pygame.event.get():
        if event.type==10:
            if event.dict['button']==4:
                #reset cam
                print 'cam change'
            elif event.dict['button']==0:
                myglobals.shooting = 1
                print 'now shooting'
            elif event.dict['button']==2:
                pass
                #other buttons
        elif event.type == 11:
            if event.dict['button'] == 0:
                myglobals.shooting = 0
            elif event.dict['button'] == 2:
                pass
    x = 0
    y = 0
    z = 0
    x = mystick.get_axis(0) # roll
    y = mystick.get_axis(1) # pitch     # easily disableable
    z = mystick.get_axis(3) # heading
    th = mystick.get_axis(2)*-1+1    #throttle axis
    if throt == 0:
        if th== 1.0:
            th = 0
        else:
            throt = 1
    if th < .1:
        th = 0
    if abs(x) < .11:    #lessens sensitivity
        x = 0
    if abs(y) < .11:
        y = 0
    if abs(z) < .15:
        z = 0
    plane.model.setHpr(plane.model,-z*.45,y*.6,x*.8)    #differential factors
    plane.changethrust(th/2.5)
    if myglobals.print_debug:
        #print th
        pass
    return Task.cont

if joysticken:  #check if there is a joystick
    taskMgr.add(joystick_check, 'joystick')

class makenewbullet:
    def __init__(self):
        pass

    def makebullet(self, task):
        if myglobals.shooting:
            myglobals.bulletwait+=1
            if myglobals.bulletwait > myglobals.bulletpause:
                exec("self.bullet"+str(myglobals.bullet)+"=newbullet()")
                myglobals.bulletwait = 0
                print 'make bullet'
        return Task.cont

    def deletebullet(self, num):
        exec("del self.bullet"+str(num))
        print 'del bullet'

Bullets = makenewbullet()
taskMgr.add(Bullets.makebullet, "bullet_maker")

class newbullet:
    def __init__(self):
        self.num = myglobals.bullet
        self.speed = .4
        self.time = 0
        self.model = loader.loadModelCopy('models/bullet')
        self.model.setScale(3)
        self.model.reparentTo(render)
        self.model.setHpr(plane.model.getHpr())
        self.model.setPos(plane.model.getPos())
        taskMgr.add(self.move, "bullet"+str(myglobals.bullet))

    def move(self, task):
        self.model.setY(self.model, self.speed)
        self.time += 1
        if self.time < 900:
            return Task.cont
        else:
            Bullets.deletebullet(self.num)
            return Task.done

class thePlane:
    def __init__(self):
        self.model = loader.loadModel('models/plane.x')
        self.model.reparentTo(render)
        self.model.setScale(4)
        self.H = self.model.getH
        self.P = self.model.getP
        self.R = self.model.getR
        self.velocity = [0,0,0]     #unsure of which variables are going to be used
        self.speed = 0
        self.thrust = 0

    def move(self):
        self.model.setY(self.model, self.thrust)

    def changethrust(self, thrust):
        self.thrust = thrust

## plane moving task
def moveplane(task):
    plane.move()
    return Task.cont

taskMgr.add(moveplane, 'moveplane')

plane = thePlane()

the plane somewhat rotates relative to itself, but still not right.
Im not sure how to make it work better, or if i should change the Hpr of a parent node

You have to do rotation in respect to the previous transform:

self.model.setHpr(self.model, h,p,r)

Thanks, I had no clue about that

I got it to change the thrust, but it keeps going after I turn thrust off.
I think I could make it slow down with a viscosity force, but I have no clue how that works, its not in the manual. Does anyone know about viscosity, and would help me on that? Or is it LinearFrictionForce?

also, How would I make the camera follow behind the plane, like in Roaming Ralph, where the camera slowly adjustst to be behind it, not absolutely, and follows its rotation? (not roll)

You can model the viscous force with the following equation:

F = 0.5p(v^2)aCd*D

Where :

  • p is a constant related to the air viscosity
  • v is the speed of the object relative to the air
  • a is the area of the object exposed to the air in the direction of travel
  • Cd is a dimensionless constant called the coefficient of drag (0.1 or 0.2 for an airplane i believe)
  • D is the direction vector of the object

You can simplify this in a game by the following:

F = k*(v^2)*D

Where k is a constant that you can tweak until things look right( reflecting p,a, and Cd above). F is the force vector you are calculating.

Once you have the force F, the acceleration is simple :

F = m*A
where m is the object mass and A is the acceleration vector that you want to solve for:

A = F/m

All the above is taken from Drag (physics) wiki : en.wikipedia.org/wiki/Drag_(physics

Well, I saw in the manual/physics section - viscosity. It said there was a viscosity force included, but nothing else to it.

Aaand im not taking physics till next year.

No degree in physics is really needed, just note that the drag force is proportional to the square of the velocity and fudge until it looks/behaves the way you want.

F = x*(v^2)

Where x is some constant you tweak until you get the effect you want.

Once you have that compute the acceleration from the equation F=m*a

Apply the acceleration using the linear equations of motion : en.wikipedia.org/wiki/Equations_of_motion

I didn’t understand that well enough…

and I am changing my tactics: I saw in the manual a page that described a physics engine, with linear and viscosity forces. I wanted to apply those to my plane, with my joystick changing the Hpr, and thrust (or linear force) to the plane; and the viscosity would keep the plane from infinitely accelerating, and slow it when the thrust is down
the page: https://www.panda3d.org/manual/index.php/Physics_Engine

I tried the linear force, but it kept going too much; as in you turn, and hold thrust on, but you just kept going, not turning.

as for viscosity force, I didn’t see anything. I would like help from someone who understands how those things work.

why do you want to use the physics engine for this anyway?
it’s so much easier without it!

Calculate a vector that’ll always point in the direction your plane is heading.
To do this you can reparent a node to the plane, where the node is exactly in front of the plane (easy while the plane still has a hpr of 0,0,0).

plane.reparentTo(render)
node.reparentTo(plane)
node.setPos(0,-1,0)

Get tha absoulute position of the plane (plane.getPos() ) and the absolute position of the node (node.getPos(render) ) and calculate the vector from this(v1 = node.getPos(render) - plane.getPos() )
Then normalize this vector (v1.normalize() )

Calculate the current speed of your plane. I mean, you can set the speed it should have via user input and then use a task to go up from the actual speed of the plane to the desired speed in a certain time.
Let’s say your current speed is 0.5 (world units or whatever) and you want the plane to go to 1.0, then the task would add 0.1 to the actual speed every few milliseconds. This way you can create the effect of linear acceleration.

Apply the movement to your plane.
plane.setPos(plane, (v1*actual_speed) )

So, the whole task to move the plane looks like this:

v1 = node.getPos(render)-plane.getPos()
v1.normalize()
plane.setPos(plane, (v1*actual_speed))

This way you’ll always have an updated direction vector.
No need for a physics engine at all.

Ok, thanks.
the idea for a node in front of it was smart, I was trying to use trigonometric stuff to calculate

But, how would simulate gravity? or is it worth trying?
and how would it decelerate slowly?
(possibly to where it still moves, but slowly(horizontally); it would be dropping by gravity)

But… I suppose that’s good enough.

We know, that your plane won’t change it’s aerodynamic properties in flight (at least not too much).
So we can assume a constant for lift in a function that only depends on the speed. Gravitational pull is also a constant.
So we have two forces (basically vectors) where one points upwards and one points downwards. The lift force (vector) depends on speed and on the user input (does he want the plane to move upwards or downwards).
So my suggestion would be to reparent another node over the top of the plane(node2.setPos(1,0,0) ).
Like before for forward flight we calculate a vector(v2) from that node and normalize it.
Now about the direction and length of the vector…
As I said before, gravity is a constant, so this will be how we calculate our gravity vector (g):

g = v2 * (-g_const)

where g_const is a constant you insert that represents the gravitational pull. In this equation the constant must have a negative value for the vector to point downwards (hence the - ).
You only need to calculate the g vector once, because it’s a constant and always points downwards to the ground.
Now whe have our gravity in the game.
It’s time to decide how much realism you want to have, because that decision will determine how we calculate our lift vector.
Normally the lift force will raise with speed constantly, so that at a certain point a pilot needs to steer against it in order to keep a certain altitude and not fly higher and higher. But that of course is only true up to a certain altitude where the air gets thinner and the lift gets weaker.
So I would prefer to be not so realistic and stop the lift force from getting bigger after it equals the gravitational pull.
This way the whole thing looks like this:

liftVar = lift_const * speed
if (liftVar >= g_const) :
    liftVar=g_const

liftVec = v2 * liftVar

where you need to play around with the lift_const value to find something realistic.

All you need to do now is to add those vectors (liftVec and g) to your movement vector (v1) before you apply the v1 vector on your model.

Ok, thanks. This is getting to what I want.
But, for the gravity, wouldn’t that just pull it at a constant speed? I would want it to accelerate it downward, but then slow down against speed or thrust pulling it up. … and that would be sorta difficult. Have any ideas?

Also, I want to make a HUD, and I suppose I would use the render2d (or aspect2d to make it nice), but how do I put objects to it? would I still use 3d models, or could I use plain images, or what? ps, I just want a crosshair

ok, we’re lucky here, because in the earths athmosphere the plane can’t fall faster than ~280km/h…
Which means we can again create a task like the one we used for speed up/down…
remember the speed up/down task. We had a setSpeed variable and an actual speed variable.
Our setSpeed variable will be the maximum speed our plane can fall.
The major difference will be, that we don’t add a constant value after every running trough the task, but rather add the difference between the gravitational force and the lift force.

difference = liftVar - g_const

If difference is equal to 0 we set the maxSpeed to 0
If difference is below 0 we set the maxSpeed to -280km/h (instead of 280 you should use a value appropriate in your world)
If difference is above 0 we set the maxSpeed to +280km/h

then we do the calculations:
upDownSpeed = actualSpeed + difference

difference=0 is a special case where we need to do something special:

if (difference == 0):

    if(actualSpeed > maxSpeed):
        upDownSpeed = actualSpeed - const
    if(actualSpeed < maxSpeed):
        upDownSpeed = actualSpeed + const

So now what to do with the upDownSpeed…
We drop g and liftVec and create a new Vector upDownVec
upDownVec = v2 * upDownSpeed

So instead of adding both the g and the liftVec Vector to our speed vector we now only add the upDownVec to our speed vector…

I almost forgot the crosshair:

self.crosshair = loader.loadModel('models/box')
self.crosshair.reparentTo(render2d)
self.crosshair.setScale(0.08,0,0.1)
self.crosshair.setPos(-0.04,0,-0.05)
self.crosshair.setTexture(self.crosshairTexture,1)
self.crosshair.setTransparency(TransparencyAttrib.MAlpha)

where self.crosshairTexture is the texture (transparent png) of your crosshair. The ‘models/box’ is a standard panda model.
This is as simple as it gets.

Thanks, I finally got it to work.
My game is working wonderfully, and the only things I need now are, possibly a better way to make the camera follow behind the plane,
collision detection, for the bullets (to target) and plane (to environ), and to upload the game, so others can demo it.
Mostly, could you help me figure out uploading, so you could try it? (also, it works with a joystick, but it could be easily changed to accept alternately keyboard control)

You should check the manual on collision detection.
You basically just set up a collision traverser.
You can then set the collision bitmask for the env. (so it becomes an into node)
For the planes you should start simply with a collision sphere as a from node.
I don’t know how accurately you want the bullets to be. Anyway there’s just two things you can do.
Either set up a collision sphere for every bullet that has been fired (You might want to have a look into the showcase section of the forum, you’ll find my space shooter sample there, it’ll help you with this), or you just determine that bullets are so damn fast that they’ll reach their target instantly, which means you’ll only need to use a collision ray.
Anyway have a look at the manual, so you’ll understand what I just said.
Once you’ve read it you’ll know what to do…

Sorry its been a while; and I did get collision detection working (somewhat).

One thing about the gravity, when the plane is tilted up, lift is pulling up, relative to the plane(which is good); But, how you say to apply gravity, is against the lift, but that is relative to the plane and forward, it should be pulling down. Also, with that, would that mean I have to have a gravity speed, different from the plane speed?
Another thing I was aiming to do was to have speed changed according to thrust. So, if the thrust is at 0, the plane will decelerate, and after a certain point, the thrust would make the plane stop decelerating, and accelerate above that point. (and a max speed to cap acceleration.)
I have this:

def changethrust(self, thrust):
    self.thrust = (thrust)/40
    if self.thrust < .0089:
        self.speed -= -self.thrust+self.decel
        if self.speed < 0:
            self.speed = 0

    elif self.thrust < .02:
        if self.speed > self.thrust*5:
            self.speed -= self.decel
        else:
            self.speed += self.thrust*.14
    else:
        if self.speed < self.maxspeed:
            self.speed += self.thrust*.2
        else:
            self.speed -= self.decel

Which does work, but not excellently
I intend the ‘point’ not to be clearly defined, but the deceleration actually would be from a drag force, that the more speed, the more it reduces the speed (which may actually account for maxspeed), and the thrust would be fighting the drag. (I guess the drag wouldnt be used for gravity)
p.s. : this would be called every frame, by the task that checks the throttle on the joystick.