@series-inc/rundot-3d-engine 0.3.0 → 0.4.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.
@@ -1,290 +1,290 @@
1
- # Creating GameObjects
2
-
3
- Best practices for GameObject instantiation, hierarchy, and lifecycle management.
4
-
5
- ## Basic Creation
6
-
7
- ```typescript
8
- // Always name your GameObjects
9
- const player = new GameObject("Player")
10
- player.position.set(0, 1, 0)
11
-
12
- // Add components for behavior
13
- player.addComponent(new PlayerController())
14
- player.addComponent(new RigidBodyComponentThree({
15
- type: RigidBodyType.DYNAMIC
16
- }))
17
- ```
18
-
19
- ## Hierarchy Patterns
20
-
21
- ### Parent-Child Relationships
22
-
23
- ```typescript
24
- // Create parent
25
- const vehicle = new GameObject("Vehicle")
26
-
27
- // Create children
28
- const body = new GameObject("Body")
29
- const wheel1 = new GameObject("Wheel1")
30
- const wheel2 = new GameObject("Wheel2")
31
-
32
- // Build hierarchy
33
- vehicle.add(body)
34
- vehicle.add(wheel1)
35
- vehicle.add(wheel2)
36
-
37
- // Position children relative to parent
38
- wheel1.position.set(-1, 0, 0)
39
- wheel2.position.set(1, 0, 0)
40
-
41
- // Moving parent moves all children
42
- vehicle.position.x += 5
43
- ```
44
-
45
- ### Separation of Concerns
46
-
47
- ```typescript
48
- // Separate visual from logic
49
- const character = new GameObject("Character")
50
-
51
- // Logic/physics on parent
52
- character.addComponent(new CharacterController())
53
- character.addComponent(new RigidBodyComponentThree({
54
- type: RigidBodyType.DYNAMIC,
55
- shape: ColliderShape.CAPSULE
56
- }))
57
-
58
- // Visual as child (can be offset)
59
- const visual = new GameObject("Visual")
60
- visual.addComponent(new SkeletalRenderer("character.fbx"))
61
- character.add(visual)
62
- visual.position.y = -1 // Offset visual down
63
- ```
64
-
65
- ## Component Organization
66
-
67
- ### Single Responsibility
68
-
69
- ```typescript
70
- // Good - Each component does one thing
71
- const enemy = new GameObject("Enemy")
72
- enemy.addComponent(new EnemyAI()) // Behavior
73
- enemy.addComponent(new HealthComponent()) // Health tracking
74
- enemy.addComponent(new MeshRenderer("enemy_mesh")) // Visual
75
-
76
- // Bad - One component doing everything
77
- enemy.addComponent(new EnemyEverything()) // AI + health + rendering
78
- ```
79
-
80
- ### Component Dependencies
81
-
82
- ```typescript
83
- class WeaponComponent extends Component {
84
- private meshRenderer?: MeshRenderer
85
-
86
- protected onCreate(): void {
87
- // Get required components
88
- this.meshRenderer = this.getComponent(MeshRenderer)
89
-
90
- if (!this.meshRenderer) {
91
- console.error("WeaponComponent requires MeshRenderer!")
92
- }
93
- }
94
- }
95
- ```
96
-
97
- ## Lifecycle Management
98
-
99
- ### Proper Initialization
100
-
101
- ```typescript
102
- class SpawnManager extends Component {
103
- private enemies: GameObject[] = []
104
-
105
- public spawnEnemy(): void {
106
- // Create
107
- const enemy = new GameObject("Enemy")
108
-
109
- // Configure
110
- enemy.position.set(10, 0, 10)
111
- enemy.addComponent(new EnemyAI())
112
-
113
- // Track
114
- this.enemies.push(enemy)
115
- }
116
-
117
- protected onCleanup(): void {
118
- // Clean up all spawned objects
119
- for (const enemy of this.enemies) {
120
- enemy.dispose()
121
- }
122
- this.enemies = []
123
- }
124
- }
125
- ```
126
-
127
- ### Pooling Pattern
128
-
129
- ```typescript
130
- class ObjectPool {
131
- private pool: GameObject[] = []
132
- private active: GameObject[] = []
133
-
134
- public get(): GameObject {
135
- // Reuse from pool
136
- let obj = this.pool.pop()
137
-
138
- if (!obj) {
139
- // Create new if pool empty
140
- obj = new GameObject("Pooled")
141
- obj.addComponent(new PooledComponent())
142
- }
143
-
144
- obj.setEnabled(true)
145
- this.active.push(obj)
146
- return obj
147
- }
148
-
149
- public release(obj: GameObject): void {
150
- // Return to pool
151
- obj.setEnabled(false)
152
- const index = this.active.indexOf(obj)
153
- if (index > -1) {
154
- this.active.splice(index, 1)
155
- this.pool.push(obj)
156
- }
157
- }
158
-
159
- public cleanup(): void {
160
- // Dispose all
161
- for (const obj of [...this.pool, ...this.active]) {
162
- obj.dispose()
163
- }
164
- this.pool = []
165
- this.active = []
166
- }
167
- }
168
- ```
169
-
170
- ## Common Patterns
171
-
172
- ### Factory Pattern
173
-
174
- ```typescript
175
- class EnemyFactory {
176
- static createBasicEnemy(): GameObject {
177
- const enemy = new GameObject("BasicEnemy")
178
- enemy.addComponent(new EnemyAI())
179
- enemy.addComponent(new HealthComponent(100))
180
-
181
- const visual = new GameObject("Visual")
182
- visual.addComponent(new MeshRenderer("enemy_basic"))
183
- enemy.add(visual)
184
-
185
- return enemy
186
- }
187
-
188
- static createBossEnemy(): GameObject {
189
- const boss = new GameObject("BossEnemy")
190
- boss.addComponent(new BossAI())
191
- boss.addComponent(new HealthComponent(1000))
192
-
193
- const visual = new GameObject("Visual")
194
- visual.addComponent(new SkeletalRenderer("boss.fbx"))
195
- boss.add(visual)
196
-
197
- return boss
198
- }
199
- }
200
- ```
201
-
202
- ### Builder Pattern
203
-
204
- ```typescript
205
- class CharacterBuilder {
206
- private character: GameObject
207
-
208
- constructor(name: string) {
209
- this.character = new GameObject(name)
210
- }
211
-
212
- withMesh(meshName: string): this {
213
- const visual = new GameObject("Visual")
214
- visual.addComponent(new MeshRenderer(meshName))
215
- this.character.add(visual)
216
- return this
217
- }
218
-
219
- withPhysics(options: RigidBodyOptions): this {
220
- this.character.addComponent(new RigidBodyComponentThree(options))
221
- return this
222
- }
223
-
224
- withAI(): this {
225
- this.character.addComponent(new EnemyAI())
226
- return this
227
- }
228
-
229
- build(): GameObject {
230
- return this.character
231
- }
232
- }
233
-
234
- // Use it
235
- const enemy = new CharacterBuilder("Enemy")
236
- .withMesh("enemy_mesh")
237
- .withPhysics({ type: RigidBodyType.DYNAMIC })
238
- .withAI()
239
- .build()
240
- ```
241
-
242
- ## Anti-Patterns
243
-
244
- ### Don't Create in Update
245
-
246
- ```typescript
247
- // BAD - Creates objects every frame
248
- public update(deltaTime: number): void {
249
- const temp = new GameObject("Temp") // Memory leak!
250
- }
251
-
252
- // GOOD - Create once, reuse
253
- private tempObject: GameObject
254
- protected onCreate(): void {
255
- this.tempObject = new GameObject("Temp")
256
- }
257
- ```
258
-
259
- ### Don't Forget Disposal
260
-
261
- ```typescript
262
- // BAD - Memory leak
263
- spawnProjectile() {
264
- const bullet = new GameObject("Bullet")
265
- // Never disposed!
266
- }
267
-
268
- // GOOD - Track and clean up
269
- private bullets: GameObject[] = []
270
-
271
- spawnProjectile() {
272
- const bullet = new GameObject("Bullet")
273
- this.bullets.push(bullet)
274
- }
275
-
276
- cleanupBullet(bullet: GameObject) {
277
- bullet.dispose()
278
- const index = this.bullets.indexOf(bullet)
279
- if (index > -1) {
280
- this.bullets.splice(index, 1)
281
- }
282
- }
283
- ```
284
-
285
- ## Related Patterns
286
-
287
- - [Mesh Loading](MeshLoading.md) - Loading meshes correctly
288
- - [Component Communication](ComponentCommunication.md) - Inter-component patterns
289
- - [GameObject](../core/GameObject.md) - GameObject documentation
290
-
1
+ # Creating GameObjects
2
+
3
+ Best practices for GameObject instantiation, hierarchy, and lifecycle management.
4
+
5
+ ## Basic Creation
6
+
7
+ ```typescript
8
+ // Always name your GameObjects
9
+ const player = new GameObject("Player")
10
+ player.position.set(0, 1, 0)
11
+
12
+ // Add components for behavior
13
+ player.addComponent(new PlayerController())
14
+ player.addComponent(new RigidBodyComponentThree({
15
+ type: RigidBodyType.DYNAMIC
16
+ }))
17
+ ```
18
+
19
+ ## Hierarchy Patterns
20
+
21
+ ### Parent-Child Relationships
22
+
23
+ ```typescript
24
+ // Create parent
25
+ const vehicle = new GameObject("Vehicle")
26
+
27
+ // Create children
28
+ const body = new GameObject("Body")
29
+ const wheel1 = new GameObject("Wheel1")
30
+ const wheel2 = new GameObject("Wheel2")
31
+
32
+ // Build hierarchy
33
+ vehicle.add(body)
34
+ vehicle.add(wheel1)
35
+ vehicle.add(wheel2)
36
+
37
+ // Position children relative to parent
38
+ wheel1.position.set(-1, 0, 0)
39
+ wheel2.position.set(1, 0, 0)
40
+
41
+ // Moving parent moves all children
42
+ vehicle.position.x += 5
43
+ ```
44
+
45
+ ### Separation of Concerns
46
+
47
+ ```typescript
48
+ // Separate visual from logic
49
+ const character = new GameObject("Character")
50
+
51
+ // Logic/physics on parent
52
+ character.addComponent(new CharacterController())
53
+ character.addComponent(new RigidBodyComponentThree({
54
+ type: RigidBodyType.DYNAMIC,
55
+ shape: ColliderShape.CAPSULE
56
+ }))
57
+
58
+ // Visual as child (can be offset)
59
+ const visual = new GameObject("Visual")
60
+ visual.addComponent(new SkeletalRenderer("character.fbx"))
61
+ character.add(visual)
62
+ visual.position.y = -1 // Offset visual down
63
+ ```
64
+
65
+ ## Component Organization
66
+
67
+ ### Single Responsibility
68
+
69
+ ```typescript
70
+ // Good - Each component does one thing
71
+ const enemy = new GameObject("Enemy")
72
+ enemy.addComponent(new EnemyAI()) // Behavior
73
+ enemy.addComponent(new HealthComponent()) // Health tracking
74
+ enemy.addComponent(new MeshRenderer("enemy_mesh")) // Visual
75
+
76
+ // Bad - One component doing everything
77
+ enemy.addComponent(new EnemyEverything()) // AI + health + rendering
78
+ ```
79
+
80
+ ### Component Dependencies
81
+
82
+ ```typescript
83
+ class WeaponComponent extends Component {
84
+ private meshRenderer?: MeshRenderer
85
+
86
+ protected onCreate(): void {
87
+ // Get required components
88
+ this.meshRenderer = this.getComponent(MeshRenderer)
89
+
90
+ if (!this.meshRenderer) {
91
+ console.error("WeaponComponent requires MeshRenderer!")
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Lifecycle Management
98
+
99
+ ### Proper Initialization
100
+
101
+ ```typescript
102
+ class SpawnManager extends Component {
103
+ private enemies: GameObject[] = []
104
+
105
+ public spawnEnemy(): void {
106
+ // Create
107
+ const enemy = new GameObject("Enemy")
108
+
109
+ // Configure
110
+ enemy.position.set(10, 0, 10)
111
+ enemy.addComponent(new EnemyAI())
112
+
113
+ // Track
114
+ this.enemies.push(enemy)
115
+ }
116
+
117
+ protected onCleanup(): void {
118
+ // Clean up all spawned objects
119
+ for (const enemy of this.enemies) {
120
+ enemy.dispose()
121
+ }
122
+ this.enemies = []
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### Pooling Pattern
128
+
129
+ ```typescript
130
+ class ObjectPool {
131
+ private pool: GameObject[] = []
132
+ private active: GameObject[] = []
133
+
134
+ public get(): GameObject {
135
+ // Reuse from pool
136
+ let obj = this.pool.pop()
137
+
138
+ if (!obj) {
139
+ // Create new if pool empty
140
+ obj = new GameObject("Pooled")
141
+ obj.addComponent(new PooledComponent())
142
+ }
143
+
144
+ obj.setEnabled(true)
145
+ this.active.push(obj)
146
+ return obj
147
+ }
148
+
149
+ public release(obj: GameObject): void {
150
+ // Return to pool
151
+ obj.setEnabled(false)
152
+ const index = this.active.indexOf(obj)
153
+ if (index > -1) {
154
+ this.active.splice(index, 1)
155
+ this.pool.push(obj)
156
+ }
157
+ }
158
+
159
+ public cleanup(): void {
160
+ // Dispose all
161
+ for (const obj of [...this.pool, ...this.active]) {
162
+ obj.dispose()
163
+ }
164
+ this.pool = []
165
+ this.active = []
166
+ }
167
+ }
168
+ ```
169
+
170
+ ## Common Patterns
171
+
172
+ ### Factory Pattern
173
+
174
+ ```typescript
175
+ class EnemyFactory {
176
+ static createBasicEnemy(): GameObject {
177
+ const enemy = new GameObject("BasicEnemy")
178
+ enemy.addComponent(new EnemyAI())
179
+ enemy.addComponent(new HealthComponent(100))
180
+
181
+ const visual = new GameObject("Visual")
182
+ visual.addComponent(new MeshRenderer("enemy_basic"))
183
+ enemy.add(visual)
184
+
185
+ return enemy
186
+ }
187
+
188
+ static createBossEnemy(): GameObject {
189
+ const boss = new GameObject("BossEnemy")
190
+ boss.addComponent(new BossAI())
191
+ boss.addComponent(new HealthComponent(1000))
192
+
193
+ const visual = new GameObject("Visual")
194
+ visual.addComponent(new SkeletalRenderer("boss.fbx"))
195
+ boss.add(visual)
196
+
197
+ return boss
198
+ }
199
+ }
200
+ ```
201
+
202
+ ### Builder Pattern
203
+
204
+ ```typescript
205
+ class CharacterBuilder {
206
+ private character: GameObject
207
+
208
+ constructor(name: string) {
209
+ this.character = new GameObject(name)
210
+ }
211
+
212
+ withMesh(meshName: string): this {
213
+ const visual = new GameObject("Visual")
214
+ visual.addComponent(new MeshRenderer(meshName))
215
+ this.character.add(visual)
216
+ return this
217
+ }
218
+
219
+ withPhysics(options: RigidBodyOptions): this {
220
+ this.character.addComponent(new RigidBodyComponentThree(options))
221
+ return this
222
+ }
223
+
224
+ withAI(): this {
225
+ this.character.addComponent(new EnemyAI())
226
+ return this
227
+ }
228
+
229
+ build(): GameObject {
230
+ return this.character
231
+ }
232
+ }
233
+
234
+ // Use it
235
+ const enemy = new CharacterBuilder("Enemy")
236
+ .withMesh("enemy_mesh")
237
+ .withPhysics({ type: RigidBodyType.DYNAMIC })
238
+ .withAI()
239
+ .build()
240
+ ```
241
+
242
+ ## Anti-Patterns
243
+
244
+ ### Don't Create in Update
245
+
246
+ ```typescript
247
+ // BAD - Creates objects every frame
248
+ public update(deltaTime: number): void {
249
+ const temp = new GameObject("Temp") // Memory leak!
250
+ }
251
+
252
+ // GOOD - Create once, reuse
253
+ private tempObject: GameObject
254
+ protected onCreate(): void {
255
+ this.tempObject = new GameObject("Temp")
256
+ }
257
+ ```
258
+
259
+ ### Don't Forget Disposal
260
+
261
+ ```typescript
262
+ // BAD - Memory leak
263
+ spawnProjectile() {
264
+ const bullet = new GameObject("Bullet")
265
+ // Never disposed!
266
+ }
267
+
268
+ // GOOD - Track and clean up
269
+ private bullets: GameObject[] = []
270
+
271
+ spawnProjectile() {
272
+ const bullet = new GameObject("Bullet")
273
+ this.bullets.push(bullet)
274
+ }
275
+
276
+ cleanupBullet(bullet: GameObject) {
277
+ bullet.dispose()
278
+ const index = this.bullets.indexOf(bullet)
279
+ if (index > -1) {
280
+ this.bullets.splice(index, 1)
281
+ }
282
+ }
283
+ ```
284
+
285
+ ## Related Patterns
286
+
287
+ - [Mesh Loading](MeshLoading.md) - Loading meshes correctly
288
+ - [Component Communication](ComponentCommunication.md) - Inter-component patterns
289
+ - [GameObject](../core/GameObject.md) - GameObject documentation
290
+