반응형

<폭발>

 

- 새로운 씬 생성

- sprite노드 추가 후 explosion 으로 변경

- Texture 지정

- Z 값을 5 정도로 상향 조정

- explosion에 하위노드로 Particles2D 노드 추가

- 이름을 p_smoke로 변경

- 각종 파라미터 적절히 변경

- Texture 를 클릭하여 smoke.png를 할당

 

- 추가 설정

- 추가 설정

- 추가 설정

- emmiting 기능으로 애니메이션 확인

- p_smoke 노드를 복사하여 p_flare노드 생성

- Texture에 flare.png파일을 할당하여 애니메이션 확인

- 노드 추가 > Merge from scene > flare.tscn 선택

- anim노드 선택

- 애니메이션이 영향받지 않도록 유니크하게 만들기

- length를 0.7초로 변경하고,

- 마지막 프레임을 0.7초 위치로 변경시킨다.

- explosion노드에 explosion.gd 스크립트를 추가

<ship.gd>에서 폭발 애니메이션 스크립트 추가 

<enemy.gd>스크립트 수정 (enemy.tscn)

- 소스코드는 ship.gd의 함수와 동일

- 충돌 시 폭발하는 부분도 동일하게 추가하는 것 주의

- ship에서 발사되는 레이저가 2개인 관계로, enemy와 충돌할 시 폭발이 2번 발생하는 오류가 있음

- 따라서 enemy가 폭발중일 때에는 처리하지 않도록 문구 추가 필요

반응형
반응형

<ship.gd> 수정

- 스크립트에 체력(armor) 변수를 설정

- "ship"그룹에 추가

- 체력이 0 이하로 가면 삭제되는 set_armor함수 추가

<enemy.gd> 수정

- 스크립트에 체력(armor) 변수를 설정

- "enemy"그룹에 추가

- 체력이 0 이하로 가면 삭제되는 set_armor함수 추가

- enemy_kamikaze.tscn의 Armor값은 2로 설정

- enemy_clever.tscn의 Armor값은 6으로 설정

<laser 수정>

- laser_ship.tscn을 불러와서 기존의 laser.gd스크립트를 제거

- 새로운 스크립트 laser_ship.gd 생성

- 속도를 -350으로 설정

<laser_ship.gd>

- "area_enter"이벤트 발생 시 "_on_area_enter"함수와 연결

- 접촉한 외부물체가 "enemy"이면 Armor를 -1 차감

- 플레어 생성

- 레이저 자체는 삭제됨(queue_free())

- 아직 enemy가 죽지 않음. laser_ship.tscn의 상위인 laser.tscn의 shape에 아무것도 지정되지 않음

- laser.tscn > shape에 RectangleShape2D 설정

<laser_enemy.gd>

- laser_enemy.tscn에서 기존의 스크립트 laser.gd 제거

- 새로운 스크립트 laser_enemy.gd 생성

- 기존의 laser_ship.gd의 내용을 복사해옴

- 충돌 감지 대상만 "enemy" -> "ship"으로 변경

- laser_enemy의 속도는 150으로 재설정

 

- 마지막으로 enemy.tscn에서

- enemy와 충돌했을 때에 ship의 armor를 -1 차감하고

- 충돌한 enemy는 사라지는 함수(_on_area_enter) 구현

반응형
반응형

<enemy_clever>

- Laser 씬을 상속하여 새로운 씬 생성

- New Inherited Scene... > laser.tscn 

- 노드 이름을 laser_enemy로 변경하고, laser_enemy.tscn으로 저장

- sprite에 enemy_laser.png 지정

- shape에 rectangleShape2D 지정 후 Edit

- Extents: (4.5, 7) 지정

- vis_notifier의 Rect값 지정(x:-4.5, y:-7, w:9, h:14)

- 속도 (0,150) 지정

- 아래방향으로 이동하는지 테스트

- 원점으로 복귀시켜 놓음

 

<enemy_clever>

- 상속으로 새로운 씬 생성 > enemy.tscn 선택

- 노드 이름을 enemy_clever로 변경

- 다른 이름으로 저장하기 > enemy_clever.tscn으로 저장

- sprite에 enemy_clever.png 지정

- shape에서 Make Unique 지정하여 다른 노드에 영향받지 않도록 함

- Position2D노드를 추가하여 cannon으로 이름 변경하고,

- Pos를 (0, 16) 지정

- 속도 50 지정

- 속도를 x:50, y:50 지정

- 기존의 스크립트 제거

- 새로운 스크립트 생성

- enemy_clever.gd

 

- spawner_enemy.gd 스크립트 수정

- enemy_kamikaze, enemy_clever를 미리 불러와 배열로 저장

- utils.choose함수로 랜덤하게 선택하여 생성

반응형
반응형

<플레어>

- Flare 씬 생성

- sprite 노드 생성 후 이름을 flare로 변경

- flare 첫번째 이미지를 지정해줌

- 애니메이션 노드 추가 후 이름을 anim으로 변경, fade_out 애니메이션 추가

- 0초에서 flare 스프라이트의 Opacity 1로 하여 키를 추가 (Modulate의 Opacity속성을 255)

- 0.1초에서 Opacity 0으로 하여 키를 추가 (Modulate의 Opacity속성을 0)

- length를 0.1초로 변경

- flare sprite노드에 스크립트 추가(flare.gd)

 

 

<flare.gd>

시그널 "finished"은 "animation_finished"로 변경

 

<레이저>

- Laser 씬 생성(enemy용, player용 공통), Area2D 노드를 추가 후 laser로 변경

- Sprite, CollisionShape2D, VisibilityNotifier2D 노드를 추가하고, 아래와 같이 이름을 변경해준다.

- 세부 설정은 추후 상속 노드에서 할 예정이므로 더이상의 설정은 진행하지 않는다.

- laser노드에 스크립트 추가

extends Area2D

export var velocity = Vector2()
const scn_flare = preload("res://scenes/flare.tscn")

func _ready():
	set_process(true)
	create_flare()
    
	yield(get_node("vis_notifier"), "screen_exited")
	queue_free()
	pass
    
func _process(delta):
	translate(velocity * delta)
	pass
    
func create_flare():
	var flare = scn_flare.instance()
	flare.set_global_position(get_global_position())
	utils.main_node.add_child(flare)
	pass

 

- 상속으로 Player의 laser씬 만들기

- laser_ship.tscn으로 저장

- sprite에는 laser_ship.png 지정

- shape에는 rectangle, extends (3,6)

- vis_notifier에는 Rect w:6, h:12, x:-3, y:-6 으로 설정

- y속도: 350으로 설정

- laser_ship노드를 화면 중앙에 놓고 잘 실행되는지 확인

- Debugger > Remote Inspector에 보면 해당 노드가 사라졌음을 확인할 수 있다.

- 확인 후 원점으로 되돌려놓는다.

 

<Ship에 레이저 발사 구현하기>

- ship 노드를 불러와서 하위에 Node2D (cannons로 변경) 추가

- cannons노드 하위에 position2D(left로 변경) 추가

- cannons > Node2D > Transform > Pos에 (-12, -8) 입력하여 위치 수정

- left를 복사하여 right노드로 변경

- Pos값을 (12, -8)로 변경

- ship.gd 수정

반응형
반응형

2 타입의 Enemy 생성

Area2D 노드를 추가하여 enemy로 변경

- colisionShape2D 추가 > RectangleShape2D > Extents (16,16) 설정

- enemy 스크립트 추가

- y 속도 100으로 설정

- 화면을 넘어가면 삭제되도록 수정

 

- 첫번째 enemy: enemy_kamikaze

- sprite에 enemy_kamikaze 이미지를 불러옴

- CollisionShape2D에서 Make Unique를 설정하고, 사이즈를 12,16으로 변경

- 속도를 350으로 설정

- enemy spawn

- 자주 사용하는 함수를 utils.gd로 묶어서 스크립트 수정

# script: utils

extends Node

var main_node setget , _get_main_node
var view_size setget , _get_view_size
var mouse_pos setget , _get_mouse_pos

func _ready():
	pass

func create_timer(wait_time):
	var timer = Timer.new()
	timer.set_wait_time(wait_time)
	timer.set_one_shot(true)
	timer.connect("timeout", timer, "queue_free")
	add_child(timer)
	timer.start()
	return timer
	pass

func choose(choises):
	randomize()
	var rand_index = randi() % choises.size()
	return choises[rand_index]
	pass

func find_node(node):
	return self.main_node.find_node(node)
	pass

func attach(src_node, src_signal, trg_node, trg_func):
	if typeof(src_node) == TYPE_STRING:
		src_node = find_node(src_node)
	
	if typeof(trg_node) == TYPE_STRING:
		trg_node = find_node(trg_node)
	
	if src_node != null and trg_node != null:
		src_node.connect(src_signal, trg_node, trg_func)
	pass

func remote_call(src_node, method, arg0 = null, arg1 = null):
	src_node = find_node(src_node)
	
	if src_node and src_node.has_method(method):
		if arg0 and arg1:
			return src_node.call(method, arg0, arg1)
		if arg0:
			return src_node.call(method, arg0)
		
		return src_node.call(method)
	pass

func _get_mouse_pos():
	return get_viewport().get_mouse_pos()
	pass

func _get_main_node():
	var root = get_tree().get_root()
	return root.get_child( root.get_child_count()-1 )
	pass

func _get_view_size():
	return get_tree().get_root().get_visible_rect().size
	pass

- Project Settings > Autoload에 utils.gd 추가

- 수정된 함수 (계속 랜덤시기에 생성하는 부분 추가 while, yield)

- world씬에 추가

반응형
반응형

마우스 따라가는 동작 스크립팅

 

(수정..'2024.01.09) godot 버전 상승으로 get_pos()함수는 사용되지 않습니다. 그 외의 변경사항은 아래와 같습니다.

- get_pos() -->  get_global_pos()

- set_pos() -->  set_position()

- view_size.width --> view_size.x

extends Area2D 

func _ready():
	set_process(true)
	pass # Replace with function body.

func _process(delta):	
	var motion = (get_global_mouse_position().x - get_global_position().x) * 0.2
	translate(Vector2(motion, 0))
	
	var view_size = get_viewport_rect().size
	var pos = get_global_position()
	pos.x = clamp(pos.x, 0+16, view_size.x-16)
	set_position(pos)	
	pass

 

흐르는 별 배경화면 만들기

- 빈 노드를 추가하여 stars로 이름 변경

- sprite노드 추가하여 star_far_0로 이름 변경

- 이미지를 불러오고 Centered on을 해제

- star_far_0에 star.gd스크립트 붙이기

- 배경 이미지의 속도를 50으로 설정

- 배경을 다시 복사하여 위치를 0,0으로

- 배경을 다시 복사하여 위치를 0,+180으로

- 지금까지 만든것을 빈 노드를 하나 더 추가하여 stars_far로 이름짓고, 그 하위노드로 옮긴다.

- 이걸 통째로 복사하여 stars_close를 만들고 stars_close이미지로 바꿔 넣는다.

- world 씬에 stars씬을 추가하고, 위치를 상단으로 조정하여 화면 뒤쪽에 보이도록 한다.

- star_close의 Z값을 10정도로 하여, 우주선보다 위에 보이도록 설정한다.

 

반응형
반응형

이런거 한번 만들어보겠습니다.

(https://www.youtube.com/watch?v=Z9W6dlP-RB8&list=PLv3l-oZCXaqkUEqrLsKJIAhAxK_Im6Qew)

 

1. Project Settings

반응형
반응형


1. HUD Scene 추가

HUD는 Head Up Display의 약자인데 게임의 요소와는 상관없는 UI 작성을 위한 부분입니다. Scene을 하나 추가한 뒤 CanvasLayer노드를 추가합니다. HUD에서 표시할 내용으로는 Score, "Game Over" 또는 "Get Ready!" 같은 문구, "Start" 버튼입니다. 즉 레이블과 버튼 요소가 필요합니다. 아래의 노드들을 CanvasLayer노드 하위에 자식노드로 추가해줍니다.

 

  • ScoreLabel (Label)
  • Message (Label)
  • StartButton (Button)
  • MessageTimer (Timer)

2. 폰트

폰트를 추가합니다. 경로는 인스펙터 창에서 Control > Theme Overrides > Fonts > 새 DynamicFont를 선택하고, 한번 더 클릭하여 Font > Font Data부분에 dodge_assets > font에 있는 "Xolonium-Regular.ttf"폰트를 넣어줍니다.(드래그 앤 드랍)

Font > Settings > Size는 64로 설정합니다.

 

font >Dyna....의 아래쪽 화살표를 누르면 여러 메뉴가 나오고, "복사" 메뉴가 나옵니다. 이걸 누르면 복사가 가능한데, 만들어두었던 Message 라벨로 가서 동일한 위치에서 "붙여넣기"를 해주면 지금 했던 설정을 복사해 넣게됩니다.




3. 레이아웃

우선 ScoreLabel을 설정해보겠습니다. 상단 오른쪽에 나타나는 레이아웃을 선택하고 '위쪽 넓게'를 클릭합니다. 그리고 인스펙터 창에서는 Text: 0, Align: Center, Valign: Center로 설정해줍니다.

다음으로 Message 라벨을 수정해줍니다.

그리고 StartButton은 "Start"라고 텍스트를 입력하고, 레이아웃은 "아래쪽 중앙", Font도 복하를 해줍니다.

그리고나서  Margin속성에 Top: -200, Button: -100을 입력합니다.


MessageTimer노드에서 Wait Time을 2초로 설정해주고, One Shot속성을 "On"으로 합니다.

 

4. HUD.gd 스크립팅

start_game 시그널은 버튼이 눌렸을 때 Main노드에게 알려주는 시그널로 쓰일 예정입니다.

extends CanvasLayer

signal start_game


전달되는 메시지를 표시하기위한 함수를 작성합니다.

func show_message(text):
    $Message.text = text
    $Message.show()
    $MessageTimer.start()


Player가 충돌하여 죽었을 때 텍스트를 보여주는 함수를 아래와 같이 작성합니다.

func show_game_over():
    show_message("Game Over")
    # Wait until the MessageTimer has counted down.
    yield($MessageTimer, "timeout")

    $Message.text = "Dodge the\nCreeps!"
    $Message.show()
    # Make a one-shot timer and wait for it to finish.
    yield(get_tree().create_timer(1), "timeout")
    $StartButton.show()


그리고 시간이 변할때마다 Main 씬에의해 아래의 코드가 지속적으로 호출되어 점수(시간)을 증가시킵니다.

func update_score(score):
    $ScoreLabel.text = str(score)


그리고 MessageTimer의 timeout()시그널과, StartButton버튼의 pressed()시그널에 함수를 연결하겠습니다. 함수는 아래와 같이 작성해줍니다.

func _on_StartButton_pressed():
    $StartButton.hide()
    emit_signal("start_game")

func _on_MessageTimer_timeout():
    $Message.hide()


5. HUD를 Main에 연결

Main 씬에서 HUD를 불러와 연결하도록 하겠습니다.

Main 씬에서 HUD 씬(노드)를 선택하고, 노드탭으로 가면 연결할 수 있는 HUD의 시그널들이 나타납니다. 여기서 start_game시그널을 연결할 함수로 new_game()이라고 이름짓고 아래의 코드를 추가해줍니다.

$HUD.update_score(score)
$HUD.show_message("Get Ready")


game_over() 함수가 실행될 때 HUD에 표시되는 메시지를 실행하도록 아래 라인을 추가해줍니다.

$HUD.show_game_over()


_on_ScoreTimer_timeout() 함수에 아래 코드를 추가하여 점수 변경시 업데이트되도록 합니다.

$HUD.update_score(score)



6. 오래된 크리프 제거

아직은 Player가 죽고나서 다시 시작할 때 Mob들이 살아있습니다. 그래서 시작버튼을 누르면 전부 사라지도록 수정할 필요가 있습니다.

 

Mob 씬에서 루트노드를 선택하고 노드탭 > Groups탭 으로 갑니다. 그리고 이름을 "mobs"라고하여 Add버튼을 눌러 Mob들의 그룹을 지정합니다. 그리고는 game_over()함수에 아래의 코드를 추가합니다. 해당 그룹에 있는 객체들을 한번에 제거하는 명령입니다.

get_tree().call_group("mobs", "queue_free")

7. 마무리

Background

Main노드 최상단 자식노드로 ColorRect 노드를 추가한다. "Layout" -> "Full Rect" 으로 전체 화면 커버가 가능하다.TextureRect노드를 사용하면 이미지를 불러올 수도 있다.

Sound effects

Main신의 하위로 AudioStreamPlayer노드를 추가하고 이름을 Music이라고 변경합니다. 하나더 추가하여 DeathSound라고 이름을 변경합니다. Stream속성의 Load를 클릭하여 해당되는 오디오 파일을 지정해줍니다.
 
new_game()함수 아래 아래 코드를 추가합니다.
$Music.play()

game_over() 함수 아래 아래코드를 추가합니다.

$Music.stop()
$DeathSound.play()

Keyboard shortcut

HUD씬에서 StartButton을 클릭하고 Shortcut속성을 찾아서 "New Shortcut" > "Shortcut"을 클릭하면 두번째 속성이 나타납니다. "New InputEventAction">"InputEventAction"을 입력하면 Action속성이 나타나는데, ui_select라고 타이핑 입력합니다. 이게 스페이스바와 연동되는 지시어라고 합니다.

 

- 끝 -

 
반응형

+ Recent posts