Menu
CoddyTech

Kontrollpunkte der Reihe nach

Lektion 9 von 20 im Kurs Godot-Spiel: Neon-Rennstrecke von Coddy.

Ein Rennen braucht Runden, und eine Runde zählt nur, wenn du wirklich einmal herumgefahren bist. Andernfalls könntest du die Linie überqueren, zurückfahren und sie noch einmal überqueren. Deshalb hat die Strecke 8 gleichmäßig verteilte Kontrollpunkte, die der Reihe nach passiert werden müssen.

Das Rennen befindet sich in race.gd auf dem Main-Knoten. track.offset_of(point) gibt an, wie weit ein Punkt auf der Strecke herum liegt, von 0 an der Linie bis track.length. Kontrollpunkt k liegt bei k * seg:

func check_progress() -> void:
	var seg: float = track.length / CHECKPOINTS
	var offset: float = track.offset_of(car.position)
	var target := next_checkpoint * seg
	var gap: float = absf(wrapf(offset - target, -track.length / 2.0, track.length / 2.0))
	if gap < 24.0 and track.is_on_road(car.position):
		next_checkpoint = (next_checkpoint + 1) % CHECKPOINTS

wrapf hält den Abstand an der Linie korrekt, wo 1390 und 5 nur 14 Pixel voneinander entfernt sind. % CHECKPOINTS setzt den nächsten Kontrollpunkt nach Kontrollpunkt 7 auf 0, die Linie. Durch die Abfrage von is_on_road zählt eine Abkürzung über das Gras nie.

challenge icon

Aufgabe

Mittel
  1. Füge in race.gd const CHECKPOINTS := 8 und var next_checkpoint := 1 hinzu.
  2. Hole dir mit @onready track ($Track) und car ($Car).
  3. Schreibe check_progress und rufe es von _physics_process aus auf.

Probier es selbst

extends Node2D

@export var accel := 260.0
@export var max_speed := 200.0
@export var turn_speed := 3.2
@export var drag := 0.6
@export var grip := 7.0

var velocity := Vector2.ZERO
var boost_time := 0.0
var boost_charge := 0.0

@onready var track: Node2D = $"../Track"


func _physics_process(delta: float) -> void:
	var throttle := Input.get_axis("move_down", "move_up")
	var steer := Input.get_axis("move_left", "move_right")
	if Input.is_action_just_pressed("action") and boost_charge >= 1.0:
		boost_charge = 0.0
		boost_time = 1.0
	boost_charge = minf(1.0, boost_charge + delta / 10.0)
	$"../HUD/Boost".scale.x = boost_charge

	var forward := Vector2.RIGHT.rotated(rotation)
	var speed := velocity.dot(forward)
	var top := max_speed
	var grip_now := grip
	if boost_time > 0.0:
		boost_time -= delta
		top = max_speed * 1.3
		velocity += forward * accel * delta
	for pad in get_tree().get_nodes_in_group("boost_pads"):
		if position.distance_to(pad.position) < 22.0:
			boost_time = maxf(boost_time, 0.4)
	for oil in get_tree().get_nodes_in_group("oil"):
		if position.distance_to(oil.position) < 20.0:
			grip_now = grip * 0.12
	if not track.is_on_road(position):
		top = max_speed * 0.45
		velocity *= 1.0 - 2.5 * delta

	if throttle < 0.0 and speed > 10.0:
		velocity += forward * throttle * accel * 1.6 * delta
	else:
		velocity += forward * throttle * accel * delta
	rotation += steer * turn_speed * delta * clampf(absf(speed) / 90.0, 0.0, 1.0) * signf(speed + 0.01)

	var side := forward.orthogonal()
	velocity -= side * velocity.dot(side) * minf(1.0, grip_now * delta)
	velocity *= 1.0 - drag * delta
	if velocity.length() > top:
		velocity = velocity.move_toward(velocity.limit_length(top), accel * 2.0 * delta)
	position += velocity * delta
	$Exhaust.emitting = throttle > 0.0 or boost_time > 0.0
	$Flame.visible = boost_time > 0.0

Alle Lektionen in Godot-Spiel: Neon-Rennstrecke

Übe selbstständig: Godot-Playground