-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcollision_detection.asm
394 lines (294 loc) · 10.2 KB
/
collision_detection.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
/* This file handles collision detection. It
does NOT work in the following circumstances:
Sprites very big (Should not happen)
Sprites very close to x=255
*/
#import "data_exchange.asm"
.var spr9th = $d010 //00000000
.var spr0_x = $d000 //spr0 is right paddle
.var spr0_y = $d001
.var spr1_x = $d002 //spr1 is left
.var spr1_y = $d003
.var spr2_x = $d004 //spr2 is ball
.var spr2_y = $d005
.var paddle_height = 21*2 //paddle height is multiplied by 2
.var paddle_half_height = 21
.var paddle_width = 6
.var paddle_half_width = 3
.var ball_height = 7
.var ball_half_height = 3
.var ball_width = 10
.var ball_half_width = 5
coll_func_vars: .fill 9, 0
.var x1 = coll_func_vars //position of segment 1
.var x2 = coll_func_vars + 1 //pos of segment 2
.var x91 = coll_func_vars + 2 //9th bit of pos segment 1
.var x92 = coll_func_vars + 3 //9th bit of pos segment 2
.var d1 = coll_func_vars + 4 //dimension 1
.var d2 = coll_func_vars + 5 //dimension 2
.var r1 = coll_func_vars + 6 //result
.var r2 = coll_func_vars + 7 //result 2
.var tmp = coll_func_vars + 8 //working variable
detect_collisions:
jsr clear_vars //set all variable to 0
jsr detect_ball_lpad //jump to subroutine to detect collision between ball and left paddle
lda r1 // load result into A register
and #%00000010 // isolate 2nd bit
sta r2 // store A register into r2
lda collisions // load collisions variable into A register
ora r2 // bitwise OR in order to mark new collision as on without affecting other bits
sta collisions //sets bit in collision if necessary
jsr clear_vars //set all variable to 0
sta x92 // set x92 to 0
jsr detect_ball_rpad //jump to subroutine to detect collision between ball and right paddle
lda r1 // load result into A register
and #%00000001 // isolate 1st bit
sta r2 // store A register into r2
lda collisions // load collisions variable into A register
ora r2 // bitwise OR in order to mark new collision as on without affecting other bits
sta collisions //sets bit in collision if necessary
jsr clear_vars //set all variable to 0
jsr detect_ball_upper_border // jump to subroutine to detect collision between ball and upper border
lda r1 // load result into A register
and #%00000100 // isolate 3rd bit
sta r2 // store A register into r2
lda collisions // load collisions variable into A register
ora r2 // bitwise OR in order to mark new collision as on without affecting other bits
sta collisions //sets bit in collision if necessary
jsr clear_vars //set all variable to 0
jsr detect_ball_lower_border // jump to subroutine to detect collision between ball and lower border
lda r1 // load result into A register
and #%00001000 // isolate 4th bit
sta r2 // store A register into r2
lda collisions // load collisions variable into A register
ora r2 // bitwise OR in order to mark new collision as on without affecting other bits
sta collisions //sets bit in collision if necessary
jsr clear_vars //set all variable to 0
jsr detect_ball_left_border // jump to subroutine to detect collision between ball and left border
lda r1 // load result into A register
and #%00100000 // isolate 6th bit
sta r2 // store A register into r2
lda collisions // load collisions variable into A register
ora r2 // bitwise OR in order to mark new collision as on without affecting other bits
sta collisions //sets bit in collision if necessary
jsr clear_vars //set all variable to 0
jsr detect_ball_right_border // jump to subroutine to detect collision between ball and lower border
lda r1 // load result into A register
and #%00010000 // isolate 5th bit
sta r2 // store A register into r2
lda collisions // load collisions variable into A register
ora r2 // bitwise OR in order to mark new collision as on without affecting other bits
sta collisions //sets bit in collision if necessary
rts // returns from subroutine
detect_ball_right_border: //detects if ball has collided with the right border
lda #%00000100
and spr9th
bne d_b_r_b_1 //if 9th bit is 1, branch
rts
d_b_r_b_1:
lda spr2_x
cmp #$4e
bcs d_b_r_b_2 //if $4e <= position, branch
rts
d_b_r_b_2:
lda #$FF
sta r1
rts
rts
detect_ball_left_border: //detects if the ball has collided with the left border of the screen
lda #%00000100
and spr9th
beq d_b_le_b_1 //if 9th bit of ball is 0, branch
rts
d_b_le_b_1:
lda #$18
cmp spr2_x
bcs d_b_le_b_2 // if position <= $18, branch
rts
d_b_le_b_2:
lda #$FF
sta r1
rts
detect_ball_upper_border: //detects if the ball has collided with the upper border
lda #00
sta r1
lda #$33
cmp spr2_y
bcs d_b_u_b_1 // if position <= $33, branch
rts
d_b_u_b_1:
lda #$FF
sta r1
rts
detect_ball_lower_border: //detects if ball has collided with lower border
lda #00
sta r1
lda spr2_y
cmp #$f3
bcs d_b_l_b_1 // if $f3 <= position, branch
rts
d_b_l_b_1:
lda #$FF
sta r1
rts
detect_ball_lpad:
lda spr1_x
clc
adc #paddle_half_width // add half the width, to find center of object
sta x1
lda x91
adc #$00 //add the carry of the last operation to 9th bit in case it overflowed
sta x91
lda spr9th
clc
ror
and #$01 //Isolate 9th bit
clc //need to clear, as ror might have set carry
adc x91
sta x91
lda #paddle_width
sta d1
jsr load_ball_x
jsr detect_dimension_collision //Detect if x-coordinate collides
lda r1
sta r2
lda spr1_y
clc
adc #paddle_half_height
sta x1
lda #$00
sta x91
lda #paddle_height
sta d1
jsr load_ball_y
jsr detect_dimension_collision
lda r1
and r2 // if both results were $FF, then a will contain $FF
sta r1
rts
detect_ball_rpad: //checks whether a collision exists between the ball and right paddle, sets r1 to $FF if true
lda spr0_x // load x coordinate of sprite 0 into A register
clc // clear carry flag
adc #paddle_half_width // add half the width, to find center of object
sta x1 // store A register into x1 variable
lda x91 // load contents of x91 variable into A register
adc #$00 //add the carry of the last operation to 9th bit in case it overflowed
sta x91 // store A register into x91 variable
lda spr9th // load spr9th into A register, where the 9th bit of the sprites' x-coordinates are stored
and #$01 //Isolate 9th bit
adc x91 // add x91 unto A register and store in A register
sta x91 // store A register into x91
lda #paddle_width // load paddle width constant into A register
sta d1 // store A register in first dimension variable
jsr load_ball_x // jump to subroutine that loads ball's (sprite 2) x variables
jsr detect_dimension_collision //Jump to subroutine that detects whether there is a collision in the x dimension
lda r1 // load collision detection result into A register
sta r2 // load A register into r2
lda spr0_y // load sprite 0 y coordinate into A register
clc // clear carry flag
adc #paddle_half_height // add paddle half height constant, to get coordinate of center of the paddle
sta x1 // store result into x1
lda #$00 // load 0 into A register
sta x91 // store A register into x91
lda #paddle_height // load paddle height constant into A register
sta d1 // store A register into dimension 1 variable
jsr load_ball_y //jump into subroutine to load variables for ball (sprite 2) y coordinates
jsr detect_dimension_collision // detect collision in the y dimension
lda r1 // load y dimension collision test result
and r2 // bitwise AND with previous result, if both results were $FF, then a will contain $FF
sta r1 // store final result into r1
rts // return from subroutine
load_ball_x:
lda spr2_x // load sprite 2 x coordinate into A register
clc // clear carry flag
adc #ball_half_width //add half width constant, in order to get center coordinate of ball
sta x2 //store into x2 variable
lda x92 //load x92 into A register
adc #$00 // If there was an overflow, add 1 to A register
sta x92 // Store A register into x92
lda spr9th // load spr9th into A register
clc // clear carry flag
ror // Bitwise shift right of A register
clc // clear carry flag
ror // bitwise shift right
and #$01 //Isolate 9th bit of ball only
adc x92 // set 9th bit of sprite 2 in x92 variable
sta x92 // store A in x92
lda #ball_width // load ball width constant into A register
sta d2 // store A register into dimension 2 variable
rts
detect_dimension_collision: // finds if 9th bit is the same, if so continue
//TODO: Make collision work even if 9th bit is different on each sprite
lda x91 // load x91 into A register
cmp x92 // compare x92 with A register
beq detect_dimension_collision_2 //if first sprite 9th bit is equal to second sprite 9th bit, jump to label
rts
detect_dimension_collision_2: //finds whether it is possible for the objects to collide in the given dimension, must be given paramenters, returns $FF in A register if true
lda #$00 // load 0 into A
sta r1 //load preliminary result
jsr ensure_dimension // jump to subroutine to make sure the first dimension is greater than the second
sec // set carry flag
lda x1 // load x1 into A register
sbc x2 //subtract x2 from x1, getting distance between points
clc // clear carry flag
sta tmp // store A register into tmp
adc tmp // multiply a by 2, by adding it unto itself
bcc d_d_1 // if no overflow was found, jump to label
rts //carry was set, number too large to possibly be close enough, as there was an overflow
d_d_1: tay // transfer A register into Y register
lda d1 // load d1 into A register
clc // clear carry flag
adc d2 //add both dimension sizes together
sty tmp //store distance*2 in tmp
cmp tmp // compare distance*2 with width1+width2
bcs d_d_2 //if distance*2 < width1+width2, jump to label
rts // return from subroutine
d_d_2: lda #$FF // load 255 into A register
sta r1 // store A register into r1, meaning the dimension does collide
rts //return from subroutine
load_ball_y:
lda spr2_y
adc #ball_half_height
sta x2
lda #$00
sta x92
lda #ball_height
sta d2
rts
ensure_dimension: //Makes sure the first dimension is greater than the second
lda x1
sec
sbc x2
lda x91
sbc x92
bcc swap_d //x1<x2, swap numbers
rts
swap_d:
lda x1
ldx x2
sta x2
txa
sta x1 //swap x1 and x2
lda x91
ldx x92
sta x92
txa
sta x91 //swap x91 and x92
lda d1
ldx d2
sta d2
txa
sta d1 //swap d1 and d2
clc
rts
clear_vars:
lda #$00
sta x1
sta x2
sta x91
sta x92
sta d1
sta d2
sta r1
sta r2
rts