-
Notifications
You must be signed in to change notification settings - Fork 10
/
physics.s
279 lines (272 loc) · 9.93 KB
/
physics.s
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
MB_GROUNDED = 1
MB_LANDED = 2
MB_HITWALL = 4
MB_HITWALLVERTICAL = 8
MB_HITCEILING = 16
MB_STARTFALLING = 32
MB_INWATER = 128
; Move actor and stop at obstacles
;
; Parameters: X actor index, A Y offset position for obstacles (vertical),
; temp4 X offset position for obstacles (horizontal), Y required charinfo
; (minus ground bit)
; Returns: A charinfo
; Modifies: A,Y,temp vars
MoveFlyer: sty temp6
MF_HasCharInfo: sta temp5
lda actMB,x ;Clear other bits except water
and #MB_INWATER
sta actMB,x
lda actSX,x
beq MF_XMoveOK
bpl MF_NoNegate
lda temp4 ;Negate X check offset if moving left
beq MF_NoNegate2
eor #$ff
sta temp4
inc temp4
MF_NoNegate2: lda actSX,x
MF_NoNegate: jsr MoveActorX
lda #$00
ldy temp4
jsr GetCharInfoXYOffset
and #CI_OBSTACLE|CI_WATER
cmp temp6
beq MF_XMoveOK
lda actMB,x
ora #MB_HITWALL
sta actMB,x
lda actSX,x
jsr MoveActorXNeg
lda #$00
sta actSX,x
MF_XMoveOK: lda actSY,x
jsr MoveActorY
lda temp5
jsr GetCharInfoOffset
sta temp8
and #CI_OBSTACLE|CI_WATER
cmp temp6
beq MF_YMoveOK
lda actMB,x
ora #MB_HITWALLVERTICAL
sta actMB,x
lda actSY,x
jsr MoveActorYNeg
lda #$00
sta actSY,x
MF_YMoveOK: lda temp8
rts
; Move actor with gravity and ground/wall collisions. Does not modify horizontal velocity
;
; Parameters: X actor index, A gravity acceleration (should be positive), Y Y-speed limit,
; temp4 vertical char offset (negative) for ceiling check
; Returns: actMB updated, also returned in A
; Modifies: A,Y,temp5-temp8
FallingMotionCommon:
lda #-1 ;Ceiling check offset
sta temp4
lda #GRENADE_ACCEL
ldy #GRENADE_MAX_YSPEED
MoveWithGravity:sta temp6
lda actMB,x ;Only retain the grounded & water flags
and #MB_GROUNDED|MB_INWATER
sta temp5
lsr
bcs MWG_NoYMove ;If not grounded, move in Y-dir first
lda temp6
jsr AccActorYNoClc
jsr MoveActorY
MWG_NoYMove: lda actSX,x ;Have X-speed?
beq MWG_NoXMove
jsr MoveActorX
jsr GetCharInfo1Above ;Charinfos above & at needed several times,
sta temp7 ;get them now
and #CI_OBSTACLE
bne MWG_HasWallHit
lda temp5 ;If grounded, do not check obstacle at feet
lsr ;(would prevent going up slopes with obstacle below)
bcs MWG_NoWallHit
jsr GetCharInfoOptimizedAfter1Above
sta temp8
and #CI_OBSTACLE
beq MWG_NoWallHit2
MWG_HasWallHit: lda actSX,x
bmi MWG_WallHitLeft
MWG_WallHitRight:
lda #-8*8
jsr MoveActorX
ora #$3f
bne MWG_WallHitDone
MWG_WallHitLeft:lda #8*8
jsr MoveActorX
and #$c0
MWG_WallHitDone:sta actXL,x
lda temp5
ora #MB_HITWALL
sta temp5
MWG_NoXMove: jsr GetCharInfo1Above ;Need to re-get the charinfos after modifying position
sta temp7
MWG_NoWallHit: jsr GetCharInfoOptimizedAfter1Above
sta temp8
MWG_NoWallHit2: lda temp7
ldy temp5
bmi MWG_CheckLeaveWater
MWG_CheckEnterWater:
and #CI_WATER
beq MWG_NoLeaveWater
lda actT,x ;Items may create multiple splashes, so avoid
cmp #ACT_ITEM
beq MWG_SkipSplash
jsr CreateSplash
MWG_SkipSplash: lda temp5
ora #MB_INWATER
bne MWG_CheckWaterStoreFlags
MWG_CheckLeaveWater:
and #CI_WATER|CI_OBSTACLE|CI_GROUND ;Leaving water conclusive only if no ground/obstacles at feet
bne MWG_NoLeaveWater
lda temp5
and #$ff-MB_INWATER
MWG_CheckWaterStoreFlags:
sta temp5
tay
MWG_NoLeaveWater:
tya
lsr
bcc MWG_InAir
jmp MWG_OnGround
MWG_InAir: lda actSY,x ;Check landing or ceiling hit?
bpl MWG_CheckLanding
MWG_CheckCeiling:
lda temp4
jsr GetCharInfoOffset
and #CI_OBSTACLE
beq MWG_NoLanding
lda #$00 ;If hit ceiling, reset Y-speed
sta actSY,x
lda temp5
ora #MB_HITCEILING
bne MWG_StoreMB
MWG_CheckLanding:
lda temp8 ;Charinfo at actor pos
lsr ;Hit ground?
bcc MWG_CheckCharCrossY ;If not directly, check also possible char crossing
rol
ldy #$00
and #$e0 ;Get the slopebits
beq MWG_HitGround ;Optimization for slope0 (most common)
sta temp6
lda actXL,x
lsr
and #$1c
ora temp6
lsr
lsr
tay
lda actYL,x
and #$3f
cmp slopeTbl,y
bcs MWG_HitGround
adc actSY,x ;Check if we would hit the slope next frame
cmp slopeTbl,y ;(must land also in that case, because next frame
bcs MWG_HitGround ;we also move in X-dir and possibly clip through)
MWG_CheckCharCrossY:
lda actYL,x
and #$3f
sec
sbc actSY,x
bcs MWG_NoLanding
MWG_CrossedChar:lda temp7 ;Get char above
lsr
bcc MWG_NoLanding
and #$70 ;Char crossing is only important on slopes; skip on level ground
beq MWG_NoLanding ;(prevents a certain bug with obstacle+ground underneath it)
lda #-8*8 ;Move the actor 1 char up
jsr MoveActorY
lda temp7
and #$e0
sta temp6
MWG_HitGround2: lda actXL,x
lsr
and #$1c
ora temp6
lsr
lsr
tay
MWG_HitGround: lda #$00
sta actSY,x ;Reset vertical velocity to zero
lda actYL,x
and #$c0
ora slopeTbl,y
sta actYL,x ;Align actor to slope
lda temp5
ora #MB_GROUNDED|MB_LANDED
bne MWG_StoreMB
MWG_NoLanding: lda temp5
MWG_StoreMB: sta actMB,x
rts
MWG_OnGround: cpx #MAX_COMPLEXACT ;Check for player/NPC wanting to go up stairs
bcs MWG_PreferLevel
lda actMoveCtrl,x
lsr
bcc MWG_PreferLevel
MWG_PreferUp: lda temp7
lsr
bcs MWG_FinalizeGroundAbove
lda temp8
lsr
bcs MWG_FinalizeGround
jsr GetCharInfo1Below
lsr
bcs MWG_FinalizeGroundBelow
bcc MWG_StartFalling
MWG_PreferLevel:lda temp8
lsr
bcs MWG_FinalizeGround
jsr GetCharInfo1Below
lsr
bcs MWG_FinalizeGroundBelow
lda temp7
lsr
bcs MWG_FinalizeGroundAbove
MWG_StartFalling:
lda temp5 ;If no ground anywhere, start falling
and #$ff-MB_GROUNDED
ora #MB_STARTFALLING
bne MWG_StoreMB2
MWG_FinalizeGroundBelow:
tay
lda #8*8
bne MWG_FinalizeGroundMove
MWG_FinalizeGroundAbove:
tay
lda #-8*8
MWG_FinalizeGroundMove:
jsr MoveActorY
tya
sec
MWG_FinalizeGround:
rol
cpx #MAX_COMPLEXACT
bcs MWG_DoNotSaveCharInfo
sta actGroundCharInfo,x
MWG_DoNotSaveCharInfo:
ldy #$00 ;Get slopebits, optimize for slope0
and #$e0
beq MWG_OnGroundDone
sta temp6
lda actXL,x
lsr
and #$1c
ora temp6
lsr
lsr
tay
MWG_OnGroundDone:
lda actYL,x
and #$c0
ora slopeTbl,y
sta actYL,x
lda temp5
MWG_StoreMB2: sta actMB,x
rts