Các trạm kiểm tra theo thứ tự
Bài học 9 trên 20 trong khóa học Trò chơi Godot: Mạch neon của Coddy.
Một cuộc đua cần có các vòng, và một vòng chỉ được tính nếu bạn thực sự chạy hết một vòng. Nếu không, bạn có thể vượt qua vạch đích, lùi lại rồi vượt qua vạch đó lần nữa. Vì vậy, đường đua có 8 trạm kiểm soát cách đều nhau và bạn phải đi qua chúng theo đúng thứ tự.
Cuộc đua nằm trong race.gd, trên nút Main. track.offset_of(point) cho biết một điểm cách vạch xuất phát bao xa dọc theo đường đua, với 0 tại vạch và track.length là độ dài đường đua. Trạm kiểm soát k nằm tại 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) % CHECKPOINTSwrapf giữ cho khoảng cách được tính chính xác tại vạch đích, nơi 1390 và 5 chỉ cách nhau 14 pixel. % CHECKPOINTS đưa trạm kiểm soát tiếp theo sau trạm 7 về 0, tức vạch đích. Điều kiện is_on_road đảm bảo đường tắt băng qua bãi cỏ không được tính.
Thử thách
Trung bìnhHãy tính các trạm kiểm soát theo thứ tự trong cuộc đua.
- Trong
race.gd, thêmconst CHECKPOINTS := 8vàvar next_checkpoint := 1. - Lấy
track($Track) vàcar($Car) bằng@onready. - Viết hàm
check_progressvà gọi hàm này từ_physics_process.
Nhấn Chơi rồi lái xe một vòng: hiện chưa có gì mới xuất hiện, vòng đua sẽ có trong bài học tiếp theo. Sau đó, nhấn Kiểm tra.
Tự làm thử
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
Tất cả bài học trong Trò chơi Godot: Mạch neon
Tự luyện tập: Playground Godot