small racing game im working on
Diffstat (limited to 'race.gd')
-rw-r--r--race.gd165
1 files changed, 107 insertions, 58 deletions
diff --git a/race.gd b/race.gd
index 594579f..a2056de 100644
--- a/race.gd
+++ b/race.gd
@@ -7,21 +7,26 @@ var track_loader_scene: PackedScene
var ghost_scene: PackedScene
var track_res: TrackResource
var track: TrackLoader
-var data: GhostData
+var data: Array[GhostData]
var best_time_data: GhostData
-var car: Car
+var cars: Array[Car]
+var cars_needed: PackedInt32Array = []
+var finished_cars := 0
+@onready var mp := cars_needed.size() > 1
var ghost: GhostCar
var start_frame: int
-var current_lap := 0
+var current_lap: PackedInt32Array = []
var playing := false
-var timer := GameTimer.new()
+var timers: Array[GameTimer]
+var distances: PackedFloat32Array = []
signal next_lap
-signal created_car(car: Car)
+signal created_car(car: Car, n: int)
signal created_ghost(ghost: GhostCar)
-signal finished(time: float, prev_time: float)
-signal split(time: float, prev_time: float)
+signal finished(time: float, prev_time: float, n: int)
+signal all_finished
+signal split(time: float, prev_time: float, n: int)
signal did_reset
func _init(t: TrackResource, ghost_data: GhostData, _car_scene, _ghost_scene, _track_loader_scene) -> void:
@@ -43,36 +48,48 @@ func reset_ghost() -> void:
ghost.engine.volume = .2
else:
ghost.engine.volume = 0
- ghost.global_position = track.start_transf.origin + Vector3(0, 1, 0)
+ ghost.global_position = track.start_transf.origin + Vector3(0, 1, -2)
ghost.rotation = track.start_transf.basis.get_euler()# + Vector3(0, PI, -PI/2)
ghost.reset()
ghost.hide()
-func reset_car() -> void:
+func reset_car(i: int) -> void:
await get_tree().physics_frame
- car.rotation = track.start_transf.basis.get_euler()# + Vector3(0, PI, -PI/2)
- car.global_position = track.start_transf.origin + Vector3(0, 1, 0)
- car.linear_velocity = Vector3.ZERO
- car.angular_velocity = Vector3.ZERO
- car.current_gear = 0
- car.reset()
-
-func mkcar() -> void:
- car = HumanCar.attach(car_scene)
- add_child(car)
- reset_car()
- created_car.emit(car)
+ cars[i].rotation = track.start_transf.basis.get_euler()# + Vector3(0, PI, -PI/2)
+ cars[i].global_position = track.start_transf.origin + Vector3(0, 1, -2)
+ cars[i].linear_velocity = Vector3.ZERO
+ cars[i].angular_velocity = Vector3.ZERO
+ cars[i].current_gear = 0
+ cars[i].reset()
+
+func mkcar(i: int, dev: int) -> void:
+ cars[i] = HumanCar.attach(car_scene, dev)
+ add_child(cars[i])
+ reset_car(i)
+ created_car.emit(cars[i], i)
+ if !mp:
+ cars[i].collision_mask = 2 ^ 1
func _ready() -> void:
set_physics_process(false)
track = track_loader_scene.instantiate()
track.track = track_res
add_child(track)
- data = GhostData.new(track.checkpoints.size(), track_res.laps)
- mkcar()
+ data.resize(cars_needed.size())
+ cars.resize(cars_needed.size())
+ current_lap.resize(cars_needed.size())
+ current_lap.fill(0)
+ timers.resize(cars_needed.size())
+ if mp:
+ distances.resize(cars_needed.size())
+ distances.fill(0)
+ for i in cars_needed.size():
+ data[i] = GhostData.new(track.checkpoints.size(), track_res.laps)
+ timers[i] = GameTimer.new()
+ add_child(timers[i])
+ mkcar(i, cars_needed[i])
mkghost()
connect_checkpoints()
- add_child(timer)
func _input(event: InputEvent) -> void:
if event.is_action("reset") and playing:
@@ -80,46 +97,76 @@ func _input(event: InputEvent) -> void:
func reset() -> void:
playing = false
+ finished_cars = 0
if best_time_data:
if ghost:
reset_ghost()
- await reset_car()
+ distances.fill(0)
+ for car in cars.size():
+ await reset_car(car)
+ current_lap[car] = 0
set_physics_process(false)
- current_lap = 0
- data.clear()
- timer.reset()
+ for d in data:
+ d.clear()
+ for timer in timers:
+ timer.reset()
did_reset.emit()
+func fcar(c: Car) -> int:
+ return cars.find(c)
+
func connect_checkpoints() -> void:
for i in len(track.checkpoints):
- track.checkpoints[i].collected.connect(passed_cp.bind(i))
- track.finish.collected.connect(passed_finish)
+ track.checkpoints[i].collected.connect(func(c: Car): passed_cp(i, fcar(c)))
+ track.finish.collected.connect(func(c: Car): passed_finish(fcar(c)))
-func passed_cp(cp: int) -> void: if playing and !data.has_collected(current_lap, cp): collect(cp)
+func passed_cp(cp: int, car: int) -> void: if playing and !data[car].has_collected(current_lap[car], cp): collect(cp, car)
-func passed_finish() -> void:
+func passed_finish(car: int) -> void:
if !playing: return
- for i in len(data.checkpoints[current_lap]) - 1:
- if data.checkpoints[current_lap][i] < 0:
+ for i in len(data[car].checkpoints[current_lap[car]]) - 1:
+ if data[car].checkpoints[current_lap[car]][i] < 0:
return
- collect(-1)
- if track_res.laps - 1 == current_lap:
- playing = false
- timer.stop()
- car.reset()
- if not best_time_data or data.time < best_time_data.time:
- finished.emit(data.time, best_time_data.time if best_time_data else -1.0)
- data.save(Globals.SAVES % track_res.name)
- best_time_data = data
- else:
- finished.emit(data.time, best_time_data.time)
- data = GhostData.new(track.checkpoints.size(), track_res.laps)
+ collect(-1, car)
+ if track_res.laps - 1 == current_lap[car]:
+ timers[car].stop()
+ cars[car].reset()
+ finished_cars += 1
+ finished.emit(data[car].time, best_time_data.time if best_time_data else -1.0, car)
+ if finished_cars > cars.size() - 1: # all finished
+ var best = {time = INF}
+ for datapoint in data:
+ if best.time > datapoint.time:
+ best = datapoint
+ if not best_time_data or best.time < best_time_data.time:
+ best.save(Globals.SAVES % track_res.name)
+ best_time_data = best
+ all_finished.emit()
+ playing = false
else:
- current_lap += 1
+ current_lap[car] += 1
next_lap.emit()
func _physics_process(delta: float) -> void:
- data.snapshot(car)
+ if mp:
+ for i in cars_needed.size():
+ if distances[i] < 0:
+ continue
+ var flag := true
+ for j in cars_needed.size():
+ if j == i: continue
+ var dist := cars[i].global_position.distance_squared_to(cars[j].global_position)
+ if dist > 50:
+ continue
+ flag = false
+ break # gdscript cant label loops
+ if flag:
+ distances[i] = distances[i] + delta
+ if distances[i] > 1.5: # when apart for longer than 1.5 seconds, enable collisions
+ distances[i] = -1
+ cars[i].collision_mask = 1 ^ 2 # world & players
+ for i in data.size():
+ data[i].snapshot(cars[i])
if best_time_data:
if best_time_data.snap_count - 1 < Engine.get_physics_frames() - start_frame:
if ghost.visible:
@@ -127,20 +174,22 @@ func _physics_process(delta: float) -> void:
ghost.engine.volume = 0
return
ghost.update(best_time_data.load_snap(Engine.get_physics_frames() - start_frame), delta)
- ghost.visible = (ghost.global_position.distance_squared_to(car.global_position) > 10)
- ghost.engine.volume = lerpf(ghost.engine.volume, .7, delta * 3) if (ghost.global_position.distance_squared_to(car.global_position) > 20) else lerpf(ghost.engine.volume, .2, delta * 3)
+ ghost.visible = (ghost.global_position.distance_squared_to(cars[0].global_position) > 10)
+ ghost.engine.volume = lerpf(ghost.engine.volume, .7, delta * 3) if (ghost.global_position.distance_squared_to(cars[0].global_position) > 20) else lerpf(ghost.engine.volume, .2, delta * 3)
-func collect(cp: int) -> void:
+func collect(cp: int, car: int) -> void:
if cp != -1:
- car.checkpoint_sound.play()
- var time := best_time_data.get_time(current_lap, cp) if best_time_data else -1.0
- time = best_time_data.time if (not track_res.laps or track_res.laps == current_lap + 1) and cp == -1 and time != -1.0 else time
- split.emit(snappedf(timer.now(), .001), time)
- data.collect(current_lap, cp, snappedf(timer.now(), .001))
+ cars[car].checkpoint_sound.play()
+ var time := best_time_data.get_time(current_lap[car], cp) if best_time_data else -1.0
+ time = best_time_data.time if (not track_res.laps or track_res.laps == current_lap[car] + 1) and cp == -1 and time != -1.0 else time
+ split.emit(snappedf(timers[car].now(), .001), time, car)
+ data[car].collect(current_lap[car], cp, snappedf(timers[car].now(), .001))
func start() -> void:
- timer.start()
+ for timer in timers:
+ timer.start()
start_frame = Engine.get_physics_frames()
playing = true
- car.start()
set_physics_process(true)
+ for car in cars:
+ car.start()