Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
L
ldefense
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Packages
Packages
Container Registry
Analytics
CI / CD Analytics
Repository Analytics
Value Stream Analytics
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Gavin An
ldefense
Commits
b553c088
Commit
b553c088
authored
Jul 20, 2026
by
Gavin An
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
유닛 생성 대기 시, 팔기 버튼 활성화
parent
45c18ca1
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
95 additions
and
8 deletions
+95
-8
src/ui/hud.gd
src/ui/hud.gd
+3
-3
src/ui/unit_placement/hud_unit_placement.gd
src/ui/unit_placement/hud_unit_placement.gd
+92
-5
No files found.
src/ui/hud.gd
View file @
b553c088
...
...
@@ -45,9 +45,9 @@ func _ready() -> void:
_create_runtime_bottom_buttons
()
_on_gold_changed
(
GameManager
.
player_gold
)
##
마우스/터치 입력 중 유닛 배치 확정에 해당하는 입력을
HudUnitPlacement에 위임합니다.
##
배치 입력이 처리된 경우 viewport에 handled를 표시해 같은 클릭이 다른 게임 입력으로 중복 전달되지 않게
합니다.
func
_input
(
event
:
InputEvent
)
->
void
:
##
GUI가 처리하지 않은 마우스/터치 입력만
HudUnitPlacement에 위임합니다.
##
팔기 버튼 같은 HUD 컨트롤이 먼저 클릭을 소비해야 하므로 _input이 아닌 _unhandled_input에서 타일 배치를 처리
합니다.
func
_
unhandled_
input
(
event
:
InputEvent
)
->
void
:
if
_unit_placement
and
_unit_placement
.
has_method
(
"handle_input"
):
var
handled
:
bool
=
_unit_placement
.
call
(
"handle_input"
,
event
)
if
handled
:
...
...
src/ui/unit_placement/hud_unit_placement.gd
View file @
b553c088
...
...
@@ -16,6 +16,7 @@ const OVERLAY_POOL_WARMUP_BATCH_SIZE: int = 16
var
_hud
:
Control
=
null
var
_unit_spawn_button
:
Button
=
null
var
_bottom_bar
:
Control
=
null
var
_base_unit_scene
:
PackedScene
=
null
var
_spawn_button_default_text
:
String
=
""
...
...
@@ -38,12 +39,15 @@ var _pending_preview_cooldown_label: Label = null
var
_pending_preview_range_label
:
Label
=
null
var
_pending_preview_cost_label
:
Label
=
null
var
_pending_preview_color_swatch
:
ColorRect
=
null
var
_pending_sell_button
:
Button
=
null
var
_bottom_bar_visibility_before_pending
:
Dictionary
=
{}
## HUD에서 필요한 참조를 주입받습니다.
## RefCounted는 씬 트리에 직접 붙지 않으므로, viewport/tree 접근은 HUD 노드를 통해 수행합니다.
func
setup
(
hud
:
Control
,
unit_spawn_button
:
Button
,
base_unit_scene
:
PackedScene
)
->
void
:
_hud
=
hud
_unit_spawn_button
=
unit_spawn_button
_bottom_bar
=
_unit_spawn_button
.
get_parent
()
as
Control
_base_unit_scene
=
base_unit_scene
_spawn_button_default_text
=
_unit_spawn_button
.
text
...
...
@@ -90,7 +94,7 @@ func handle_input(event: InputEvent) -> bool:
return
false
## 현재 보유한 유닛 템플릿 중 하나를 무작위로 골라 타일 선택 대기 상태로 전환합니다.
##
실제 골드 차감은 타일 배치가 확정되는 순간 처리하여, 잘못 누른 소환 버튼이 즉시 비용을 쓰지 않게
합니다.
##
pending 상태에서 팔기 환불이 가능해야 하므로, 유닛 생성 버튼을 누르는 순간 소환 비용을 먼저 지불
합니다.
func
begin_random_unit_placement
()
->
void
:
if
GameManager
.
is_game_over
or
has_pending_unit_placement
():
return
...
...
@@ -104,6 +108,9 @@ func begin_random_unit_placement() -> void:
var
random_index
:
int
=
randi
()
%
DataManager
.
unit_templates
.
size
()
var
chosen_template
:
UnitData
=
DataManager
.
unit_templates
[
random_index
]
var
target_scene
:
PackedScene
=
_get_scene_for_unit
(
chosen_template
)
if
not
GameManager
.
spend_gold
(
GameManager
.
unit_spawn_cost
):
return
_begin_unit_placement
(
target_scene
,
chosen_template
,
GameManager
.
unit_spawn_cost
)
## 유닛 ID에 대응하는 전용 씬을 반환합니다.
...
...
@@ -128,6 +135,7 @@ func _begin_unit_placement(unit_scene: PackedScene, unit_data: UnitData, spawn_c
_pending_spawn_cost
=
spawn_cost
_unit_spawn_button
.
text
=
"Select Tile"
_show_pending_unit_preview
(
unit_data
,
spawn_cost
)
_enter_pending_bottom_bar_mode
()
_show_placement_tile_overlays
()
## 배치 대기 상태와 타일 오버레이를 함께 정리합니다.
...
...
@@ -138,6 +146,7 @@ func clear_pending_unit_placement() -> void:
_pending_spawn_cost
=
0
_unit_spawn_button
.
text
=
_spawn_button_default_text
_hide_pending_unit_preview
()
_restore_bottom_bar_from_pending_mode
()
_clear_placement_tile_overlays
()
## 화면 좌표에서 타일을 찾고, 점유/골드 조건을 검증한 뒤 유닛을 실제 전장에 배치합니다.
...
...
@@ -150,10 +159,6 @@ func _try_place_pending_unit(screen_pos: Vector2) -> void:
if
_is_tile_occupied
(
tile_cell
):
return
if
not
GameManager
.
spend_gold
(
_pending_spawn_cost
):
clear_pending_unit_placement
()
return
var
new_unit
:
Node
=
_pending_unit_scene
.
instantiate
()
var
parent_scene
:
Node
=
_hud
.
get_tree
()
.
current_scene
var
tile_center
:
Vector3
=
tile_info
[
"center"
]
...
...
@@ -168,6 +173,88 @@ func _try_place_pending_unit(screen_pos: Vector2) -> void:
clear_pending_unit_placement
()
## pending 상태에 진입하면 BottomBar의 기존 UI를 모두 숨기고 팔기 버튼만 표시합니다.
## 기존 버튼들의 visible 상태는 Dictionary에 저장해 배치 완료/판매 후 원래 상태로 복구합니다.
func
_enter_pending_bottom_bar_mode
()
->
void
:
if
not
_bottom_bar
:
return
_ensure_pending_sell_button
()
_bottom_bar_visibility_before_pending
.
clear
()
for
child
:
Node
in
_bottom_bar
.
get_children
():
if
child
is
Control
:
var
control_child
:
Control
=
child
as
Control
_bottom_bar_visibility_before_pending
[
control_child
]
=
control_child
.
visible
control_child
.
visible
=
control_child
==
_pending_sell_button
var
refund_amount
:
int
=
_get_pending_sell_refund_amount
()
_pending_sell_button
.
text
=
"팔기 (+
%d
G)"
%
refund_amount
_pending_sell_button
.
visible
=
true
_pending_sell_button
.
disabled
=
false
## pending 상태가 끝나면 BottomBar 자식들의 visible 상태를 pending 진입 전으로 되돌립니다.
## 팔기 버튼은 재사용을 위해 삭제하지 않고 숨겨 둡니다.
func
_restore_bottom_bar_from_pending_mode
()
->
void
:
if
not
_bottom_bar
:
return
for
child
:
Node
in
_bottom_bar
.
get_children
():
if
child
is
Control
:
var
control_child
:
Control
=
child
as
Control
if
control_child
==
_pending_sell_button
:
control_child
.
visible
=
false
else
:
control_child
.
visible
=
_bottom_bar_visibility_before_pending
.
get
(
control_child
,
true
)
_bottom_bar_visibility_before_pending
.
clear
()
## pending 전용 팔기 버튼을 최초 1회 생성합니다.
## hud.tscn의 BottomBar 원본을 직접 수정하지 않고, 런타임에 추가해 필요할 때만 보여줍니다.
func
_ensure_pending_sell_button
()
->
void
:
if
_pending_sell_button
and
is_instance_valid
(
_pending_sell_button
):
return
_pending_sell_button
=
Button
.
new
()
_pending_sell_button
.
name
=
"SellPendingUnitButton"
_pending_sell_button
.
text
=
"팔기"
_pending_sell_button
.
custom_minimum_size
=
Vector2
(
150
,
46
)
_pending_sell_button
.
mouse_filter
=
Control
.
MOUSE_FILTER_STOP
_pending_sell_button
.
add_theme_font_size_override
(
"font_size"
,
18
)
_pending_sell_button
.
add_theme_stylebox_override
(
"normal"
,
_create_pending_sell_button_style
())
_pending_sell_button
.
pressed
.
connect
(
_on_sell_pending_unit_pressed
)
_bottom_bar
.
add_child
(
_pending_sell_button
)
## pending 유닛을 판매하고 소환 비용의 50%만 환불합니다.
## 생성 시 이미 전체 비용을 지불했으므로, 여기서는 절반만 add_gold()로 돌려준 뒤 pending 상태를 정리합니다.
func
_on_sell_pending_unit_pressed
()
->
void
:
if
not
has_pending_unit_placement
():
return
var
refund_amount
:
int
=
_get_pending_sell_refund_amount
()
if
refund_amount
>
0
:
GameManager
.
add_gold
(
refund_amount
)
clear_pending_unit_placement
()
## 현재 pending 유닛을 팔 때 돌려받을 골드를 계산합니다.
## 비용이 홀수일 경우 소수점은 버려 과지급이 발생하지 않게 합니다.
func
_get_pending_sell_refund_amount
()
->
int
:
return
int
(
float
(
_pending_spawn_cost
)
*
0.5
)
## 팔기 버튼 스타일을 생성합니다.
## pending 중 BottomBar에 버튼 하나만 남기 때문에, 위험/취소 계열 액션임을 붉은 색감으로 구분합니다.
func
_create_pending_sell_button_style
()
->
StyleBoxFlat
:
var
style
:
StyleBoxFlat
=
StyleBoxFlat
.
new
()
style
.
bg_color
=
Color
(
0.55
,
0.08
,
0.08
,
0.95
)
style
.
border_color
=
Color
(
1.0
,
0.35
,
0.25
,
0.9
)
style
.
border_width_left
=
1
style
.
border_width_top
=
1
style
.
border_width_right
=
1
style
.
border_width_bottom
=
1
style
.
set_corner_radius_all
(
4
)
return
style
## 화면 좌표에 대응하는 GridMap 셀과 배치 중심 좌표를 계산합니다.
## 카메라에서 월드로 레이를 쏜 뒤, 맞은 지점 주변에서 실제 타일 셀을 찾습니다.
func
_get_tile_info_from_screen
(
screen_pos
:
Vector2
)
->
Dictionary
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment