매일 업데이트
2023-08-21 03:10 10 min

Godot에서 Parallax Scrolling을 구현하는 방법

패럴랙스 스크롤링은 2D 게임에서 깊이감을 부여하고 배경에 시각적인 흥미를 더하는 데 널리 사용되는 기법입니다. 이 기술은 카메라 이동에 따라 배경의 각 레이어를 서로 다른 속도로 움직여 깊이감을 만들어냅니다.

Godot 4 엔진은 패럴랙스 스크롤링 구현을 매우 간편하게 만들어줍니다. 강력한 2D 엔진은 시차 레이어에 대한 내장 지원을 제공하여 최소한의 노력으로 멋진 시각 효과를 연출할 수 있게 합니다.

Godot 게임 환경 설정

시작하려면 Godot 게임 엔진에서 새로운 2D 프로젝트를 만들고, 플레이어 캐릭터를 포함한 게임 장면을 구성해야 합니다.

이 문서에서 사용된 코드는 GitHub 저장소에서 제공되며, MIT 라이선스 하에 자유롭게 사용할 수 있습니다.

예시에서는 CharacterBody2D 노드를 사용하여 플레이어의 움직임을 제어합니다. 또한 플레이어 캐릭터를 시각적으로 표현하기 위해 직사각형 모양의 CollisionShape2D와 Sprite2D를 추가합니다.

 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)

이 코드를 사용하면, 플레이어 캐릭터는 화살표 키나 유사한 입력 장치를 사용하여 상하좌우로 움직일 수 있습니다.

ParallaxLayer 노드를 활용한 다양한 레이어 생성

다음 단계로, 장면 내에 여러 개의 ParallaxLayer 노드를 추가하여 패럴랙스 효과를 만들 수 있습니다. 각각의 ParallaxLayer는 서로 다른 배경 레이어를 나타냅니다. 카메라에서 멀리 떨어진 레이어일수록 카메라에 가까운 레이어보다 더 느리게 움직여야 효과적인 시차 효과를 얻을 수 있습니다.

각 ParallaxLayer 내에 StaticBody2D 노드와 CollisionShape2D를 추가하여 배경에서 충돌이 가능한 물체를 만들 수 있습니다. 이러한 충돌 가능 객체는 플레이어 및 다른 게임 요소와 상호 작용하여 게임 플레이에 깊이를 더해줍니다.

다음은 충돌 가능한 객체를 포함한 시차 레이어를 생성하는 GDScript 코드 예시입니다.

 extends ParallaxBackground

func _ready():
    
    var layer1 = ParallaxLayer.new()
    layer1.motion_scale = Vector2(0.2, 0.2)
    add_child(layer1)

    
    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)

    
    var layer2 = ParallaxLayer.new()
    layer2.motion_scale = Vector2(0.5, 0.5)
    add_child(layer2)

    
    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)

    
    var layer3 = ParallaxLayer.new()
    layer3.motion_scale = Vector2(1.0, 1.0)
    add_child(layer3)

    
    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)

이 코드를 사용하면 각 시차 레이어는 배경에서 충돌 가능한 객체를 나타내는 CollisionShape2D를 포함한 StaticBody2D 노드를 갖게 됩니다.

이러한 충돌 가능 객체는 플레이어 캐릭터 및 다른 게임 요소와 상호작용하여 게임 플레이에 깊이와 복잡성을 더합니다.

서로 다른 속도로 레이어 움직이기

이제 시차 레이어가 설정되었으므로, 플레이어의 움직임에 따라 각 레이어의 위치를 업데이트해야 합니다. 이렇게 하면 카메라에 가까운 레이어는 멀리 있는 레이어보다 더 빠르게 움직이는 패럴랙스 효과가 생성됩니다.

다음 GDScript 코드를 플레이어 장면에 추가합니다.

 extends CharacterBody2D

func _physics_process(delta):
    ...
    move_and_collide(velocity * delta)

    
    var parallax_background = get_parent()
    var motion = -velocity * delta
    parallax_background.set_scroll_offset(parallax_background.scroll_offset + motion)

이 코드는 플레이어의 움직임을 기반으로 시차 레이어의 이동량을 계산하고, 그에 따라 ParallaxBackground 노드의 스크롤 오프셋을 업데이트합니다. 레이어가 플레이어의 움직임과 반대 방향으로 움직이도록 하려면 음수 부호를 사용해야 합니다.

무작위 패럴랙스 스크롤링은 게임 배경에 놀라움과 예측 불가능성을 부여합니다. 게임 플레이 중에 패럴랙스 레이어를 동적으로 생성하고 배치함으로써 플레이어에게 더욱 몰입감 있고 역동적인 경험을 제공할 수 있습니다.

랜덤 패럴랙스 스크롤링을 구현하려면, 무작위 모션 스케일과 위치를 가진 새로운 패럴랙스 레이어를 추가하면 됩니다.

 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():
    
    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)

    
    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():
    
    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)

이 코드는 시차 레이어의 무작위성을 제어하는 상수를 정의합니다. lerp 함수를 사용하여 MIN_SCALE과 MAX_SCALE 사이의 값을 보간하여 각 레이어에 대한 임의의 모션 스케일을 생성합니다. lerp 함수의 형식은 다음과 같습니다.

 Variant lerp ( Variant from, Variant to, float weight ) 

randf() 함수의 결과를 가중치로 전달하면 임의 스케일을 가진 레이어를 생성할 수 있습니다.

randf_range 함수는 주어진 범위 내에서 무작위 값을 생성하는 또 다른 방법입니다. create_random_layer 함수에서는 이 함수를 사용하여 지정된 범위 내에서 새로운 레이어의 임의 위치를 생성합니다.

 var x_position = randf_range(MIN_X_POSITION, MAX_X_POSITION) 

이제 데모 게임은 다음과 같이 보여야 합니다.

추가 기능 통합

패럴랙스 스크롤링은 플랫포머 게임의 시각적 매력을 향상시키는 훌륭한 기반이지만, 추가 기능을 통합하여 더욱 발전시킬 수 있습니다. 고려해볼 만한 몇 가지 아이디어를 소개합니다.

배경 객체

떠다니는 플랫폼, 움직이는 장애물, 애니메이션 배경 캐릭터 등 시차 레이어에 더욱 다양한 상호작용 요소를 추가해 보세요. 이러한 객체는 플랫포머 게임에 깊이와 상호작용성을 더할 수 있습니다.

다이내믹 라이팅

시차 레이어에 다이내믹 라이팅 효과를 추가해 보세요. 광원과 그림자를 추가하여 게임 세계에 현실감과 깊이감을 부여할 수 있습니다. Godot의 조명 시스템은 2D 게임에 효과적이며 시각적 품질을 크게 향상시킬 수 있습니다.

입자 효과

미묘한 시각 효과를 더하기 위해 시차 레이어에 입자 시스템을 통합해 보세요. 떨어지는 나뭇잎, 떠다니는 구름, 반짝이는 별 등의 입자 효과는 분위기를 향상시키고 게임 세계를 더욱 생생하게 만들 수 있습니다. 게임에 저작권 없는 사운드 효과를 추가하여 몰입감을 높이는 것도 좋습니다.

낮/밤 주기

게임 내 시간 경과에 따라 시차 레이어의 색상과 강도를 변화시키는 낮/밤 주기를 구현해 보세요. 이러한 동적인 기능은 게임 진행에 따라 지속적으로 변화하는 경험을 제공합니다.

패럴랙스 스크롤링은 게임의 시각적 측면을 크게 향상시킬 수 있지만, 부드럽고 즐거운 경험을 보장하기 위해 몇 가지 모범 사례를 따르는 것이 중요합니다.

성능 최적화

시차 레이어의 수와 복잡성에 유의하세요. 너무 많은 레이어 또는 고해상도 자산은 특히 저성능 기기에서 성능 문제를 유발할 수 있습니다. 아트워크를 최적화하고, 가능하면 단순화된 충돌 모양을 사용하세요.

레이어 배치

시차 레이어를 신중하게 배치하세요. 시각적 계층 구조와 원하는 깊이 효과를 고려해야 합니다. 카메라에 가까운 레이어는 더 빨리 움직여야 하고, 멀리 있는 레이어는 더 느리게 움직여야 합니다.

카메라 경계

플레이어가 게임 세계의 가장자리에 도달했을 때 원치 않는 빈 공간이나 시각적 오류가 발생하지 않도록 카메라 이동에 대한 경계를 설정하세요. 이를 통해 플레이어에게 매끄러운 경험을 보장할 수 있습니다.

테스트 및 조정

다양한 기기와 화면 크기에서 패럴랙스 스크롤링을 테스트하여 다양한 플랫폼에서 시각적으로 정상적으로 작동하는지 확인하세요. 모션 스케일, 레이어 위치 및 기타 매개변수를 조정하여 패럴랙스 효과를 최적화할 수 있습니다.

랜덤 패럴랙스 스크롤링을 추가하면 Godot 게임의 몰입도를 크게 향상시킬 수 있습니다. 랜덤 패럴랙스 스크롤링은 게임 플레이 중에 패럴랙스 레이어를 동적으로 생성하고 배치하는 것을 의미합니다.

이렇게 하면 배경에 움직임과 역동성을 부여하여 게임 세계가 생생하고 예측 불가능한 느낌을 주게 됩니다. 플레이어는 끊임없이 변화하는 시각적 환경을 경험하게 되어 게임 경험에 흥미를 더할 수 있습니다.

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.