오늘도 godot 을 열심히 공부했답니닷!~!
오늘은 script 코드가 너무 왔다 갔다 했어서 공부하는데.. 많이 헷갈렸어요... T-T
처음에는 player.gd 에 signal player_hit 을 추가 시켜줍니다.
player 는 맞았으면 "나 맞았어" 라고 알려주기만 하면 돼요!
func hit():
player_hit.emit()
on_dead()
그리고 그 함수에서 emit() 을 호출해 줍니다.
emit() 은 신호를 보내주는 역할을 해요!
그러면 이제 누군가는 반응을 해야겠죠?
이때 반응은 game 이 해 줍니다! 돌 씬이 할 일은 없고, 돌을 뿌려주는 씬도 반응 할 일이 당연히 없으니 game 밖에 반응할 게 없어요!
그래서 game 에서 이 함수를
$Player.player_hit.connect(_on_player_hit)
fun _on_player_hit():
print("Player Hit (Game)")
이렇게 연결하고, 호출해 줬어요!
extends Node2D
signal player_hit
const SPEED = 400
const CHARACTER_HALF_WIDTH = 40
var no_dir_input
# 남은 체력을 저장할 변수 추가
var health
func _ready():
$AnimatedSprite2D.play("idle")
# 체력 초기화
health = 3
func _process(delta):
no_dir_input = true
if Input.is_action_pressed("right"):
no_dir_input = false
scale.x = 1
$AnimatedSprite2D.play("run")
position.x += SPEED * delta
if (position.x + CHARACTER_HALF_WIDTH) >= 540:
position.x = (540 - CHARACTER_HALF_WIDTH)
if Input.is_action_pressed("left"):
no_dir_input = false
scale.x = -1
$AnimatedSprite2D.play("run")
position.x -= SPEED * delta
if (position.x - CHARACTER_HALF_WIDTH) <= 0:
position.x = (0 + CHARACTER_HALF_WIDTH)
if no_dir_input:
$AnimatedSprite2D.play("idle")
func _on_hit_area_area_entered(area):
if area.is_in_group("rock"):
hit()
func hit():
# 체력을 1 감소 시킨 후
health -= 1
# emit 메서드로 시그널 발생시키기
player_hit.emit()
# 체력이 0이면 죽도록 설정
if health == 0:
on_dead()
func on_dead():
queue_free()
여기서 health 를 시작하자 마자 3으로 초기화 해줍니다.
func hit():
health -= 1;
player_hit.emit()
if health == 0:
on_dead()
이 코드는 hit 이 호출될 때마다 health 가 하나 씩 감소되고 신호를 보내주고, health 가 0 이 되면 죽는 모션을 하게 하는 코드입니당.
func _on_player_hit():
$GameUI/RemainHealthCountText.text = str($Player.health)
print("Player Hit (Game)")
목숨이 몇 개 남았는지는 사용자에게도 보여 줘야 하기 때문에, 이를 str 로 형변환 하여 사용자에게 보여줍니다.
저희는 목숨을 하트 이모티콘으로 보여줄 거라서 Texture 에 하트 이모티콘을 넣어 줬어요!
이것은 GameUI 에서 추가해 주었습니당.
이제 죽었을 때 쓰러지는 이모션을 보여줄 건데요!
우선
옛날에 해 줬던 것처럼 dead 라는 이름의 모션을 추가해 줬어요!
이를 한 후, 저는 player.gd 에
func on_dead():
$AnimatedSprite2D.play("dead")
queue_free()
이걸 넣어줬어요!
근데 함수가 실행될 때 있는 queue_free() 가 바로 실행돼서 이모션이 안 보이는 거예요!
그래서 저희는 이 문제를 방지하기 위해 dead 모션이 끝나야 queue_free() 를 해주도록 할 것입니닷.
extends Node2D
signal player_hit
const SPEED = 400
const CHARACTER_HALF_WIDTH = 40
var no_dir_input
var health
# 죽었는지 여부 확인할 변수 추가
var dead = false
func _ready():
$AnimatedSprite2D.play("idle")
health = 3
func _process(delta):
# 죽었으면 입력여부 확인하지 않도록 변경
if not dead:
no_dir_input = true
if Input.is_action_pressed("right"):
no_dir_input = false
scale.x = 1
$AnimatedSprite2D.play("run")
position.x += SPEED * delta
if (position.x + CHARACTER_HALF_WIDTH) >= 540:
position.x = (540 - CHARACTER_HALF_WIDTH)
if Input.is_action_pressed("left"):
no_dir_input = false
scale.x = -1
$AnimatedSprite2D.play("run")
position.x -= SPEED * delta
if (position.x - CHARACTER_HALF_WIDTH) <= 0:
position.x = (0 + CHARACTER_HALF_WIDTH)
if no_dir_input:
$AnimatedSprite2D.play("idle")
func _on_hit_area_area_entered(area):
if area.is_in_group("rock"):
hit()
func hit():
health -= 1
player_hit.emit()
if health == 0:
on_dead()
func on_dead():
dead = true
# 애니메이션 재생이 끝난 후 시그널에 대응할 함수 추가
# (단, 루프 애니메이션은 끝나지 않기 떄문에 루프 설정을 해놨다면 시그널이 발생하지 않음을 유의)
$AnimatedSprite2D.animation_finished.connect(_on_dead_animation_finished)
# 죽는 애니메이션 재생
$AnimatedSprite2D.play("dead")
# queue_free()
func _on_dead_animation_finished():
# 재생이 끝난 후 씬 인스턴스 제거
queue_free()
처음에 dead 는 false 로 설정해 줘요!
그리고 만약 dead 가 false 라면 돌을 피하는 모션들을 수행해 줘요~
그러다가 만약 목숨이 0 개가 되어 on_dead() 가 실행이 되면 이때 dead 를 true 로 만들어 줍니다.
그리고 시그널을 연결해 줘서 dead 모션이 다 끝나면 queue_free() 를 해주게 합니다.
그래서 _on_dead_animation_finished() 라는 함수도 만들어 줬어요~ ^3^
여기서 queue_free() 를 할 수 있게 되었답니당 -_-
'레쭈고 godot' 카테고리의 다른 글
godot 11차시 (3) | 2024.11.10 |
---|---|
godot 10차시 (3) | 2024.10.31 |
godot 8차시 (1) | 2024.10.20 |
godot 7차시 (1) | 2024.09.27 |
godot 6차시 (3) | 2024.09.26 |