Ray car

rayCar2.blend (565.3 KB)

import bge
from mathutils import Vector

def main():

    cont = bge.logic.getCurrentController()
    own = cont.owner
    S = cont.sensors['S']
    #store wheelbases
    if 'wheelBases' not in own:
        wb = []
        sp = []
        for child in own.children:
            if 'WheelPoint' in child:
                
                wb.append(child)
            
        own['wheelBases'] = wb
        print('stored '+str(len(wb))+' Wheels')
    
    
    # apply wheel code to each wheel
    for wheelBase in own['wheelBases']:
        if 'SteerMe' in wheelBase:
            rot = own.worldOrientation.to_euler()
            rot.z += own['Steering']*.5
            wheelBase.worldOrientation = rot
            
        end = wheelBase.worldPosition+own.worldOrientation.col[2]*-.66
        start = wheelBase.worldPosition+own.worldOrientation.col[2]*-.125
        ray = own.rayCast(end, start, 0, '', 0,0,0)
        local =  wheelBase.localPosition
        travel = (start-end).magnitude
        
        
        #if the ray hits the wheel is on something
        if ray[0]:
            tire = wheelBase.children[0]
            own.localAngularVelocity.z*=.975
            tire['roll']= ((tire['roll']*7)+own.localLinearVelocity.x*.025*local.y)/8
            tire.applyRotation((0,0,tire['roll']*.5),1)
            if 'SteerMe' in wheelBase:
                if abs(own.localLinearVelocity.y)<2.5:
                    own.applyTorque( (0,0,own.localLinearVelocity.x * own['Steering']),1 )
                else:
                    own.applyTorque( (0,0,own.localLinearVelocity.x * (own['Steering']* 1.5)),1 )
                        
                             
            if 'DriveMe' in wheelBase:
                if abs(own.localLinearVelocity.y)<1.5:
                    own.applyImpulse((start+ray[1])/2,own.worldOrientation.col[0]*own['Throttle']*.025)
                    
                    
                    if  own['Throttle']>0 and 'RTime' in own and not S.positive:
                        del own['RTime']
                        
                    elif own['Throttle']<=0 and 'RTime' not in own and S.positive:
                        own['RTime'] =0
                    elif 'RTime' in own:    
                        if own['RTime']<=14:
                            own['RTime']+=1
                        elif own['RTime']<=19:
                            own['RTime']+=.1
                            own.applyImpulse((start+ray[1])/2,own.worldOrientation.col[0]*own['RTime']*-.005)
                            
                        else:
                            own.applyImpulse((start+ray[1])/2,own.worldOrientation.col[0]*own['RTime']*.1)
                else:
                    own.applyImpulse((start+ray[1])/2,own.worldOrientation.col[0]*own['Throttle']*.025)
                                            
            
            hit_distance = (start-ray[1]).magnitude
            ratio = 1 - (hit_distance/travel)
             
            #print(ratio)
            
            #lift up car with spring force
            own.applyImpulse(ray[1], own.worldOrientation.col[2]*(ratio+ratio)*.06125*2.95)
            own.applyImpulse(ray[1], own.worldOrientation.col[2].reflect(ray[2])*ratio*.06125*-.5)
            vecDist = (own.worldOrientation.col[2]-Vector([0,0,1])).magnitude
            if vecDist<.66:
                own.applyImpulse(start, Vector([0,0,ratio*.06125*.77]))
                own.worldLinearVelocity.z*=.995
            wheelBase.children[0].worldPosition =  wheelBase.children[0].worldPosition.lerp(ray[1]+ (own.worldOrientation.col[2]*(wheelBase.children[0]['r'])),.5)
            
            
            #vertical dampening
            if own.localLinearVelocity.z < 0:
                own.localLinearVelocity.z*= .95
            elif hit_distance < (travel/2) and vecDist<.66:
                own.localLinearVelocity.z*= .975
                
            
            #angular dampening
            
            #print(vecDist)
            
            #print(local)
            diff2 = (own.worldOrientation.col[2]-ray[2]).magnitude
            print(diff2)
            if diff2 <.5:
                if local.x > 0 and own.localAngularVelocity.y < 0:
                    own.localAngularVelocity.y *= 1 -(ratio*.63)
                
                if local.x < 0 and own.localAngularVelocity.y > 0:
                    own.localAngularVelocity.y *= 1 -(ratio*.63)
                    
                if local.y > 0 and own.localAngularVelocity.x > 0:
                    own.localAngularVelocity.x *= 1 -(ratio*.63)
                
                if local.y < 0 and own.localAngularVelocity.x < 0:
                    own.localAngularVelocity.x *= 1 -(ratio*.63)
            
            if local.y > 0 and own.localLinearVelocity.y < 0:
                own.applyTorque([own.localLinearVelocity.y* -2.125,0,0],1)
                own.localLinearVelocity.y*=.995
            elif local.y < 0 and own.localLinearVelocity.y > 0:
                own.applyTorque([own.localLinearVelocity.y* -2.125,0,0],1)    
                own.localLinearVelocity.y*=.995
            if vecDist<.46:
                own.localLinearVelocity.y *= ((1-ratio)*.5 )+.5
                
                
        #push out the tire to max suspension travel if the ray does not hit                         
        else:
            tire = wheelBase.children[0]
            tire.worldPosition = tire.worldPosition.lerp(wheelBase.worldPosition + (own.worldOrientation.col[2]* - (travel-(tire['r'])) ), .5)
            tire['roll'] = ((tire['roll']*7) +  own['Throttle']*.025*local.y)/8
            tire.applyRotation((0,0,tire['roll']*.5),1)
            
main()

or you could use the vehicle wrapper. Just seems easier.

the vehicle wrapper is nice, but its not very stable.

making your own allows you to constrain forces better, or even prevent the vehicle from dropping through the ground.

yeah the vehicle wrapper is less flexible, [upbge vehicle wrapper is more flexible than bge]

this is 100% adjustable - I can tune behaviors. :smiley:

in the thirdperson videogame i made that has a car in it.you can cause the car to be upside down and get out on your head.but your car cannot be turned upside.i like that feature of your car.

Sweet! Thanks for sharing :ok_hand:

Just recently, I stumbled upon this presentation from the Rocket League devs:

As it deals heavily with tuning car physics, I’ll leave this here for your entertainment.

1 Like

thanks

I may have tuned this up after this, I am not sure.

In the above Rocke League presentation, the roll-over behavior of the car seen as in your demo video is discussed 15:55 onwards. He describes their trick of avoiding it as well. Really interesting presentation.