레쭈고 godot

godot 9차시

정땅미 2024. 10. 23. 19:43

오늘도 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