@origingame/create-game 0.2.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.
- package/README.md +2 -2
- package/archetypes/README.md +2 -1
- package/archetypes/arena/.origin/setup +14 -0
- package/archetypes/arena/LICENSES.md +8 -0
- package/archetypes/arena/README.md +67 -0
- package/archetypes/arena/assets/audio/coin.ogt +9 -0
- package/archetypes/arena/assets/audio/dash.ogt +9 -0
- package/archetypes/arena/assets/audio/win.ogt +9 -0
- package/archetypes/arena/assets/fx/coin.ogt +20 -0
- package/archetypes/arena/assets/looks/arena.ogt +10 -0
- package/archetypes/arena/gitattributes +22 -0
- package/archetypes/arena/gitignore +8 -0
- package/archetypes/arena/host.d.ts +46 -0
- package/archetypes/arena/package.json +18 -0
- package/archetypes/arena/project.ogt +14 -0
- package/archetypes/arena/src/game.ts +314 -0
- package/archetypes/arena/src/main.ts +100 -0
- package/archetypes/arena/tests/duel.og.ts +32 -0
- package/archetypes/arena/tests/solo.og.ts +22 -0
- package/archetypes/arena/tsconfig.json +17 -0
- package/archetypes/idle/LICENSES.md +1 -1
- package/archetypes/idle/README.md +5 -5
- package/archetypes/idle/assets/looks/idle.ogt +2 -2
- package/archetypes/idle/assets/{skins → styles}/sparkorb/LICENSES.md +6 -6
- package/archetypes/idle/assets/{skins/sparkorb/skin.ogt → styles/sparkorb/style.ogt} +47 -47
- package/archetypes/idle/package.json +1 -1
- package/archetypes/idle/project.ogt +1 -1
- package/archetypes/idle/references/metal/card.png +0 -0
- package/archetypes/idle/references/metal/orbit.png +0 -0
- package/archetypes/idle/references/metal/title.png +0 -0
- package/archetypes/idle/src/components.ts +1 -1
- package/archetypes/idle/src/main.ts +5 -5
- package/archetypes/idle/src/ui.ts +13 -13
- package/archetypes/idle/tools/make-assets.py +5 -5
- package/archetypes/match3/package.json +1 -1
- package/archetypes/match3/project.ogt +1 -1
- package/archetypes/rhythm/LICENSES.md +1 -1
- package/archetypes/rhythm/README.md +5 -5
- package/archetypes/rhythm/assets/{skins → styles}/lanebeat/LICENSES.md +6 -6
- package/archetypes/rhythm/assets/{skins/lanebeat/skin.ogt → styles/lanebeat/style.ogt} +45 -45
- package/archetypes/rhythm/package.json +1 -1
- package/archetypes/rhythm/project.ogt +1 -1
- package/archetypes/rhythm/references/metal/results.png +0 -0
- package/archetypes/rhythm/references/metal/title.png +0 -0
- package/archetypes/rhythm/src/components.ts +1 -1
- package/archetypes/rhythm/src/main.ts +3 -3
- package/archetypes/rhythm/src/ui.ts +12 -12
- package/archetypes/roguelike/LICENSES.md +1 -1
- package/archetypes/roguelike/README.md +5 -5
- package/archetypes/roguelike/assets/{skins → styles}/lampdive/LICENSES.md +6 -6
- package/archetypes/roguelike/assets/{skins/lampdive/skin.ogt → styles/lampdive/style.ogt} +41 -41
- package/archetypes/roguelike/package.json +1 -1
- package/archetypes/roguelike/project.ogt +1 -1
- package/archetypes/roguelike/references/metal/over.png +0 -0
- package/archetypes/roguelike/references/metal/title.png +0 -0
- package/archetypes/roguelike/src/components.ts +1 -1
- package/archetypes/roguelike/src/main.ts +2 -2
- package/archetypes/roguelike/src/ui.ts +8 -8
- package/archetypes/runner/package.json +1 -1
- package/archetypes/runner/project.ogt +1 -1
- package/archetypes/third-person/LICENSES.md +1 -1
- package/archetypes/third-person/README.md +4 -4
- package/archetypes/third-person/assets/{skins → styles}/ember/LICENSES.md +4 -4
- package/archetypes/third-person/assets/{skins/ember/skin.ogt → styles/ember/style.ogt} +40 -41
- package/archetypes/third-person/package.json +1 -1
- package/archetypes/third-person/project.ogt +1 -1
- package/archetypes/third-person/references/metal/beacon.png +0 -0
- package/archetypes/third-person/references/metal/dawn.png +0 -0
- package/archetypes/third-person/references/metal/title.png +0 -0
- package/archetypes/third-person/references/webgl2/beacon.png +0 -0
- package/archetypes/third-person/src/components.ts +1 -1
- package/archetypes/third-person/src/main.ts +3 -3
- package/archetypes/third-person/src/sound.ts +1 -1
- package/archetypes/third-person/src/ui.ts +11 -11
- package/archetypes/topdown/package.json +1 -1
- package/archetypes/topdown/project.ogt +1 -1
- package/archetypes/tower-defense/LICENSES.md +1 -1
- package/archetypes/tower-defense/README.md +5 -5
- package/archetypes/tower-defense/assets/{skins → styles}/pathguard/LICENSES.md +4 -4
- package/archetypes/tower-defense/assets/styles/pathguard/atlas.png +0 -0
- package/archetypes/tower-defense/assets/styles/pathguard/style.ogt +111 -0
- package/archetypes/tower-defense/package.json +1 -1
- package/archetypes/tower-defense/project.ogt +1 -1
- package/archetypes/tower-defense/references/metal/end.png +0 -0
- package/archetypes/tower-defense/references/metal/title.png +0 -0
- package/archetypes/tower-defense/references/metal/wave.png +0 -0
- package/archetypes/tower-defense/src/components.ts +1 -1
- package/archetypes/tower-defense/src/main.ts +2 -2
- package/archetypes/tower-defense/src/ui.ts +20 -18
- package/bin/create.ts +11 -8
- package/looks/catalogue.json +40 -40
- package/package.json +2 -2
- package/template/README.md +2 -1
- package/template/assets/audio/sting.ogt +10 -0
- package/template/assets/timelines/intro.ogt +101 -0
- package/template/assets/timelines/narration.srt +11 -0
- package/template/host.d.ts +46 -0
- package/template/package.json +1 -1
- package/template/project.ogt +1 -1
- package/template/references/metal/intro-4.png +0 -0
- package/template/references/metal/intro-8.png +0 -0
- package/template/src/main.ts +1 -1
- package/template/tests/frames.ts +134 -0
- package/template/tests/intro.og.ts +65 -0
- package/template/tests/smoke.og.ts +30 -36
- package/template/tsconfig.json +1 -1
- package/template-2d/LICENSES.md +1 -0
- package/template-2d/README.md +6 -2
- package/template-2d/assets/rigs/keeper.ogt +292 -0
- package/template-2d/assets/rigs/keeper.png +0 -0
- package/template-2d/assets/rigs/keeper.png.ogt +7 -0
- package/template-2d/package.json +1 -1
- package/template-2d/project.ogt +1 -1
- package/template-2d/src/main.ts +240 -4
- package/template-2d/tests/keeper.og.ts +178 -0
- package/archetypes/tower-defense/assets/skins/pathguard/atlas.png +0 -0
- package/archetypes/tower-defense/assets/skins/pathguard/skin.ogt +0 -111
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/ChakraPetch-BoldItalic.ttf +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/ChakraPetch-BoldItalic.ttf.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/OFL.txt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Orbitron-Medium.ttf +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Orbitron-Medium.ttf.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Rajdhani-Bold.ttf +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/Rajdhani-Bold.ttf.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/atlas.png +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/atlas.png.ogt +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/icons.png +0 -0
- /package/archetypes/idle/assets/{skins → styles}/sparkorb/icons.png.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/ChakraPetch-Medium.ttf +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/ChakraPetch-Medium.ttf.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/JetBrainsMono-Regular.ttf +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/JetBrainsMono-Regular.ttf.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/OFL.txt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/Orbitron-Bold.ttf +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/Orbitron-Bold.ttf.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/atlas.png +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/atlas.png.ogt +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/icons.png +0 -0
- /package/archetypes/rhythm/assets/{skins → styles}/lanebeat/icons.png.ogt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/DotGothic16-Regular.ttf +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/DotGothic16-Regular.ttf.ogt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/OFL.txt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/atlas.png +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/atlas.png.ogt +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/icons.png +0 -0
- /package/archetypes/roguelike/assets/{skins → styles}/lampdive/icons.png.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Cinzel-Bold.ttf +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Cinzel-Bold.ttf.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Newsreader-Medium.ttf +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/Newsreader-Medium.ttf.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/OFL.txt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/atlas.png +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/atlas.png.ogt +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/icons.png +0 -0
- /package/archetypes/third-person/assets/{skins → styles}/ember/icons.png.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/Fredoka-SemiBold.ttf +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/Fredoka-SemiBold.ttf.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/LilitaOne-Regular.ttf +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/LilitaOne-Regular.ttf.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/OFL.txt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/atlas.png.ogt +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/icons.png +0 -0
- /package/archetypes/tower-defense/assets/{skins → styles}/pathguard/icons.png.ogt +0 -0
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
type rig2d
|
|
2
|
+
version 1
|
|
3
|
+
---
|
|
4
|
+
# The lamp keeper (templates/game-2d): a 2D rig drawn as textured triangles.
|
|
5
|
+
# Bones are pixels with +y up, unit 20 pixels to a world unit; the legs are
|
|
6
|
+
# two-bone IK chains planted on the ramp by og.IkTarget2D (src/main.ts, Plant),
|
|
7
|
+
# the cape a weighted mesh over the hip and two cape bones, fluttered by the
|
|
8
|
+
# idle clip's deform keys. The walk clip bobs the hip on Bézier keys, swings
|
|
9
|
+
# the arm and trails the cape; its "step" events mark each foot's contact,
|
|
10
|
+
# and src/main.ts's Plant moves the feet's IK targets in step with it (a
|
|
11
|
+
# 0.8 s cycle of a 0.4 m stride: the keeper walks 0.5 m/s). Written by hand
|
|
12
|
+
# (og-game §8, the rig2d grammar).
|
|
13
|
+
texture "keeper.png"
|
|
14
|
+
filter nearest
|
|
15
|
+
unit 20
|
|
16
|
+
bone root {
|
|
17
|
+
}
|
|
18
|
+
bone hip {
|
|
19
|
+
parent root
|
|
20
|
+
at 0 22
|
|
21
|
+
rotation 90
|
|
22
|
+
length 16
|
|
23
|
+
}
|
|
24
|
+
bone head {
|
|
25
|
+
parent hip
|
|
26
|
+
at 16 0
|
|
27
|
+
rotation -90
|
|
28
|
+
}
|
|
29
|
+
bone arm {
|
|
30
|
+
parent hip
|
|
31
|
+
at 14 -5
|
|
32
|
+
rotation 180
|
|
33
|
+
length 13
|
|
34
|
+
}
|
|
35
|
+
bone thigh-b {
|
|
36
|
+
parent hip
|
|
37
|
+
at 0 2
|
|
38
|
+
rotation 180
|
|
39
|
+
length 11
|
|
40
|
+
}
|
|
41
|
+
bone shin-b {
|
|
42
|
+
parent thigh-b
|
|
43
|
+
at 11 0
|
|
44
|
+
length 11
|
|
45
|
+
}
|
|
46
|
+
bone thigh-f {
|
|
47
|
+
parent hip
|
|
48
|
+
at 0 -2
|
|
49
|
+
rotation 180
|
|
50
|
+
length 11
|
|
51
|
+
}
|
|
52
|
+
bone shin-f {
|
|
53
|
+
parent thigh-f
|
|
54
|
+
at 11 0
|
|
55
|
+
length 11
|
|
56
|
+
}
|
|
57
|
+
bone cape-1 {
|
|
58
|
+
parent hip
|
|
59
|
+
at 15 4
|
|
60
|
+
rotation 180
|
|
61
|
+
length 12
|
|
62
|
+
}
|
|
63
|
+
bone cape-2 {
|
|
64
|
+
parent cape-1
|
|
65
|
+
at 12 0
|
|
66
|
+
length 12
|
|
67
|
+
}
|
|
68
|
+
bone foot-b {
|
|
69
|
+
parent root
|
|
70
|
+
at -3 0
|
|
71
|
+
}
|
|
72
|
+
bone foot-f {
|
|
73
|
+
parent root
|
|
74
|
+
at 3 0
|
|
75
|
+
}
|
|
76
|
+
slot cape {
|
|
77
|
+
bone hip
|
|
78
|
+
attachment cape
|
|
79
|
+
}
|
|
80
|
+
slot thigh-b {
|
|
81
|
+
bone thigh-b
|
|
82
|
+
attachment thigh-b
|
|
83
|
+
color 0.72 0.72 0.8 1
|
|
84
|
+
}
|
|
85
|
+
slot shin-b {
|
|
86
|
+
bone shin-b
|
|
87
|
+
attachment shin-b
|
|
88
|
+
color 0.72 0.72 0.8 1
|
|
89
|
+
}
|
|
90
|
+
slot boot-b {
|
|
91
|
+
bone shin-b
|
|
92
|
+
attachment boot-b
|
|
93
|
+
color 0.72 0.72 0.8 1
|
|
94
|
+
}
|
|
95
|
+
slot torso {
|
|
96
|
+
bone hip
|
|
97
|
+
attachment torso
|
|
98
|
+
}
|
|
99
|
+
slot thigh-f {
|
|
100
|
+
bone thigh-f
|
|
101
|
+
attachment thigh-f
|
|
102
|
+
}
|
|
103
|
+
slot shin-f {
|
|
104
|
+
bone shin-f
|
|
105
|
+
attachment shin-f
|
|
106
|
+
}
|
|
107
|
+
slot boot-f {
|
|
108
|
+
bone shin-f
|
|
109
|
+
attachment boot-f
|
|
110
|
+
}
|
|
111
|
+
slot head {
|
|
112
|
+
bone head
|
|
113
|
+
attachment head
|
|
114
|
+
}
|
|
115
|
+
slot arm {
|
|
116
|
+
bone arm
|
|
117
|
+
attachment arm
|
|
118
|
+
}
|
|
119
|
+
slot lantern {
|
|
120
|
+
bone arm
|
|
121
|
+
attachment lantern
|
|
122
|
+
}
|
|
123
|
+
region torso {
|
|
124
|
+
slot torso
|
|
125
|
+
rect 0 0 12 20
|
|
126
|
+
at 8 0
|
|
127
|
+
rotation -90
|
|
128
|
+
size 12 20
|
|
129
|
+
}
|
|
130
|
+
region head {
|
|
131
|
+
slot head
|
|
132
|
+
rect 15 0 14 12
|
|
133
|
+
at 0 5
|
|
134
|
+
rotation 0
|
|
135
|
+
size 14 12
|
|
136
|
+
}
|
|
137
|
+
region arm {
|
|
138
|
+
slot arm
|
|
139
|
+
rect 32 16 4 14
|
|
140
|
+
at 6.5 0
|
|
141
|
+
rotation 90
|
|
142
|
+
size 4 14
|
|
143
|
+
}
|
|
144
|
+
region lantern {
|
|
145
|
+
slot lantern
|
|
146
|
+
rect 52 16 8 10
|
|
147
|
+
at 15 0
|
|
148
|
+
rotation 90
|
|
149
|
+
size 8 10
|
|
150
|
+
}
|
|
151
|
+
region thigh-b {
|
|
152
|
+
slot thigh-b
|
|
153
|
+
rect 32 0 5 12
|
|
154
|
+
at 5.5 0
|
|
155
|
+
rotation 90
|
|
156
|
+
size 5 12
|
|
157
|
+
}
|
|
158
|
+
region shin-b {
|
|
159
|
+
slot shin-b
|
|
160
|
+
rect 40 0 5 12
|
|
161
|
+
at 5.5 0
|
|
162
|
+
rotation 90
|
|
163
|
+
size 5 12
|
|
164
|
+
}
|
|
165
|
+
region boot-b {
|
|
166
|
+
slot boot-b
|
|
167
|
+
rect 48 0 10 5
|
|
168
|
+
at 10.5 2
|
|
169
|
+
rotation 90
|
|
170
|
+
size 10 5
|
|
171
|
+
}
|
|
172
|
+
region thigh-f {
|
|
173
|
+
slot thigh-f
|
|
174
|
+
rect 32 0 5 12
|
|
175
|
+
at 5.5 0
|
|
176
|
+
rotation 90
|
|
177
|
+
size 5 12
|
|
178
|
+
}
|
|
179
|
+
region shin-f {
|
|
180
|
+
slot shin-f
|
|
181
|
+
rect 40 0 5 12
|
|
182
|
+
at 5.5 0
|
|
183
|
+
rotation 90
|
|
184
|
+
size 5 12
|
|
185
|
+
}
|
|
186
|
+
region boot-f {
|
|
187
|
+
slot boot-f
|
|
188
|
+
rect 48 0 10 5
|
|
189
|
+
at 10.5 2
|
|
190
|
+
rotation 90
|
|
191
|
+
size 10 5
|
|
192
|
+
}
|
|
193
|
+
mesh cape {
|
|
194
|
+
slot cape
|
|
195
|
+
vertex 0 32 hip 16.000 16.000 1
|
|
196
|
+
vertex 6 32 hip 16.000 9.000 1
|
|
197
|
+
vertex 12 32 hip 16.000 2.000 1
|
|
198
|
+
vertex 0 40 hip 7.000 16.000 0.4 cape-1 8.000 -12.000 0.6
|
|
199
|
+
vertex 6 40 hip 7.000 9.000 0.4 cape-1 8.000 -5.000 0.6
|
|
200
|
+
vertex 12 40 hip 7.000 2.000 0.4 cape-1 8.000 2.000 0.6
|
|
201
|
+
vertex 0 48 cape-1 17.000 -12.000 0.5 cape-2 5.000 -12.000 0.5
|
|
202
|
+
vertex 6 48 cape-1 17.000 -5.000 0.5 cape-2 5.000 -5.000 0.5
|
|
203
|
+
vertex 12 48 cape-1 17.000 2.000 0.5 cape-2 5.000 2.000 0.5
|
|
204
|
+
vertex 0 56 cape-2 14.000 -12.000 1
|
|
205
|
+
vertex 6 56 cape-2 14.000 -5.000 1
|
|
206
|
+
vertex 12 56 cape-2 14.000 2.000 1
|
|
207
|
+
triangles 0 3 1 1 3 4 1 4 2 2 4 5 3 6 4 4 6 7 4 7 5 5 7 8 6 9 7 7 9 10 7 10 8 8 10 11
|
|
208
|
+
}
|
|
209
|
+
ik leg-b {
|
|
210
|
+
bones thigh-b shin-b
|
|
211
|
+
target foot-b
|
|
212
|
+
bend clockwise
|
|
213
|
+
}
|
|
214
|
+
ik leg-f {
|
|
215
|
+
bones thigh-f shin-f
|
|
216
|
+
target foot-f
|
|
217
|
+
bend clockwise
|
|
218
|
+
}
|
|
219
|
+
clip idle {
|
|
220
|
+
duration 2
|
|
221
|
+
loop true
|
|
222
|
+
bone hip {
|
|
223
|
+
translate 0 0 0
|
|
224
|
+
translate 1 0 -1.5
|
|
225
|
+
translate 2 0 0
|
|
226
|
+
}
|
|
227
|
+
bone head {
|
|
228
|
+
rotate 0 0
|
|
229
|
+
rotate 1 4
|
|
230
|
+
rotate 2 0
|
|
231
|
+
}
|
|
232
|
+
bone arm {
|
|
233
|
+
rotate 0 4
|
|
234
|
+
rotate 1 -8
|
|
235
|
+
rotate 2 4
|
|
236
|
+
}
|
|
237
|
+
bone cape-1 {
|
|
238
|
+
rotate 0 -4
|
|
239
|
+
rotate 1 8
|
|
240
|
+
rotate 2 -4
|
|
241
|
+
}
|
|
242
|
+
bone cape-2 {
|
|
243
|
+
rotate 0 -6
|
|
244
|
+
rotate 1 12
|
|
245
|
+
rotate 2 -6
|
|
246
|
+
}
|
|
247
|
+
deform cape {
|
|
248
|
+
key 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
249
|
+
key 0.5 0 0 0 0 0 0 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -3 0 -3 0 -3 0 -3 0 -3 0 -3 0 -5 0 -5 0 -5
|
|
250
|
+
key 1 0 0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 0 1 0 2 0 2 0 2 0 2 0 2 0 2 0 3 0 3 0 3
|
|
251
|
+
key 1.5 0 0 0 0 0 0 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -3.5 0 -3.5 0 -3.5 0 -3.5 0 -3.5 0 -3.5 0 -6 0 -6 0 -6
|
|
252
|
+
key 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
253
|
+
}
|
|
254
|
+
event 0 "inhale"
|
|
255
|
+
}
|
|
256
|
+
clip walk {
|
|
257
|
+
duration 0.8
|
|
258
|
+
loop true
|
|
259
|
+
bone hip {
|
|
260
|
+
translate 0 0 -1 curve 0.3 0 0.6 1
|
|
261
|
+
translate 0.2 0 0.6 curve 0.4 0 0.7 1
|
|
262
|
+
translate 0.4 0 -1 curve 0.3 0 0.6 1
|
|
263
|
+
translate 0.6 0 0.6 curve 0.4 0 0.7 1
|
|
264
|
+
translate 0.8 0 -1
|
|
265
|
+
}
|
|
266
|
+
bone head {
|
|
267
|
+
rotate 0 -2
|
|
268
|
+
rotate 0.4 2
|
|
269
|
+
rotate 0.8 -2
|
|
270
|
+
}
|
|
271
|
+
bone arm {
|
|
272
|
+
rotate 0 16 curve 0.42 0 0.58 1
|
|
273
|
+
rotate 0.4 -12 curve 0.42 0 0.58 1
|
|
274
|
+
rotate 0.8 16
|
|
275
|
+
}
|
|
276
|
+
bone cape-1 {
|
|
277
|
+
rotate 0 -10
|
|
278
|
+
rotate 0.2 -14
|
|
279
|
+
rotate 0.4 -10
|
|
280
|
+
rotate 0.6 -14
|
|
281
|
+
rotate 0.8 -10
|
|
282
|
+
}
|
|
283
|
+
bone cape-2 {
|
|
284
|
+
rotate 0 -12
|
|
285
|
+
rotate 0.3 -20
|
|
286
|
+
rotate 0.5 -12
|
|
287
|
+
rotate 0.7 -20
|
|
288
|
+
rotate 0.8 -12
|
|
289
|
+
}
|
|
290
|
+
event 0 "step"
|
|
291
|
+
event 0.4 "step"
|
|
292
|
+
}
|
|
Binary file
|
package/template-2d/package.json
CHANGED
package/template-2d/project.ogt
CHANGED
|
@@ -7,7 +7,7 @@ version 1
|
|
|
7
7
|
name "Origin Game 2D"
|
|
8
8
|
id "origin-game-2d"
|
|
9
9
|
# The engine this game is written against (design §9: upgrades are explicit).
|
|
10
|
-
engine "0.
|
|
10
|
+
engine "0.4.0"
|
|
11
11
|
entry "src/main.ts"
|
|
12
12
|
# 2d: an orthographic camera, sprites, flipbooks, tilemaps and 2D physics.
|
|
13
13
|
profile "2d"
|
package/template-2d/src/main.ts
CHANGED
|
@@ -11,11 +11,22 @@
|
|
|
11
11
|
// Everything the starter shows is in og-game §8 (sprites, flipbooks,
|
|
12
12
|
// tilemaps), §13 (the controller) and og-feel §12 (its tunables).
|
|
13
13
|
//
|
|
14
|
+
// Beside the spawn a lamp keeper stands on a ramp: a 2D skeletal rig
|
|
15
|
+
// (assets/rigs/keeper.ogt, og.Skeleton2D) whose cape is a weighted mesh the
|
|
16
|
+
// idle clip deforms, whose feet two-bone IK planted on the slope
|
|
17
|
+
// (og.IkTarget2D, the Plant system), and whose lantern lights the sprite
|
|
18
|
+
// layers through og.Lighting2D (og-game §8; og-anim's 2D skeletons). Sent
|
|
19
|
+
// along the ramp (`keeper:<x>`), it turns to face the way (a paper turn
|
|
20
|
+
// over a few ticks), plays its walk clip there, each foot planted while it
|
|
21
|
+
// carries the keeper and lifted while it swings, lets both feet land when
|
|
22
|
+
// it arrives, turns back and breathes again (the Walk and Plant systems).
|
|
23
|
+
// No foot ever moves faster than the gait's own swing.
|
|
24
|
+
//
|
|
14
25
|
// The frame's look is data: GameDesc.look names a file under assets/looks/
|
|
15
26
|
// that extends a preset of the style catalogue, applied before start runs.
|
|
16
27
|
|
|
17
28
|
import { og, defineComponent, defineResource, defineSystem, bool, f32, u32, SHAPE_BOX } from "@origingame/engine";
|
|
18
|
-
import type { FlipbookInfo, Result, TileObject } from "@origingame/engine";
|
|
29
|
+
import type { FlipbookInfo, Result, Rig2DInfo, TileObject, World } from "@origingame/engine";
|
|
19
30
|
|
|
20
31
|
/** The courier's clips, in the sheet's file order (og-game §8): `start` checks them. */
|
|
21
32
|
const CLIP = { idle: 0, run: 1, jump: 2, fall: 3 } as const;
|
|
@@ -28,6 +39,26 @@ const BOX = { w: 0.9, h: 1.9 } as const;
|
|
|
28
39
|
/** Below this the courier fell into the pit. */
|
|
29
40
|
const FALL_Y = -3;
|
|
30
41
|
const LIVES = 3;
|
|
42
|
+
/** The keeper's ramp: a plank from (x0, y0) on the roof rising at `slope` (tan 12°) to x1. */
|
|
43
|
+
const RAMP = { x0: 4.5, y0: 2, x1: 7.6, slope: 0.21256, sinHalf: 0.104528, cosHalf: 0.994522 } as const;
|
|
44
|
+
/** The ramp's top at x. */
|
|
45
|
+
const rampY = (x: number): number => RAMP.y0 + RAMP.slope * (x - RAMP.x0);
|
|
46
|
+
/** The keeper's ankles and its root above the ramp (its legs reach 1.1 from a hip 1.1 up: a slight bend), the lantern from its feet, in world units. */
|
|
47
|
+
const ANKLE = 0.12;
|
|
48
|
+
const LIFT = 0.08;
|
|
49
|
+
const LANTERN = { x: 0.25, y: 1.0 } as const;
|
|
50
|
+
/** The keeper's gait: the walk clip's 0.8 s cycle carries it a stride of 0.4 m (a step per foot), each foot lifted at most `lift` mid-swing. */
|
|
51
|
+
const WALK = { speed: 0.5, stride: 0.4, lift: 0.08 } as const;
|
|
52
|
+
/**
|
|
53
|
+
* The fastest a foot moves (m/s): the gait's swing at its start, a stride
|
|
54
|
+
* forward in half a cycle (twice the walking speed) while it rises up the
|
|
55
|
+
* slope and off it (the lift's parabola, 4 lift over the swing's length,
|
|
56
|
+
* at its steepest). A foot sent elsewhere (setting off, stopping, a turn)
|
|
57
|
+
* steps there no faster.
|
|
58
|
+
*/
|
|
59
|
+
const FOOT_SPEED = Math.hypot(2 * WALK.speed, 2 * WALK.speed * RAMP.slope + (8 * WALK.lift * WALK.speed) / WALK.stride);
|
|
60
|
+
/** A turn's ticks: the rig narrows to its edge and opens the other way (og.Transform's scale x, never 0). */
|
|
61
|
+
const TURN_TICKS = 12;
|
|
31
62
|
|
|
32
63
|
/** The courier. */
|
|
33
64
|
export const Hero = defineComponent("Hero", { spawnX: f32(0, { unit: "m" }), spawnY: f32(0, { unit: "m" }) });
|
|
@@ -35,6 +66,18 @@ export const Hero = defineComponent("Hero", { spawnX: f32(0, { unit: "m" }), spa
|
|
|
35
66
|
/** A coin of the map's `coin` objects; taken once. */
|
|
36
67
|
export const Coin = defineComponent("Coin", { taken: bool() });
|
|
37
68
|
|
|
69
|
+
/**
|
|
70
|
+
* One of the keeper's feet: its IK target stands on the ramp `dx` ahead of
|
|
71
|
+
* the keeper (behind when negative), `lag` of a gait cycle after the front
|
|
72
|
+
* foot; `x`, `y` is where the foot is.
|
|
73
|
+
*/
|
|
74
|
+
export const Plant = defineComponent("Plant", {
|
|
75
|
+
dx: f32(0, { unit: "m" }),
|
|
76
|
+
lag: f32(0, { min: 0, max: 1 }),
|
|
77
|
+
x: f32(0, { unit: "m" }),
|
|
78
|
+
y: f32(0, { unit: "m" }),
|
|
79
|
+
});
|
|
80
|
+
|
|
38
81
|
/** A voice: the sound bit (Sound) it plays when Game.sfx asks for it. */
|
|
39
82
|
export const Voice = defineComponent("Voice", { bit: u32() });
|
|
40
83
|
|
|
@@ -58,6 +101,28 @@ export const Game = defineResource("Game", {
|
|
|
58
101
|
/** The HUD's touch controls this tick (a phone): the run and the held jump. */
|
|
59
102
|
touchX: f32(0, { min: -1, max: 1 }),
|
|
60
103
|
touchJump: bool(),
|
|
104
|
+
/** The keeper's breaths: og.Skeleton2DEvent "inhale" (the idle clip's event at 0). */
|
|
105
|
+
inhales: u32(),
|
|
106
|
+
/** The keeper's footfalls: og.Skeleton2DEvent "step" (the walk clip's, one per foot). */
|
|
107
|
+
steps: u32(),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
/** Where the keeper walks (`keeper:<x>`), how far it has walked since it set off (its gait's phase), its turn and stop, and its clips. */
|
|
111
|
+
export const KeeperWalk = defineResource("KeeperWalk", {
|
|
112
|
+
goal: f32(6, { unit: "m" }),
|
|
113
|
+
walked: f32(0, { unit: "m" }),
|
|
114
|
+
walking: bool(),
|
|
115
|
+
/** -1 facing left (towards the spawn), 1 right. */
|
|
116
|
+
facing: f32(-1),
|
|
117
|
+
/** Ticks of a turn done (0: not turning). */
|
|
118
|
+
turning: u32(),
|
|
119
|
+
/** og.Transform's scale x: 1, or through a turn from 1 towards -1. */
|
|
120
|
+
squash: f32(1),
|
|
121
|
+
/** Arrived, the feet stepping to stand (Plant sets `landed` when both are down). */
|
|
122
|
+
settling: bool(),
|
|
123
|
+
landed: bool(true),
|
|
124
|
+
idle: u32(),
|
|
125
|
+
walk: u32(),
|
|
61
126
|
});
|
|
62
127
|
|
|
63
128
|
function must<T>(r: Result<T>): T {
|
|
@@ -161,6 +226,133 @@ export const Animate = defineSystem("Animate", { reads: [Hero, og.PlatformerCont
|
|
|
161
226
|
}
|
|
162
227
|
});
|
|
163
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Walks the keeper towards KeeperWalk.goal along the ramp at the gait's
|
|
231
|
+
* speed (by scaled time, as the clip plays: paused, both hold), facing the
|
|
232
|
+
* way it goes, with the walk clip. Facing the other way first, it turns
|
|
233
|
+
* over TURN_TICKS (og.Transform's scale x eased from 1 to -1, never 0, then
|
|
234
|
+
* flipX), its feet stepping across with it. On arrival it holds the walk
|
|
235
|
+
* pose until Plant has both feet down, turns to face the spawn, and once
|
|
236
|
+
* they are down again breathes with the idle clip (which starts over,
|
|
237
|
+
* breathing in).
|
|
238
|
+
*/
|
|
239
|
+
export const Walk = defineSystem("Walk", { writes: [KeeperWalk, og.Skeleton2D, og.Transform], after: ["Control"] }, (_q, time, world) => {
|
|
240
|
+
const keeper = world.find("keeper");
|
|
241
|
+
if (keeper === null) return;
|
|
242
|
+
const w = must(world.resource(KeeperWalk));
|
|
243
|
+
const x = must(world.get(keeper, og.Transform)).position.x;
|
|
244
|
+
const s = must(world.get(keeper, og.Skeleton2D));
|
|
245
|
+
const place = (nx: number) => must(world.set(keeper, og.Transform, { position: { x: nx, y: rampY(nx) + LIFT, z: 0 }, scale: { x: w.squash, y: 1, z: 1 } }));
|
|
246
|
+
if (w.turning > 0 || (time.scaledDt > 0 && w.turning === 0 && wantsTurn(w, x))) {
|
|
247
|
+
// A turn: the rig narrows to its edge and opens facing the other way.
|
|
248
|
+
if (time.scaledDt === 0) return;
|
|
249
|
+
w.turning += 1;
|
|
250
|
+
if (w.turning < TURN_TICKS) {
|
|
251
|
+
w.squash = Math.cos((Math.PI * (w.turning - 0.5)) / (TURN_TICKS - 0.5));
|
|
252
|
+
} else {
|
|
253
|
+
w.turning = 0;
|
|
254
|
+
w.squash = 1;
|
|
255
|
+
w.facing = -w.facing;
|
|
256
|
+
must(world.set(keeper, og.Skeleton2D, { flipX: w.facing < 0 }));
|
|
257
|
+
}
|
|
258
|
+
place(x);
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
const left = w.goal - x;
|
|
262
|
+
if (left !== 0) {
|
|
263
|
+
const step = WALK.speed * time.scaledDt;
|
|
264
|
+
const arrived = Math.abs(left) <= step;
|
|
265
|
+
const nx = arrived ? w.goal : x + Math.sign(left) * step;
|
|
266
|
+
w.walked = (w.walking ? w.walked : 0) + Math.abs(nx - x);
|
|
267
|
+
w.walking = !arrived;
|
|
268
|
+
w.settling = arrived;
|
|
269
|
+
w.landed = false;
|
|
270
|
+
place(nx);
|
|
271
|
+
// Walking plays the walk clip from its first step; arrived, it holds its pose while the feet land.
|
|
272
|
+
if (s.clip !== w.walk) must(world.set(keeper, og.Skeleton2D, { clip: w.walk, speed: 1 }));
|
|
273
|
+
else if (arrived) must(world.set(keeper, og.Skeleton2D, { speed: 0 }));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (w.settling && w.landed) w.settling = false;
|
|
277
|
+
// Standing, both feet down and facing the spawn: breathe.
|
|
278
|
+
if (!w.settling && w.landed && w.facing < 0 && s.clip !== w.idle) must(world.set(keeper, og.Skeleton2D, { clip: w.idle, speed: 1 }));
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
/** Whether the keeper must turn before it goes on: towards its goal, or back to the spawn once it stands with both feet down. */
|
|
282
|
+
function wantsTurn(w: { goal: number; facing: number; settling: boolean; walking: boolean }, x: number): boolean {
|
|
283
|
+
const left = w.goal - x;
|
|
284
|
+
if (left !== 0) return Math.sign(left) !== w.facing && !w.walking;
|
|
285
|
+
return !w.settling && w.facing > 0;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Puts the keeper's feet on the ramp (og.IkTarget2D: the legs' two-bone IK
|
|
290
|
+
* reaches each target, the knees bend as the hip bobs). Standing, each foot
|
|
291
|
+
* is `dx` from the keeper; walking, the front foot's gait phase is the
|
|
292
|
+
* distance walked over the stride and the back foot's half a cycle later:
|
|
293
|
+
* for half a cycle a foot stays where it is on the plank while the keeper
|
|
294
|
+
* passes over it, for the other half it swings a stride forward, lifted on
|
|
295
|
+
* a parabola. A foot steps to where it should be at most FOOT_SPEED fast,
|
|
296
|
+
* lifted while it is still on its way, so turning, setting off and
|
|
297
|
+
* stopping are steps, not jumps (each leg hangs from its own hip: the
|
|
298
|
+
* front foot crosses to the other side in a turn). Keeps the lantern's light at its hand, and
|
|
299
|
+
* counts the clips' breaths and footfalls.
|
|
300
|
+
*/
|
|
301
|
+
export const Plant2D = defineSystem("Plant", { reads: [og.Skeleton2DEvent], writes: [Game, KeeperWalk, Plant, og.IkTarget2D, og.Transform], after: ["Walk"] }, (q, time, world) => {
|
|
302
|
+
const keeper = world.find("keeper");
|
|
303
|
+
if (keeper === null) return;
|
|
304
|
+
const at = must(world.get(keeper, og.Transform)).position;
|
|
305
|
+
const w = must(world.resource(KeeperWalk));
|
|
306
|
+
const reach = FOOT_SPEED * time.scaledDt;
|
|
307
|
+
let down = true;
|
|
308
|
+
for (const a of q.archetypes()) {
|
|
309
|
+
const plant = a.column(Plant);
|
|
310
|
+
const target = a.column(og.IkTarget2D).target;
|
|
311
|
+
for (let i = 0; i < a.count; i++) {
|
|
312
|
+
let ahead = plant.dx[i]!;
|
|
313
|
+
let lift = 0;
|
|
314
|
+
if (w.walking) {
|
|
315
|
+
const phase = w.walked / WALK.stride + plant.lag[i]!;
|
|
316
|
+
const p = phase - Math.floor(phase);
|
|
317
|
+
if (p < 0.5) {
|
|
318
|
+
// Planted: it slides back under the keeper as fast as the keeper walks.
|
|
319
|
+
ahead += WALK.stride * (0.25 - p);
|
|
320
|
+
} else {
|
|
321
|
+
const s = (p - 0.5) * 2;
|
|
322
|
+
ahead += WALK.stride * (s - 0.5) * 0.5;
|
|
323
|
+
lift = WALK.lift * 4 * s * (1 - s);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// Turning, each foot follows its hip as the rig narrows and opens the other way.
|
|
327
|
+
const wx = at.x + w.facing * w.squash * ahead;
|
|
328
|
+
const [x, y] = toward(plant.x[i]!, plant.y[i]!, wx, rampY(wx) + ANKLE + lift, reach);
|
|
329
|
+
// Still on its way: lifted with how far it has left (a step's height at half a stride), as fast as it may rise.
|
|
330
|
+
const rest = Math.abs(wx - x);
|
|
331
|
+
const [fx, fy] = rest > 1e-6 ? toward(plant.x[i]!, plant.y[i]!, x, Math.max(y, rampY(x) + ANKLE + WALK.lift * Math.min(1, rest / (WALK.stride / 2))), reach) : [x, y];
|
|
332
|
+
plant.x[i] = fx;
|
|
333
|
+
plant.y[i] = fy;
|
|
334
|
+
target[i * 2] = fx;
|
|
335
|
+
target[i * 2 + 1] = fy;
|
|
336
|
+
if (Math.hypot(wx - fx, rampY(wx) + ANKLE + lift - fy) > 1e-5 || lift > 0) down = false;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
w.landed = down;
|
|
340
|
+
const lantern = world.find("lantern");
|
|
341
|
+
if (lantern !== null) must(world.set(lantern, og.Transform, { position: { x: at.x - w.facing * w.squash * LANTERN.x, y: at.y + LANTERN.y, z: 0 } }));
|
|
342
|
+
const g = must(world.resource(Game));
|
|
343
|
+
for (const e of world.events(og.Skeleton2DEvent)) {
|
|
344
|
+
if (e.name === "inhale") g.inhales += 1;
|
|
345
|
+
else if (e.name === "step") g.steps += 1;
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
/** (x, y) moved towards (tx, ty) by at most `reach`. */
|
|
350
|
+
function toward(x: number, y: number, tx: number, ty: number, reach: number): [number, number] {
|
|
351
|
+
const d = Math.hypot(tx - x, ty - y);
|
|
352
|
+
if (d <= reach) return [tx, ty];
|
|
353
|
+
return [x + ((tx - x) * reach) / d, y + ((ty - y) * reach) / d];
|
|
354
|
+
}
|
|
355
|
+
|
|
164
356
|
/** Plays each sound asked for once: a voice still playing is stopped this tick and played again the next. */
|
|
165
357
|
export const Voices = defineSystem("Voices", { reads: [Voice], writes: [Game, og.AudioSource], after: ["Pickups"] }, (q, _time, world) => {
|
|
166
358
|
const g = must(world.resource(Game));
|
|
@@ -212,6 +404,42 @@ export const Hud = defineSystem("Hud", { writes: [Game] }, (_q, _time, world) =>
|
|
|
212
404
|
}
|
|
213
405
|
});
|
|
214
406
|
|
|
407
|
+
/**
|
|
408
|
+
* The lamp keeper: a plank ramp, the rig on it facing the spawn, a foot
|
|
409
|
+
* target per leg, and its lantern's light; og.Lighting2D lights layers 1
|
|
410
|
+
* and 2 (the keeper, the courier, the coins), the city stays as drawn.
|
|
411
|
+
*/
|
|
412
|
+
function spawnKeeper(world: World, rig: Rig2DInfo): void {
|
|
413
|
+
const idle = og.anim.clip(rig, "idle");
|
|
414
|
+
const walk = og.anim.clip(rig, "walk");
|
|
415
|
+
if (idle < 0 || walk < 0) throw new Error("rigs/keeper.ogt needs clips idle and walk");
|
|
416
|
+
const mid = (RAMP.x0 + RAMP.x1) / 2;
|
|
417
|
+
const plank = must(world.spawn({ name: "ramp", position: { x: mid, y: rampY(mid) - 0.2, z: 0 }, quaternion: { x: 0, y: 0, z: RAMP.sinHalf, w: RAMP.cosHalf } }));
|
|
418
|
+
// The plank is a region of the keeper's texture (pixels 24..64 x 32..40 of 64 x 64).
|
|
419
|
+
must(world.insert(plank, og.Sprite, { texture: rig.texture, width: RAMP.x1 - RAMP.x0, height: 0.4, uvMin: { x: 0.375, y: 0.5 }, uvMax: { x: 1, y: 0.625 }, layer: 1 }));
|
|
420
|
+
const x = 6;
|
|
421
|
+
const keeper = must(world.spawn({ name: "keeper", position: { x, y: rampY(x) + LIFT, z: 0 } }));
|
|
422
|
+
must(world.insert(keeper, og.Skeleton2D, { rig: rig.rig, clip: idle, flipX: true, layer: 1 }));
|
|
423
|
+
const w = must(world.resource(KeeperWalk));
|
|
424
|
+
Object.assign(w, { goal: x, walked: 0, walking: false, facing: -1, turning: 0, squash: 1, settling: false, landed: true, idle, walk });
|
|
425
|
+
// Facing left, the front foot is the left one; the back foot steps half a cycle later.
|
|
426
|
+
for (const [name, ahead, lag] of [["leg-f", 0.15, 0], ["leg-b", -0.15, 0.5]] as const) {
|
|
427
|
+
const constraint = rig.constraints.indexOf(name);
|
|
428
|
+
if (constraint < 0) throw new Error(`rigs/keeper.ogt has no ik ${name}`);
|
|
429
|
+
const fx = x - ahead;
|
|
430
|
+
const foot = must(world.spawn({ name: `keeper-${name}` }));
|
|
431
|
+
must(world.insert(foot, og.IkTarget2D, { skeleton: keeper, constraint, target: { x: fx, y: rampY(fx) + ANKLE }, tolerance: 0.02 }));
|
|
432
|
+
must(world.insert(foot, Plant, { dx: ahead, lag, x: fx, y: rampY(fx) + ANKLE }));
|
|
433
|
+
}
|
|
434
|
+
const light = must(world.spawn({ name: "lantern", position: { x: x + LANTERN.x, y: rampY(x) + LIFT + LANTERN.y, z: 0 } }));
|
|
435
|
+
must(world.insert(light, og.Light2D, { color: { r: 1, g: 0.72, b: 0.35 }, intensity: 1.6, radius: 4, castShadows: false }));
|
|
436
|
+
const lighting = must(world.resource(og.Lighting2D));
|
|
437
|
+
lighting.enabled = true;
|
|
438
|
+
lighting.ambient = { r: 0.62, g: 0.64, b: 0.78 };
|
|
439
|
+
lighting.minLayer = 1;
|
|
440
|
+
lighting.maxLayer = 2;
|
|
441
|
+
}
|
|
442
|
+
|
|
215
443
|
function checkClips(info: FlipbookInfo): void {
|
|
216
444
|
for (const [name, index] of Object.entries(CLIP)) {
|
|
217
445
|
const at = og.anim.clip(info, name);
|
|
@@ -229,13 +457,14 @@ export default og.game({
|
|
|
229
457
|
look: "looks/origin-game-2d.ogt",
|
|
230
458
|
tick: 60,
|
|
231
459
|
seed: 1,
|
|
232
|
-
resources: [Game],
|
|
233
|
-
systems: [Hud, Control, Pickups, Animate, Voices],
|
|
460
|
+
resources: [Game, KeeperWalk],
|
|
461
|
+
systems: [Hud, Control, Pickups, Animate, Walk, Plant2D, Voices],
|
|
234
462
|
start(world) {
|
|
235
463
|
const map = must(og.load.tilemap(world, "maps/level.ogt"));
|
|
236
464
|
const courier = must(og.load.flipbook(world, "sprites/courier.ogt"));
|
|
237
465
|
checkClips(courier);
|
|
238
466
|
const coin = must(og.load.flipbook(world, "sprites/coin.ogt"));
|
|
467
|
+
spawnKeeper(world, must(og.load.rig2d(world, "rigs/keeper.ogt")));
|
|
239
468
|
const height = map.height * map.tileHeight;
|
|
240
469
|
|
|
241
470
|
const camera = must(world.resource(og.Camera));
|
|
@@ -293,13 +522,20 @@ export default og.game({
|
|
|
293
522
|
if (hero === null || !Number.isFinite(x) || !Number.isFinite(y)) throw new Error("write warp:<x>:<y>");
|
|
294
523
|
must(world.set(hero, og.Transform, { position: { x, y, z: 0 } }));
|
|
295
524
|
},
|
|
525
|
+
/** `keeper:<x>`: send the keeper walking along the ramp to x (the Walk system moves it; its feet step on the plank). */
|
|
526
|
+
keeper: (world, args) => {
|
|
527
|
+
const x = Math.max(RAMP.x0 + 0.4, Math.min(RAMP.x1 - 0.4, Number(args[0])));
|
|
528
|
+
if (world.find("keeper") === null || !Number.isFinite(x)) throw new Error("write keeper:<x>");
|
|
529
|
+
must(world.resource(KeeperWalk)).goal = x;
|
|
530
|
+
},
|
|
296
531
|
},
|
|
297
532
|
commandHelp: {
|
|
298
533
|
warp: { usage: "<x>:<y>", doc: "Put the courier's feet at a world point." },
|
|
534
|
+
keeper: { usage: "<x>", doc: "Send the lamp keeper walking along its ramp to x." },
|
|
299
535
|
},
|
|
300
536
|
facts: (world) => {
|
|
301
537
|
const g = world.resource(Game);
|
|
302
538
|
if (!g.ok) return {};
|
|
303
|
-
return { coins: g.value.coins, total: g.value.total, lives: g.value.lives, won: g.value.won, x: g.value.heroX, y: g.value.heroY };
|
|
539
|
+
return { coins: g.value.coins, total: g.value.total, lives: g.value.lives, won: g.value.won, inhales: g.value.inhales, steps: g.value.steps, x: g.value.heroX, y: g.value.heroY };
|
|
304
540
|
},
|
|
305
541
|
});
|