/
fly.asm
468 lines (419 loc) · 7.26 KB
/
fly.asm
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
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
.export FlyConstructor
.export FlyListUpdate
.export FlyExecute
.export FlyDraw
.include "include.branch-macros.asm"
.include "include.mov-macros.asm"
.include "include.sprites.asm"
.include "object_list.h.asm"
.include "sprite_space.h.asm"
.include "random.h.asm"
.include "explode.h.asm"
.include "points.h.asm"
.include "score_combo.h.asm"
.include "shared_object_values.asm"
.include ".b/trig.h.asm"
.include "sound.h.asm"
COLLISION_SWATTER_FLY_H_HITBOX = 10
COLLISION_SWATTER_FLY_V_HITBOX = 10
.importzp player_screen, player_h, player_owns_swatter
.importzp player_injury, player_iframe, player_gravity, player_gravity_low
.importzp player_health_delta
.importzp camera_h, camera_screen
.importzp spawn_count
.importzp draw_h, draw_v, draw_screen, draw_frame
.importzp combo_low
.importzp level_has_infinite_flies
.importzp values
adjust_v = values + 0
adjust_h = values + 1
diff_h = values + 2
is_left = values + 3
mask = values + 4
base = values + 5
.import object_data_extend
fly_direction = object_data_extend + $00
fly_v_low = object_data_extend + $10
fly_h_low = object_data_extend + $20
fly_step = object_data_extend + $30
.segment "CODE"
.proc FlyListUpdate
bit level_has_infinite_flies
bmi SpawnFlies
rts
SpawnFlies:
inc spawn_count
lda spawn_count
cmp #100
blt Return
mov spawn_count, #0
jsr ObjectListCountAvail
cmp #4
blt Return
jsr ObjectAllocate
bcc Return
jsr ObjectConstructor
mov {object_kind,x}, #OBJECT_KIND_FLY
mov {fly_direction,x}, #$ff
mov {fly_step,x}, #40
; Horizontal position
lda player_h
clc
adc #$60
sta object_h,x
lda player_screen
adc #0
sta object_screen,x
; Vertical position
jsr RandomGet
lsr a
lsr a
clc
adc #$60
sta object_v,x
Return:
rts
.endproc
.proc FlyConstructor
mov {fly_direction,x}, #$ff
mov {fly_step,x}, #40
rts
.endproc
FLY_SPEED = $110
MAX_WORD = $10000
FLY_MIN_V = $30
FLY_MAX_V = $b0
.proc FlyExecute
.scope MaybeDespawn
; If infinite flies, don't use the offscreen despawner.
bit level_has_infinite_flies
bmi Next
jsr ObjectOffscreenDespawn
bcc Next
rts
Next:
.endscope
.scope Movement
ldy fly_direction,x
bmi Wait
lda trig_lookup,y
tay
HorizontalDelta:
lda trig_movement,y
clc
adc fly_h_low,x
sta fly_h_low,x
iny
lda trig_movement,y
bmi ToTheLeft
ToTheRight:
adc object_h,x
sta object_h,x
lda object_screen,x
adc #0
sta object_screen,x
jmp VerticalDelta
ToTheLeft:
adc object_h,x
sta object_h,x
lda object_screen,x
adc #$ff
sta object_screen,x
VerticalDelta:
iny
lda trig_movement,y
clc
adc fly_v_low,x
sta fly_v_low,x
iny
lda trig_movement,y
adc object_v,x
sta object_v,x
CheckOverflow:
; check overflow when moving up
cmp #FLY_MIN_V
blt MoveUpUnderflow
; check overflow when moving down
cmp #(FLY_MAX_V + 1)
bge MoveDownOverflow
jmp Decrement
MoveUpUnderflow:
mov {object_v,x}, #FLY_MIN_V
bne RestNow
MoveDownOverflow:
mov {object_v,x}, #FLY_MAX_V
bne RestNow
Decrement:
dec fly_step,x
lda fly_step,x
cmp #1
bne Next
RestNow:
mov {fly_direction,x}, #$ff
jsr RandomGet
and #$1f
clc
adc #50
sta fly_step,x
jmp Next
Wait:
dec fly_step,x
lda fly_step,x
cmp #1
bne Next
Pick:
jsr SetNewDirection
jsr RandomGet
and #$1f
clc
adc #30
sta fly_step,x
Next:
.endscope
.scope MaybeDespawnFarAway
; Only do this if there are infinite flies.
bit level_has_infinite_flies
bpl Next
lda object_h,x
sec
sbc player_h
lda object_screen,x
sbc player_screen
eor #$80
cmp #$81
bge Despawn
cmp #$7f
blt Despawn
jmp Next
Despawn:
jsr ObjectFree
jmp Return
Next:
.endscope
.scope CollisionWithSwatter
ldy player_owns_swatter
bmi Break
; Vertical
lda object_v,x
sec
sbc object_v,y
bpl AbsoluteV
eor #$ff
clc
adc #1
AbsoluteV:
sta delta_v
cmp #COLLISION_SWATTER_FLY_V_HITBOX
bge Break
; Horizontal
lda object_h,x ; fly
sec
sbc object_h,y ; swatter
sta delta_h
lda object_screen,x ; fly
sbc object_screen,y ; swatter
beq HaveDeltaH
; If delta_screen is not 0 or -1, collision is out of range.
cmp #$ff
bne Break
lda delta_h
eor #$ff
clc
adc #1
sta delta_h
HaveDeltaH:
lda delta_h
cmp #COLLISION_SWATTER_FLY_H_HITBOX
bge Break
Collision:
jsr GainPointsDueToFlyHitByAndSwatter
jsr ExplodeTheFly
lda #SFX_FLY_KILLED
jsr SoundPlay
jmp Return
Break:
.endscope
.scope CollisionWithPlayer
lda player_iframe
bne Next
jsr ObjectCollisionWithPlayer
bcc Next
DidCollide:
jsr ExplodeTheFly
lda #SFX_GOT_HURT
jsr SoundPlay
mov player_injury, #30
mov player_iframe, #100
mov player_gravity, #$fe
mov player_gravity_low, #$00
dec player_health_delta
jmp Return
Next:
.endscope
Draw:
.scope Swivel
ldy #0
sty draw_v
sty draw_h
lda fly_step,x
lsr a
and #$07
tay
mov adjust_v, {fly_swivel_v,y}
mov adjust_h, {fly_swivel_h,y}
Next:
.endscope
; Draw position.
lda object_v,x
clc
adc adjust_v
sta draw_v
lda object_h,x
sec
sbc camera_h
sta draw_h
lda object_screen,x
sbc camera_screen
sta draw_screen
bne Return
lda draw_h
eor #$80
clc
adc adjust_h
eor #$80
sta draw_h
bvs Return
; Draw the fly.
jsr SpriteSpaceAllocate
lda draw_v
sta sprite_v,x
lda draw_h
sta sprite_h,x
ldy draw_frame
lda fly_animation_sequence,y
sta sprite_tile,x
lda #2
sta sprite_attr,x
Return:
rts
.endproc
FlyDraw = FlyExecute::Draw
fly_swivel_h:
.byte $00,$ff,$00,$01
fly_swivel_v:
.byte $00,$00,$00,$00,$ff,$00,$01,$00
.proc GainPointsDueToFlyHitByAndSwatter
lda #1
jsr ComboAddLow
lda combo_low
cmp #9
blt HaveCombo
MaxCombo:
lda #9
HaveCombo:
tay
mov draw_v, {object_v,x}
mov draw_h, {object_h,x}
mov draw_screen, {object_screen,x}
jsr PointsGainAndCreate
rts
.endproc
.proc ExplodeTheFly
mov draw_v, {object_v,x}
lda object_h,x
sec
sbc #8
sta draw_h
lda object_screen,x
sbc #0
sta draw_screen
jsr ObjectFree
jsr ObjectAllocate
bcc Return
mov {object_kind,x}, #(OBJECT_KIND_EXPLODE | OBJECT_IS_NEW)
mov {object_v,x}, draw_v
mov {object_h,x}, draw_h
mov {object_screen,x}, draw_screen
mov {object_life,x}, #15
mov {object_step,x}, #0
mov {object_frame,x}, _
mov draw_frame, #0
jsr ExplodeExecute
Return:
rts
.endproc
.proc SetNewDirection
mov mask, #$3f
mov base, #0
.scope VerticalRestrict
lda object_v,x
cmp #(FLY_MIN_V + $10)
blt AlwaysMoveDown
cmp #(FLY_MAX_V - $10)
bge AlwaysMoveUp
blt Next
AlwaysMoveDown:
lsr mask
mov base, #$20
bpl Next
AlwaysMoveUp:
lsr mask
Next:
.endscope
.scope FindHorizontalDiff
mov is_left, #0
lda object_h,x
sec
sbc player_h
sta diff_h
lda object_screen,x
sbc player_screen
bpl Next
AbsoluteValue:
lda diff_h
eor #$ff
clc
adc #1
sta diff_h
dec is_left
Next:
.endscope
.scope HorizontalRestrict
lda diff_h
cmp #$50
blt Next
FarAway:
bit is_left
bpl AlwaysMoveLeft
AlwaysMoveRight:
lda base
clc
adc #$30
sta base
lsr mask
jmp Next
AlwaysMoveLeft:
lda base
clc
adc #$10
sta base
lsr mask
Next:
.endscope
Choose:
jsr RandomGet
and mask
clc
adc base
and #$3f
sta fly_direction,x
rts
.endproc
FLY_ANIMATE_1 = $0b
FLY_ANIMATE_2 = $0d
FLY_ANIMATE_3 = $0f
fly_animation_sequence:
.byte FLY_ANIMATE_1
.byte FLY_ANIMATE_2
.byte FLY_ANIMATE_3
.byte FLY_ANIMATE_2