Bạn có thể đạt được hiệu ứng hình ảnh cuộn song song ấn tượng chỉ bằng cách di chuyển đối tượng theo các hướng khác nhau. Dưới đây là hướng dẫn chi tiết.
Parallax scrolling là một kỹ thuật mà nhiều game 2D dùng để tạo một hình ảnh chiều sâu và thêm sự thú vị về mặt hình ảnh cho background của game. Nó tạo hiệu ứng này bằng cách di chuyển các lớp background khác nhau theo các hướng tương quan với chuyển động camera.
Godot 4 khiến việc triển khai cuộn song song dễ dàng hơn bao giờ hết. Công cụ 2D mạnh mẽ của nó cung cấp sẵn hỗ trợ cho các lớp song song, cho phép bạn tạo hiệu ứng hình ảnh tuyệt vời mà không tốn nhiều công sức.
Thiết lập game Godot
Để bắt đầu, tạo dự án 2D mới trong công cụ game Godot và thiết lập cảnh game với một nhân vật người chơi.
Ở ví dụ này, thêm node CharacterBody2D cho chuyển động người chơi. Ngoài ra, thêm CollisionShape2D với hình chữ nhật và Sprite2D để đại diện cho nhân vật người chơi.
extends CharacterBody2D
var speed = 200
func _physics_process(delta):
var velocity = Vector2()
if Input.is_action_pressed('ui_right'):
velocity.x += 1
if Input.is_action_pressed('ui_left'):
velocity.x -= 1
if Input.is_action_pressed('ui_down'):
velocity.y += 1
if Input.is_action_pressed('ui_up'):
velocity.y -= 1
velocity = velocity.normalized() * speed
move_and_collide(velocity * delta)
Với code này, nhân vật người chơi có thể di chuyển sang trái, phải, lên và xuống bằng các phím mũi tên hoặc đầu vào tương tự.
Tạo các lớp khác nhau bằng node ParallaxLayer
Tiếp theo, tạo hiệu ứng song song bằng cách thêm nhiều node ParallaxLayer cho cảnh này. Mỗi ParallaxLayer sẽ đại diện cho một layer background khác. Để đạt được hiệu ứng song song tự nhiên, các layer ở xa máy ảnh nên di chuyển chậm hơn những layer ở gần.
Thêm node StaticBody2D với CollisionShape2D trong mỗi ParallaxLayer để tạo một số đối tượng có thể va chạm trong background. Những đối tượng có thể va chạm này sẽ tương tác với người chơi và các thành phần khác, thêm chiều sâu hơn vào gameplay.
Đây là code GDScript để tạo những layer song song với đối tượng có thể va chạm:
extends ParallaxBackground
func _ready():
# Tạo layer song song đầu tiên
var layer1 = ParallaxLayer.new()
layer1.motion_scale = Vector2(0.2, 0.2)
add_child(layer1)
# Thêm StaticBody2D với CollisionShape2D vào layer đầu tiên
var static_body1 = StaticBody2D.new()
layer1.add_child(static_body1)
var collision_shape1 = CollisionShape2D.new()
var shape1 = RectangleShape2D.new()
shape1.extents = Vector2(32, 32)
collision_shape1.shape = shape1
static_body1.add_child(collision_shape1)
# Tạo layer song song thứ hai
var layer2 = ParallaxLayer.new()
layer2.motion_scale = Vector2(0.5, 0.5)
add_child(layer2)
# Thêm StaticBody2D với CollisionShape2D vào layer thứ hai
var static_body2 = StaticBody2D.new()
layer2.add_child(static_body2)
var collision_shape2 = CollisionShape2D.new()
var shape2 = RectangleShape2D.new()
shape2.extents = Vector2(64, 64)
collision_shape2.shape = shape2
static_body2.add_child(collision_shape2)
# Tạo layer song song thứ ba
var layer3 = ParallaxLayer.new()
layer3.motion_scale = Vector2(1.0, 1.0)
add_child(layer3)
# Thêm StaticBody2D với CollisionShape2D vào layer thứ ba
var static_body3 = StaticBody2D.new()
layer3.add_child(static_body3)
var collision_shape3 = CollisionShape2D.new()
var shape3 = RectangleShape2D.new()
shape3.extents = Vector2(128, 128)
collision_shape3.shape = shape3
static_body3.add_child(collision_shape3)
Với code này, mỗi layer parallax giờ chứa node StaticBody2D cùng một CollisionShape2D đại diện cho các đối tượng có thể va chạm trên nền.
Những đối tượng có thể va chạm này sẽ tương tác với nhân vật người chơi và các thành phần khác trong game. Điều này làm tăng chiều sâu và độ phức tạp cho gameplay.
Di chuyển layer với tốc độ khác nhau
Giờ các layer song song đã được thiết lập, bạn cần update vị trí của chúng dựa trên chuyển động của người chơi. Điều này sẽ tạo hiệu ứng song song, tại layer gần camera hơn sẽ di chuyển nhanh hơn những lớp ở xa.
Thêm code GDScript sau vào cảnh Player:
extends CharacterBody2D
func _physics_process(delta):
...
move_and_collide(velocity * delta)
# Update layer parallax dựa trên chuyển động của người chơi
var parallax_background = get_parent()
var motion = -velocity * delta
parallax_background.set_scroll_offset(parallax_background.scroll_offset + motion)
Code này tính toán chuyển động của layer song song dựa trên chuyển động của người chơi và update offset cuộn của node ParallaxBackground tương ứng. Lưu ý, dùng ký hiệu trừ để đảm bảo các lớp di chuyển theo hướng đối lập với chuyển động của người chơi.
Thêm yếu tố bất ngờ vào cuộn song song ngẫu nhiên
Cuộn song song ngẫu nhiên giới thiệu một thành phần gây bất ngờ và khó dự đoán cho background của game. Bằng cách linh động trong việc tạo và xác định vị trí những layer song song trong suốt gameplay, bạn có thể tạo trải nghiệm hấp dẫn và năng động hơn cho người chơi.
Để triển khai cuộn song song ngẫu nhiên, thêm các layer song song mới với tỷ lệ và vị trí chuyển động ngẫu nhiên.
extends ParallaxBackground
const MAX_LAYERS = 5
const MIN_SCALE = 0.2
const MAX_SCALE = 1.5
const MIN_SPEED = 0.01
const MAX_SPEED = 0.03
const MIN_X_POSITION = -500
const MAX_X_POSITION = 500
const MIN_Y_POSITION = -300
const MAX_Y_POSITION = 300
func _ready():
for i in range(MAX_LAYERS):
create_random_layer()
func create_random_layer():
# Thêm layer parallax mới với tỷ lệ chuyển động ngẫu nhiên
var layer = ParallaxLayer.new()
var scale = lerp(MIN_SCALE, MAX_SCALE, randf())
layer.motion_scale = Vector2(scale, scale)
var x_position = randf_range(MIN_X_POSITION, MAX_X_POSITION)
var y_position = randf_range(MIN_Y_POSITION, MAX_Y_POSITION)
layer.global_transform.origin.x = x_position
layer.global_transform.origin.y = y_position
add_child(layer)
# Thêm StaticBody2D với CollisionShape2D vào layer mới
var static_body = StaticBody2D.new()
layer.add_child(static_body)
var collision_shape = CollisionShape2D.new()
var shape = RectangleShape2D.new()
shape.extents = Vector2(32, 32)
collision_shape.shape = shape
static_body.add_child(collision_shape)
func remove_random_layer():
# Loại bỏ layer song song ngẫu nhiên
if get_child_count() > 0:
var random_index = randi() % get_child_count()
var layer_to_remove = get_child(random_index)
remove_child(layer_to_remove)
Code này xác định các hằng số kiểm soát ngẫu nhiên những layer song song. Dùng hàm lerp để nội suy những giá trị nằm giữa MIN_SCALE và MAX_SCALE, tạo thang chuyển động ngẫu nhiên cho mỗi layer mới. Hàm này có signature sau:
Variant lerp ( Variant from, Variant to, float weight )
Chuyển kết quả từ randf() dưới dạng trọng số cho phép bạn tạo layer có tỷ lệ ngẫu nhiên.
Hàm randf_range cung cấp cách khác để tạo những giá trị ngẫu nhiên trong một phạm vi. Tại đây, hàm create_random_layer dùng nó để tạo những vị trí ngẫu nhiên cho các layer mới trong một phạm vi cụ thể.
var x_position = randf_range(MIN_X_POSITION, MAX_X_POSITION)
Kết quả, bạn sẽ có game như sau:
Trên đây là cách tạo hiệu ứng cuộn song song cho game phát triển trong Godot. Hi vọng bài viết hữu ích với các bạn.