Menu
CoddyTech

Vạch đích

Bài học 12 trên 20 trong khóa học Trò chơi Godot: Mạch neon của Coddy.

Đua ba vòng là cuộc đua kết thúc. state cho biết cuộc đua đang ở trạng thái nào, còn race_time tính tổng thời gian cuộc đua:

const LAPS := 3
var state := "racing"
var race_time := 0.0

Khi số vòng đạt LAPS, cuộc đua kết thúc: trạng thái chuyển sang hoàn tất, xe không còn phản hồi phím và thời gian được hiển thị. Khi đã hoàn tất, cuộc đua không làm gì thêm:

func finish_race() -> void:
	state = "done"
	car.active = false
	$HUD/Message.text = "Finished!\nTime %s" % clock(race_time)

Trong car.gd, active quyết định có đọc phím hay không. Đặt ga và hướng lái ban đầu là 0, chỉ đọc phím khi xe đang hoạt động:

var throttle := 0.0
var steer := 0.0
if active:
	throttle = Input.get_axis("move_down", "move_up")
	steer = Input.get_axis("move_left", "move_right")
challenge icon

Thử thách

Trung bình

Cuộc đua kết thúc sau ba vòng.

  1. Trong race.gd, thêm các dòng phía trên, tăng race_time mỗi khung hình và bắt đầu _physics_process bằng if state == "done": return.
  2. Viết finish_race; finish_lap gọi hàm này khi laps >= LAPS.
  3. Hiển thị "Lap %d/%d" % [mini(laps + 1, LAPS), LAPS] trong $HUD/Lap.
  4. Trong car.gd, thêm var active := true và chỉ đọc phím khi active.

Nhấn Chơi và hoàn thành ba vòng để xem thời gian. 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
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Trò chơi Godot: Mạch neon

Tự luyện tập: Playground Godot