-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfly.asm
477 lines (425 loc) · 7.39 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
469
470
471
472
473
474
475
476
477
.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 "sound.h.asm"
.include "move_trig.h.asm"
.include "hurt_player.h.asm"
COLLISION_SWATTER_FLY_H_HITBOX = 10
COLLISION_SWATTER_FLY_V_HITBOX = 10
.importzp player_screen, player_h, player_v, player_owns_swatter
.importzp player_iframe
.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
index = values + 5
towards_idx = values + 6
.import object_data_extend
fly_step = object_data_extend + $00
fly_direction = object_data_extend + $10
fly_v_low = object_data_extend + $20
fly_h_low = 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 FlyMovement
ldy fly_direction,x
bmi Wait
jsr MovementTrig
CheckOverflow:
; check overflow when moving up
lda object_v,x
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
ldy #1
jsr HurtPlayer
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 index, #0
.scope VerticalRestrict
lda object_v,x
cmp #(FLY_MIN_V + $10)
blt AlwaysMoveDown
cmp #(FLY_MAX_V - $10)
bge AlwaysMoveUp
; If player is more than $28 pixels below fly, move fly down.
lda player_v
sec
sbc object_v,x
bmi Next
cmp #$60
bge AlwaysMoveDown
blt Next
AlwaysMoveDown:
lsr mask
mov index, #6
bpl Next
AlwaysMoveUp:
lsr mask
mov index, #3
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 FindVerticalDiff
lda is_left
and #$01
sta towards_idx
lda object_v,x
sec
sbc player_v
bmi Next
;
lda towards_idx
clc
adc #2
sta towards_idx
Next:
.endscope
.scope HorizontalRestrict
lda diff_h
cmp #$50
blt Next
FarAway:
bit is_left
bpl AlwaysMoveLeft
AlwaysMoveRight:
inc index
lsr mask
jmp Next
AlwaysMoveLeft:
inc index
inc index
lsr mask
Next:
.endscope
Choose:
jsr RandomGet
cmp #$c0
bge MoveTowardsPlayer
and mask
ldy index
clc
adc quadrant_to_dir,y
and #$3f
sta fly_direction,x
rts
MoveTowardsPlayer:
ldy towards_idx
lda towards_dir,y
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
quadrant_to_dir:
.byte 0
.byte $30 ; 1, right
.byte $10 ; 2, left
.byte $00 ; 3, up
.byte $00 ; 4, up/right
.byte $10 ; 5, up/left
.byte $20 ; 6, down
.byte $30 ; 7, down/right
.byte $20 ; 8, down/left
towards_dir:
.byte $28 ; move down/left
.byte $38 ; move down/right
.byte $18 ; move up/left
.byte $08 ; move up/right