@inglorious/engine 0.1.0 → 0.1.1

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.
Files changed (92) hide show
  1. package/package.json +11 -12
  2. package/src/docs/ai/movement/dynamic/align.js +0 -131
  3. package/src/docs/ai/movement/dynamic/arrive.js +0 -88
  4. package/src/docs/ai/movement/dynamic/dynamic.mdx +0 -99
  5. package/src/docs/ai/movement/dynamic/dynamic.stories.js +0 -58
  6. package/src/docs/ai/movement/dynamic/evade.js +0 -72
  7. package/src/docs/ai/movement/dynamic/face.js +0 -90
  8. package/src/docs/ai/movement/dynamic/flee.js +0 -38
  9. package/src/docs/ai/movement/dynamic/look-where-youre-going.js +0 -114
  10. package/src/docs/ai/movement/dynamic/match-velocity.js +0 -92
  11. package/src/docs/ai/movement/dynamic/pursue.js +0 -72
  12. package/src/docs/ai/movement/dynamic/seek.js +0 -37
  13. package/src/docs/ai/movement/dynamic/wander.js +0 -71
  14. package/src/docs/ai/movement/kinematic/align.js +0 -122
  15. package/src/docs/ai/movement/kinematic/arrive.js +0 -78
  16. package/src/docs/ai/movement/kinematic/face.js +0 -82
  17. package/src/docs/ai/movement/kinematic/flee.js +0 -36
  18. package/src/docs/ai/movement/kinematic/kinematic.mdx +0 -67
  19. package/src/docs/ai/movement/kinematic/kinematic.stories.js +0 -42
  20. package/src/docs/ai/movement/kinematic/seek.js +0 -34
  21. package/src/docs/ai/movement/kinematic/wander-as-seek.js +0 -62
  22. package/src/docs/ai/movement/kinematic/wander.js +0 -28
  23. package/src/docs/bounds.js +0 -7
  24. package/src/docs/code-reuse.js +0 -35
  25. package/src/docs/collision/circles.js +0 -58
  26. package/src/docs/collision/collision.mdx +0 -27
  27. package/src/docs/collision/collision.stories.js +0 -22
  28. package/src/docs/collision/platform.js +0 -76
  29. package/src/docs/collision/tilemap.js +0 -181
  30. package/src/docs/empty.js +0 -1
  31. package/src/docs/engine.mdx +0 -81
  32. package/src/docs/engine.stories.js +0 -37
  33. package/src/docs/event-handlers.js +0 -68
  34. package/src/docs/framerate.js +0 -37
  35. package/src/docs/game.jsx +0 -15
  36. package/src/docs/image/image.js +0 -19
  37. package/src/docs/image/image.stories.js +0 -22
  38. package/src/docs/image/sprite.js +0 -39
  39. package/src/docs/image/tilemap.js +0 -84
  40. package/src/docs/input/controls.js +0 -67
  41. package/src/docs/input/gamepad.js +0 -67
  42. package/src/docs/input/input.mdx +0 -55
  43. package/src/docs/input/input.stories.js +0 -27
  44. package/src/docs/input/keyboard.js +0 -58
  45. package/src/docs/input/mouse.js +0 -32
  46. package/src/docs/instances.js +0 -49
  47. package/src/docs/player/dynamic/double-jump.js +0 -90
  48. package/src/docs/player/dynamic/dynamic.stories.js +0 -32
  49. package/src/docs/player/dynamic/jump.js +0 -83
  50. package/src/docs/player/dynamic/modern-controls.js +0 -57
  51. package/src/docs/player/dynamic/shooter-controls.js +0 -51
  52. package/src/docs/player/dynamic/tank-controls.js +0 -44
  53. package/src/docs/player/kinematic/double-jump.js +0 -90
  54. package/src/docs/player/kinematic/jump.js +0 -82
  55. package/src/docs/player/kinematic/kinematic.stories.js +0 -32
  56. package/src/docs/player/kinematic/modern-controls.js +0 -56
  57. package/src/docs/player/kinematic/shooter-controls.js +0 -48
  58. package/src/docs/player/kinematic/tank-controls.js +0 -42
  59. package/src/docs/quick-start/first-game.js +0 -49
  60. package/src/docs/quick-start/hello-world.js +0 -1
  61. package/src/docs/quick-start.mdx +0 -127
  62. package/src/docs/quick-start.stories.js +0 -17
  63. package/src/docs/recipes/add-and-remove.js +0 -71
  64. package/src/docs/recipes/add-instance.js +0 -42
  65. package/src/docs/recipes/decision-tree.js +0 -169
  66. package/src/docs/recipes/random-instances.js +0 -25
  67. package/src/docs/recipes/recipes.mdx +0 -81
  68. package/src/docs/recipes/recipes.stories.js +0 -37
  69. package/src/docs/recipes/remove-instance.js +0 -52
  70. package/src/docs/recipes/states.js +0 -64
  71. package/src/docs/ui/button.js +0 -28
  72. package/src/docs/ui/form.stories.js +0 -55
  73. package/src/docs/ui-chooser.jsx +0 -6
  74. package/src/docs/utils/data-structures/object.mdx +0 -47
  75. package/src/docs/utils/data-structures/objects.mdx +0 -30
  76. package/src/docs/utils/functions/functions.mdx +0 -34
  77. package/src/docs/utils/math/geometry/circle.mdx +0 -55
  78. package/src/docs/utils/math/geometry/point.mdx +0 -38
  79. package/src/docs/utils/math/geometry/rectangle.mdx +0 -24
  80. package/src/docs/utils/math/geometry/segment.mdx +0 -55
  81. package/src/docs/utils/math/geometry/triangle.mdx +0 -22
  82. package/src/docs/utils/math/linear-algebra/2d.mdx +0 -22
  83. package/src/docs/utils/math/linear-algebra/quaternion.mdx +0 -21
  84. package/src/docs/utils/math/linear-algebra/quaternions.mdx +0 -22
  85. package/src/docs/utils/math/linear-algebra/vector.mdx +0 -177
  86. package/src/docs/utils/math/linear-algebra/vectors.mdx +0 -58
  87. package/src/docs/utils/math/numbers.mdx +0 -76
  88. package/src/docs/utils/math/random.mdx +0 -35
  89. package/src/docs/utils/math/statistics.mdx +0 -38
  90. package/src/docs/utils/math/trigonometry.mdx +0 -85
  91. package/src/docs/utils/physics/friction.mdx +0 -20
  92. package/src/docs/utils/physics/gravity.mdx +0 -28
@@ -1,48 +0,0 @@
1
- import { enableCharacter } from "@inglorious/game/decorators/character.js"
2
- import { enableClampToBounds } from "@inglorious/game/decorators/clamp-to-bounds.js"
3
- import { enableShooterControls } from "@inglorious/game/decorators/controls/kinematic/shooter.js"
4
- import {
5
- createControls,
6
- enableControls,
7
- } from "@inglorious/game/decorators/input/controls.js"
8
- import { enableMouse } from "@inglorious/game/decorators/input/mouse.js"
9
- import { pi } from "@inglorious/utils/math/trigonometry.js"
10
-
11
- export default {
12
- types: {
13
- mouse: [enableMouse()],
14
-
15
- ...enableControls(),
16
-
17
- character: [
18
- enableCharacter(),
19
- enableShooterControls(),
20
- enableClampToBounds(),
21
- ],
22
- },
23
-
24
- instances: {
25
- mouse: {
26
- type: "mouse",
27
- position: [400, 0, 300],
28
- },
29
-
30
- ...createControls("input0", {
31
- ArrowLeft: "left",
32
- ArrowRight: "right",
33
- ArrowDown: "down",
34
- ArrowUp: "up",
35
- KeyA: "left",
36
- KeyD: "right",
37
- KeyS: "down",
38
- KeyW: "up",
39
- }),
40
-
41
- character: {
42
- type: "character",
43
- maxAngularSpeed: 2 * pi(),
44
- maxSpeed: 250,
45
- position: [400, 0, 300],
46
- },
47
- },
48
- }
@@ -1,42 +0,0 @@
1
- import { enableCharacter } from "@inglorious/game/decorators/character.js"
2
- import { enableClampToBounds } from "@inglorious/game/decorators/clamp-to-bounds"
3
- import { enableTankControls } from "@inglorious/game/decorators/controls/kinematic/tank.js"
4
- import {
5
- createControls,
6
- enableControls,
7
- } from "@inglorious/game/decorators/input/controls.js"
8
-
9
- export default {
10
- types: {
11
- ...enableControls(),
12
-
13
- character: [enableCharacter(), enableTankControls(), enableClampToBounds()],
14
- },
15
-
16
- instances: {
17
- ...createControls("input0", {
18
- ArrowUp: "up",
19
- ArrowDown: "down",
20
- ArrowLeft: "left",
21
- ArrowRight: "right",
22
- KeyW: "up",
23
- KeyS: "down",
24
- KeyA: "left",
25
- KeyD: "right",
26
- Btn12: "up",
27
- Btn13: "down",
28
- Btn14: "left",
29
- Btn15: "right",
30
- Axis0: "strafe",
31
- Axis1: "upDown",
32
- Axis2: "leftRight",
33
- }),
34
-
35
- character: {
36
- type: "character",
37
- maxAngularSpeed: 10,
38
- maxSpeed: 250,
39
- position: [400, 0, 300],
40
- },
41
- },
42
- }
@@ -1,49 +0,0 @@
1
- export default {
2
- types: {
3
- character: {
4
- draw(ctx, instance) {
5
- const {
6
- size = 24,
7
- orientation = 0,
8
- stroke = "black",
9
- fill = "transparent",
10
- } = instance
11
-
12
- const radius = size * 0.5
13
-
14
- ctx.save()
15
- ctx.rotate(-orientation)
16
- ctx.translate(radius - 1, 0)
17
-
18
- ctx.fillStyle = "black"
19
-
20
- ctx.beginPath()
21
- ctx.moveTo(0, 6)
22
- ctx.lineTo(0, -6)
23
- ctx.lineTo(6, 0)
24
- ctx.fill()
25
- ctx.closePath()
26
- ctx.restore()
27
-
28
- ctx.save()
29
- ctx.lineWidth = 1
30
- ctx.strokeStyle = stroke
31
- ctx.fillStyle = fill
32
-
33
- ctx.beginPath()
34
- ctx.arc(0, 0, radius, 0, 2 * 3.14)
35
- ctx.fill()
36
- ctx.stroke()
37
- ctx.closePath()
38
- ctx.restore()
39
- },
40
- },
41
- },
42
-
43
- instances: {
44
- character: {
45
- type: "character",
46
- position: [400, 0, 300],
47
- },
48
- },
49
- }
@@ -1 +0,0 @@
1
- export default {}
@@ -1,127 +0,0 @@
1
- import { Canvas, Meta, Source } from '@storybook/blocks'
2
- import * as QuickStart from './quick-start.stories'
3
-
4
- import helloWorld from './quick-start/hello-world?raw'
5
- import firstGame from './quick-start/first-game?raw'
6
-
7
- <Meta of={QuickStart} />
8
-
9
- # Quick Start Guide
10
-
11
- Welcome to Inglorious Engine! This guide will get you up and running in minutes.
12
-
13
- ## What is Inglorious Engine?
14
-
15
- Inglorious Engine is a **functional programming** game engine for JavaScript. Instead of object-oriented programming, it uses:
16
- - **Global state** - One source of truth for your entire game
17
- - **Immutability** - State changes create new state, never modify existing
18
- - **Pure functions** - Predictable, testable, and reusable functions
19
- - **Function composition** - Combine behaviors like building blocks
20
-
21
- ## Your First Game
22
-
23
- ### Step 1: Basic Setup
24
-
25
- Create an HTML file with this structure:
26
-
27
- ```html
28
- <!doctype html>
29
- <html lang="en">
30
- <body>
31
- <canvas id="canvas"></canvas>
32
-
33
- <script type="importmap">
34
- {
35
- "imports": {
36
- "immer": "https://unpkg.com/immer@10.1.1/dist/immer.mjs",
37
- "@inglorious/": "/src/",
38
- "game": "./my-game.js"
39
- }
40
- }
41
- </script>
42
-
43
- <script type="module" src="/src/main.js"></script>
44
- </body>
45
- </html>
46
- ```
47
-
48
- ### Step 2: Hello World
49
-
50
- Create `my-game.js` with the simplest possible game:
51
-
52
- <Source dark code={helloWorld} />
53
-
54
- <Canvas of={QuickStart.HelloWorld} />
55
-
56
- This creates an 800x600 canvas with a light grey background. Not exciting yet, but it's working!
57
-
58
- ### Step 3: Add a Character
59
-
60
- Let's add something to the scene:
61
-
62
- <Source dark code={firstGame} />
63
-
64
- <Canvas of={QuickStart.FirstGame} />
65
-
66
- ## Key Concepts
67
-
68
- ### 1. Game Configuration Structure
69
-
70
- Every game has this structure:
71
- ```javascript
72
- export default {
73
- // Static definitions - never change
74
- types: {
75
- // Define what kinds of objects exist
76
- },
77
-
78
- // Dynamic state - changes during gameplay
79
- instances: {
80
- // Actual objects in the scene
81
- }
82
- }
83
- ```
84
-
85
- ### 2. Types vs Instances
86
-
87
- - **Types**: Define what something *is* (like a blueprint)
88
- - **Instances**: Define specific *examples* of that type (like actual objects)
89
-
90
- ### 3. Event Handlers
91
-
92
- To make things move and interact, use event handlers:
93
-
94
- ```javascript
95
- types: {
96
- character: {
97
- // Drawing logic here
98
- draw(ctx, instance) { /* ... */ },
99
-
100
- // Event handlers here
101
- events: {
102
- 'game:update': (instance, event, { dt, config, instances }) => {
103
- // This runs every frame
104
- // Update position, velocity, etc.
105
- }
106
- }
107
- }
108
- }
109
- ```
110
-
111
- ## Next Steps
112
-
113
- Now that you have a basic understanding of the engine, you're ready to dive deeper.
114
-
115
- Continue to the **[Core Concepts](/docs/engine--docs)** page to learn about event handlers, code reuse, and other essential features.
116
-
117
- ## Why Functional Programming?
118
-
119
- Traditional game engines use objects with methods that modify internal state. Inglorious Engine is different:
120
-
121
- ✅ **Predictable**: Same input always produces same output
122
- ✅ **Testable**: Pure functions are easy to test
123
- ✅ **Composable**: Combine behaviors like LEGO blocks
124
- ✅ **Debuggable**: State changes are explicit and traceable
125
- ✅ **Performant**: Immutability enables efficient rendering
126
-
127
- Ready to build your first game? Let's go!
@@ -1,17 +0,0 @@
1
- import UiChooser from "@inglorious/docs/ui-chooser.jsx"
2
-
3
- import firstGame from "./quick-start/first-game.js"
4
- import helloWorld from "./quick-start/hello-world.js"
5
-
6
- export default {
7
- title: "Quick Start",
8
- component: UiChooser,
9
- }
10
-
11
- export const HelloWorld = {
12
- args: { config: helloWorld },
13
- }
14
-
15
- export const FirstGame = {
16
- args: { config: firstGame },
17
- }
@@ -1,71 +0,0 @@
1
- import { enableCharacter } from "@inglorious/game/decorators/character.js"
2
- import { enableMouse } from "@inglorious/game/decorators/input/mouse.js"
3
- import { filter } from "@inglorious/utils/data-structures/object.js"
4
- import { random } from "@inglorious/utils/math/rng.js"
5
- import { pi } from "@inglorious/utils/math/trigonometry.js"
6
-
7
- export default {
8
- types: {
9
- mouse: [
10
- enableMouse(),
11
- {
12
- "scene:click"(instance, event, options) {
13
- const { instances, notify } = options
14
- const characters = filter(
15
- instances,
16
- (_, { type }) => type === "character",
17
- )
18
- const ids = Object.keys(characters)
19
-
20
- const maxId = ids.length
21
- ? Number(ids[ids.length - 1].replace("character", ""))
22
- : 0
23
-
24
- notify({
25
- id: "instance:add",
26
- payload: {
27
- id: `character${maxId + 1}`,
28
- type: "character",
29
- position: event.payload,
30
- orientation: random(0, 2 * pi(), 0.01),
31
- collisions: {
32
- hitbox: {
33
- shape: "circle",
34
- radius: 12,
35
- },
36
- },
37
- },
38
- })
39
- },
40
-
41
- // this event handler is needed for React
42
- "instance:click"(instance, event, { notify }) {
43
- notify({ id: "instance:remove", payload: event.payload })
44
- },
45
- },
46
- ],
47
-
48
- character: [
49
- enableCharacter(),
50
- {
51
- // this event handler is needed in React
52
- "instance:click"(instance, event, { notify }) {
53
- notify({ id: "instance:remove", payload: event.payload })
54
- },
55
- },
56
- ],
57
- },
58
-
59
- instances: {
60
- mouse: {
61
- type: "mouse",
62
- position: [400, 0, 300],
63
- collisions: {
64
- hitbox: {
65
- shape: "circle",
66
- radius: 1,
67
- },
68
- },
69
- },
70
- },
71
- }
@@ -1,42 +0,0 @@
1
- import { enableCharacter } from "@inglorious/game/decorators/character.js"
2
- import { enableMouse } from "@inglorious/game/decorators/input/mouse.js"
3
- import { filter } from "@inglorious/utils/data-structures/object.js"
4
- import { random } from "@inglorious/utils/math/rng.js"
5
- import { pi } from "@inglorious/utils/math/trigonometry.js"
6
-
7
- export default {
8
- types: {
9
- mouse: [
10
- enableMouse(),
11
- {
12
- "mouse:click"(instance, event, options) {
13
- const { instances, notify } = options
14
- const characters = filter(
15
- instances,
16
- (_, { type }) => type === "character",
17
- )
18
- const ids = Object.keys(characters)
19
-
20
- notify({
21
- id: "instance:add",
22
- payload: {
23
- id: `character${ids.length + 1}`,
24
- type: "character",
25
- position: event.payload,
26
- orientation: random(0, 2 * pi(), 0.01),
27
- },
28
- })
29
- },
30
- },
31
- ],
32
-
33
- character: [enableCharacter()],
34
- },
35
-
36
- instances: {
37
- mouse: {
38
- type: "mouse",
39
- position: [400, 0, 300],
40
- },
41
- },
42
- }
@@ -1,169 +0,0 @@
1
- import arrive from "@inglorious/engine/ai/movement/kinematic/arrive.js"
2
- import { enableFsm } from "@inglorious/game/decorators/fsm.js"
3
- import { enableSprite } from "@inglorious/game/decorators/image/sprite.js"
4
- import { enableMouse } from "@inglorious/game/decorators/input/mouse.js"
5
- import { Sprite } from "@inglorious/game/sprite.js"
6
- import { decide } from "@inglorious/utils/algorithms/decision-tree.js"
7
- import { merge } from "@inglorious/utils/data-structures/objects.js"
8
- import { length } from "@inglorious/utils/math/linear-algebra/vector.js"
9
- import { subtract } from "@inglorious/utils/math/linear-algebra/vectors.js"
10
-
11
- // A reusable decision tree node
12
- const wakeUp = () => ({
13
- test: ({ instance, target }) => {
14
- const distance = length(subtract(target.position, instance.position))
15
- return distance >= 10
16
- },
17
- true: () => "aware",
18
- false: ({ instance }) => instance.state,
19
- })
20
-
21
- // Our decision tree
22
- const nextState = {
23
- test: ({ instance }) => instance.state,
24
- idle: () => ({
25
- test: ({ instance, target }) => {
26
- const distance = length(subtract(target.position, instance.position))
27
- return distance < 250
28
- },
29
- true: () => "aware",
30
- false: ({ instance }) => instance.state,
31
- }),
32
- chasing: () => ({
33
- test: ({ instance, target }) => {
34
- const distance = length(subtract(target.position, instance.position))
35
- return distance >= 250
36
- },
37
- true: () => "idle",
38
- false: () => ({
39
- test: ({ instance, target }) => {
40
- const distance = length(subtract(target.position, instance.position))
41
- return distance < 10
42
- },
43
- true: () => "sleepy",
44
- false: ({ instance }) => instance.state,
45
- }),
46
- }),
47
- sleepy: wakeUp,
48
- sleeping: wakeUp,
49
- }
50
-
51
- export default {
52
- types: {
53
- mouse: [enableMouse()],
54
-
55
- cat: [
56
- enableSprite(),
57
- enableFsm({
58
- idle: {
59
- "game:update"(instance, event, options) {
60
- const { mouse } = options.instances
61
-
62
- Sprite.play("idle", instance, options)
63
-
64
- instance.state = decide(nextState, { instance, target: mouse })
65
- },
66
- },
67
-
68
- aware: {
69
- "game:update"(instance, event, options) {
70
- Sprite.play("aware", instance, options)
71
- },
72
-
73
- "sprite:animationEnd"(instance, event) {
74
- const { id, spriteState } = event.payload
75
-
76
- // always check who originated the event and which sprite is running!
77
- if (id === instance.id && spriteState === "aware") {
78
- instance.state = "chasing"
79
- }
80
- },
81
- },
82
-
83
- chasing: {
84
- "game:update"(instance, event, options) {
85
- const { mouse } = options.instances
86
-
87
- merge(instance, arrive(instance, mouse, options))
88
-
89
- const spriteState = Sprite.move8(instance)
90
- Sprite.play(spriteState, instance, options)
91
-
92
- instance.state = decide(nextState, { instance, target: mouse })
93
- },
94
- },
95
-
96
- sleepy: {
97
- "game:update"(instance, event, options) {
98
- const { mouse } = options.instances
99
-
100
- Sprite.play("sleepy", instance, options)
101
-
102
- instance.state = decide(nextState, { instance, target: mouse })
103
- },
104
-
105
- "sprite:animationEnd"(instance, event) {
106
- const { id, spriteState } = event.payload
107
-
108
- // always check who originated the event and which sprite is running!
109
- if (id === instance.id && spriteState === "sleepy") {
110
- instance.state = "sleeping"
111
- }
112
- },
113
- },
114
-
115
- sleeping: {
116
- "game:update"(instance, event, options) {
117
- const { mouse } = options.instances
118
-
119
- Sprite.play("sleeping", instance, options)
120
-
121
- instance.state = decide(nextState, { instance, target: mouse })
122
- },
123
- },
124
- }),
125
- ],
126
- },
127
-
128
- instances: {
129
- game: {
130
- pixelated: true,
131
- },
132
-
133
- mouse: {
134
- type: "mouse",
135
- position: [0, 0, 0],
136
- },
137
-
138
- neko: {
139
- type: "cat",
140
- state: "idle",
141
- maxSpeed: 250,
142
- position: [400, 0, 300],
143
- sprite: {
144
- image: {
145
- id: "neko",
146
- src: "/sprites/neko.png",
147
- imageSize: [192, 192],
148
- tileSize: [32, 32],
149
- scale: 2,
150
- },
151
- speed: 0.2,
152
- frames: {
153
- idle: [4],
154
- aware: [0, 4],
155
- leftUp: [0x80000000 + 23, 0x80000000 + 29],
156
- up: [28, 30, 28, 31],
157
- rightUp: [23, 29],
158
- right: [16, 22],
159
- rightDown: [13, 14],
160
- down: [1, 2, 1, 7],
161
- leftDown: [0x80000000 + 13, 0x80000000 + 14],
162
- left: [0x80000000 + 16, 0x80000000 + 22],
163
- sleepy: [4, 10, 10, 3, 9, 15, 9, 15, 15],
164
- sleeping: [26, 26, 27, 27],
165
- },
166
- },
167
- },
168
- },
169
- }
@@ -1,25 +0,0 @@
1
- import { enableCharacter } from "@inglorious/game/decorators/character.js"
2
- import { random } from "@inglorious/utils/math/rng.js"
3
- import { pi } from "@inglorious/utils/math/trigonometry.js"
4
-
5
- export default {
6
- types: {
7
- character: [enableCharacter()],
8
- },
9
-
10
- instances: {
11
- ...Object.fromEntries(
12
- Array(100)
13
- .fill(null)
14
- .map((_, index) => [
15
- `character${index + 1}`,
16
- {
17
- id: `character${index + 1}`,
18
- type: "character",
19
- position: [random(0, 800), 0, random(0, 600)],
20
- orientation: random(0, 2 * pi(), 0.01),
21
- },
22
- ]),
23
- ),
24
- },
25
- }
@@ -1,81 +0,0 @@
1
- import { Canvas, Meta, Source } from '@storybook/blocks'
2
- import * as Recipes from './recipes.stories'
3
-
4
- import addAndRemove from './add-and-remove?raw'
5
- import addInstance from './add-instance?raw'
6
- import decisionTree from './decision-tree?raw'
7
- import randomInstances from './random-instances?raw'
8
- import removeInstance from './remove-instance?raw'
9
- import states from './states?raw'
10
-
11
- <Meta of={Recipes} />
12
-
13
- # Recipes
14
-
15
- Some common patterns that can be used in your game. Check the source code of each recipe and take inspiration!
16
-
17
- ## Spawning Random Instances
18
-
19
- The game configuration is pure JavaScript, so there's not much difference between defining the instances one by one or writing some code that generates them automatically!
20
-
21
- Here we are using a couple of utility functions from the [rng](/?path=/docs/utils-math-rng--docs) and [trigonometry](/?path=/docs/utils-math-trigonometry--docs) packages.
22
-
23
- <Source dark code={randomInstances} />
24
-
25
- <Canvas of={Recipes.RandomInstances} />
26
-
27
- ## Adding An Instance
28
-
29
- Programmatically adding a new instance to the scene is as easy as sending an event to the game engine asking nicely.
30
-
31
- Try clicking anywhere on the scene to create a new instance with random orientation.
32
-
33
- Here, apart from some math functions, we are also using a predefined mouse [input](/?path=/docs/games-input--docs) package that allows us to position a cursor and handle its events.
34
-
35
- <Source dark code={addInstance} />
36
-
37
- <Canvas of={Recipes.AddInstance} />
38
-
39
- ## Removing An Instance
40
-
41
- Removing an instance is pretty much the same: we notify the engine of our intention and we enjoy the result.
42
-
43
- Try clicking on any instance do remove it from the scene.
44
-
45
- <Source dark code={removeInstance} />
46
-
47
- <Canvas of={Recipes.RemoveInstance} />
48
-
49
- ## Add And Remove
50
-
51
- Clicking on a character will prevent the event from bubbling on the scene, so it's safe to add and remove characters by using the same strategy: click as if there's no tomorrow!
52
-
53
- The most complex part of this code is generating new incremental ids, which is not even mandatory. You know best what's good for your game!
54
-
55
- <Source dark code={addAndRemove} />
56
-
57
- <Canvas of={Recipes.AddAndRemove} />
58
-
59
- ## States
60
-
61
- Adding a states to our character is very easy, in fact every game so far was secretely using states already!
62
-
63
- We just need to wrap our event handlers into a `states` object, set an initial `state` on our instance, and transition from one state to another inside our event handlers.
64
-
65
- Try moving the cursor near the character to make it hunt you, and then moving it away to see the character wander around aimlessly.
66
-
67
- This code may seem a lot, but it's just a merge of the *Arrive* and *Wander* [Kinematic AI Movement](/?path=/docs/games-ai-movement-kinematic--docs) examples so feel free to take a look at them before approaching this one.
68
-
69
- <Source dark code={states} />
70
-
71
- <Canvas of={Recipes.States} />
72
-
73
- ## Decision Trees
74
-
75
- Decision trees are another sweet feature built-in inside of Inglorious Engine. The following example doesn't really need one, but why not?
76
-
77
- This game also showcases sprites!
78
-
79
- <Source dark code={decisionTree} />
80
-
81
- <Canvas of={Recipes.DecisionTree} />