Menu
CoddyTech

Ba đối thủ

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

Có thêm hai đối thủ tham gia cuộc đua, một màu hổ phách và một màu xanh lá, mỗi đối thủ có tốc độ tối đa và làn đường riêng. Cuộc đua cần biết khi nào từng đối thủ về đích.

Số vòng đua của một đối thủ là tiến độ của nó trên quãng đường đua, làm tròn xuống:

func laps_done() -> int:
	return int(progress / track.length)

Các đối thủ thuộc nhóm rivals. Trong mỗi khung hình, mọi đối thủ đã chạy được ba vòng và chưa có tên trong danh sách finished sẽ được thêm vào danh sách đó:

for rival in rivals:
	if rival.laps_done() >= LAPS and not finished.has(rival.name):
		finished.append(rival.name)
challenge icon

Thử thách

Dễ

Ghi lại thời điểm mỗi đối thủ về đích.

  1. Trong rival.gd, thêm laps_done.
  2. Trong race.gd, thêm var finished: Array[String] = [] và @onready var rivals: Array[Node] = get_tree().get_nodes_in_group("rivals").
  3. Sau check_progress(), thêm vòng lặp ở trên.

Nhấn Chơi: các đối thủ màu hổ phách và xanh lá đua cùng đối thủ màu hồng. 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