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
98017115
Commit
98017115
authored
Jun 17, 2026
by
Gavin An
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
공격 방식 - 범위 내 들어오면 자동으로 공격하도록 변경
parent
68ca2daf
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
54 additions
and
18 deletions
+54
-18
.idea/libraries/GdSdk.xml
.idea/libraries/GdSdk.xml
+9
-0
.idea/vcs.xml
.idea/vcs.xml
+6
-0
docs/agents_docs/game_design.md
docs/agents_docs/game_design.md
+1
-1
docs/agents_docs/todo.md
docs/agents_docs/todo.md
+3
-1
src/autoload/game_manager.gd
src/autoload/game_manager.gd
+1
-1
src/core/unit_controller.gd
src/core/unit_controller.gd
+18
-9
src/entities/monsters/base_monster.gd
src/entities/monsters/base_monster.gd
+2
-0
src/entities/units/base_unit.gd
src/entities/units/base_unit.gd
+13
-6
src/ui/hud.tscn
src/ui/hud.tscn
+1
-0
No files found.
.idea/libraries/GdSdk.xml
0 → 100644
View file @
98017115
<component
name=
"libraryTable"
>
<library
name=
"GdSdk"
type=
"GdScript"
>
<CLASSES
/>
<JAVADOC
/>
<SOURCES>
<root
url=
"file://$APPLICATION_PLUGINS_DIR$/GdScript/extracted/Master"
/>
</SOURCES>
</library>
</component>
\ No newline at end of file
.idea/vcs.xml
0 → 100644
View file @
98017115
<?xml version="1.0" encoding="UTF-8"?>
<project
version=
"4"
>
<component
name=
"VcsDirectoryMappings"
>
<mapping
directory=
"$PROJECT_DIR$"
vcs=
"Git"
/>
</component>
</project>
\ No newline at end of file
docs/agents_docs/game_design.md
View file @
98017115
...
@@ -68,4 +68,4 @@
...
@@ -68,4 +68,4 @@
-
**RTS식 유닛 컨트롤:**
-
**RTS식 유닛 컨트롤:**
-
**선택:**
마우스 왼쪽 버튼 클릭으로 단일 유닛 선택, 또는 드래그(Box Selection)로 여러 유닛을 동시에 선택할 수 있습니다.
-
**선택:**
마우스 왼쪽 버튼 클릭으로 단일 유닛 선택, 또는 드래그(Box Selection)로 여러 유닛을 동시에 선택할 수 있습니다.
-
**이동:**
유닛을 선택한 상태에서 맵의 바닥을 마우스 오른쪽 버튼으로 클릭하면 해당 위치로 이동합니다.
-
**이동:**
유닛을 선택한 상태에서 맵의 바닥을 마우스 오른쪽 버튼으로 클릭하면 해당 위치로 이동합니다.
-
**공격:**
유닛을 선택한 상태에서 무한 루프 경로를 돌고 있는 몬스터를 마우스 오른쪽 버튼으로 클릭하면, 해당 몬스터를 추격하며 사거리 내에 들어올 시 자동으로 공격을 시작합니다.
-
**공격:**
유닛을 선택한 상태에서 무한 루프 경로를 돌고 있는 몬스터 근처로 가면, 해당 몬스터를 추격하며 공격 사거리 내에 들어올 시 자동으로 공격을 시작합니다.
\ No newline at end of file
\ No newline at end of file
docs/agents_docs/todo.md
View file @
98017115
...
@@ -6,10 +6,12 @@
...
@@ -6,10 +6,12 @@
-
[
]
프로젝트 기본 폴더 구조 생성 (
`src/core`
,
`src/autoload`
,
`src/entities`
,
`src/ui`
,
`src/utils`
등)
-
[
]
프로젝트 기본 폴더 구조 생성 (
`src/core`
,
`src/autoload`
,
`src/entities`
,
`src/ui`
,
`src/utils`
등)
-
[
]
메인 게임 씬 (
`src/core/main.tscn`
) 생성
-
[
]
메인 게임 씬 (
`src/core/main.tscn`
) 생성
-
[
]
3D 기본 지형 구축 (지상 바닥 및 조명, 환경 설정)
-
[
]
3D 기본 지형 구축 (지상 바닥 및 조명, 환경 설정)
-
맵은 해상도에 맞게 최대로 만들어짐
-
[
]
몬스터 이동 경로 (
`Path3D`
) 배치 (맵 가장자리를 도는 루프 형태)
-
[
]
몬스터 이동 경로 (
`Path3D`
) 배치 (맵 가장자리를 도는 루프 형태)
-
[
]
RTS 스타일 3D 카메라 구현 (
`src/core/rts_camera.gd`
)
-
[
]
RTS 스타일 3D 카메라 구현 (
`src/core/rts_camera.gd`
)
-
WASD / 방향키를 통한 화면 이동
-
마우스 휠을 통한 줌인/줌아웃
-
마우스 휠을 통한 줌인/줌아웃
-
맵이 줌인 되었을 때 WASD / 방향키를 통한 화면 이동
-
맵이 최대로 줌 아웃 되었을 때는 화면 이동 없음
-
화면 가장자리에 마우스 위치 시 카메라 스크롤 (선택 사항)
-
화면 가장자리에 마우스 위치 시 카메라 스크롤 (선택 사항)
## [ ] 2단계: 글로벌 게임 매니저와 스테이지 시스템
## [ ] 2단계: 글로벌 게임 매니저와 스테이지 시스템
...
...
src/autoload/game_manager.gd
View file @
98017115
...
@@ -10,7 +10,7 @@ signal game_lost
...
@@ -10,7 +10,7 @@ signal game_lost
signal
game_victory
signal
game_victory
# 글로벌 플레이어 상태 변수 (정적 타이핑 적용)
# 글로벌 플레이어 상태 변수 (정적 타이핑 적용)
var
player_gold
:
int
=
300
:
var
player_gold
:
int
=
300
00
:
set
(
value
):
set
(
value
):
player_gold
=
value
player_gold
=
value
gold_changed
.
emit
(
player_gold
)
gold_changed
.
emit
(
player_gold
)
...
...
src/core/unit_controller.gd
View file @
98017115
...
@@ -20,7 +20,7 @@ func _ready() -> void:
...
@@ -20,7 +20,7 @@ func _ready() -> void:
# 화면 전체를 덮도록 설정
# 화면 전체를 덮도록 설정
anchor_right
=
1.0
anchor_right
=
1.0
anchor_bottom
=
1.0
anchor_bottom
=
1.0
mouse_filter
=
MOUSE_FILTER_
PASS
# 마우스 입력을 통과시켜 카메라 등으로 전달 가능하게 함
mouse_filter
=
MOUSE_FILTER_
IGNORE
# UI가 아닌 unhandled input으로 동작하게 통과 처리
# 런타임에 NavigationRegion3D를 찾아 맵을 베이크시킴 (4.2 구현 보완)
# 런타임에 NavigationRegion3D를 찾아 맵을 베이크시킴 (4.2 구현 보완)
var
nav_region
:
NavigationRegion3D
=
get_node_or_null
(
"../NavigationRegion3D"
)
as
NavigationRegion3D
var
nav_region
:
NavigationRegion3D
=
get_node_or_null
(
"../NavigationRegion3D"
)
as
NavigationRegion3D
...
@@ -28,7 +28,7 @@ func _ready() -> void:
...
@@ -28,7 +28,7 @@ func _ready() -> void:
nav_region
.
bake_navigation_mesh
()
nav_region
.
bake_navigation_mesh
()
print
(
"UnitController: Navigation mesh baked successfully on start."
)
print
(
"UnitController: Navigation mesh baked successfully on start."
)
func
_
gui
_input
(
event
:
InputEvent
)
->
void
:
func
_
unhandled
_input
(
event
:
InputEvent
)
->
void
:
if
GameManager
.
is_game_over
:
if
GameManager
.
is_game_over
:
return
return
...
@@ -110,7 +110,6 @@ func _perform_selection(start: Vector2, end: Vector2) -> void:
...
@@ -110,7 +110,6 @@ func _perform_selection(start: Vector2, end: Vector2) -> void:
selected_units
.
append
(
unit
)
selected_units
.
append
(
unit
)
if
unit
.
has_method
(
"select"
):
if
unit
.
has_method
(
"select"
):
unit
.
call
(
"select"
)
unit
.
call
(
"select"
)
print
(
"UnitController: Selected "
,
selected_units
.
size
(),
" units via drag."
)
print
(
"UnitController: Selected "
,
selected_units
.
size
(),
" units via drag."
)
## 우클릭 액션 (이동 목적지 지정 또는 적 공격 타겟팅)
## 우클릭 액션 (이동 목적지 지정 또는 적 공격 타겟팅)
...
@@ -178,14 +177,18 @@ func _raycast_from_mouse(mouse_pos: Vector2) -> Dictionary:
...
@@ -178,14 +177,18 @@ func _raycast_from_mouse(mouse_pos: Vector2) -> Dictionary:
func
_get_unit_node
(
collider
:
Node
)
->
Node
:
func
_get_unit_node
(
collider
:
Node
)
->
Node
:
if
not
collider
:
if
not
collider
:
return
null
return
null
# 유닛의 충돌체(Area3D)가 자식일 경우 부모 노드를 추적
if
collider
is
BaseUnit
:
if
collider
.
is_in_group
(
"units"
):
return
collider
return
collider
var
parent
:
Node
=
collider
.
get_parent
()
var
parent
:
Node
=
collider
.
get_parent
()
if
parent
and
parent
.
is_in_group
(
"units"
)
:
if
parent
and
parent
is
BaseUnit
:
return
parent
return
parent
# 한 단계 더 위를 체크 (CharacterBody3D의 CollisionShape 구조 등)
var
grandparent
:
Node
=
parent
.
get_parent
()
if
parent
else
null
var
grandparent
:
Node
=
parent
.
get_parent
()
if
parent
else
null
if
grandparent
and
grandparent
is
BaseUnit
:
return
grandparent
if
collider
.
is_in_group
(
"units"
):
return
collider
if
parent
and
parent
.
is_in_group
(
"units"
):
return
parent
if
grandparent
and
grandparent
.
is_in_group
(
"units"
):
if
grandparent
and
grandparent
.
is_in_group
(
"units"
):
return
grandparent
return
grandparent
return
null
return
null
...
@@ -194,12 +197,18 @@ func _get_unit_node(collider: Node) -> Node:
...
@@ -194,12 +197,18 @@ func _get_unit_node(collider: Node) -> Node:
func
_get_monster_node
(
collider
:
Node
)
->
Node
:
func
_get_monster_node
(
collider
:
Node
)
->
Node
:
if
not
collider
:
if
not
collider
:
return
null
return
null
if
collider
.
is_in_group
(
"monsters"
)
:
if
collider
is
BaseMonster
:
return
collider
return
collider
var
parent
:
Node
=
collider
.
get_parent
()
var
parent
:
Node
=
collider
.
get_parent
()
if
parent
and
parent
.
is_in_group
(
"monsters"
)
:
if
parent
and
parent
is
BaseMonster
:
return
parent
return
parent
var
grandparent
:
Node
=
parent
.
get_parent
()
if
parent
else
null
var
grandparent
:
Node
=
parent
.
get_parent
()
if
parent
else
null
if
grandparent
and
grandparent
is
BaseMonster
:
return
grandparent
if
collider
.
is_in_group
(
"monsters"
):
return
collider
if
parent
and
parent
.
is_in_group
(
"monsters"
):
return
parent
if
grandparent
and
grandparent
.
is_in_group
(
"monsters"
):
if
grandparent
and
grandparent
.
is_in_group
(
"monsters"
):
return
grandparent
return
grandparent
return
null
return
null
src/entities/monsters/base_monster.gd
View file @
98017115
...
@@ -12,6 +12,8 @@ var gold_reward: int = 15
...
@@ -12,6 +12,8 @@ var gold_reward: int = 15
var
is_dead
:
bool
=
false
var
is_dead
:
bool
=
false
func
_ready
()
->
void
:
func
_ready
()
->
void
:
# 몬스터 그룹 등록
add_to_group
(
"monsters"
)
# PathFollow3D 루프 설정 활성화 (경로 끝 도달 시 처음으로 돌아감)
# PathFollow3D 루프 설정 활성화 (경로 끝 도달 시 처음으로 돌아감)
loop
=
true
loop
=
true
...
...
src/entities/units/base_unit.gd
View file @
98017115
...
@@ -11,8 +11,10 @@ var is_selected: bool = false
...
@@ -11,8 +11,10 @@ var is_selected: bool = false
var
_target_monster
:
Node3D
=
null
var
_target_monster
:
Node3D
=
null
var
_attack_timer
:
float
=
0.0
var
_attack_timer
:
float
=
0.0
# 자동 탐색 범위
# 자동 탐색 범위 (맵 가장자리를 회전하는 적들을 스폰존에서 인식 가능하도록 30.0m로 확대)
@
export
var
detection_range
:
float
=
16.0
@
export
var
detection_range
:
float
=
30.0
var
_auto_target_cooldown
:
float
=
0.0
# 노드 캐싱
# 노드 캐싱
@
onready
var
_nav_agent
:
NavigationAgent3D
=
$
NavigationAgent3D
@
onready
var
_nav_agent
:
NavigationAgent3D
=
$
NavigationAgent3D
...
@@ -39,15 +41,21 @@ func _physics_process(delta: float) -> void:
...
@@ -39,15 +41,21 @@ func _physics_process(delta: float) -> void:
velocity
=
Vector3
.
ZERO
velocity
=
Vector3
.
ZERO
return
return
# 공격 타이머 차감
# 공격 타이머
및 자동 타겟팅 쿨타임
차감
if
_attack_timer
>
0.0
:
if
_attack_timer
>
0.0
:
_attack_timer
-=
delta
_attack_timer
-=
delta
if
_auto_target_cooldown
>
0.0
:
_auto_target_cooldown
-=
delta
# 1. 공격 대상이 유효한지 검증 (사망했거나 삭제되었는지 체크)
# 1. 공격 대상이 유효한지 검증 (사망했거나 삭제되었는지 체크)
if
_target_monster
and
(
not
is_instance_valid
(
_target_monster
)
or
_target_monster
.
get
(
"is_dead"
)):
if
_target_monster
and
(
not
is_instance_valid
(
_target_monster
)
or
_target_monster
.
get
(
"is_dead"
)):
_target_monster
=
null
_target_monster
=
null
# 2. 상태에 따른 AI 동작 분기
# 2. 적 자동 탐색 (타겟이 없고 수동 강제 이동 방지 쿨다운이 완료된 경우)
if
not
_target_monster
and
_auto_target_cooldown
<=
0.0
:
_find_nearest_target
()
# 3. 상태에 따른 AI 동작 분기
if
_target_monster
:
if
_target_monster
:
_process_attack_logic
(
delta
)
_process_attack_logic
(
delta
)
else
:
else
:
...
@@ -78,8 +86,6 @@ func _process_normal_logic(_delta: float) -> void:
...
@@ -78,8 +86,6 @@ func _process_normal_logic(_delta: float) -> void:
_navigate_to_target
(
_delta
)
_navigate_to_target
(
_delta
)
else
:
else
:
velocity
=
Vector3
.
ZERO
velocity
=
Vector3
.
ZERO
# 정지 상태에서 주변 몬스터 탐지
_find_nearest_target
()
## 네비게이션 타겟 방향으로 캐릭터 이동
## 네비게이션 타겟 방향으로 캐릭터 이동
func
_navigate_to_target
(
_delta
:
float
)
->
void
:
func
_navigate_to_target
(
_delta
:
float
)
->
void
:
...
@@ -152,6 +158,7 @@ func _show_attack_visual() -> void:
...
@@ -152,6 +158,7 @@ func _show_attack_visual() -> void:
## 외부에서 호출하는 수동 이동 명령
## 외부에서 호출하는 수동 이동 명령
func
move_to
(
target_pos
:
Vector3
)
->
void
:
func
move_to
(
target_pos
:
Vector3
)
->
void
:
_target_monster
=
null
# 이동 명령 시 강제 공격 해제
_target_monster
=
null
# 이동 명령 시 강제 공격 해제
_auto_target_cooldown
=
0.5
# 수동 강제 이동 시 0.5초 동안 자동 공격 타겟 지정을 비활성화하여 피신을 허용
_nav_agent
.
target_position
=
target_pos
_nav_agent
.
target_position
=
target_pos
## 외부에서 호출하는 특정 몬스터 강제 공격 지정
## 외부에서 호출하는 특정 몬스터 강제 공격 지정
...
...
src/ui/hud.tscn
View file @
98017115
...
@@ -9,6 +9,7 @@ anchor_right = 1.0
...
@@ -9,6 +9,7 @@ anchor_right = 1.0
anchor_bottom = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_horizontal = 2
grow_vertical = 2
grow_vertical = 2
mouse_filter = 2
script = ExtResource("1_hud")
script = ExtResource("1_hud")
[node name="TopBar" type="HBoxContainer" parent="."]
[node name="TopBar" type="HBoxContainer" parent="."]
...
...
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