omgkit 2.12.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -12
- package/package.json +2 -2
- package/plugin/agents/api-designer.md +5 -0
- package/plugin/agents/architect.md +8 -0
- package/plugin/agents/brainstormer.md +4 -0
- package/plugin/agents/cicd-manager.md +6 -0
- package/plugin/agents/code-reviewer.md +6 -0
- package/plugin/agents/copywriter.md +2 -0
- package/plugin/agents/data-engineer.md +255 -0
- package/plugin/agents/database-admin.md +10 -0
- package/plugin/agents/debugger.md +10 -0
- package/plugin/agents/devsecops.md +314 -0
- package/plugin/agents/docs-manager.md +4 -0
- package/plugin/agents/domain-decomposer.md +181 -0
- package/plugin/agents/embedded-systems.md +397 -0
- package/plugin/agents/fullstack-developer.md +12 -0
- package/plugin/agents/game-systems-designer.md +375 -0
- package/plugin/agents/git-manager.md +10 -0
- package/plugin/agents/journal-writer.md +2 -0
- package/plugin/agents/ml-engineer.md +284 -0
- package/plugin/agents/observability-engineer.md +353 -0
- package/plugin/agents/oracle.md +9 -0
- package/plugin/agents/performance-engineer.md +290 -0
- package/plugin/agents/pipeline-architect.md +6 -0
- package/plugin/agents/planner.md +12 -0
- package/plugin/agents/platform-engineer.md +325 -0
- package/plugin/agents/project-manager.md +3 -0
- package/plugin/agents/researcher.md +5 -0
- package/plugin/agents/scientific-computing.md +426 -0
- package/plugin/agents/scout.md +3 -0
- package/plugin/agents/security-auditor.md +7 -0
- package/plugin/agents/sprint-master.md +17 -0
- package/plugin/agents/tester.md +10 -0
- package/plugin/agents/ui-ux-designer.md +12 -0
- package/plugin/agents/vulnerability-scanner.md +6 -0
- package/plugin/commands/data/pipeline.md +47 -0
- package/plugin/commands/data/quality.md +49 -0
- package/plugin/commands/domain/analyze.md +34 -0
- package/plugin/commands/domain/map.md +41 -0
- package/plugin/commands/game/balance.md +56 -0
- package/plugin/commands/game/optimize.md +62 -0
- package/plugin/commands/iot/provision.md +58 -0
- package/plugin/commands/ml/evaluate.md +47 -0
- package/plugin/commands/ml/train.md +48 -0
- package/plugin/commands/perf/benchmark.md +54 -0
- package/plugin/commands/perf/profile.md +49 -0
- package/plugin/commands/platform/blueprint.md +56 -0
- package/plugin/commands/security/audit.md +54 -0
- package/plugin/commands/security/scan.md +55 -0
- package/plugin/commands/sre/dashboard.md +53 -0
- package/plugin/registry.yaml +711 -0
- package/plugin/skills/ai-ml/experiment-tracking/SKILL.md +338 -0
- package/plugin/skills/ai-ml/feature-stores/SKILL.md +340 -0
- package/plugin/skills/ai-ml/llm-ops/SKILL.md +454 -0
- package/plugin/skills/ai-ml/ml-pipelines/SKILL.md +390 -0
- package/plugin/skills/ai-ml/model-monitoring/SKILL.md +398 -0
- package/plugin/skills/ai-ml/model-serving/SKILL.md +386 -0
- package/plugin/skills/event-driven/cqrs-patterns/SKILL.md +348 -0
- package/plugin/skills/event-driven/event-sourcing/SKILL.md +334 -0
- package/plugin/skills/event-driven/kafka-deep/SKILL.md +252 -0
- package/plugin/skills/event-driven/saga-orchestration/SKILL.md +335 -0
- package/plugin/skills/event-driven/schema-registry/SKILL.md +328 -0
- package/plugin/skills/event-driven/stream-processing/SKILL.md +313 -0
- package/plugin/skills/game/game-audio/SKILL.md +446 -0
- package/plugin/skills/game/game-networking/SKILL.md +490 -0
- package/plugin/skills/game/godot-patterns/SKILL.md +413 -0
- package/plugin/skills/game/shader-programming/SKILL.md +492 -0
- package/plugin/skills/game/unity-patterns/SKILL.md +488 -0
- package/plugin/skills/iot/device-provisioning/SKILL.md +405 -0
- package/plugin/skills/iot/edge-computing/SKILL.md +369 -0
- package/plugin/skills/iot/industrial-protocols/SKILL.md +438 -0
- package/plugin/skills/iot/mqtt-deep/SKILL.md +418 -0
- package/plugin/skills/iot/ota-updates/SKILL.md +426 -0
- package/plugin/skills/microservices/api-gateway-patterns/SKILL.md +201 -0
- package/plugin/skills/microservices/circuit-breaker-patterns/SKILL.md +246 -0
- package/plugin/skills/microservices/contract-testing/SKILL.md +284 -0
- package/plugin/skills/microservices/distributed-tracing/SKILL.md +246 -0
- package/plugin/skills/microservices/service-discovery/SKILL.md +304 -0
- package/plugin/skills/microservices/service-mesh/SKILL.md +181 -0
- package/plugin/skills/mobile-advanced/mobile-ci-cd/SKILL.md +407 -0
- package/plugin/skills/mobile-advanced/mobile-security/SKILL.md +403 -0
- package/plugin/skills/mobile-advanced/offline-first/SKILL.md +473 -0
- package/plugin/skills/mobile-advanced/push-notifications/SKILL.md +494 -0
- package/plugin/skills/mobile-advanced/react-native-deep/SKILL.md +374 -0
- package/plugin/skills/simulation/numerical-methods/SKILL.md +434 -0
- package/plugin/skills/simulation/parallel-computing/SKILL.md +382 -0
- package/plugin/skills/simulation/physics-engines/SKILL.md +377 -0
- package/plugin/skills/simulation/validation-verification/SKILL.md +479 -0
- package/plugin/skills/simulation/visualization-scientific/SKILL.md +365 -0
- package/plugin/templates/autonomous/archetypes/event-driven-app.yaml +460 -0
- package/plugin/templates/autonomous/archetypes/microservices-app.yaml +431 -0
- package/plugin/templates/autonomous/state-schema.yaml +1 -1
- package/plugin/workflows/ai-engineering/agent-development.md +3 -3
- package/plugin/workflows/ai-engineering/fine-tuning.md +3 -3
- package/plugin/workflows/ai-engineering/model-evaluation.md +3 -3
- package/plugin/workflows/ai-engineering/prompt-engineering.md +2 -2
- package/plugin/workflows/ai-engineering/rag-development.md +4 -4
- package/plugin/workflows/ai-ml/data-pipeline.md +188 -0
- package/plugin/workflows/ai-ml/experiment-cycle.md +203 -0
- package/plugin/workflows/ai-ml/feature-engineering.md +208 -0
- package/plugin/workflows/ai-ml/model-deployment.md +199 -0
- package/plugin/workflows/ai-ml/monitoring-setup.md +227 -0
- package/plugin/workflows/api/api-design.md +1 -1
- package/plugin/workflows/api/api-testing.md +2 -2
- package/plugin/workflows/content/technical-docs.md +1 -1
- package/plugin/workflows/database/migration.md +1 -1
- package/plugin/workflows/database/optimization.md +1 -1
- package/plugin/workflows/database/schema-design.md +3 -3
- package/plugin/workflows/development/bug-fix.md +3 -3
- package/plugin/workflows/development/code-review.md +2 -1
- package/plugin/workflows/development/feature.md +3 -3
- package/plugin/workflows/development/refactor.md +2 -2
- package/plugin/workflows/event-driven/consumer-groups.md +190 -0
- package/plugin/workflows/event-driven/event-storming.md +172 -0
- package/plugin/workflows/event-driven/replay-testing.md +186 -0
- package/plugin/workflows/event-driven/saga-implementation.md +206 -0
- package/plugin/workflows/event-driven/schema-evolution.md +173 -0
- package/plugin/workflows/fullstack/authentication.md +4 -4
- package/plugin/workflows/fullstack/full-feature.md +4 -4
- package/plugin/workflows/game-dev/content-pipeline.md +218 -0
- package/plugin/workflows/game-dev/platform-submission.md +263 -0
- package/plugin/workflows/game-dev/playtesting.md +237 -0
- package/plugin/workflows/game-dev/prototype-to-production.md +205 -0
- package/plugin/workflows/microservices/contract-first.md +151 -0
- package/plugin/workflows/microservices/distributed-tracing.md +166 -0
- package/plugin/workflows/microservices/domain-decomposition.md +123 -0
- package/plugin/workflows/microservices/integration-testing.md +149 -0
- package/plugin/workflows/microservices/service-mesh-setup.md +153 -0
- package/plugin/workflows/microservices/service-scaffolding.md +151 -0
- package/plugin/workflows/omega/1000x-innovation.md +2 -2
- package/plugin/workflows/omega/100x-architecture.md +2 -2
- package/plugin/workflows/omega/10x-improvement.md +2 -2
- package/plugin/workflows/quality/performance-optimization.md +2 -2
- package/plugin/workflows/research/best-practices.md +1 -1
- package/plugin/workflows/research/technology-research.md +1 -1
- package/plugin/workflows/security/penetration-testing.md +3 -3
- package/plugin/workflows/security/security-audit.md +3 -3
- package/plugin/workflows/sprint/sprint-execution.md +2 -2
- package/plugin/workflows/sprint/sprint-retrospective.md +1 -1
- package/plugin/workflows/sprint/sprint-setup.md +1 -1
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
# Godot Patterns
|
|
2
|
+
|
|
3
|
+
Godot 4 architecture patterns including node composition, signals, resources, and GDScript/C# best practices.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Godot's scene/node architecture enables composition-based game design with powerful signal systems and resource management.
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
### Node Hierarchy
|
|
12
|
+
- **Node**: Base class for everything
|
|
13
|
+
- **Scene**: Reusable node tree
|
|
14
|
+
- **Resource**: Shareable data objects
|
|
15
|
+
- **Autoload**: Global singletons
|
|
16
|
+
|
|
17
|
+
### Design Philosophy
|
|
18
|
+
- Composition over inheritance
|
|
19
|
+
- Scenes as prefabs
|
|
20
|
+
- Signals for decoupling
|
|
21
|
+
- Resources for data
|
|
22
|
+
|
|
23
|
+
## Scene Architecture
|
|
24
|
+
|
|
25
|
+
### Component Pattern
|
|
26
|
+
```gdscript
|
|
27
|
+
# health_component.gd
|
|
28
|
+
class_name HealthComponent
|
|
29
|
+
extends Node
|
|
30
|
+
|
|
31
|
+
signal health_changed(current: float, maximum: float)
|
|
32
|
+
signal died
|
|
33
|
+
|
|
34
|
+
@export var max_health: float = 100.0
|
|
35
|
+
var current_health: float:
|
|
36
|
+
set(value):
|
|
37
|
+
var old_health = current_health
|
|
38
|
+
current_health = clampf(value, 0.0, max_health)
|
|
39
|
+
health_changed.emit(current_health, max_health)
|
|
40
|
+
if current_health <= 0 and old_health > 0:
|
|
41
|
+
died.emit()
|
|
42
|
+
|
|
43
|
+
func _ready() -> void:
|
|
44
|
+
current_health = max_health
|
|
45
|
+
|
|
46
|
+
func take_damage(amount: float) -> void:
|
|
47
|
+
current_health -= amount
|
|
48
|
+
|
|
49
|
+
func heal(amount: float) -> void:
|
|
50
|
+
current_health += amount
|
|
51
|
+
|
|
52
|
+
func is_alive() -> bool:
|
|
53
|
+
return current_health > 0
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```gdscript
|
|
57
|
+
# hitbox_component.gd
|
|
58
|
+
class_name HitboxComponent
|
|
59
|
+
extends Area3D
|
|
60
|
+
|
|
61
|
+
signal hit(damage: float, source: Node)
|
|
62
|
+
|
|
63
|
+
@export var damage: float = 10.0
|
|
64
|
+
@export var knockback_force: float = 500.0
|
|
65
|
+
|
|
66
|
+
func _on_area_entered(area: Area3D) -> void:
|
|
67
|
+
if area is HurtboxComponent:
|
|
68
|
+
area.receive_hit(damage, knockback_force, owner)
|
|
69
|
+
hit.emit(damage, area.owner)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
```gdscript
|
|
73
|
+
# hurtbox_component.gd
|
|
74
|
+
class_name HurtboxComponent
|
|
75
|
+
extends Area3D
|
|
76
|
+
|
|
77
|
+
signal damage_received(amount: float, source: Node)
|
|
78
|
+
|
|
79
|
+
@export var health_component: HealthComponent
|
|
80
|
+
|
|
81
|
+
func receive_hit(damage: float, knockback: float, source: Node) -> void:
|
|
82
|
+
if health_component:
|
|
83
|
+
health_component.take_damage(damage)
|
|
84
|
+
damage_received.emit(damage, source)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Entity Composition
|
|
88
|
+
```gdscript
|
|
89
|
+
# player.gd
|
|
90
|
+
extends CharacterBody3D
|
|
91
|
+
|
|
92
|
+
@onready var health: HealthComponent = $HealthComponent
|
|
93
|
+
@onready var hurtbox: HurtboxComponent = $HurtboxComponent
|
|
94
|
+
@onready var state_machine: StateMachine = $StateMachine
|
|
95
|
+
@onready var animation_player: AnimationPlayer = $AnimationPlayer
|
|
96
|
+
|
|
97
|
+
func _ready() -> void:
|
|
98
|
+
health.died.connect(_on_death)
|
|
99
|
+
hurtbox.damage_received.connect(_on_damage_received)
|
|
100
|
+
|
|
101
|
+
func _physics_process(delta: float) -> void:
|
|
102
|
+
state_machine.process_physics(delta)
|
|
103
|
+
|
|
104
|
+
func _on_death() -> void:
|
|
105
|
+
state_machine.transition_to("Dead")
|
|
106
|
+
|
|
107
|
+
func _on_damage_received(amount: float, source: Node) -> void:
|
|
108
|
+
animation_player.play("hit")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Signal Patterns
|
|
112
|
+
|
|
113
|
+
### Event Bus (Autoload)
|
|
114
|
+
```gdscript
|
|
115
|
+
# events.gd (Autoload)
|
|
116
|
+
extends Node
|
|
117
|
+
|
|
118
|
+
# Game events
|
|
119
|
+
signal game_started
|
|
120
|
+
signal game_paused(is_paused: bool)
|
|
121
|
+
signal game_over(won: bool)
|
|
122
|
+
|
|
123
|
+
# Player events
|
|
124
|
+
signal player_spawned(player: Node)
|
|
125
|
+
signal player_died(player: Node)
|
|
126
|
+
signal player_scored(points: int)
|
|
127
|
+
|
|
128
|
+
# UI events
|
|
129
|
+
signal show_dialog(text: String)
|
|
130
|
+
signal update_health(current: float, max: float)
|
|
131
|
+
signal update_score(score: int)
|
|
132
|
+
|
|
133
|
+
# Combat events
|
|
134
|
+
signal enemy_killed(enemy: Node, killer: Node)
|
|
135
|
+
signal damage_dealt(amount: float, target: Node, source: Node)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```gdscript
|
|
139
|
+
# Usage in player
|
|
140
|
+
func _ready() -> void:
|
|
141
|
+
Events.player_spawned.emit(self)
|
|
142
|
+
|
|
143
|
+
func die() -> void:
|
|
144
|
+
Events.player_died.emit(self)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```gdscript
|
|
148
|
+
# Usage in UI
|
|
149
|
+
extends Control
|
|
150
|
+
|
|
151
|
+
func _ready() -> void:
|
|
152
|
+
Events.update_health.connect(_on_health_updated)
|
|
153
|
+
Events.update_score.connect(_on_score_updated)
|
|
154
|
+
Events.game_over.connect(_on_game_over)
|
|
155
|
+
|
|
156
|
+
func _on_health_updated(current: float, max: float) -> void:
|
|
157
|
+
$HealthBar.value = current / max * 100
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Resource System
|
|
161
|
+
|
|
162
|
+
### Custom Resources
|
|
163
|
+
```gdscript
|
|
164
|
+
# weapon_resource.gd
|
|
165
|
+
class_name WeaponResource
|
|
166
|
+
extends Resource
|
|
167
|
+
|
|
168
|
+
@export var weapon_name: String
|
|
169
|
+
@export var icon: Texture2D
|
|
170
|
+
@export var damage: float
|
|
171
|
+
@export var attack_speed: float
|
|
172
|
+
@export var range: float
|
|
173
|
+
@export_enum("Melee", "Ranged", "Magic") var weapon_type: int
|
|
174
|
+
@export var attack_animation: String
|
|
175
|
+
@export var attack_sound: AudioStream
|
|
176
|
+
|
|
177
|
+
func get_dps() -> float:
|
|
178
|
+
return damage * attack_speed
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```gdscript
|
|
182
|
+
# character_stats.gd
|
|
183
|
+
class_name CharacterStats
|
|
184
|
+
extends Resource
|
|
185
|
+
|
|
186
|
+
@export var character_name: String
|
|
187
|
+
@export var max_health: float = 100.0
|
|
188
|
+
@export var move_speed: float = 300.0
|
|
189
|
+
@export var jump_force: float = 400.0
|
|
190
|
+
@export var starting_weapon: WeaponResource
|
|
191
|
+
@export_multiline var description: String
|
|
192
|
+
|
|
193
|
+
func apply_to(character: CharacterBody2D) -> void:
|
|
194
|
+
character.max_health = max_health
|
|
195
|
+
character.move_speed = move_speed
|
|
196
|
+
character.jump_force = jump_force
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Inventory System
|
|
200
|
+
```gdscript
|
|
201
|
+
# inventory.gd
|
|
202
|
+
class_name Inventory
|
|
203
|
+
extends Resource
|
|
204
|
+
|
|
205
|
+
signal item_added(item: ItemResource, slot: int)
|
|
206
|
+
signal item_removed(item: ItemResource, slot: int)
|
|
207
|
+
signal inventory_changed
|
|
208
|
+
|
|
209
|
+
@export var slots: Array[ItemResource] = []
|
|
210
|
+
@export var max_slots: int = 20
|
|
211
|
+
|
|
212
|
+
func _init() -> void:
|
|
213
|
+
slots.resize(max_slots)
|
|
214
|
+
|
|
215
|
+
func add_item(item: ItemResource) -> bool:
|
|
216
|
+
# Try to stack first
|
|
217
|
+
for i in range(slots.size()):
|
|
218
|
+
if slots[i] and slots[i].can_stack_with(item):
|
|
219
|
+
slots[i].quantity += item.quantity
|
|
220
|
+
inventory_changed.emit()
|
|
221
|
+
return true
|
|
222
|
+
|
|
223
|
+
# Find empty slot
|
|
224
|
+
for i in range(slots.size()):
|
|
225
|
+
if slots[i] == null:
|
|
226
|
+
slots[i] = item.duplicate()
|
|
227
|
+
item_added.emit(item, i)
|
|
228
|
+
inventory_changed.emit()
|
|
229
|
+
return true
|
|
230
|
+
|
|
231
|
+
return false
|
|
232
|
+
|
|
233
|
+
func remove_item(slot: int) -> ItemResource:
|
|
234
|
+
if slot < 0 or slot >= slots.size():
|
|
235
|
+
return null
|
|
236
|
+
|
|
237
|
+
var item = slots[slot]
|
|
238
|
+
slots[slot] = null
|
|
239
|
+
if item:
|
|
240
|
+
item_removed.emit(item, slot)
|
|
241
|
+
inventory_changed.emit()
|
|
242
|
+
return item
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## State Machine
|
|
246
|
+
|
|
247
|
+
### GDScript State Machine
|
|
248
|
+
```gdscript
|
|
249
|
+
# state_machine.gd
|
|
250
|
+
class_name StateMachine
|
|
251
|
+
extends Node
|
|
252
|
+
|
|
253
|
+
signal state_changed(old_state: State, new_state: State)
|
|
254
|
+
|
|
255
|
+
@export var initial_state: State
|
|
256
|
+
var current_state: State
|
|
257
|
+
var states: Dictionary = {}
|
|
258
|
+
|
|
259
|
+
func _ready() -> void:
|
|
260
|
+
for child in get_children():
|
|
261
|
+
if child is State:
|
|
262
|
+
states[child.name.to_lower()] = child
|
|
263
|
+
child.state_machine = self
|
|
264
|
+
|
|
265
|
+
if initial_state:
|
|
266
|
+
current_state = initial_state
|
|
267
|
+
current_state.enter()
|
|
268
|
+
|
|
269
|
+
func process_input(event: InputEvent) -> void:
|
|
270
|
+
if current_state:
|
|
271
|
+
current_state.handle_input(event)
|
|
272
|
+
|
|
273
|
+
func process_frame(delta: float) -> void:
|
|
274
|
+
if current_state:
|
|
275
|
+
current_state.update(delta)
|
|
276
|
+
|
|
277
|
+
func process_physics(delta: float) -> void:
|
|
278
|
+
if current_state:
|
|
279
|
+
current_state.physics_update(delta)
|
|
280
|
+
|
|
281
|
+
func transition_to(state_name: String, params: Dictionary = {}) -> void:
|
|
282
|
+
var new_state = states.get(state_name.to_lower())
|
|
283
|
+
if new_state == null:
|
|
284
|
+
push_error("State not found: " + state_name)
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
if current_state:
|
|
288
|
+
current_state.exit()
|
|
289
|
+
|
|
290
|
+
var old_state = current_state
|
|
291
|
+
current_state = new_state
|
|
292
|
+
current_state.enter(params)
|
|
293
|
+
|
|
294
|
+
state_changed.emit(old_state, new_state)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
```gdscript
|
|
298
|
+
# state.gd
|
|
299
|
+
class_name State
|
|
300
|
+
extends Node
|
|
301
|
+
|
|
302
|
+
var state_machine: StateMachine
|
|
303
|
+
|
|
304
|
+
func enter(params: Dictionary = {}) -> void:
|
|
305
|
+
pass
|
|
306
|
+
|
|
307
|
+
func exit() -> void:
|
|
308
|
+
pass
|
|
309
|
+
|
|
310
|
+
func handle_input(event: InputEvent) -> void:
|
|
311
|
+
pass
|
|
312
|
+
|
|
313
|
+
func update(delta: float) -> void:
|
|
314
|
+
pass
|
|
315
|
+
|
|
316
|
+
func physics_update(delta: float) -> void:
|
|
317
|
+
pass
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
```gdscript
|
|
321
|
+
# player_idle_state.gd
|
|
322
|
+
extends State
|
|
323
|
+
|
|
324
|
+
@onready var player: CharacterBody2D = owner
|
|
325
|
+
|
|
326
|
+
func enter(params: Dictionary = {}) -> void:
|
|
327
|
+
player.animation_player.play("idle")
|
|
328
|
+
|
|
329
|
+
func physics_update(delta: float) -> void:
|
|
330
|
+
var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down")
|
|
331
|
+
|
|
332
|
+
if input_dir.length() > 0.1:
|
|
333
|
+
state_machine.transition_to("Move")
|
|
334
|
+
|
|
335
|
+
if Input.is_action_just_pressed("jump") and player.is_on_floor():
|
|
336
|
+
state_machine.transition_to("Jump")
|
|
337
|
+
|
|
338
|
+
if Input.is_action_just_pressed("attack"):
|
|
339
|
+
state_machine.transition_to("Attack")
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## C# Patterns
|
|
343
|
+
|
|
344
|
+
### Component in C#
|
|
345
|
+
```csharp
|
|
346
|
+
using Godot;
|
|
347
|
+
|
|
348
|
+
public partial class HealthComponent : Node
|
|
349
|
+
{
|
|
350
|
+
[Signal]
|
|
351
|
+
public delegate void HealthChangedEventHandler(float current, float max);
|
|
352
|
+
|
|
353
|
+
[Signal]
|
|
354
|
+
public delegate void DiedEventHandler();
|
|
355
|
+
|
|
356
|
+
[Export]
|
|
357
|
+
public float MaxHealth { get; set; } = 100f;
|
|
358
|
+
|
|
359
|
+
private float _currentHealth;
|
|
360
|
+
public float CurrentHealth
|
|
361
|
+
{
|
|
362
|
+
get => _currentHealth;
|
|
363
|
+
set
|
|
364
|
+
{
|
|
365
|
+
float oldHealth = _currentHealth;
|
|
366
|
+
_currentHealth = Mathf.Clamp(value, 0f, MaxHealth);
|
|
367
|
+
EmitSignal(SignalName.HealthChanged, _currentHealth, MaxHealth);
|
|
368
|
+
|
|
369
|
+
if (_currentHealth <= 0 && oldHealth > 0)
|
|
370
|
+
EmitSignal(SignalName.Died);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
public override void _Ready()
|
|
375
|
+
{
|
|
376
|
+
CurrentHealth = MaxHealth;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
public void TakeDamage(float amount) => CurrentHealth -= amount;
|
|
380
|
+
public void Heal(float amount) => CurrentHealth += amount;
|
|
381
|
+
public bool IsAlive() => CurrentHealth > 0;
|
|
382
|
+
}
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Best Practices
|
|
386
|
+
|
|
387
|
+
1. **Use Composition**: Build entities from components
|
|
388
|
+
2. **Leverage Signals**: Decouple systems
|
|
389
|
+
3. **Resources for Data**: Share data between scenes
|
|
390
|
+
4. **Autoloads Sparingly**: Only for truly global systems
|
|
391
|
+
5. **Type Hints**: Use static typing in GDScript
|
|
392
|
+
|
|
393
|
+
## Anti-Patterns
|
|
394
|
+
|
|
395
|
+
- Deep inheritance hierarchies
|
|
396
|
+
- Direct node references across scenes
|
|
397
|
+
- Business logic in UI nodes
|
|
398
|
+
- Hardcoded paths
|
|
399
|
+
- Overusing autoloads
|
|
400
|
+
|
|
401
|
+
## When to Use
|
|
402
|
+
|
|
403
|
+
- Godot game projects
|
|
404
|
+
- 2D and 3D games
|
|
405
|
+
- Rapid prototyping
|
|
406
|
+
- Open-source game development
|
|
407
|
+
- Cross-platform games
|
|
408
|
+
|
|
409
|
+
## When NOT to Use
|
|
410
|
+
|
|
411
|
+
- AAA-scale projects (consider Unity/Unreal)
|
|
412
|
+
- Specialized engines exist (racing, sports)
|
|
413
|
+
- Team heavily invested in other engines
|