Menu
CoddyTech

Đếm ngược

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

Một cuộc đua bắt đầu với đèn tín hiệu: 3, 2, 1, XUẤT PHÁT. Trước khi có tín hiệu xuất phát, không ai di chuyển.

Bắt đầu cuộc đua ở trạng thái thứ ba, countdown, với đồng hồ đếm ngược ba giây, và giữ mọi chiếc xe đứng yên trong _ready. Trong lúc đếm ngược, hiển thị số giây còn lại và không làm gì khác:

if state == "countdown":
	countdown -= delta
	$HUD/Message.text = str(ceili(countdown)) if countdown > 0.0 else "GO!"
	if countdown <= 0.0:
		state = "racing"
		car.active = true
		for rival in rivals:
			rival.active = true
	return

ceili làm tròn lên, nên khi còn 2.4 giây sẽ hiển thị 3. Tiếp tục đếm sau tín hiệu xuất phát và xóa thông báo khi đồng hồ chạm -1, tức là một giây sau:

if countdown > -1.0:
	countdown -= delta
	if countdown <= -1.0:
		$HUD/Message.text = ""
challenge icon

Thử thách

Dễ

Bắt đầu cuộc đua bằng đồng hồ đếm ngược.

  1. Đặt state thành "countdown" và thêm var countdown := 3.0.
  2. Trong _ready, đặt car.active và active của từng đối thủ thành false.
  3. Đặt khối đếm ngược ở đầu _physics_process.
  4. Sau phần kiểm tra trạng thái hoàn tất, thêm khối xóa ở phía trên.

Nhấn Chơi: 3, 2, 1, GO! sẽ hiển thị, rồi cuộc đua bắt đầu. 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
var active := true

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


func _physics_process(delta: float) -> void:
	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")
		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