import bge import time import math import bpy import random import numpy import aud import mathutils import inspect import Reuse import Distraction import Opt import Character_Controll deleteAtDistance = 500 fixGaragePosition = [-754.61, -1043.9, 409.32] raceNames = {"RedKissBox":"Tali", "NeonSpeedsterBox":"Jack"} def start_car(): # This function runs when the car is created. # It creates the Bullet Physics RayCast Vehicle # wrapper for the car. # Getting basic things cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() car = cont.owner # Creating the vehicle constraint itself vehicle = bge.constraints.createVehicle(car.getPhysicsId()) # Saving the ID of the constraint so we could access it later. car["cid"] = vehicle.getConstraintId() bge.logic.globalDict[car["cid"]] = {"wheels":[]} ###### SETTING UP WHEELS ##### # LEFT BACK wheel0 = car.children[car.get("wheelsname", "Wheel")+""] bge.logic.globalDict[car["cid"]]["wheels"].append(wheel0) wheel0.removeParent() vehicle.addWheel(wheel0, [car.get("wheelswidth", 0.89), car.get("wheelsback", 1.65), car.get("wheelsdown", -0.1)], # Pos Local [0, 0, -1], # Dir Local [-1, 0, 0], # Axl Local 0.2, # Suspention length car.get("wheelradius", 0.42), # Wheel Radius 1 ) # RIGHT BACK wheel1 = car.children[car.get("wheelsname", "Wheel")+".001"] bge.logic.globalDict[car["cid"]]["wheels"].append(wheel1) wheel1.removeParent() vehicle.addWheel(wheel1, [-car.get("wheelswidth", 0.89), car.get("wheelsback", 1.65), car.get("wheelsdown", -0.1)], # Pos Local [0, 0, -1], # Dir Local [-1, 0, 0], # Axl Local 0.2, # Suspention length car.get("wheelradius", 0.42), # Wheel Radius 1 ) # LEFT FRONT wheel2 = car.children[car.get("wheelsname", "Wheel")+".002"] bge.logic.globalDict[car["cid"]]["wheels"].append(wheel2) wheel2.removeParent() vehicle.addWheel(wheel2, [car.get("wheelswidth", 0.89), car.get("wheelsfront", -1.25), car.get("wheelsdown", -0.1)], # Pos Local [0, 0, -1], # Dir Local [-1, 0, 0], # Axl Local 0.2, # Suspention length car.get("wheelradius", 0.42), # Wheel Radius 1 ) # RIGHT FRONT wheel3 = car.children[car.get("wheelsname", "Wheel")+".003"] bge.logic.globalDict[car["cid"]]["wheels"].append(wheel3) wheel3.removeParent() vehicle.addWheel(wheel3, [-car.get("wheelswidth", 0.89), car.get("wheelsfront", -1.25), car.get("wheelsdown", -0.1)], # Pos Local [0, 0, -1], # Dir Local [-1, 0, 0], # Axl Local 0.2, # Suspention length car.get("wheelradius", 0.42), # Wheel Radius 1 ) # Setting up wheel physics characteristics. # ( NOTE: ) This is not the only place where those are set. # Damage and Rescue functions update those values. car["suspensions"] = [] for i in range(4): vehicle.setSuspensionStiffness(car.get("suspension", 200), i) car["suspensions"].append(car.get("suspension", 200)) vehicle.setTyreFriction(car.get("friction", 1), i) vehicle.setRollInfluence(car.get("roll", 0), i) ##### SETTING UP THE DAMAGE MODEL ##### def collision_callback(object, point, normal): # This function will run whenever the car colides with anything. # Dani object ( main human character ) dani = scene.objects["Dani_Box"] toFPS = Opt.ToFPS() # Near misses - when the player drives quickly # near a different vehicle. If colision happens, # near misses are canceled. car["veryclose"] = None # If anywhere within the proximity of the car, # an explosion was set off ( car colided with the shockwave sphere ). # we want to setup a timer, to blow car up in a few ticks after that. # Doing it immediately makes the second explosion almost inconciaveable. if object.get("explosion"): car["blowuptimer"] = 20 # Canceling the rest of the calculation if we can't see it, or it is too far from the camera. cam = scene.active_camera if car.getDistanceTo("Dani_Box") > 20 or cam.pointInsideFrustum(car.worldPosition) == cam.OUTSIDE: return # If human pushes the car, there is no damage if dani == object: return # Separation is an invisible object that bots see to navigate. # We don't want it to cause damage. if "Separation" in object.name: return #### WATER INTERACTIONS #### if object.name == "Water": car["underwater"] = True if car["active"]: dani["underwater"] = True # Sound device = bge.logic.globalDict["SoundDevice"] s = "//sfx/splash.ogg" code = s+str(car["cid"]) if code not in bge.logic.globalDict["sounds"]: bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(s)), "play":None} sound = bge.logic.globalDict["sounds"][code] if not sound["play"] or not sound["play"].status: sound["play"] = device.play(sound["sound"]) sound["play"].location = point sound["play"].velocity = car.getLinearVelocity() sound["play"].relative = False sound["play"].distance_maximum = 100 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 return # Returning if performance is not good if not Opt.GoodFPS("Car Collisions", 0.9) and not car.get("active"): return # Velocity of the car cv = car.getLinearVelocity() # Averagin the values av = sum(cv) / 3 if av < 0: av *= -1 av /= (toFPS ** 2) # Setting off sparks if the velocity is beyond a certain amount if av > 0.1: Distraction.particles("Sparkle", point, despawn = random.randint(30, 100), amount = random.randint(0, 3), max = 50, spread = 0, normal = 0.04, velocity = cv * 0.015) # Restricting all the rest of the calculations based on a timer # between the colisions. if car.get("lastdamage"): return car["lastdamage"] = random.randint(10, 60) # Adding nitro on colision ( based on the speed of the car ) car["nitro"] += av*20 #### ENEMY VOICES #### # NPC cars might get angry and start attacking you if you hit them. # When they get angry they swear at you. This is the logic of the # swearing sounds. And the getting angry logic. if object.get("engine") and car.get("npc") and car.get("npc") != "racer" and object.get("enemy") != car: device = bge.logic.globalDict["SoundDevice"] if not car["npc"] == "enemy": sound = random.choice(bge.logic.globalDict["sounds_angry_start"]) sound = bge.logic.globalDict["sounds"][sound] sound["play"] = device.play(sound["sound"]) sound["play"].location = car.position sound["play"].relative = False sound["play"].distance_maximum = 50 sound["play"].distance_reference = 5 sound["play"].attenuation = 1 sound["play"].volume = 1.5 car["enemysound"] = sound["play"] if object.get("active"): scene.objects["Angry_pusuit"]["pusuit"] = True if not dani.get("active_sound"): dani["active_sound"] = device.play(bge.logic.globalDict["sounds"]["dani_ohno"]["sound"]) bge.logic.globalDict["sounds"]["dani_ohno"]["play"] = dani["active_sound"] dani["active_sound_is"] = "dani_ohno" elif car["enemy"] == object and ( not car.get("enemysound") or not car["enemysound"].status ): sound = random.choice(bge.logic.globalDict["sounds_angry_hit"]) sound = bge.logic.globalDict["sounds"][sound] sound["play"] = device.play(sound["sound"]) sound["play"].location = car.position sound["play"].relative = False sound["play"].distance_maximum = 50 sound["play"].distance_reference = 5 sound["play"].attenuation = 1 sound["play"].volume = 1.5 car["enemysound"] = sound["play"] if object.get("active") and not dani.get("active_sound_is") == "dani_ohnoindeed" and not dani.get("active_sound"): dani["active_sound"] = device.play(bge.logic.globalDict["sounds"]["dani_ohnoindeed"]["sound"]) bge.logic.globalDict["sounds"]["dani_ohnoindeed"]["play"] = dani["active_sound"] dani["active_sound_is"] = "dani_ohnoindeed" # Getting angry car["npc"] = "enemy" car["enemy"] = object object["chased"] = True # Getting car's body. rig = car.children[car.get("rig","RIG")] body = rig.children["Car_body"] # Getting the velocity of the colision ( comparing to the valocity of the object we are coliding with ) ov = object.getLinearVelocity() ov /= (toFPS ** 2) sp = cv - ov # We can't simply average the velocity since it could be negative. sm = 0 for i in sp: if i > 0: sm += i else: sm += i*-1 sp = sm / 3 # Adding the mass of both objects to the calculation obmass = object.mass if not obmass: obmass = 1 breakMultiply = max(0, min(1, 1-(sp * obmass)/55)) ** 0.05 breakMultiply *= (toFPS ** 2) # Blow up when getting a 0 breakMultiply if not breakMultiply: car["blowuptimer"] = 10 ####### BREAKING THE CAR ####### if breakMultiply < 0.999 or object.get("explosion"): # Hit sound device = bge.logic.globalDict["SoundDevice"] # Hit versus scrape sound if breakMultiply < 0.98: s = "//sfx/hit.ogg" else: s = "//sfx/scrape.ogg" code = s+str(car["cid"]) if code not in bge.logic.globalDict["sounds"]: bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(s)), "play":None} sound = bge.logic.globalDict["sounds"][code] sound["play"] = device.play(sound["sound"]) sound["play"].location = point sound["play"].relative = False sound["play"].distance_maximum = 100 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 sound["play"].pitch = random.choice([1, 0.8, 1.2, 0.6, 1.4]) sound["play"].volume = 1 / max(0.1, breakMultiply ) # slecting what area of the car to effect areas = {"Front_Left" : normal[0] < 0.1 and normal[1] < 0.1, "Front_Right": normal[0] < 0.1 and normal[1] > -0.1, "Back_Left" : normal[0] > -0.1 and normal[1] < 0.1, "Back_Right" : normal[0] > -0.1 and normal[1] < 0.1} wheels = {"Front_Left" : 2, "Front_Right": 3, "Back_Left" : 0, "Back_Right" : 1} for area in areas: if ( areas[area] and car[area] > 0 ) or object.get("explosion"): # Reducing health car[area] *= breakMultiply # If broken toally we pop a wheel if car[area] <= 0.01: # We can't simply undo the wheel from the constraint. But # we can do the next best thing. bge.logic.globalDict[car["cid"]]["wheels"][wheels[area]].setVisible(False) vehicle.applyBraking(10, wheels[area]) vehicle.setSuspensionStiffness(0,wheels[area]) # If it is an npc, we make him give up trying to drive. if not car.get("racing"): car["npc"] = "" # Tire Pop sound = bge.logic.globalDict["sounds"]["tire_pop"] sound["play"] = device.play(sound["sound"]) sound["play"].location = point sound["play"].relative = False sound["play"].distance_maximum = 100 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 sound["play"].volume = 2 # If we are not totally broken, make the wheel worse handeling-wise. elif car["Front_Left"] < 0.7: vehicle.setSuspensionStiffness(car.get("suspension", 200)*car["Front_Left"],wheels[area]) vehicle.setRollInfluence(1-car[area], wheels[area]) # If below a certain health, we make the car body look borked if car[area] < 0.7: body.replaceMesh(car.get("borked", "Borked")) # If the heal even lower. if car[area] < 0.3: # Removing left door. if "Left" in area: try: door = rig.children["Door_Pease.001"] door.visible = False except: pass # Removing right door. elif "Right" in area: try: door = rig.children["Door_Pease"] door.visible = False except: pass # Adding the collision function to the car's collision functions. car.collisionCallbacks.append(collision_callback) def update(): # This function is called on ever game logic tick for every car # in the scene. This is the logic of the car. # BGE logic stuff cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() car = cont.owner toFPS = Opt.ToFPS() carRacing = car.get("racing") carEnemy = car.get("enemy") carBehaviour = car.get("npc") carActive = car.get("active") carSpeed = car.get("speed") rig = car.children[car.get("rig","RIG")] cam = scene.active_camera camtarget = car.children["CarCamTarget"] # Is the car in view distanceToCam = car.getDistanceTo(cam) inview = ( cam.pointInsideFrustum(car.worldPosition) == cam.INSIDE and distanceToCam < deleteAtDistance / 2 ) or distanceToCam < deleteAtDistance / 3 or distanceToCam > deleteAtDistance # Dani related things dani = scene.objects["Dani_Box"] # Delete vehicle ( at distance, usually done for NPC cars ). if car.getDistanceTo(cam) > deleteAtDistance and not carRacing and car in bge.logic.globalDict["allcars"]: def RemovingTheCar(car, dani): # If car is waiting for a race to start, we don't delete it if carBehaviour == "racer": racename = car["race"] race = bge.logic.globalDict["races"][racename] starter = race["starters"][0] if dani.getDistanceTo(starter["location"]) < deleteAtDistance or car["racing"]: return print("Removing Car:", car) # Making sure it can be respawned if car.get("spawnPoint"): car["spawnPoint"]["to_spawn"] = True # Removing the car from races for racename in bge.logic.globalDict["races"]: race = bge.logic.globalDict["races"][racename] try: race["racers"].remove(car) except: pass if car in bge.logic.globalDict["allcars"]: bge.logic.globalDict["allcars"].remove(car) # Removing from cache if too many cars in cache if Reuse.reuse.get(car.name):# or len(bge.logic.globalDict["allcars"]) > bge.logic.globalDict["maxCars"]: for i in bge.logic.globalDict[car["cid"]]["wheels"]: i.endObject() Reuse.EndObject(car) # Otherwise storing it for later. else: Reuse.Delete(car, inactive=True) # Undoing angry pursuit try: if car["enemy"]["active"]: scene.objects["Angry_pusuit"]["pusuit"] = False except: pass if Reuse.reuse.get(car.name) or len(bge.logic.globalDict["allcars"]) > bge.logic.globalDict["maxCars"]: Opt.ScheduleTask("Removing Car ["+car.name+"]", 1.0, RemovingTheCar, car, dani) else: RemovingTheCar(car, dani) # Cutting down on unnesesary running of the script if ( not carRacing and not carActive ) and ( not inview ): car["deactivated"] = True car.suspendPhysics() return elif car.get("deactivated"): car.restorePhysics() car["deactivated"] = False # Physics constraint for the vehicle vehicle = bge.constraints.getVehicleConstraint(car["cid"]) # Sound device for sounds. device = bge.logic.globalDict["SoundDevice"] # Car's health health = sum([car["Front_Left"], car["Front_Right"], car["Back_Left"], car["Back_Right"]])/4 engineHealth = ( car["Front_Left"] + car["Front_Right"] ) / 2 car["health"] = health # Fixing the car ( when in the garage) if distanceToCam < 30 and car.getDistanceTo(fixGaragePosition) < 2 and health < 1: bge.logic.globalDict["print"] = "Press F to fix the car." # Fix car if F is pressed if 28 in bge.logic.globalDict["keys"]: body = rig.children["Car_body"] body.replaceMesh( body["good"] ) for i in range(4): vehicle.setSuspensionStiffness(car.get("suspension", 200), i) vehicle.applyBraking(0, i) vehicle.setTyreFriction(car.get("friction", 1), i) vehicle.setRollInfluence(car.get("roll", 0), i) bge.logic.globalDict[car["cid"]]["wheels"][i].setVisible(True) for i in ["Front_Right", "Front_Left", "Back_Left", "Back_Right"]: car[i] = 1 # Doors ( some cars have them falling ) try: rig.children["Door_Pease.001"].visible = True rig.children["Door_Pease"].visible = True except: pass elif carActive and health < 0.98: toprint = "You can fix the car in the garage at home." if toprint not in bge.logic.globalDict["done-prints"]: bge.logic.globalDict["print"] = toprint # Whether the car is on graound. graypos = car.position.copy() graypos[2] -= 1.5 onGround = car.rayCastTo(graypos) # Car's rotation rot = car.localOrientation.to_euler() upsideDown = not ( -2.5 < rot[0] < 2.5 and -2.5 < rot[1] < 2.5 ) # Colision timer if car.get("lastdamage"): car["lastdamage"] -= 1 # Lauchtime timer if "launchtime" not in car: car["launchtime"] = 300 car["launchtime"] -= 1 # Water boyancy if car.position[2] < -9.5 and car.get("underwater"): car.applyForce([0,0,-5*(car.position[2]+9.5)]) if car["speed"] < -1.5: car.applyForce([0,-80,0], True) car.orientation = [0,0,rot[2]] elif car.position[2] > -9.5: car["underwater"] = False # Speed calculation psp = vehicle.getWheelRotation(0)+vehicle.getWheelRotation(1) sp = psp - car["prevwheelrot"] car["prevwheelrot"] = psp car["speed"] = sp # sp will be speed normalized if sp < 0: sp *= -1 # Down Force dforce = -5*sp*car.get("downforce", 1) if onGround: dforce = min(-5, dforce) car.applyForce([0,0, Opt.Force(dforce)], True) # Gage if carActive: gagerotation = sp * 0.214 # 400 km/h == 4.27 radiance on the gage gage = scene.objects["Gage_Arrow"] gage.orientation = [0,0,-gagerotation] gage_health = scene.objects["Gage_Health"] gage_health["Health"] = int(( (health ** 2 ** 3) / (1 ** 2 ** 3 ) )*100) ###### NITRO ###### # Making sure that nitro isn't overboard. car["nitro"] = max(0,min(10000, car.get("nitro", 0.0))) if carActive: gage_nitro = scene.objects["Gage_Nitro"] gage_nitro["Nitro"] = car["nitro"]/100 # Function activated when Nitro is used def nitro(): if car["nitro"] <= 0: stopNitro() return # Actual Nitro Effect on the car #if car["engine"] < car.get("maxengine", 2)-0.1: car["engine"] += car.get("maxaccel",0.003)* 5 * toFPS #else: # car["engine"] = car.get("maxengine", 2)*1.5 car["nitro"] -= 20 # Anti bank if car.get("roll",0): car.applyRotation([0.05*car.get("roll",0),0,0], True) car.applyForce([0,0, -20*car.get("roll",0)], True) # Nitro Sound s = "//sfx/nitro.ogg" code = s+str(car["cid"]) if code not in bge.logic.globalDict["sounds"]: bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(s)), "play":None} sound = bge.logic.globalDict["sounds"][code] if not sound["play"] or not sound["play"].status: sound["play"] = device.play(sound["sound"]) sound["play"].location = car.position sound["play"].relative = False sound["play"].distance_maximum = 100 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 sound["play"].pitch = 1 sound["play"].volume = 5 car["nitroing"] = True if not carActive and not Opt.GoodFPS("Nitro", 0.9): return for nitroObject in car.children: if "nitro" in nitroObject.name: if not nitroObject.get("nitroCone"): nitroCone = Reuse.Create("NitroCone") nitroObject["nitroCone"] = nitroCone nitroCone.position = nitroObject.worldPosition nitroCone.orientation = nitroObject.worldOrientation nitroCone.setParent(nitroObject) # Camera effect if carActive: camtarget = car.children["CarCamTarget"] if not car.get("zoom"): car["zoom"] = camtarget.scaling[0] camtarget.scaling *= 1.02 # Unction activated when nitro isn't used. def stopNitro(): # Grpaphics stop for nitroObject in car.children: if "nitro" in nitroObject.name: if nitroObject.get("nitroCone"): nitroObject["nitroCone"].removeParent() Reuse.Delete(nitroObject["nitroCone"]) nitroObject["nitroCone"] = None # Sound stop s = "//sfx/nitro.ogg" code = s+str(car["cid"]) if code in bge.logic.globalDict["sounds"]: sound = bge.logic.globalDict["sounds"][code] try: if sound["play"].volume > 0: sound["play"].volume -= 0.5 else: sound["play"].stop() except: pass # Activating nitro if carActive and 48 in bge.logic.globalDict["keys"]: # 48 is Z nitro() else: stopNitro() if not onGround: car["nitro"] += 5 # Telling the player that the car is availble if dani.get("doesntknowhowtositintocars", True) and not dani["driving"] and distanceToCam < 7: bge.logic.globalDict["print"] = "Press E to sit into the car." dani["doesntknowhowtositintocars"] = False # Camera changes ( help camera show you where you are going ). if carActive and not upsideDown and sp > 0.1: dontseecar = cam.rayCastTo(car) != car if dontseecar and camtarget.scaling[0] > 0.1: if not car.get("zoom"): car["zoom"] = camtarget.scaling[0] camtarget.scaling *= 0.97 elif car.get("zoom") and scene.objects["SecondaryCamSensor"].rayCastTo(car) == car: newzoom = camtarget.scaling[0] + (( car["zoom"] - camtarget.scaling[0] ) / ( 30 / toFPS ) ) camtarget.scaling = [ newzoom, newzoom, newzoom ] if camtarget.scaling[0] == car["zoom"]: car["zoom"] = False camrot = mathutils.Vector(camtarget.localOrientation.to_euler()) reference = car.getVectTo(car.position + car.getLinearVelocity())[2] rotref = car.localAngularVelocity backorfoth = ((reference[1]+1)/2) if backorfoth > 0.6: backorforth = 1 else: backorforth = 0 if camtarget["back"] and backorforth: backorforth = 0 elif camtarget["back"]: backorforth = 1 camnewrot = mathutils.Vector( [ 0.3 - max(-0.1, min(0.2, rotref[0]/2)),# - (car["engine"]*0.005), 0 - (rotref[2]/10) - (rotref[1]/6), ( math.pi * backorforth ) - (rotref[2]/4)] ) if backorforth and camrot[2] < 0: camnewrot[2] -= math.pi * 2 camnewrot = mathutils.Vector(camnewrot) camrot = camrot + (( camnewrot - camrot ) / 10 ) camtarget.localOrientation = camrot elif carActive and cam.rayCastTo(car) != car: camrot = camtarget.localOrientation.to_euler() camrot[0] -= 0.02 #camrot[2] += 0.01 camtarget.localOrientation= camrot # Smoke ( if health too low ) if not car["underwater"] and inview: smokeCoefitient = max(0, 1-engineHealth*1.1)*0.2 fireCoefitient = max(0, 1-engineHealth*2)*0.2 smokeemiter = car.children["SmokeEmmiter"] Distraction.Smoke(smokeemiter.position, smokeCoefitient) Distraction.Fire(smokeemiter.position, fireCoefitient) # Exposion if engineHealth < 0.2 and not car.get("blown"): boompos = smokeemiter.position.copy() boompos[2] -= 2 Distraction.Explosion(boompos, mass=0.5, size=2) car["blown"] = True # Blowuptimer if car.get("blowuptimer") != None: if car["blowuptimer"] == 0 and not car.get("blown"): Distraction.Explosion(car.children["SmokeEmmiter"].position.copy(), mass=0.5, size=2) car["blown"] = True else: car["blowuptimer"] -= 1 ######### SOUND ######## if carActive: # Dani yelling when in air if not onGround and not car["underwater"] and not dani.get("active_sound"): dani["active_sound"] = device.play(bge.logic.globalDict["sounds"]["dani_yelling"]["sound"]) bge.logic.globalDict["sounds"]["dani_yelling"]["play"] = dani["active_sound"] dani["active_sound_is"] = "dani_yelling" elif onGround and dani["active_sound"] and dani["active_sound_is"] == "dani_yelling": dani["active_sound"].stop() dani["active_sound"] = None # Sinking if car.get("underwater") and not dani.get("active_sound") and not dani.get("active_sound_is") == "dani_wearesinking" and dani.get("sinking_timer", 0) < time.time(): dani["active_sound"] = device.play(bge.logic.globalDict["sounds"]["dani_wearesinking"]["sound"]) bge.logic.globalDict["sounds"]["dani_wearesinking"]["play"] = dani["active_sound"] dani["active_sound_is"] = "dani_wearesinking" dani["sinking_timer"] = time.time() + 40 # Very close to another car try: for i in bge.logic.globalDict["allcars"]: if i != car and i.getDistanceTo(car) < 6: car["veryclose"] = i break except: pass if sp < 0.3: car["veryclose"] = None elif car.get("veryclose") and car["veryclose"].getDistanceTo(car) > 7: if not dani.get("active_sound"): dani["active_sound"] = device.play(bge.logic.globalDict["sounds"]["dani_ohgod"]["sound"]) bge.logic.globalDict["sounds"]["dani_ohgod"]["play"] = dani["active_sound"] dani["active_sound_is"] = "dani_ohgod" car["nitro"] += 200 car["veryclose"] = None if not dani.get("active_sound") or not dani["active_sound"].status: dani["active_sound"] = None # Engine sound s = car.get("engine_sound","//sfx/engines/neonspeedster.ogg") code = s+str(car["cid"]) if code not in bge.logic.globalDict["sounds"]: bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(s)), "play":None} sound = bge.logic.globalDict["sounds"][code] esp = car["engine"] if esp < 0: esp *= -1 esp = math.log1p(esp) * 5 if 0.01 < esp or car.get("engineStarted"): car["engineStarted"] = True if not sound["play"] or not sound["play"].status: sound["play"] = device.play(sound["sound"]) sound["play"].location = car.worldPosition sound["play"].velocity = car.getLinearVelocity() sound["play"].relative = False sound["play"].distance_maximum = 200 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 revs = ( esp + ( esp % 1.5 ) ) * 0.5 sound["play"].pitch = max(0.4, revs ) sound["play"].volume = engineHealth * 1 if carActive: scene.objects["Gage_Tachometer"]["Health"] = revs * 30 else: try: bge.logic.globalDict["sounds"][code]["play"].stop() except: pass # Grind sound s = "//sfx/grind.ogg" code = s+str(car["cid"]) if code not in bge.logic.globalDict["sounds"]: bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(s)), "play":None} sound = bge.logic.globalDict["sounds"][code] if 0.01 < sp: if not sound["play"] or not sound["play"].status: sound["play"] = device.play(sound["sound"]) sound["play"].location = car.worldPosition sound["play"].velocity = car.getLinearVelocity() sound["play"].relative = False sound["play"].distance_maximum = 200 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 sound["play"].pitch = max(0.3, engineHealth) * 2 sound["play"].volume = (1-engineHealth) * min(1.5, sp *8) * 1 else: try: bge.logic.globalDict["sounds"][code]["play"].stop() except: pass # Drift sound s = "//sfx/drift.ogg" code = s+str(car["cid"]) if code not in bge.logic.globalDict["sounds"]: bge.logic.globalDict["sounds"][code] = {"sound":aud.Sound(bge.logic.expandPath(s)), "play":None} slide = car.localLinearVelocity[0] if car.get("deccelerating"): slide = car.localLinearVelocity[1] if slide < 0: slide *= -1 sound = bge.logic.globalDict["sounds"][code] if slide > 1 and -0.5 < rot[0] < 0.5 and -0.5 < rot[1] < 0.5 and onGround: car["nitro"] += 2 if not sound["play"] or not sound["play"].status: sound["play"] = device.play(sound["sound"]) sound["play"].location = car.worldPosition sound["play"].velocity = car.getLinearVelocity() sound["play"].relative = False sound["play"].distance_maximum = 200 sound["play"].distance_reference = 1 sound["play"].attenuation = 1 #sound["play"].pitch = 0.8 sound["play"].volume = min(2, slide / 5) / 5 else: try: bge.logic.globalDict["sounds"][code]["play"].stop() except: pass #### RACE RESCUE FUNCTION #### def rescue(): if car.get("launchtime", 0) > 0: return # Sparkles on disappearing positiong Distraction.particles("Sparkle", car.position.copy(), despawn = random.randint(30, 100), amount = 30, max = 30, spread = 2, normal = 0.05, scale = 7) # Camera if carActive: def resetCarZoom(): car["zoom"] = False Character_Controll.ChangeCameraTarget(car.children["CarCamTarget"], 100, [3,3,3],callable=resetCarZoom) car.children["CarCamTarget"].orientation = [0.2,0,0] # Teleportation car.position = car["rescue"] car.localLinearVelocity = [0,0,0] car["checkpoint"] = ( car.get("rescueTo", car["checkpoint"]-1) + 1 ) % len(bge.logic.globalDict["races"][car.get("race")]["checkpoints"]) nextcheckpointn = car["checkpoint"] nextcheckpoint = bge.logic.globalDict["races"][car.get("race")]["checkpoints"][ nextcheckpointn ]["location"] prevcheckpoint = ( car["checkpoint"]-2 ) % len(bge.logic.globalDict["races"][car.get("race")]["checkpoints"]) car["prevrescue"] = bge.logic.globalDict["races"][car.get("race")]["checkpoints"][ prevcheckpoint ]["location"] print("Rescue at: Car:", car, "Checkpoint:", car["checkpoint"]) # Sparkles on the new position Distraction.particles("Sparkle", car.position, despawn = random.randint(30, 100), amount = 50, max = 100, spread = 2, normal = 0.05, scale = 5) # Rotation the car based on the locations of checkpoints. tocheck = car.getVectTo(nextcheckpoint) car.alignAxisToVect(tocheck[1], 1, 1.0) car.alignAxisToVect( (0,0,1), 2, 1.0 ) # Rotating the car 180 degrees since forward it -Y not Y. rot = car.worldOrientation.to_euler() car.worldOrientation = [rot[0], rot[1], rot[2]+math.pi] # Adding the rotation of the previous checkpoint. # if car.get("prevrescue"): # tocheck = car.getVectTo(car.get("prevrescue")) # car.alignAxisToVect(tocheck[1], 1, 0.7) # car.alignAxisToVect( (0,0,1), 2, 1.0 ) # Putting the car a bit higher than the road. car.position[2] += 2 car["launchtime"] = 200 car["nitro"] = max(1000, car["nitro"]) car["underwater"] = False car["engine"] = 0 # Restoring the wheels. for i in range(4): #vehicle.setSuspensionStiffness(car.get("suspension", 200), i) car["suspensions"][i] = car.get("suspension", 200) vehicle.applyBraking(0, i) vehicle.setTyreFriction(car.get("friction", 1), i) vehicle.setRollInfluence(car.get("roll", 0), i) bge.logic.globalDict[car["cid"]]["wheels"][i].setVisible(True) for i in ["Front_Right", "Front_Left", "Back_Left", "Back_Right"]: car[i] = max(0.8, car[i]) # Rescuing the active car in the race when pressing Backspace ( code 59 ) if carActive and dani.get("race") and dani.get("rescue") and ( ( car["speed"] > -0.02 and car["engine"] > 0.5 ) or engineHealth <= 0.2 or car["underwater"]): #if carActive and dani.get("race") and dani.get("rescue") and 59 in bge.logic.globalDict["keys"] and car["launchtime"] <=0: if not car.get("toresquetimer", 50): nextcheckpoint = bge.logic.globalDict["races"][dani.get("race")]["checkpoints"][ ( dani.get("checkpoint") + 1 ) % len(bge.logic.globalDict["races"][dani.get("race")]["checkpoints"]) ]["location"] car["rescue"] = dani["rescue"] car["race"] = dani["race"] car["checkpoint"] = dani["checkpoint"] car["rescueTo"] = dani["rescueTo"] car["prevrescue"] = dani["prevrescue"] rescue() car["toresquetimer"] = 50 else: car["toresquetimer"] = car.get("toresquetimer", 50) -1 bge.logic.globalDict["cheat"] = [0] ###### NPC LOGIC ####### if car.get("npc") and bge.logic.globalDict["derby-cheat"]: debryclosest = None derbydistance = 1000 for i in scene.objects: if "speed" in i and i != car: idist = car.getDistanceTo(i) if idist < derbydistance and car.rayCastTo(i.position) == i: derbydistance = idist debryclosest = i if derbydistance < 10: break if debryclosest: car["npc"] = "enemy" car["enemy"] = debryclosest ## NPC PREPARATIONS ## if car.get("npc"): #### CAR VISION OF THE ROAD AND OBSTACLES #### # To make the vision work we are going to use Ray Casting # but instead of doing a whole path tracing thing to see # everything in front of the car ( which you be slow ) # instead we trace only 5 specifically chosen points. # Each car model has those 5 points positioned by hand # in respecive car blend files. Those 5 points are. left = 50 # To the forward - left diagonal \ # } On the height of the car right = 50 # To the forward - right diagonal / leftf = 50 # To the forward - left diagonal \ # } Slightly lower than the car ( to scan road ) rightf = 50 # To the forward - right diagonal / forward = 50 # Directly in front of the car. forwardData = None # Data of the ray casting for the forward. leftm = "" # Material on the left of the car rightm = "" # Material on the right of the car # Each ray has it's default value be 50. During ray casting, the value will # change to the distance of whatever the car "sees". If it sees nothing, the # values will stay 50. # Few more things to consider. road = "Track2" # Material of the road ( to ignore ) separator = "Track_light" # Material of the separator line ( drawn in the middle of the road ). separator_object = "Separation" # Name of an invisible object sticking out of this separator line. # Left, slightly lower ray ray = car.rayCast(car.children["Left"], car, poly=True) # rayCast returns a list of values [ Hit Object , Hit Location, Hit Angle, Hit Polygon ] # If we have any hit object ( exluding the road separator line if the car is a racing npc ) if ray[1] and ( not carRacing or not str(ray[0]) == separator_object ): # Excluding if the Polygon's material is road material if not ray[3] or road not in str(ray[3].material): # Getting the distance to the hit location and storing it as both left = car.getDistanceTo(ray[1]) # left and leftf = left # leftf try: leftm = str(ray[3].material)# And storing the material name for later except: pass # Doing something similar to the left point on the same heigh as the car ray = car.rayCast(car.children["Left.001"],car, poly=True) if ray[1] and ( not carRacing or not str(ray[0]) == separator_object ): if not ray[3] or road not in str(ray[3].material): # Only instead of doing the complex appending, we only # overwrite the left variable, if the distance is lower. # Basically left will end up the closest visible point from # the left of the car. And leftf will be the original left. left = min(car.getDistanceTo(ray[1]), left) # Doing something similar for the right side as well ray = car.rayCast(car.children["Right"],car, poly=True) # Only now we exclude the separator line regardless if it # is a racer or not. So if the car ends up on the wrong # side of the road and goes British, it could find its way # back to the right side of the road. if ray[1] and not str(ray[0]) == separator_object: if not ray[3] or road not in str(ray[3].material) : right = car.getDistanceTo(ray[1]) rightf = right try: rightm = str(ray[3].material) except: pass # And we slightly enfoce it to go to the right side of # the road. By folling it to think that there is something # of the left. elif not carRacing and str(ray[0]) == separator_object: left = min(car.getDistanceTo(ray[1]), left) # And now for the slightly higher point on the right. ray = car.rayCast(car.children["Right.001"],car, poly=True) if ray[1] and not str(ray[0]) == separator_object: if not ray[3] or road not in str(ray[3].material): right = min(car.getDistanceTo(ray[1]), right) elif not carRacing and str(ray[0]) == separator_object: left = min(car.getDistanceTo(ray[1]), left) # And for the forward. ray = car.rayCast(car.children["Forward"],car, poly=True) forwardData = ray if ray[1] and str(ray[0]) == separator_object: if not ray[3] or road not in str(ray[3].material): forward = car.getDistanceTo(ray[1]) # Minimum value will be the smallest distance out of all of them # which is useful for all sorts of things. minimum = min(left, right, forward) # And now we calculate how much the car needs to actually turn. turn = max(-0.8, min(0.8, (( max(0, min(1, (right/12))) - max(0, min(1, (left/12))) ) *-2 ))) ## NORMAL NPC CARS ## if car.get("npc") == "npc": # Normal NPC cars are those you can see driving around the city # at a regular speed. # Activate enemy logic when pursuit cheat is enabled if distanceToCam < 100 and bge.logic.globalDict["pursuit-cheat"]: car["npc"] = "enemy" for i in scene.objects: if i.get("active"): car["enemy"] = i break # Applying the turn calculated in vision step car["turn"] = turn # Accelerating the car, with the target speed based on distance # to the closest seen point. targetSpeed = 4 * ((minimum/12)-0.4) # We also ignore target speed, and make the car drive as fast # as it can, when it is chased by somebody. if (sp < targetSpeed or car.get("chased")) and minimum > 2: accelerate(car) else: deccelerate(car) # To help it avoid obstacles better. if minimum < 2 and car.get("accelerating"): car["turn"] = -0.8 # If we about to hit a car head first if forwardData[0] and forwardData[0].get("speed"): turn = max(-0.8, min(0.8, turn*10)) car["engine"] = car["speed"]*10 # Cliffs # turnback = True # if rot[0] > 0.1 and not car.get("chased"): # accelerate(car) # elif rot[0] < -0.9 and sp < 0.9 and onGround: # car.applyForce([0,-20, 0], True) # turnback = False # # # # if minimum < 5: # deccelerate(car) # if 0.9 < turn or turn < -0.9: # car["turn"] = turn *-1 # car.applyTorque([0.0,0.0,turn*-30],1) # # elif turnback: # car["turn"] = 0.3 # car.applyTorque([0.0,0.0,car["turn"]*30],1) # # if "launchtime" not in car: # car["launchtime"] = 300 # car["launchtime"] -= 1 # if 0.03 > sp and ( car["engine"] / max(0.1, engineHealth) > 1 ) and car["launchtime"] < 0: # if not rot[0] < -0.1 and (leftm or rightm): # car.applyTorque([0.0,0.0,50],1) # car.position[2] += 0.05 # # # if sp > 2.8 and (0.3 < turn or turn < -0.3): # for i in range(4): # vehicle.applyEngineForce(car["speed"]*5* toFPS, i) # if sp < 0: sp *= -1 # car.applyTorque([0.0,0.0,car["turn"]*sp*5* toFPS],1) # #for i in range(4): # vehicle.applyEngineForce(car["engine"], i) ## ANGRY CARS GUIDED TO A POINT ## elif car.get("npc") == "enemy" or ( car.get("npc") == "racer" and car.get("racing")): # If racing if car.get("npc") == "racer": checkpoint = bge.logic.globalDict["races"][car.get("race")]["checkpoints"][car.get("checkpoint")].copy() if "raceData" in bge.logic.globalDict["races"][car.get("race")]: raceData = bge.logic.globalDict["races"][car.get("race")]["raceData"] targetTime = raceData["times"][car["checkpoint"]] try: prevTime = raceData["times"][car["checkpoint"]-1] except: prevTime = 0 lastCheckPointTime = car.get("last-checkpoint-time", bge.logic.globalDict["races"][car.get("race")]["start-time"]) currentTime = bge.logic.getRealTime() - bge.logic.globalDict["races"][car.get("race")]["start-time"] targetTimeToCheckpoint = targetTime - prevTime currentTimeToCheckpoint = currentTime - lastCheckPointTime else: targetTimeToCheckpoint = 1 currentTimeToCheckpoint = 1 car["enemy"] = checkpoint["location"] # If the racing bot is following the player, it will mimic the player #racePositions = bge.logic.globalDict["races"][car.get("race")].get("positions", [dani, car]) #if dani in racePositions and dani.get("driving") != car and racePositions.index(dani) < racePositions.index(car): # car["enemy"] = dani["driving"] # If reached checkpoint if car.getDistanceTo(car["enemy"]) < checkpoint["radius"]: if not checkpoint.get("OnLoop"): car["prevrescue"] = car["rescue"] car["rescue"] = checkpoint["location"] car["rescueTo"] = car["checkpoint"] # Printing if the bot is on time if "raceData" in bge.logic.globalDict["races"][car.get("race")]: car["last-checkpoint-time"] = currentTime print("Race Time of [", car, "]:", round(currentTimeToCheckpoint, 2), round(targetTimeToCheckpoint - currentTimeToCheckpoint, 2)) # Calibrating the stopping distance if checkpoint.get("Uturn"): targetSpeed = -checkpoint.get("Uturn") * toFPS car["stopdistance"] = car.get("stopdistance", -18) * ( car["speed"] / targetSpeed ) print("Race Stopping Calibration [", car, "]:", car.get("stopdistance", -18), int( ( car["speed"] / targetSpeed ) * 100), "%") car["checkpoint"] = car["checkpoint"]+1 car["launchtime"] = 50 try: car["distanceBetweenCheckpoints"] = car.getDistanceTo(bge.logic.globalDict["races"][car.get("race")]["checkpoints"][car.get("checkpoint")]["location"]) except: pass # If finished lap if car.get("checkpoint") == len(bge.logic.globalDict["races"][car.get("race")]["checkpoints"]): print(car, "LAP") car["checkpoint"] = 0 car["lap"] += 1 # If finished race if car["lap"] == bge.logic.globalDict["races"][car.get("race")]["laps"]: car["racing"] = False car["npc"] = "" bge.logic.globalDict["print"] = raceNames.get(car.name, car.name) + " finished race!" # Making rescuing less sensitive when passing a Uturn if bge.logic.globalDict["races"][car.get("race")]["checkpoints"][car.get("checkpoint")].get("Uturn"): car["launchtime"] = 500 nextcheckpoint = bge.logic.globalDict["races"][car.get("race")]["checkpoints"][ ( car.get("checkpoint") + 1 ) % len(bge.logic.globalDict["races"][car.get("race")]["checkpoints"]) ]["location"] tonextcheckpoint = car.getVectTo(nextcheckpoint) # Moving the indicator car["beam"].position = car.position car["beam"].position[2] += 1 tocam = car["beam"].getVectTo(cam) car["beam"].alignAxisToVect(tocam[1], 1, 1.0) car["beam"].alignAxisToVect( (0,0,1), 2, 1.0 ) beamscale = max( 0.2, car.getDistanceTo(dani) / 100 ) car["beam"].scaling = [beamscale, beamscale, beamscale] try: toenemy = car.getVectTo(car.get("enemy", dani)) if car.get("npc") == "enemy" and sum([car["enemy"].get("Front_Right"), car["enemy"].get("Front_Left"), car["enemy"].get("Back_Right"), car["enemy"].get("Back_Left")])/4 < 0.2: car["npc"] = "npc" car["enemy"] = "" except: car["npc"] = "npc" car["enemy"] = "" return enemyturn = min(0.8, toenemy[2][0]*2) onenemy = toenemy[2][1] *-1 oldenemyturn = enemyturn onoldenemy = onenemy # If we are too slow. NITRO if car.get("npc") == "racer": betweencheckpoints = car.get("distanceBetweenCheckpoints", toenemy[0]) - checkpoint["radius"] fractionDistance = 1 - (toenemy[0] / betweencheckpoints) if ( currentTimeToCheckpoint * 1.2 > targetTimeToCheckpoint * fractionDistance or onenemy > 0.6 ) and not car.get("deccelerating") and onGround: nitro() else: stopNitro() try: tonext = 1-min(1, toenemy[0]/(car["speed"]*-50) ) ** 0.2 except: tonext = 0 if type(tonext) == complex: tonext = float(tonext.real) targetSpeed = 0 if car.get("npc") == "racer": if "raceData" in bge.logic.globalDict["races"][car.get("race")]: raceData = bge.logic.globalDict["races"][car.get("race")]["raceData"] checkpoint["Uturn"] = raceData["targetSpeed"][car.get("checkpoint")] if checkpoint.get("Uturn"): # At current configuration car looses 1 speed at about 12.2 units of distance targetSpeed = -checkpoint.get("Uturn") * toFPS brakingDistance = ( car["speed"] - targetSpeed ) * -18# car.get("stopdistance", -18) if toenemy[0] <= brakingDistance and car["speed"] < targetSpeed: deccelerate(car) # We want to record the stopdistance # if targetSpeed <= car["speed"]: # car["stopdistance"] = car.get("stopdistance", -18) + toenemy[0] # print(car, "stopdistance Calibrated at:", car["stopdistance"]) # elif car["speed"] > targetSpeed and onenemy > 0.8: # nitro() if onenemy > 0.7 and minimum > 7: nextenemyturn = min(0.8, tonextcheckpoint[2][0]*2) nextonenemy = tonextcheckpoint[2][1] *-1 enemyturn = enemyturn + ( ( nextenemyturn - enemyturn ) * tonext ) onenemy = onenemy + ( ( nextonenemy - onenemy ) * tonext ) if type(onenemy) == complex: onenemy = float(onenemy.real) enemyturn = float(enemyturn.real) if car["speed"] > -0.2 or engineHealth <= 0.2 or car["underwater"]:# or onenemy < 0.4: rescue() smartturn = ( turn * onoldenemy ) + ( oldenemyturn * onenemy) + ( enemyturn ) / ( onoldenemy + onenemy + 1) #if onenemy < 0.6: # smartturn = oldenemyturn #if toenemy[0] < 60: #smartturn = enemyturn #if onenemy < 0.9: # smartturn = enemyturn #if onoldenemy < 0.7: # smartturn = oldenemyturn # If we about to hit a car head first #if forwardData[0] and forwardData[0].get("speed"): # handbreak(car) # turn = max(-0.8, min(0.8, turn*-1000)) # smartturn = turn if (( minimum < 10 and onenemy > 0.3 ) or ( minimum < 5 and onenemy > 0.1 )) and toenemy[0] > 50: smartturn = turn if minimum < 7: car["turn"] = max(-0.5, min( 0.8 , car["turn"] * 1.5 )) if carRacing: angleAt = -0.7 else: angleAt = 0 if onenemy > angleAt: car["turn"] = smartturn t = car["turn"] if t < 0: t *= -1 # If we turning, turn harder if t > 0.3 and car["speed"] < -1: car["turn"] *= 3 # If we are turning hard enough, drift #if t > 0.4 and car["speed"] < -2 and car["speed"] < targetSpeed / 2: # handbreak(car) # If we are turning very hard, use breaks if t > 0.4 and car["speed"] < -1.5 and car["speed"] < targetSpeed: deccelerate(car) if not car.get("deccelerating"): accelerate(car) else: if car.get("npc") == "racer": rescue() car["turn"] = enemyturn *-1 deccelerate(car) #for i in range(4): # vehicle.applyEngineForce(car["engine"], i) ################### APPLYING ########################## # This is here to trigger an error for if car's object # has been deleted from the game during the execution # of this script. Otherwise, applying things to the vehicle # constraints might result in Segmentation Fault ( the engine # crashing ). car.position # Auto deceleration if not car.get("accelerating") and car["engine"] > 0: car["engine"] -= car.get("maxaccel",2) * toFPS elif not car.get("accelerating") and car["engine"] < 0: car["engine"] += car.get("maxaccel",2) * toFPS else: car["accelerating"] = False # Auto going straiter if not car.get("turning"): car["turn"] *= 0.5 ** toFPS else: car["turning"] = False ApplyEnginePower(car, vehicle) # if not car.get("deccelerating"): # minusfrac = 1 # if car["engine"] < 0: minusfrac = -1 # applyforce = math.log1p(car["engine"]*minusfrac) / 4 # if -0.05 < applyforce < 0.05: # applyforce = 0 # else: # #applyforce = Opt.Force(applyforce**0.1*3*minusfrac) # applyforce = Opt.Force(HorsePowerToNewton(applyforce))*minusfrac # # if car.get("nitroing"): # applyforce *= Opt.Force(0.3) # # vehicle.applyEngineForce(applyforce*car["Back_Left"], 0) # vehicle.applyEngineForce(applyforce*car["Back_Right"], 1) # vehicle.applyEngineForce(0, 2) # vehicle.applyEngineForce(0, 3) if not car.get("nitroing"): car["engine"] = min( car.get("maxengine", 800)*engineHealth, max( -car.get("maxengine", 800)*engineHealth, car["engine"])) else: car["nitroing"] = False if car.get("deccelerating"): car["deccelerating"] = False # Making sure the car is not turning more than it is possible. car["turn"] = max(-0.8, min(0.8, car["turn"])) # Suspension updates ( important due to FPS flactuations ) ApplySuspension(car, vehicle) # Turning Force Update vehicle.setSteeringValue(car["turn"]*car["Front_Left"] , 2) vehicle.setSteeringValue(car["turn"]*car["Front_Left"] , 3) # Adding fake torque to the car, to make it easier to turn #if carSpeed < -0.05 and onGround: # car.applyTorque([0.0,0.0,Opt.Force(car["turn"]*10)],1) #elif carSpeed > 0.05 and onGround: # car.applyTorque([0.0,0.0,Opt.Force(car["turn"]*-10)],1) def ApplySuspension(car, vehicle): for i in range(4): suspension = car["suspensions"][i] / 100 suspense = Opt.Force(suspension*car.mass) damping = 0.3 vehicle.setSuspensionCompression(1, i) vehicle.setSuspensionStiffness(suspense, i) vehicle.setSuspensionDamping(1, i) def ApplyEnginePower(car, vehicle): if not car.get("deccelerating"): # minusfrac = 1 # if car["engine"] < 0: minusfrac = -1 # applyforce = math.log1p(car["engine"]*minusfrac) / 4 # if -0.05 < applyforce < 0.05: # applyforce = 0 # else: # #applyforce = Opt.Force(applyforce**0.1*3*minusfrac) # applyforce = Opt.Force(HorsePowerToNewton(applyforce))*minusfrac # # if car.get("nitroing"): # applyforce *= Opt.Force(0.3) # Getting car's horse power horses = car.get("horses", 750) rpm = car["engine"] maxrpm = car.get("maxengine", 800) horses = EngineCurve(rpm, maxrpm, horses) if car["active"]: print(horses) applyforce = Opt.Force(HorsePowerToNewton(horses / 2000)) vehicle.applyEngineForce(0, 0) vehicle.applyEngineForce(0, 1) vehicle.applyEngineForce(applyforce*car["Front_Left"], 2) vehicle.applyEngineForce(applyforce*car["Front_Left"], 3) def HorsePowerToNewton(value): return value * 745.6998715823 def EngineCurve(rpm, maxrpm, horses): # This function draws a simulated # Engine RPM curve and outputs # house power. return math.sin(rpm/maxrpm*(math.pi/4*3))*horses def accelerate(car): if type(car) == bge.types.SCA_PythonController: cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() car = cont.owner if not car["active"]: return toFPS = Opt.ToFPS() vehicle = bge.constraints.getVehicleConstraint(car["cid"]) car["engine"] += car.get("maxaccel",2) * toFPS if car["engine"] > 0 and car["speed"] <= 0.2: car["accelerating"]= True else: car["engine"] *= 0.95 ** toFPS car["deccelerating"]= True for i in range(4): vehicle.applyEngineForce(Opt.Force(car["speed"]*5*car.mass), i) def deccelerate(car): if type(car) == bge.types.SCA_PythonController: cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() car = cont.owner if not car["active"]: return toFPS = Opt.ToFPS() vehicle = bge.constraints.getVehicleConstraint(car["cid"]) car["engine"] -= car.get("maxaccel",0.003) * toFPS if car["engine"] < 0 and car["speed"] >= -0.2: car["accelerating"]= True else: car["engine"] *= 0.95 ** toFPS car["deccelerating"]= True for i in range(4): vehicle.applyEngineForce(Opt.Force(car["speed"]*5*car.mass), i) def turn(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() car = cont.owner if not car["active"]: return toFPS = Opt.ToFPS() if car["turn"] < 0: car["turn"] = 0 car["turn"] += 0.005 * toFPS car["turning"]= True def unturn(): cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() car = cont.owner if not car["active"]: return toFPS = Opt.ToFPS() if car["turn"] > 0: car["turn"] = 0 car["turn"] -= 0.005 * toFPS car["turning"]= True def handbreak(car): if type(car) == bge.types.SCA_PythonController: cont = bge.logic.getCurrentController() scene = bge.logic.getCurrentScene() car = cont.owner if not car["active"]: return toFPS = Opt.ToFPS() vehicle = bge.constraints.getVehicleConstraint(car["cid"]) for i in range(4): vehicle.applyEngineForce(Opt.Force(car["speed"]*2*car.mass), i) car["deccelerating"]= True sp = car["speed"] if sp < 0: sp *= -1 car.applyTorque([0.0,0.0,Opt.Force(car["turn"]*sp*2*car.mass)],1) def get_in(): return # This function has been moved to Character Controlls