-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathLogic.yue
391 lines (374 loc) · 11.6 KB
/
Logic.yue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
--[[ Copyright (c) 2016-2025 Li Jin <dragon-fly@qq.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]]
_ENV = Dora Dora.Platformer
store: Store = Data
{
:GroupPlayer
:GroupEnemy
:GroupDisplay
:GroupPlayerBlock
:GroupEnemyBlock
:GroupPlayerPoke
:GroupEnemyPoke
:LayerBunny
:LayerPlayerHero
:LayerEnemyHero
:LayerBlock
:MaxEP
:MaxHP
} = Store
heroes = Group ["hero",]
with Observer "Add", ["world",]
\watch (_entity, world): false ->
Store.world = with world
with .camera
.followRatio = Vec2 0.03, 0.03
.boundary = Rect 0, -110, 4096, 1004
.position = Vec2 1024, 274
\setIterations 2, 3
\gslot "BlockValue", (group, value) -> heroes\each (hero) ->
hero.blocks = value if hero.group == group
\gslot "BlockChange", (group, value) -> heroes\each (hero) ->
if hero.group == group and hero.blocks
hero.blocks = math.max hero.blocks + value, 0
hero.defending = true if value < 0
\gslot "EPChange", (group, value) -> heroes\each (hero) ->
hero.ep += value if hero.group == group
\gslot "PlayerSelect", (hero) -> thread ->
sleep 1
\clearScene!
for ep in *[6, 1, 1]
emit "EPChange", GroupPlayer, ep
emit "EPChange", GroupEnemy, ep
Store.winner = nil
.playing = true
Audio\playStream "Audio/LOOP14.ogg", true
names = [n for n in *["Flandre", "Dorothy", "Villy"] when n ~= hero]
enemyHero = names[(App.rand % 2) + 1]
Entity
hero: hero
group: GroupPlayer
faceRight: true
AI: "PlayerControlAI"
layer: LayerPlayerHero
position: Vec2 512, 1004 - 712
ep: MaxEP
Entity
hero: enemyHero
group: GroupEnemy
faceRight: false
AI: "HeroAI"
layer: LayerEnemyHero
position: Vec2 3584, 1004 - 712
ep: MaxEP
world\buildCastles!
world\addBunnySwither GroupPlayer
world\addBunnySwither GroupEnemy
world\buildBackground!
world\buildSwitches!
world\buildGameReadme!
Audio\playStream "Audio/LOOP13.ogg", true
mutables =
* "hp"
* "moveSpeed"
* "move"
* "jump"
* "targetAllow"
* "attackBase"
* "attackPower"
* "attackSpeed"
* "damageType"
* "attackBonus"
* "attackFactor"
* "attackTarget"
* "defenceType"
with Observer "Add", ["hero", "group", "layer", "position", "faceRight", "AI"]
\watch (hero, group, layer, position, faceRight, AI): false =>
:world = Store
def = Store[hero]
for var in *mutables
@[var] = def[var]
unit = with Unit def, world, @, position
.group = group
.faceRight = faceRight
.order = layer
.decisionTree = AI
@attackSpeed = switch hero
when "Dorothy" then 1.2
when "Villy" then 1.3
when "Flandre" then 1.8
@moveSpeed = 1.5
\eachAction => @recovery = 0.05
\addTo world
\addChild with Visual "Particle/select.par"
\autoRemove!
\start!
if group == GroupPlayer
world.camera.followTarget = unit
emit "HPChange", @group, @hp
with Observer "Add", ["bunny", "group", "layer", "position", "faceRight", "AI"]
\watch (bunny, group, layer, position, faceRight, AI): false =>
:world = Store
def = Store[bunny]
for var in *mutables
if var == "hp" and @[var] ~= nil
continue
@[var] = def[var]
with Unit def, world, @, position
.group = group
.faceRight = faceRight
.order = layer
.decisionTree = AI
\eachAction => @recovery = 0.1
\addTo world
@hp -= 1.0 if @hp == 0.0
with Observer "Add", ["switch", "group", "layer", "look", "position"]
\watch (switchType, group, layer, look, position): false =>
:world = Store
unit = with Unit Store[switchType], world, @, position
.group = group
.order = layer
with .playable
.look = look
.scaleX = 2
.scaleY = 2
\addTo world
.emittingEvent = true
\slot "BodyEnter", (sensorTag) =>
if .attackSensor.tag == sensorTag and @entity and Data\isFriend @, unit
if @group == GroupPlayer and @entity.hero and not @data.tip
floating = Action Sequence(
Y 0.5, 140, 150, Ease.OutQuad
Y 0.3, 150, 140, Ease.InQuad
)
@data.tip = with Sprite "Model/items.clip|keyf_down"
.y = 140
scaleOut = Action Spawn(
Opacity 0.3, 0, 1
Scale 0.3, 0, 1, Ease.OutQuad
)
\runAction scaleOut
\slot "ActionEnd", -> \runAction floating
\addTo @
@data.atSwitch = unit
\slot "BodyLeave", (sensorTag) =>
if .attackSensor.tag == sensorTag and Data\isFriend @, unit
@data.atSwitch = nil
if @data.tip
with @data.tip
\perform Spawn(
Scale 0.3, .scaleX, 0
Opacity 0.3, 1, 0
)
\slot("ActionEnd")\set -> \removeFromParent!
@data.tip = nil
with Observer "Add", ["block", "group", "layer", "look", "position"]
\watch (block, group, layer, look, position): false =>
:world = Store
def = Store[block]
@hp = def.hp
@defenceType = 0
with Unit def, world, @, position
.group = group
.order = layer
.playable.look = look
\addTo world
with Observer "Add", ["poke", "group", "layer", "position"]
\watch (_entity, poke, group, layer, position): false ->
:world = Store
pokeDef = with BodyDef!
.linearAcceleration = Vec2 0, -10
.type = "Dynamic"
\attachDisk 192, 10.0, 0.1, 0.4
\attachDiskSensor 0, 194
with Body pokeDef, world, position
.group = group
.velocityX = switch group
when GroupPlayerPoke then 400
when GroupEnemyPoke then -400
normal = with Sprite "Model/poke.clip|#{poke}"
.scaleX = 4
.scaleY = 4
.filter = "Point"
\addChild normal
glow = with Sprite "Model/poke.clip|#{poke}l"
.scaleX = 4
.scaleY = 4
.filter = "Point"
.visible = false
\addChild glow
\slot "BodyEnter", (sensorTag) =>
if sensorTag == 0 and switch @group
when GroupPlayer, GroupEnemy then Data\isEnemy @group, .group
else false then
if (.x < @x) == (.velocityX > 0)
@velocity = Vec2 .velocityX > 0 and 500 or -500, 400
@start "strike"
\schedule once ->
while 50 < math.abs .velocityX
sleep 0.1
for _ = 1, 6
Audio\play "Audio/di.wav"
normal.visible = not normal.visible
glow.visible = not glow.visible
sleep 0.5
sensor = \attachSensor 1,
BodyDef\disk 500
sleep!
for body in *sensor.sensedBodies
if Data\isEnemy body.group, .group
:entity = body
if entity and entity.hp > 0
x = .x
with body.data
.hitPoint = body\convertToWorldSpace Vec2.zero
.hitPower = Vec2 2000, 2400
.hitFromRight = body.x < x
entity.hp -= 1
pos = \convertToWorldSpace Vec2.zero
with Visual "Particle/boom.par"
.position = pos
.scaleX = 4
.scaleY = 4
\addTo world, LayerBlock
\autoRemove!
\start!
\removeFromParent!
Audio\play "Audio/explosion.wav"
\addTo world, layer
Audio\play "Audio/quake.wav"
with Observer "Change", ["hp", "unit", "block"]
\watch (hp, unit): false =>
hp: lastHp = @oldValues
if hp < lastHp
unit\start "cancel" if unit\isDoing "hit"
if hp > 0
unit\start "hit"
unit.faceRight = true
with unit.playable
.recovery = 0.5
\play "hp#{math.floor hp}"
else
unit\start "hit"
unit.faceRight = true
unit.group = Data.groupHide
unit.playable\perform Scale 0.3, 1, 0, Ease.OutQuad
unit\schedule once ->
sleep 5
unit\removeFromParent!
group = switch @group
when GroupPlayerBlock then GroupEnemy
when GroupEnemyBlock then GroupPlayer
emit "EPChange", group, 1
group = switch @group
when GroupPlayerBlock then GroupPlayer
when GroupEnemyBlock then GroupEnemy
emit "BlockChange", group, math.max(hp, 0) - lastHp
with Observer "Change", ["hp", "bunny"]
\watch (hp): false =>
:unit = @
hp: lastHp = @oldValues
if hp < lastHp
unit\start "cancel" if unit\isDoing "hit"
if hp > 0
unit\start "hit"
else
unit\start "hit"
unit\start "fall"
unit.group = Data.groupHide
group = switch @group
when GroupPlayer then GroupEnemy
when GroupEnemy then GroupPlayer
emit "EPChange", group, 1
unit\schedule once ->
sleep 5
unit\removeFromParent!
with Observer "Change", ["hp", "hero"]
\watch (hp): false =>
:unit = @
hp: lastHp = @oldValues
:world = Store
if hp < lastHp
unit\start "cancel" if unit\isDoing "hit"
if hp > 0
unit\start "hit"
else
unit\start "hit"
unit\start "fall"
lastGroup = unit.group
unit.group = Data.groupHide
if unit.data.tip
unit.data.tip\removeFromParent!
unit.data.tip = nil
emit "EPChange", lastGroup, 6
switch lastGroup
when GroupPlayer
Audio\play "Audio/hero_fall.wav"
when GroupEnemy
Audio\play "Audio/hero_kill.wav"
if lastGroup == GroupPlayer
world\addChild with Node!
\schedule once ->
View.postEffect = with SpriteEffect "builtin:vs_sprite", "builtin:fs_spritesaturation"
\get(1)\set "u_adjustment", 0
sleep 3
cycle 5, (dt) -> View.postEffect\get(1)\set "u_adjustment", dt
View.postEffect = nil
\slot "Cleanup", ->
View.postEffect = nil
Director.scheduler.timeScale = 1
unit\schedule once ->
Director.scheduler.timeScale = 0.25
sleep 3
Director.scheduler.timeScale = 1
sleep 2
world\addBunnySwither lastGroup
unit.visible = false
start = unit.position
stop = switch lastGroup
when GroupPlayer then Vec2 512, 1004 - 512
when GroupEnemy then Vec2 3584, 1004 - 512
cycle 5, (dt) -> unit.position = start + (stop - start) * Ease\func Ease.OutQuad, dt
unit.playable.look = "happy"
unit.visible = true
unit.velocityY = 1
unit.group = lastGroup
@hp = MaxHP
emit "HPChange", lastGroup, MaxHP
with Visual "Particle/select.par"
\addTo unit
\start!
\autoRemove!
group = switch @group
when GroupPlayer then GroupEnemy
when GroupEnemy then GroupPlayer
emit "EPChange", group, 1
emit "HPChange", @group, math.max(hp, 0) - lastHp
with Observer "Change", ["blocks", "group"]
\watch (_entity, blocks, group): false ->
:world = Store
return false unless world.playing
if blocks == 0
world.playing = false
Audio\playStream "Audio/LOOP11.ogg", true
Store.winner, clip, sound = switch group
when GroupPlayer then GroupEnemy, "lose", "hero_lose"
when GroupEnemy then GroupPlayer, "win", "hero_win"
Audio\play "Audio/#{sound}.wav"
sp = with Sprite "Model/misc.clip|#{clip}"
.scaleX = 2
.scaleY = 2
.filter = "Point"
rectDef = with BodyDef!
.linearAcceleration = Vec2 0, -10
.type = "Dynamic"
\attachPolygon sp.width * 2, sp.height * 2, 1, 0, 1
heroes\each (hero) ->
if hero.group == GroupPlayer
with Body rectDef, world, Vec2(hero.unit.x, 512)
.order = LayerBunny
.group = GroupDisplay
\addChild sp
\addTo world