모든 요소들을 모을 Main Scene 을 생성합니다. 새 씬 생성후 "Node"라는 이름의 노드를 추가해줍니다.
그리고 "인스턴스화"아이콘을 클릭하여 Player.tscn을 불러옵니다.
그 외에는 자식노드 추가 기능에서 Timer 3개, Position2D 노드를 추가해주고, 각각의 이름을 아래와 같이 수정해줍니다.
MobTimer - 가장자리에서 Mob이 생성되는 시간 통제 (0.5초) ScoreTimer - 매초마다 점수 증가시킴 (1.0초) StartTimer - 시작하기 전에 지연 시간 부여 (2.0초) StartPosition - Player의 시작 위치(240, 450)
2. Mob 생성
Main 노드가 Mob을 가장자리를 따라 랜덤한 위치에서 생성합니다. 이를 위해서는 Main 노드 하위에 Path2D 노드를 추가해줍니다. Path2D노드를 선택하면 아래와 같은 화면으로 변경되는데, 그 전에 "스마트 스냅 사용", "격자 스냅 사용" 을 클릭합니다. 그리고, 새로 생긴 Path관련 버튼 중 가운데 버튼(1: 점추가)을 누른다음 화면의 네 꼭지점을 시계방향(2~5)으로 클릭해줍니다. 마지막으로 마지막 버튼(6: 곡선닫기)을 클릭해주면 경로가 완성됩니다.
다음으로 PathFollow2D 노드를 Path2D노드 하위에 추가해줍니다. 이 노드는 Path를 따라서 어떤 작업을 해줍니다. 이 게임에서는 Mob 생성이겠죠?
그리고 각각의 이름을 MobPath, MobSpawnLocation으로 바꿔줍니다.
3. Main.gd 스크립팅
우선 아래의 코드로 시작하겠습니다.
extends Node
export (PackedScene) var Mob
var score
func _ready():
randomize()
export (PackedScene) var Mob 구문으로 선언하면, 인스펙터 창에서 Mob이라는 속성이 나타나는 것을 확인할 수 있습니다. 여기에는 Scene을 넣어줄 수 있는데, 우리가 구성한 Mob.tscn을 넣어줍니다.(드래그 앤 드랍)
다음으로 Player가 Mob과 부딛혔을 때(hit signal) 게임오버를 나타내는 함수를 작성/연결하겠습니다. 조금 헷갈릴 수도 있는데요, Main Scene 하위에 있는 Player Scene을 선택(한번 클릭)하면, 우측의 "노드" 창에 시그널들이 나타납니다. 우리가 만든 hit 시그널도 보입니다. hit()시그널을 더블클릭하면 메서드 연결창이 나타납니다. 작성할 스크립트가 Main인 것을 확인하고, 받는 메서드의 이름을 game_over로 하여 "연결"을 클릭합니다.
func _on_MobTimer_timeout():
# Choose a random location on Path2D.
$MobPath/MobSpawnLocation.offset = randi()
# Create a Mob instance and add it to the scene.
var mob = Mob.instance()
add_child(mob)
# Set the mob's direction perpendicular to the path direction.
var direction = $MobPath/MobSpawnLocation.rotation + PI / 2
# Set the mob's position to a random location.
mob.position = $MobPath/MobSpawnLocation.position
# Add some randomness to the direction.
direction += rand_range(-PI / 4, PI / 4)
mob.rotation = direction
# Set the velocity (speed & direction).
mob.linear_velocity = Vector2(rand_range(mob.min_speed, mob.max_speed), 0)
mob.linear_velocity = mob.linear_velocity.rotated(direction)
4. 테스트
func _ready():
randomize()
new_game()
플레이어 이동, 몹 생성, 충돌시 사라지기가 정상 작동되면 다음 HUD 구성을 위해 new_game()부분은 제거해줍니다.
웹 설명서를 그대로 번역하면 적 신으로 나오는데, 마음에 들지않아 장애물이라고 표현하겠습니다. 장애물에 해당하는 몹(Mob)들은 화면 가장자리 4군데에서 랜덤하게 생성되고, 직선방향으로 움직이도록 할 계획입니다. 우선 Player에서 했던 것과 마찬가지로 새 신(scene)을 추가하고 Rigidbody2D 노드를 추가합니다. 그리고 이름은 Mob으로 바꿔주겠습니다.
그리고 아래의 버튼(잠금열쇠 옆에있는거..)을 클릭하여, 추가되는 자식노드만 따로따로 선택되지 않도록 해 줍니다.
이어서, Gravity Scale을 0으로 해 줍니다. 즉, 중력에 영향을 받지 않게 해줍니다. 이 값이 0이 아닐경우, Mob들은 중력의 영향을 받도록 계산되고, 화면 아래로 떨어지게됩니다. 조금 아래로 내려와 CollisionObject2D 카테고리의 Mask에 1을 체크 해제합니다. 이렇게 하면 Mob들끼리 서로 충돌하는 상황은 발생하지 않습니다.
2. 애니메이션 추가
Player 씬에서 수행했던 것과 마찬가지로, AnimatedSprite를 Node 하위에 추가하고,
인스펙터에서 Frames > 새 SpriteFrame 을 추가하여 한번 더 클릭하여 Animation 창을 띄워줍니다.
애니메이션은 fly, swim, walk의 세가지가 있으며, 각각의 케이스에 대해 2개의 이미지가 있습니다. 기존에 했던 것과 동일한 방식으로 이미지를 추가해줍니다. 아울러 재생속도를 초당 3프레임으로 변경해줍니다.
또한 Mob들의 사이즈를 조절하기 위해 AnimatedSprite 노드를 한번 더 클릭하고, 인스펙터 창의 Playing 속성을 "사용", Scale속성을 x, y 방향으로 각각 0.75씩 입력해줍니다.
3. 충돌 노드(CollisionShape2D) 추가
Player 씬과 마찬가지로 충돌 감지노드를 추가해야합니다. Mob 노드를 선택한 상태에서 새 노드를 추가해줍니다.
이번엔, CapsuleShape이면서도 Mob의 형상에 맞게 90도 회전하여 잘 커버되도록 조정해줍니다.
4. Mob.gd 스크립트
스크립트에서는 Mob이 생성될때 랜덤 형상, 랜덤 속도, 화면 밖으로 나갔을 때 삭제 처리를 할 예정입니다.
extends RigidBody2D
export var min_speed = 150 # Minimum speed range.
export var max_speed = 250 # Maximum speed range.
# Called when the node enters the scene tree for the first time.
func _ready():
var mob_types = $AnimatedSprite.frames.get_animation_names()
$AnimatedSprite.animation = mob_types[randi() % mob_types.size()]
func _on_VisibilityNotifier2D_screen_exited():
queue_free()
# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
# pass
mob_types는 애니메이션에서 설정한 3가지의 몹 이름을 배열로 갖게 됩니다. 그리고 실제 보여줄 에니메이션에서는 이 중 랜덤하게 골라서 설정하게 됩니다.
화면에서 해당 객체(생성된 Mob)가 나가게 되면 자체 제거(메모리 회수)를 하게되는데, 이때 사용하는 함수가 queue_free()입니다.
프로젝트 > 프로젝트 설정을 클릭한 후, display > window메뉴로 가서 width480, height720으로 설정해줍니다.
그리고, Stretch로 내려가서 Mode: 2d, Aspect: keep으로 변경해줍니다.
2. Resource 폴더 추가
dodge_assets 파일은 링크 에서 다운받을 수 있습니다. Godot엔진 홈페이지의 Your First Game 챕터에서 찾을 수도 있습니다. 압축을 풀어서 생성된 프로젝트 폴더에 집어넣으면 아래와 같이 자동으로 프로젝트에 폴더가 추가됩니다.
3. Player 씬 추가
왼쪽 씬 탐색기에서 다른노드 > Area2D검색 >Area2D 를 선택합니다.
노드를 더블클릭하여 이름을 Player로 바꿔줍니다. 그리고 Player.tscn으로 저장합니다.
그리고 자물쇠 아이콘 옆의 아이콘을 클릭해줍니다. 추후 자식 노드들이 추가될텐데, 자식노드들만 따로 선택되는 것을 방지해주는 기능이라고 합니다.
Player 노드 하위에 AnimatedSprite를 검색하여 추가합니다.
AnimatedSprite노드가 추가되면 우측의 Frames속성이 아직 [비었음] 상태입니다. [비었음]을 클릭하여 새 SpriteFrames를 선택합니다.
그리고 선택된 SpriteFrame를 한번 더 눌러주면 아래의 애니메이션 패널이 나타납니다.
4. 애니메이션 프레임 추가
Default를 walk라고 이름을 바꾸고, 새 애니메이션 추가 버튼을 클릭하여 up으로 이름으로 만들어줍니다. 아까 추가한 dodge_assets 폴더로 가보면 art라는 하위폴더가 있는데, 여기에서 PlayerGrey_walk1, 2는 walk프레임에, PlayerGrey_up1, 2는 up프레임에 드래그앤드랍으로 추가해줍니다.
다시 AnimationSprite노드를 클릭하고, 인스펙터 창에서 Node2D > Scale에서 x와 y를 각각 0.5로 입력하여 사이즈를 반으로 줄여줍니다.
5. 충돌감지노드 추가
Player노드에서 우클릭하여 새 노드를 추가합니다.검색창에 CollisionShape2D를 검색하여 추가해줍니다.
이 노드는 현재의 노드가 장애물(Mob)과 충돌을 감지할 수 있는 영역을 만들수 있게 해 줍니다. 즉, 이 노드만으로는 안되고, 실제 감지되는 영역을 지정해줘야합니다. 인스펙터 창에서 Shape > [비었음] 클릭 > 새 CapsuleShape2D 를 클릭하여 추가해줍니다.
그러면 캐릭터에 캡슐형 감지영역이 나타나게 됩니다. 감지영역의 핸들을 조정하여 적당히 커버될 수 있도록 조정합니다. 약간 이미지보다 작게 나타나도록 설정하는 것을 추천합니다.
6. Player 방향키 설정
적당히 진행하며 저장해주시고, 이제 Player의 움직임을 설정해줘야합니다. 여기서부터 코딩이 들어갑니다. Attach Script 버튼을 클릭합니다.
우선 필요한 변수를 선언합니다. (speed, screen_size)
export 키워드는 작업을 굉장히 편리하게 해 줍니다. 변수 앞에 export를 붙여주면 inpector 창에서 나타나게 됩니다. 그럼 inpector에서 값을 직접 설정하여, 테스트할 때 일일이 코드를 보지 않고도 테스트할 수 있도록 도와줍니다. 물론 스크립트에 설정된 기본값은 무시됩니다.
처음 게임이 시작되면 _ready()함수를 실행하게 되는데, 게임 창의 크기값을 가져와 screen_size라는 변수에 지정하도록 하겠습니다. 이 값은 나중에 활용할 계획입니다. 기존에 있던 pass 부분은 지워줍니다. 아무것도 안하는 함수일 때 필요한 지시어입니다.
func _process(delta):
var velocity = Vector2() # The player's movement vector.
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
if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite.play()
else:
$AnimatedSprite.stop()
우선 $AnimatedSprite.play() 의$는 get_node()의 단축 표기형입니다. get_node("AnimatedSprite").play()와 동일합니다. 위 코드는 아직 오류가 있는 것이 상하키와 좌우키를 동시에 누르면 1+1=2의 속도로 원래 움직임보다 더 빠르게 움직입니다. 다음으로 화면 밖으로 나가는 것을 방지하기 위해 clamp()함수로 영역을 지정해줍니다. func _process(delta)함수 하부에 이어서 아래 코드를 추가해줍니다.
func start(pos):
position = pos
show()
$CollisionShape2D.disabled = false
<전체 코드:Player.gd>
extends Area2D
signal hit
export var speed = 400
var screen_size
# Called when the node enters the scene tree for the first time.
func _ready():
screen_size = get_viewport_rect().size
hide()
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
var velocity = Vector2() # The player's movement vector.
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
if velocity.length() > 0:
velocity = velocity.normalized() * speed
$AnimatedSprite.play()
else:
$AnimatedSprite.stop()
# position
position += velocity * delta
position.x = clamp(position.x, 0, screen_size.x)
position.y = clamp(position.y, 0, screen_size.y)
# 방향 역전
if velocity.x != 0:
$AnimatedSprite.animation = "walk"
$AnimatedSprite.flip_v = false
$AnimatedSprite.flip_h = velocity.x < 0
elif velocity.y != 0:
$AnimatedSprite.animation = "up"
$AnimatedSprite.flip_v = velocity.y > 0
func start(pos):
position = pos
show()
$CollisionShape2D.disabled = false
func _on_Player_body_entered(body):
hide() # Player disappears after being hit.
emit_signal("hit")
$CollisionShape2D.set_deferred("disabled", true)
tool #플러그인 사용
extends Button
export(String, FILE) var next_scene_path:="" #string형태로 scene을 받아들이고, 파일 다이얼로그를 보여줌
func _on_button_up():
get_tree().change_scene(next_scene_path)
func _get_configuration.warning() -> String:
return "next_screne_path must be set for the button to work" if next_scene_path=="" else ""
- Merge from scene - mainscreen.tscn에서 Menu 선택으로 메뉴/버튼 불러오기 ○ Next scene에 mainscreen을 선택 ○ Play버튼 텍스트를 Play Again으로 변경
- EndScreen선택 후 resource에서 title검색으로 title.tscn을 가져와서 화면으로 drag & drop ○ Title text변경: Congratulations, you finished the game ○ Layout: center top ○ 아래쪽으로 위치이동
- Label 노드 추가 ○Layout: center top ○Text수정: 텍스트 오른쪽의 expand button
your final score is %s
you died times %s
- 헌번 더 layout 조정, 텍스트 얼라인 center조정
- Title, Label, Menu를 동시 선택 후 layout - center로 중앙 정렬 후 위치 조정 ○ 화면 사이즈가 변하더라도 위치변화로 이미지가 겹치지 않는다.
extends Control
onready var scene_tree: = get_tree() #_ready함수 전에 실행됨
onready var pause_overlay: ColorRect= get_node("PauseOverlay") #ColorRect type임을 명시해줌. 혼선의 여지가 없을 경우는 선언 안하더라도 상관 없음.
var paused: = false setget set_paused
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("pause"):
self.paused = !paused #(== "paused = not paused") #Self는 gdscript에서 기본이지만, setget함수를 위해서...
scene_tree.set_input_as_handled() #pause event가 끝날때까지 propagate하지 않고 기다린다.
func set_paused(value: bool) ->void:
paused = value
scene_tree.paused = value
- Project Settings - Input Map - pause생성 - Key 추가(+버튼) - Esc로 설정 - UserInterface.tscn을 Level01에 추가 ○ Canvaslayer추가(UserInterface로 변경) ○ 상위 노드로 위치를 바꾸고 Layer를 +100정도로 앞쪽으로 한다. ○ 그 후 Canvaslayer에 UserInterface.tscn을 하위 자식으로 추가
- UserInterface노드 선택 후 Node-Pause-Process로 선택(Inherit(default)/Stop/Process 중) ○ 기본으로 되어있는 Inherit는 상위노드를 상속하고 상위노드는 Stop으로 되어있다. ○ Stop은 완전 정지로 아무것도 Process할 수 없는 상태임
- 추가로, UserInterface 씬에서 Label을 hide하고, 각 level에서 인스턴스된 UserInterface 노드에서는 Label을 show해야만 Label이 이중으로 나타나는 현상이 사라진다.
tool
extends Area2D
onready var anim_player: animationPlayer = $AnimationPlayer
export var next_scene: PackedScene
func _on_body_entered(body: PhysicsBody2D) -> void:
teleport()
func _get_configuration_warning() -> String:
return "The next scene property can't be empty" if not next_scene else ""
func teleport() ->void:
anim_player.play("fade_in")
yield(anim_player, "animation_finished") #anim_player가 끝나서 animation_finished 시그널을 보낼 때까지 기다림
get_tree().change_scene_to(next_scene)
- nextscene을 export로 추가하고, 없으면 에러메세지 popup띄우는 기능 추가
- teleport함수 추가 - body_entered(PhysicsBody2D body) 시그널 연결 : _on_body_entered - Level을 우선 복제하여 테스트
#참고로...터치패드에서 대량으로 tilemap을 지울 때에는 우클릭에 해당하는 두손가락 클릭을 하는데,,,한번하면 생성, 두번하면 삭제 #한손가락은 패드도 눌러야하고, 검지손가락은 터치도 해야함...두번씩....
- platformer폴더 생성 후 assets폴더를 복사해 넣습니다. - assets 폴더에 이미지 등 소스 추가 - src 폴더 추가
2. Player 생성
- kinematicbody2D 추가
- Player로 변경 - CollisionShape2D추가 ->Rectangle shape 설정 - Player 이미지를 끌어오면 자동으로 sprite node가 추가되며 이름은 player로 설정됨 - magnetic을 클릭하여 snap 활성화 - pixel snap을 활성화하여 맨 바닥이 0에 오도록 설정 - Collisionshape2D의 크기 조정(캐릭터 이미지보다 약간 작도록 설정, 단 바닥은 0에 닿도록 함) - Player Scene을 src/Actors폴더 안에 저장 - Player node에 script 추가(Empty template로 설정하여 추가) - File menu에서 script 추가하여 Actor.gd(palyer와 enemy가 공유할 base script)를 추가 (player.gd는 현 단계에서는 필요 없음.
extends Actor
func _physics_process(delta: float) -> void:
var direction: = Vector2(
Input.get_action_strength("move_right") -
Input.get_action_strength("move_left"),
1.0
)
velocity = speed * direction
velocity = move_and_slide(velocity)
- 최종 -
extends Actor
export var stomp_impulse: = 1000
func _on_EnemyDetector_area_entered(area: Area2D) ->void:
_velocity = calculate_stomp_velocity(_velocity, stomp_impulse) #enemy를 밟을때 충격으로 튀어오르는 기능
func _on_EnemyDetector_body_entered(body: PhysicsBody2D) -> void: #enemy와 부딛혔을 때 죽는 기능
queue_free()
#1단계
func _physics_process(delta: float)->void:
var is_jump_interrupted: = Input.is_action_just_released("jump") and velocity.y <0.0 #현재 점프상태가 끝나면 jump도 짧게 끝남. 키 누르는 시간에 비례하도록)
direction: = get_direction()
velocity = calculate_move_velocity(velocity, direction, speed, is_jump_interrupted)
velocity = move_and_slide(velocity, FLOOR_NORMAL) #현재 player가 frame 밖에 있으므로 안쪽으로 옮겨준 뒤 실행가능
#1단계
func get_direction() -> Vector2:
return Vector2(
Input.get_action_strength("move_right")-Input.get_action_strength("move_left"), -1.0 if Input.is_action_just_pressed("jump") and is_on_floor() else 1.0) #벽에서 점프한 경우에만 y 방향을 -1로 설정하고, 그 외에는 1로 설정함
#1단계
func calculate_move_velocity(
linear_velocity: Vector2,
direction: Vector2,
speed: Vector2
is_jump_interrupted: bool
) ->Vector2:
var new_velocity: = linear_velocity
new_velocity.x = speed.x * direction.x
new_velocity.y += gravity * get_physics_process_delta_time() //delta값을 호출해줌
if direction.y == -1.0:
new_velocity.y = speed.y * direction.y
if is_jump_interrupted:
new_velocity.y = 0.0
return new_velocity
func calculate_stomp_velocity(linear_velocity: vector2, impulse: float) -> Vector2:
var out: = linear_velocity
out.y = -impulse
return out
- player와 enemy속도 차이를 위해 player 600 설정 - Jump 함수 추가(방향함수를 추가하여 가독성 향상) - Jump 함수에 FLOOR_NORMAL 상수를 추가로 전달하여야 JUMP가 가능함 - new_velocity 변수 일괄 변경: 선택-> Ctrl+R(대체)->out - Ctrl+Shift+F: 파일 전체(전체프로젝트)에서 찾기: velocity찾기->whole word체크(전체일치)->replace->_velocity 로 변경(private:해당 script/class에서만 쓸 수 있음)
6. Enemy
- Player.tscn -> duplicate: 이름 변경 to Enemy, sprite 이름 enemy - enemy.png를 sprite texture에 놓는다. - Collisionshape2D 사이즈 변경
extends "res://src/Actors/Actor.gd"
func _ready() ->void:
set_physices_process(false) #enemy가 밖에 있을 때 작동하지 않도록 하는 기능
_velocity.x = -speed.x
func _on_StompDetector_body_entered(body:
PhysicsBody2D) ->void:
if body.global_positioy.y < get_node("StompDetector").global_position.y:
return
get_node("CollisionShape2D").disabled = true # 죽이고도 내가 또 죽는 오류를 방지
queue_free() # 적 삭제
func _physics_process(delta: float) ->void: #1단계
_velocity.y +=gravity * delta
if is_on_wall(): #1단계
_velocity.x *= -1.0 #1단계
_velocity.y = move_and_slice(_velocity, FLOOR_NORMAL).y #1단계
- Frame 밖에 있을 때는 작동하지 않도록 하는 기능 ( 노드 추가: VisibilityEnabler2D )
- physics Process Par: on, process parent: on
- "physics Process Par: on" 옵션은 화면 밖으로 나가는 것에대해서만 Trigger역할을 합니다. 즉, 이미 오른쪽 밖에서 안으로 이동하는 녀석에 대해서는 작동하지 않습니다. 계속 왼쪽 (화면 안쪽)으로 이동합니다. 따라서 추가 함수가 필요합니다.
func _ready() ->void:
set_physices_process(false) #enemy가 이미 밖에 있을 때도 작동하지 않도록 하는 기능
_velocity.x = -speed.x
- Frame Trigger box 사이즈/위치 조절(-50, -50, 100, 60)
- Enemy에 Area2D 노드 추가(StompDetector로 이름 변경)
- Layer 체크 삭제 - Monitorable: off
- CollisionShape2D 노드 추가: rectangleshape/사이즈 조정
- StompDetector위치는 위로 올리고, 아래에서부터 부딛힐 때도 죽으면 안되니까..
- 내부의 CollisionShape2D는 아래로 내려서 위치를 조정한다.
- 박스 색깔을 조절한다.
- signal연결: body_entered(PhysicsBody2d)
7. 적을 밟아 제거하면 튀어오르는 모션 추가
이제 적당히 움직임이 구현되었습니다. 거기에 더해 Player 동작에 적을 밟았을 때 튀어오르는 모션을 추가해보겠습니다.
- player에 Area2D 노드 추가(EnemyDetector로 이름 변경)
- Layer: 없음, Mask: enemy - Monitorable: off
- collisionshape2D - rectangleshape추가 - 사이즈 조절
살짝 크게, 아래쪽으로 살짝 더 내려오게 박스 설정
- visibility tab에서 색깔 변경(파란색으로)
- 적 제거후 튀어오르는 애니메이션 구현 코드
8. 적과 충돌시 Player 죽는 기능 구현
- signal 연결: body_entered(PhysicsBody2D body) 적에 닿으면 죽는 기능 구현
_on_EnemyDetector_body_entered(body: PhysicsBody2D) 함수 추가
9. 적당한 시점에 Level TileMap을 수정해준다.
10. 카메라
- Player 노드에 Camera2D 추가 - current: on으로 설정해야 카메라 뷰로 보임
- w키로 프레임 위치 상향 조정
- 카메라 이동 제한 - player - camera2D -limit의 값 수정(left: 0, top: 0) - Drag Margin: 카메라 이동 없이 player가 움직일 수 있는 공간, left 0, right 0
- Drag Margin H/V Enabled - Smoothing - Enabled:on, Speed:2로 카메라가 따라오는 속도를 낮춤.. 7정도로 유지
- player-right click - Editable Children - Limit Right:3600으로 해당 레벨에서만 리밋 설정 가능
11. 배경 이미지 설정
- backgraound 이미지를 Texture Rectangle로 화면 안쪽으로 끌고 들어옵니다. (TextureRect노드안에 설정)
- Layout: Full Rect정 - 맨 위로 올리면 제일 뒤쪽에 보이도록 할 수 있다.
- CanvasLayer 추가후 background 를 자식으로 추가하면, 일일이 배경을 복사해서 추가하지 않아도, 게임 진행하면서 일관되게 배경을 추력해줍니다. - layer에 -100으로 설정
- visible Collision Shapes 체크를 끔으로써 게임에서 Collision shape들이 안보이게 하여 마무리 해 줍니다.
흔히 슈퍼마리오 게임으로 익숙하게 알고있는 횡 스크롤 형태의 게임을 Platformer 라고 하는 것 같습니다. Godot 엔진을 이용한 Platformer 게임만들기를 시작하려고 하는데요, youtube강좌 https://www.youtube.com/watch?v=Mc13Z2gboEk 를 따라해보았습니다. 총 3편에 걸쳐 진행하며 Godot 엔진에 익숙해질 시간을 가져보겠습니다.
아래는 예전에 핸드폰에 넣으려고 만들었던 게임의 스크린 샷인데, 지금은 소스가 안남아있네요..ㅠㅠ