@dcl/playground-assets 7.0.5-3640831568.commit-60f39b0 → 7.0.5-3649654995.commit-ad4efbc

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.
@@ -0,0 +1,121 @@
1
+ import {
2
+ Entity,
3
+ engine,
4
+ Material,
5
+ Transform,
6
+ MeshRenderer,
7
+ Billboard,
8
+ BillboardMode,
9
+ TextShape,
10
+ Schemas
11
+ } from '@dcl/sdk/ecs'
12
+ import { Vector3, Color3, Color4 } from '@dcl/sdk/math'
13
+
14
+ function createPlaneTexture(x: number, y: number, z: number): Entity {
15
+ const meshEntity = engine.addEntity()
16
+
17
+ Material.create(meshEntity, {
18
+ material: {
19
+ $case: 'pbr',
20
+ pbr: {
21
+ texture: {
22
+ tex: {
23
+ $case: 'texture',
24
+ texture: { src: 'models/polaroid2.png' }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ })
30
+ Transform.create(meshEntity, {
31
+ position: { x, y, z },
32
+ scale: Vector3.create(2, 2, 2)
33
+ })
34
+ MeshRenderer.create(meshEntity, {
35
+ mesh: {
36
+ $case: 'plane',
37
+ plane: {
38
+ uvs: [...Array.from({ length: 40 }, () => 0), 0, 1, 1, 1, 1, 0, 0, 0]
39
+ }
40
+ }
41
+ })
42
+ return meshEntity
43
+ }
44
+
45
+ function createBillboards() {
46
+ const plane1 = createPlaneTexture(8, 3, 1)
47
+ const plane2 = createPlaneTexture(12, 3, 1)
48
+ createPlaneTexture(4, 3, 1)
49
+
50
+ const plane5 = createPlaneTexture(8, 3, 8)
51
+ const plane4 = createPlaneTexture(12, 3, 8)
52
+ createPlaneTexture(4, 3, 8)
53
+
54
+ Billboard.create(plane1, {
55
+ billboardMode: BillboardMode.BM_Y_AXE
56
+ })
57
+ Billboard.create(plane2)
58
+ Billboard.create(plane4, {
59
+ oppositeDirection: true,
60
+ billboardMode: BillboardMode.BM_ALL_AXES
61
+ })
62
+ Billboard.create(plane5, {
63
+ oppositeDirection: true,
64
+ billboardMode: BillboardMode.BM_Y_AXE
65
+ })
66
+ }
67
+
68
+ function createTextShape(text: string, position: Vector3, textColor: Color4) {
69
+ const entity = engine.addEntity()
70
+ Transform.create(entity, { position })
71
+ return TextShape.create(entity, {
72
+ text,
73
+ fontSize: 3,
74
+ outlineWidth: 0.1,
75
+ outlineColor: Color3.Black(),
76
+ textColor
77
+ })
78
+ }
79
+
80
+ function createTextShapes() {
81
+ const regularColor = Color4.create(1, 0.2, 0.8, 0.8)
82
+ const oppositeColor = Color4.create(0.8, 0.2, 1, 0.8)
83
+
84
+ createTextShape(
85
+ 'Regular, only Y-rotation',
86
+ Vector3.create(8, 1, 1),
87
+ regularColor
88
+ )
89
+ createTextShape('Regular', Vector3.create(12, 1, 1), regularColor)
90
+ createTextShape('Without billboard', Vector3.create(4, 1, 1), regularColor)
91
+ createTextShape('Opposite, only Y', Vector3.create(8, 1, 8), oppositeColor)
92
+ createTextShape('Opposite', Vector3.create(12, 1, 8), oppositeColor)
93
+ createTextShape('Without billboard', Vector3.create(4, 1, 8), oppositeColor)
94
+ }
95
+
96
+ createBillboards()
97
+ createTextShapes()
98
+
99
+ const BouncingBillboard = engine.defineComponent(
100
+ {
101
+ t: Schemas.Number,
102
+ originalPosition: Schemas.Vector3
103
+ },
104
+ 123123
105
+ )
106
+
107
+ engine.addSystem((dt: number) => {
108
+ for (const [entity] of engine.getEntitiesWith(Billboard, Transform)) {
109
+ if (BouncingBillboard.getOrNull(entity) === null) {
110
+ BouncingBillboard.create(entity, {
111
+ originalPosition: Transform.get(entity).position
112
+ })
113
+ }
114
+
115
+ const bounce = BouncingBillboard.getMutable(entity)
116
+ bounce.t += dt
117
+
118
+ Transform.getMutable(entity).position.y =
119
+ bounce.originalPosition.y + 0.05 * Math.sin(10 * bounce.t)
120
+ }
121
+ })
@@ -0,0 +1,50 @@
1
+ import {
2
+ Entity,
3
+ engine,
4
+ pointerEventsSystem,
5
+ Transform,
6
+ MeshRenderer,
7
+ MeshCollider,
8
+ InputAction
9
+ } from '@dcl/sdk/ecs'
10
+ import { Quaternion, Vector3 } from '@dcl/sdk/math'
11
+
12
+ // Cube factory
13
+ function createCube(x: number, y: number, z: number): Entity {
14
+ const meshEntity = engine.addEntity()
15
+ Transform.create(meshEntity, { position: { x, y, z } })
16
+ MeshRenderer.create(meshEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
17
+ MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
18
+
19
+ return meshEntity
20
+ }
21
+
22
+ // Systems
23
+ function circularSystem(dt: number) {
24
+ const entitiesWithMeshRenderer = engine.getEntitiesWith(
25
+ MeshRenderer,
26
+ Transform
27
+ )
28
+ for (const [entity, _meshRenderer, _transform] of entitiesWithMeshRenderer) {
29
+ const mutableTransform = Transform.getMutable(entity)
30
+
31
+ mutableTransform.rotation = Quaternion.multiply(
32
+ mutableTransform.rotation,
33
+ Quaternion.fromAngleAxis(dt * 10, Vector3.Up())
34
+ )
35
+ }
36
+ }
37
+
38
+ // Init
39
+ const initEntity = createCube(8, 1, 8)
40
+ pointerEventsSystem.onPointerDown(
41
+ initEntity,
42
+ () => {
43
+ createCube(1 + Math.random() * 8, Math.random() * 8, 1 + Math.random() * 8)
44
+ },
45
+ { button: InputAction.IA_PRIMARY, hoverText: 'Press E to spawn' }
46
+ )
47
+
48
+ engine.addSystem(circularSystem)
49
+
50
+ export {}
@@ -0,0 +1 @@
1
+ [{"name":"Billboard","category":"sample","path":"billboard.ts"},{"name":"Cube Spawner","category":"sample","path":"cube-spawner.ts"},{"name":"Material","category":"component","path":"material.ts"},{"name":"Mesh","category":"component","path":"mesh.ts"},{"name":"Pointer Events","category":"sample","path":"pointer-events.ts"},{"name":"Raycast Hit","category":"component","path":"raycast-hit.ts"},{"name":"Raycast Hit many","category":"sample","path":"raycast-hit-many.ts"},{"name":"Container","category":"ui","path":"ui.tsx"}]
@@ -0,0 +1,57 @@
1
+ import {
2
+ Entity,
3
+ engine,
4
+ Transform,
5
+ MeshRenderer,
6
+ Material,
7
+ MaterialTransparencyMode
8
+ } from '@dcl/sdk/ecs'
9
+
10
+ function createSphere(x: number, y: number, z: number): Entity {
11
+ const meshEntity = engine.addEntity()
12
+ Transform.create(meshEntity, { position: { x, y, z } })
13
+ MeshRenderer.create(meshEntity, { mesh: { $case: 'sphere', sphere: {} } })
14
+ return meshEntity
15
+ }
16
+
17
+ Material.create(createSphere(15, 1, 15), {
18
+ material: {
19
+ $case: 'pbr',
20
+ pbr: {
21
+ albedoColor: { r: 0, g: 0, b: 1 },
22
+ reflectivityColor: { r: 0.5, g: 0.5, b: 0.5 },
23
+ metallic: 0.8,
24
+ roughness: 0.1
25
+ }
26
+ }
27
+ })
28
+
29
+ Material.create(createSphere(13, 1, 15), {
30
+ material: {
31
+ $case: 'pbr',
32
+ pbr: {
33
+ albedoColor: { r: 1, g: 1, b: 0 },
34
+ reflectivityColor: { r: 0.5, g: 0.5, b: 0.5 },
35
+ metallic: 0.1,
36
+ roughness: 0.8,
37
+
38
+ alphaTest: 0.2,
39
+ transparencyMode: MaterialTransparencyMode.MTM_ALPHA_TEST
40
+ }
41
+ }
42
+ })
43
+
44
+ Material.create(createSphere(11, 1, 15), {
45
+ material: {
46
+ $case: 'pbr',
47
+ pbr: {
48
+ albedoColor: { r: 0, g: 0, b: 1 },
49
+ reflectivityColor: { r: 0.5, g: 0.5, b: 0.5 },
50
+ metallic: 0.1,
51
+ roughness: 0.1
52
+ }
53
+ }
54
+ })
55
+
56
+ // add textures
57
+ export {}
@@ -0,0 +1,70 @@
1
+ import { engine, Transform, MeshRenderer, MeshCollider } from '@dcl/sdk/ecs'
2
+
3
+ enum Mesh {
4
+ BOX,
5
+ CYLINDER,
6
+ SPHERE,
7
+ CONE
8
+ }
9
+
10
+ function createMesh(
11
+ x: number,
12
+ y: number,
13
+ z: number,
14
+ mesh: Mesh,
15
+ withCollider: boolean = false
16
+ ) {
17
+ const meshEntity = engine.addEntity()
18
+ Transform.create(meshEntity, { position: { x, y, z } })
19
+
20
+ switch (mesh) {
21
+ case Mesh.BOX:
22
+ MeshRenderer.create(meshEntity, {
23
+ mesh: { $case: 'box', box: { uvs: [] } }
24
+ })
25
+ if (withCollider)
26
+ MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
27
+ break
28
+ case Mesh.SPHERE:
29
+ MeshRenderer.create(meshEntity, { mesh: { $case: 'sphere', sphere: {} } })
30
+ if (withCollider)
31
+ MeshCollider.create(meshEntity, {
32
+ mesh: { $case: 'sphere', sphere: {} }
33
+ })
34
+ break
35
+ case Mesh.CONE:
36
+ case Mesh.CYLINDER:
37
+ MeshRenderer.create(meshEntity, {
38
+ mesh: {
39
+ $case: 'cylinder',
40
+ cylinder: {
41
+ radiusBottom: 1,
42
+ radiusTop: mesh === Mesh.CONE ? 0 : 1
43
+ }
44
+ }
45
+ })
46
+ if (withCollider)
47
+ MeshCollider.create(meshEntity, {
48
+ mesh: {
49
+ $case: 'cylinder',
50
+ cylinder: {
51
+ radiusBottom: 1,
52
+ radiusTop: mesh === Mesh.CONE ? 0 : 1
53
+ }
54
+ }
55
+ })
56
+ break
57
+ }
58
+ return meshEntity
59
+ }
60
+
61
+ createMesh(15, 1, 15, Mesh.BOX)
62
+ createMesh(12, 1, 15, Mesh.CONE)
63
+ createMesh(9, 1, 15, Mesh.SPHERE)
64
+ createMesh(6, 1, 15, Mesh.CYLINDER)
65
+ createMesh(15, 1, 1, Mesh.BOX, true)
66
+ createMesh(12, 1, 1, Mesh.CONE, true)
67
+ createMesh(9, 1, 1, Mesh.SPHERE, true)
68
+ createMesh(6, 1, 1, Mesh.CYLINDER, true)
69
+
70
+ export {}
@@ -0,0 +1,62 @@
1
+ import {
2
+ Entity,
3
+ engine,
4
+ Transform,
5
+ MeshRenderer,
6
+ MeshCollider,
7
+ InputAction,
8
+ PBPointerHoverFeedback_Entry,
9
+ PointerHoverFeedback,
10
+ PointerEventType
11
+ } from '@dcl/sdk/ecs'
12
+
13
+ // Cube factory
14
+ function createCube(
15
+ x: number,
16
+ y: number,
17
+ z: number,
18
+ pointerEvents: PBPointerHoverFeedback_Entry[]
19
+ ): Entity {
20
+ const meshEntity = engine.addEntity()
21
+ Transform.create(meshEntity, { position: { x, y, z } })
22
+ MeshRenderer.create(meshEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
23
+ MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
24
+ PointerHoverFeedback.create(meshEntity, { pointerEvents })
25
+ return meshEntity
26
+ }
27
+
28
+ createCube(15, 1, 15, [
29
+ {
30
+ eventType: PointerEventType.PET_DOWN,
31
+ eventInfo: {
32
+ button: InputAction.IA_PRIMARY,
33
+ hoverText: 'PrimaryDown',
34
+ maxDistance: 5,
35
+ showFeedback: true
36
+ }
37
+ }
38
+ ])
39
+
40
+ createCube(13, 1, 15, [
41
+ {
42
+ eventType: PointerEventType.PET_UP,
43
+ eventInfo: {
44
+ button: InputAction.IA_SECONDARY,
45
+ hoverText: 'Secondary Up',
46
+ maxDistance: 5,
47
+ showFeedback: true
48
+ }
49
+ }
50
+ ])
51
+
52
+ createCube(11, 1, 15, [
53
+ {
54
+ eventType: PointerEventType.PET_HOVER_ENTER,
55
+ eventInfo: {
56
+ button: InputAction.IA_ANY,
57
+ hoverText: 'Infinity Hover',
58
+ maxDistance: 10000000,
59
+ showFeedback: true
60
+ }
61
+ }
62
+ ])
@@ -0,0 +1,78 @@
1
+ import {
2
+ engine,
3
+ Transform,
4
+ MeshRenderer,
5
+ MeshCollider,
6
+ InputAction,
7
+ pointerEventsSystem,
8
+ Raycast,
9
+ RaycastQueryType,
10
+ RaycastResult
11
+ } from '@dcl/sdk/ecs'
12
+ import { Vector3 } from '@dcl/sdk/math'
13
+
14
+ function createCube(
15
+ x: number,
16
+ y: number,
17
+ z: number,
18
+ scaleMultiplier: number = 1
19
+ ) {
20
+ const cubeEntity = engine.addEntity()
21
+
22
+ Transform.create(cubeEntity, {
23
+ position: { x, y, z },
24
+ scale: { x: scaleMultiplier, y: scaleMultiplier, z: scaleMultiplier }
25
+ })
26
+
27
+ MeshRenderer.create(cubeEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
28
+ MeshCollider.create(cubeEntity, { mesh: { $case: 'box', box: {} } })
29
+
30
+ return cubeEntity
31
+ }
32
+
33
+ // Create cube to hit
34
+ const cubeEntity = createCube(8, 1, 8)
35
+ const _cubeEntity2 = createCube(8, 1, 13)
36
+ const raycastEntity = engine.addEntity()
37
+
38
+ // Add OnPointerDown component to cube entity to trigger ray casting on interaction
39
+ pointerEventsSystem.onPointerDown(
40
+ cubeEntity,
41
+ () => {
42
+ Raycast.createOrReplace(raycastEntity, {
43
+ origin: Vector3.create(8, 1, 0.1),
44
+ direction: Vector3.create(0, 0, 1),
45
+ maxDistance: 16,
46
+ queryType: RaycastQueryType.RQT_QUERY_ALL
47
+ })
48
+ },
49
+ {
50
+ button: InputAction.IA_POINTER,
51
+ hoverText: 'CAST RAY'
52
+ }
53
+ )
54
+
55
+ // System to detect new raycast responses and instantiate a cube where the ray hits
56
+ let lastRaycastTimestamp = -1
57
+ engine.addSystem(() => {
58
+ for (const [_entity, result] of engine.getEntitiesWith(RaycastResult)) {
59
+ if (result.hits?.length === 0 || result.timestamp <= lastRaycastTimestamp)
60
+ continue
61
+ lastRaycastTimestamp = result.timestamp
62
+
63
+ if (result.hits[0] && result.hits[0].position) {
64
+ createCube(
65
+ result.hits[0].position.x,
66
+ result.hits[0].position.y,
67
+ result.hits[0].position.z,
68
+ 0.3
69
+ )
70
+ }
71
+
72
+ console.log(
73
+ `Hits (this should be '2' the first time): '${result.hits.length}'`
74
+ )
75
+ }
76
+ })
77
+
78
+ export {}
@@ -0,0 +1,75 @@
1
+ import {
2
+ engine,
3
+ Transform,
4
+ MeshRenderer,
5
+ MeshCollider,
6
+ InputAction,
7
+ pointerEventsSystem,
8
+ Raycast,
9
+ RaycastQueryType,
10
+ RaycastResult
11
+ } from '@dcl/sdk/ecs'
12
+ import { Vector3 } from '@dcl/sdk/math'
13
+
14
+ function createCube(
15
+ x: number,
16
+ y: number,
17
+ z: number,
18
+ scaleMultiplier: number = 1
19
+ ) {
20
+ const cubeEntity = engine.addEntity()
21
+
22
+ Transform.create(cubeEntity, {
23
+ position: { x, y, z },
24
+ scale: { x: scaleMultiplier, y: scaleMultiplier, z: scaleMultiplier }
25
+ })
26
+
27
+ MeshRenderer.create(cubeEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
28
+ MeshCollider.create(cubeEntity, { mesh: { $case: 'box', box: {} } })
29
+
30
+ return cubeEntity
31
+ }
32
+
33
+ // Create cube to hit
34
+ const cubeEntity = createCube(8, 1, 8)
35
+ const raycastEntity = engine.addEntity()
36
+
37
+ // Add OnPointerDown component to cube entity to trigger ray casting on interaction
38
+ pointerEventsSystem.onPointerDown(
39
+ cubeEntity,
40
+ () => {
41
+ Raycast.createOrReplace(raycastEntity, {
42
+ origin: Vector3.create(8, 1, 0.1),
43
+ direction: Vector3.create(0, 0, 1),
44
+ maxDistance: 16,
45
+ queryType: RaycastQueryType.RQT_HIT_FIRST
46
+ })
47
+ },
48
+ {
49
+ button: InputAction.IA_POINTER,
50
+ hoverText: 'CAST RAY'
51
+ }
52
+ )
53
+
54
+ // System to detect new raycast responses and instantiate a cube where the ray hits
55
+ let lastRaycastTimestamp = -1
56
+ engine.addSystem(() => {
57
+ for (const [_entity, result] of engine.getEntitiesWith(RaycastResult)) {
58
+ if (result.hits?.length === 0 || result.timestamp <= lastRaycastTimestamp)
59
+ continue
60
+ lastRaycastTimestamp = result.timestamp
61
+
62
+ if (result.hits[0] && result.hits[0].position) {
63
+ createCube(
64
+ result.hits[0].position.x,
65
+ result.hits[0].position.y,
66
+ result.hits[0].position.z,
67
+ 0.3
68
+ )
69
+ }
70
+
71
+ console.log(`Hits (this should be '1'): '${result.hits.length}'`)
72
+ }
73
+ })
74
+
75
+ export {}
@@ -0,0 +1,143 @@
1
+ import {
2
+ Entity,
3
+ engine,
4
+ Transform,
5
+ MeshRenderer,
6
+ MeshCollider,
7
+ InputAction,
8
+ inputSystem,
9
+ PointerHoverFeedback,
10
+ YGAlign,
11
+ YGDisplay,
12
+ YGJustify,
13
+ PointerEventType
14
+ } from '@dcl/sdk/ecs'
15
+ import { Vector3, Color4, Quaternion } from '@dcl/sdk/math'
16
+ import ReactEcs, { UiEntity, ReactEcsRenderer } from '@dcl/sdk/react-ecs'
17
+
18
+ let counter = 0
19
+
20
+ export const uiComponent = () => (
21
+ <UiEntity
22
+ uiTransform={{
23
+ width: 700,
24
+ height: 400,
25
+ margin: { top: '35px', left: '500px' }
26
+ }}
27
+ uiBackground={{ backgroundColor: Color4.create(0.5, 0.8, 0.1, 0.6) }}
28
+ >
29
+ <UiEntity
30
+ uiTransform={{
31
+ width: '100%',
32
+ height: '20%',
33
+ justifyContent: YGJustify.YGJ_CENTER,
34
+ alignItems: YGAlign.YGA_CENTER,
35
+ display: YGDisplay.YGD_FLEX
36
+ }}
37
+ >
38
+ <UiEntity
39
+ uiText={{ value: 'SDK 7', fontSize: 80 }}
40
+ uiBackground={{ backgroundColor: Color4.fromHexString('#fbf0f0') }}
41
+ />
42
+ </UiEntity>
43
+ <UiEntity
44
+ uiTransform={{
45
+ width: '100%',
46
+ height: '20%',
47
+ justifyContent: YGJustify.YGJ_CENTER,
48
+ alignItems: YGAlign.YGA_CENTER,
49
+ display: YGDisplay.YGD_FLEX
50
+ }}
51
+ >
52
+ <UiEntity
53
+ uiText={{ value: `Counter: ${counter}`, fontSize: 60 }}
54
+ uiBackground={{ backgroundColor: Color4.fromHexString('#fbf0f0') }}
55
+ />
56
+ </UiEntity>
57
+ <UiEntity
58
+ uiTransform={{
59
+ width: '100%',
60
+ height: '100px',
61
+ justifyContent: YGJustify.YGJ_CENTER,
62
+ alignItems: YGAlign.YGA_CENTER,
63
+ display: YGDisplay.YGD_FLEX
64
+ }}
65
+ >
66
+ <UiEntity
67
+ uiText={{ value: `Player: ${getPlayerPosition()}`, fontSize: 40 }}
68
+ uiBackground={{ backgroundColor: Color4.fromHexString('#fbf0f0') }}
69
+ />
70
+ </UiEntity>
71
+ </UiEntity>
72
+ )
73
+
74
+ function getPlayerPosition() {
75
+ const playerPosition = Transform.getOrNull(engine.PlayerEntity)
76
+ if (!playerPosition) return ''
77
+ const { x, y, z } = playerPosition.position
78
+ return `{x: ${x.toFixed(2)}, y: ${y.toFixed(2)}, z: ${z.toFixed(2)} }`
79
+ }
80
+
81
+ ReactEcsRenderer.setUiRenderer(uiComponent)
82
+
83
+ // Cube factory
84
+ function createCube(x: number, y: number, z: number, spawner = true): Entity {
85
+ const meshEntity = engine.addEntity()
86
+ Transform.create(meshEntity, { position: { x, y, z } })
87
+ MeshRenderer.create(meshEntity, { mesh: { $case: 'box', box: { uvs: [] } } })
88
+ MeshCollider.create(meshEntity, { mesh: { $case: 'box', box: {} } })
89
+ if (spawner) {
90
+ PointerHoverFeedback.create(meshEntity, {
91
+ pointerEvents: [
92
+ {
93
+ eventType: PointerEventType.PET_DOWN,
94
+ eventInfo: {
95
+ button: InputAction.IA_PRIMARY,
96
+ hoverText: 'Press E to spawn',
97
+ maxDistance: 100,
98
+ showFeedback: true
99
+ }
100
+ }
101
+ ]
102
+ })
103
+ }
104
+ return meshEntity
105
+ }
106
+
107
+ // Systems
108
+ function circularSystem(dt: number) {
109
+ const entitiesWithMeshRenderer = engine.getEntitiesWith(
110
+ MeshRenderer,
111
+ Transform
112
+ )
113
+ for (const [entity, _meshRenderer, _transform] of entitiesWithMeshRenderer) {
114
+ const mutableTransform = Transform.getMutable(entity)
115
+
116
+ mutableTransform.rotation = Quaternion.multiply(
117
+ mutableTransform.rotation,
118
+ Quaternion.fromAngleAxis(dt * 10, Vector3.Up())
119
+ )
120
+ }
121
+ }
122
+
123
+ function spawnerSystem() {
124
+ const clickedCubes = engine.getEntitiesWith(PointerHoverFeedback)
125
+ for (const [entity] of clickedCubes) {
126
+ if (
127
+ inputSystem.isTriggered(
128
+ InputAction.IA_PRIMARY,
129
+ PointerEventType.PET_DOWN,
130
+ entity
131
+ )
132
+ ) {
133
+ counter++
134
+ }
135
+ }
136
+ }
137
+
138
+ // Init
139
+ createCube(8, 1, 8)
140
+ engine.addSystem(circularSystem)
141
+ engine.addSystem(spawnerSystem)
142
+
143
+ export {}