Responsive collision, on the other hand, can be attained by calling the Add_SpriteToCollisionResponseList function:
Add_SpriteToCollisionResponseList: lea (Collision_response_list).w,a1 cmpi.w #$7E,(a1) ; Is list full? bhs.s locret_1041C ; If so, return addq.w #2,(a1) ; Count this new entry adda.w (a1),a1 ; Offset into right area of list move.w a0,(a1) ; Store RAM address in list locret_1041C: rtsMuch like with the Draw_Sprite function, responsive collision works in a subscription-based model: calling the function simply adds the object to a list of items to be processed in the future. The actual work of performing bound checks and producing the appropriate effects is deferred to the next frame, where it is done by the player object.
(Note that the collision response list is actually processed twice in a Sonic and Tails game, once per player object. This will become relevant later. Foreshadowing: the sign of a quality blog.)
For this reason, the collision parameters cannot be passed through registers; instead, a single byte of the solid object's SST is reserved for this purpose:
collision_flags = $28 ; byte ; TT SSSSSS ; TT = collision type, SSSSSS = sizeThe decision to stuff everything in a single byte, presumably to save space on the SST, has a couple of consequences. First off, the collision_flags attribute carries information about both the collision size and the collision type. As a result, each time the game needs to read either value, it must clear out the remaining bits.
Touch_Loop: movea.w (a4)+,a1 ; Get address of first object's RAM move.b collision_flags(a1),d0 ; Get its collision_flags bne.s Touch_Width ; If it actually has collision, branch ... Touch_Width: andi.w #$3F,d0 ; Get only collision size add.w d0,d0 ; Turn into index lea Touch_Sizes(pc,d0.w),a2 moveq #0,d1 move.b (a2)+,d1 ; Get width value from Touch_Sizes move.w x_pos(a1),d0 ; Get object's x_pos sub.w d1,d0 ; Subtract object's width ...Then, because six bits are obviously not enough to store the actual dimensions of the object's hitbox, the collision size is really just an index to a lookup table of hardcoded size definitions, stored in pairs of width by height.
Touch_Sizes: dc.b 4, 4 dc.b $14, $14 dc.b $C, $14 dc.b $14, $C dc.b 4, $10 dc.b $C, $12 dc.b $10, $10 ...Collision type, on the other hand, is fairly straightforward. There are four collision types, and the appropriate behavior is selected by a series of branches; no fancypants arithmetic involved.
Touch_ChkValue: move.b collision_flags(a1),d1 ; Get its collision_flags andi.b #$C0,d1 ; Get only collision type bits beq.w Touch_Enemy ; If 00, enemy, branch cmpi.b #$C0,d1 beq.w Touch_Special ; If 11, "special thing for starpole", branch tst.b d1 bmi.w Touch_ChkHurt ; If 10, "harmful", branch ... ; If 01...Next time, we'll continue our foray into responsive collision by taking a look at the implementation of each collision type.
No comments:
Post a Comment