← A75E Resolve both balls' bounces for the frame Map A889 → Point IX at an object-pool slot by index
A777: Resolve a ball bounce
Reflects the selected ball off the bat, and off the second bat the same way.
Input
IY the selected ball state record
ball_bounce A777 LD A,(IY+$0B) A ball that already sits on the bat is in contact: skip the gap tests and resolve it as a hit.
A77A OR A
A77B JP NZ,ball_bounce_after_hit
A77E LD A,(double_bat_active) With the second bat in play, first test ball A and the second bat against the return window.
A781 OR A
A782 JR Z,ball_bounce_vs_bat
A784 LD IX,ball_a_object Read both records' positions.
A788 LD B,(IX+$00)
A78B LD D,(IX+$01)
A78E LD IX,obj2_object
A792 LD C,(IX+$00)
A795 LD E,(IX+$01)
A798 LD A,D Take the Y gap between them. A negative gap folds to one less than its magnitude, as in the overlap test.
A799 SUB E
A79A JP P,ball_bounce_bat2_dy
A79D CPL
ball_bounce_bat2_dy A79E CP $0C Hold the Y gap inside the return window, then measure the X gap. A positive gap is held to it directly.
A7A0 JR NC,ball_bounce_vs_bat
A7A2 LD A,B
A7A3 SUB C
A7A4 JP M,ball_bounce_bat2_dxneg
A7A7 CP $0A
A7A9 JR C,ball_bounce_hit_right
ball_bounce_bat2_dxneg A7AB CPL A negative gap folds to one less than its magnitude, so this side of the window reaches a pixel further.
A7AC CP $0A
A7AE JR C,ball_bounce_hit_left
ball_bounce_vs_bat A7B0 LD A,(resolve_ball_sel) Main path: reflect this ball off the bat. Ball A reads its own pool record.
A7B3 OR A
A7B4 JR NZ,ball_bounce_pick_b
A7B6 LD IX,ball_a_object
A7BA JR ball_bounce_read_bat
ball_bounce_pick_b A7BC LD IX,obj2_object Ball B reads its own.
ball_bounce_read_bat A7C0 LD B,(IX+$00) Take the ball's and the bat's positions for the gap tests below.
A7C3 LD D,(IX+$01)
A7C6 LD IX,object_table
A7CA LD C,(IX+$00)
A7CD LD E,(IX+$01)
A7D0 LD A,D Measure the Y gap between the ball and the bat; a positive one carries straight to the expanded-bat test.
A7D1 SUB E
A7D2 JP P,ball_bounce_expand_test
A7D5 CPL A negative gap folds one short of its magnitude, and that path skips the expanded-bat test.
A7D6 JR ball_bounce_check_dy
ball_bounce_expand_test A7D8 EX AF,AF' With the bat expanded the hit window reaches further, so a wider gap still counts.
A7D9 LD A,(expand_active)
A7DC OR A
A7DD JR Z,ball_bounce_restore_dy
A7DF EX AF,AF'
ball_bounce_expand_dy A7E0 CP $1C
A7E2 RET NC
ball_bounce_restore_dy A7E3 EX AF,AF' Swap the gap back for the 12-px test below. The expanded path is the exception. It arrives here after its own 28-px test passes, and gets the flag byte back instead. That test then passes on the flag, so the 28 is the only Y bound on this side.
ball_bounce_check_dy A7E4 CP $0C Hold the ball inside the Y window of the bat, then measure the X gap.
A7E6 RET NC
A7E7 LD A,B
A7E8 SUB C
A7E9 JP M,ball_bounce_dx_neg
ball_bounce_check_dx A7EC CP $0A
A7EE RET NC
A7EF JR ball_bounce_hit_right
ball_bounce_dx_neg A7F1 CPL A negative X gap folds one short and is held to the same window.
A7F2 CP $0A
A7F4 RET NC
ball_bounce_hit_left A7F5 LD A,(IY+$04) Ball to the left of the bat: it counts as a hit only while it travels rightward. The impact side records as the left one.
A7F8 OR A
A7F9 RET Z
A7FA XOR A
A7FB LD (bat_impact_side),A
A7FE JR ball_bounce_after_hit
ball_bounce_hit_right A800 LD A,(IY+$04) Ball to the right: it only counts while it travels leftward, and the impact side records as the right one.
A803 OR A
A804 RET NZ
A805 LD A,$01
A807 LD (bat_impact_side),A
ball_bounce_after_hit A80A LD A,(IY+$0C) Bat-catch bypass set for this ball? Jump straight to the bat-angle bounce. That skips the catch test, the combo reset and the rally speed step. Otherwise run the catch test, and stop while it holds the ball.
A80D OR A
A80E JR NZ,ball_bounce_angle
A810 CALL ball_catch_test
A813 OR A
A814 RET Z
A815 LD A,(resolve_ball_sel)
A818 OR A
A819 JR NZ,ball_bounce_reset_combo
A81B XOR A Reset the combo of whichever ball struck, so a fresh run of bricks scores from the bottom again. This arm is ball A's.
A81C LD (combo_a),A
A81F JR ball_bounce_speed_up
ball_bounce_reset_combo A821 XOR A This arm is ball B's.
A822 LD (combo_b),A
ball_bounce_speed_up A825 CALL ball_accelerate Then count the bounce toward the rally speed step.
ball_bounce_angle A828 LD A,(resolve_ball_sel) Compare the ball against the bat for the angle bounce, ball A from its own pool record.
A82B OR A
A82C JR NZ,ball_bounce_angle_b
A82E LD IX,ball_a_object
A832 JR ball_bounce_hit_offset
ball_bounce_angle_b A834 LD IX,obj2_object Ball B compares from its own.
ball_bounce_hit_offset A838 LD D,(IX+$01) Take both Y positions for the offset that picks the reflection angle.
A83B LD IX,object_table
A83F LD E,(IX+$01)
A842 LD A,D
A843 ADD A,$10
A845 SUB E
A846 LD E,A
A847 LD A,(expand_active) An expanded bat uses the expanded-bat angle tables, and the impact side picks which.
A84A OR A
A84B JR Z,ball_bounce_normal
A84D LD A,(bat_impact_side)
A850 OR A
A851 JR NZ,ball_bounce_exp_table_b
A853 LD HL,bat_angle_exp_a
A856 JR ball_bounce_apply_angle
ball_bounce_exp_table_b A858 LD HL,bat_angle_exp_b A strike right of the bat's origin takes the expanded bat's right-side table.
A85B JR ball_bounce_apply_angle
ball_bounce_normal A85D LD A,(bat_impact_side) A normal bat uses the narrow pair, and the impact side picks again.
A860 OR A
A861 JR NZ,ball_bounce_normal_b
A863 LD HL,bat_angle_norm_a
A866 JR ball_bounce_apply_angle
ball_bounce_normal_b A868 LD HL,bat_angle_norm_b Here too a strike right of the bat's origin takes the right-side table.
ball_bounce_apply_angle A86B LD D,$00 Index the chosen table by the impact offset and take the new heading.
A86D ADD HL,DE
A86E LD A,(HL)
A86F EX AF,AF'
A870 LD HL,ball_a_heading
A873 LD D,$00
A875 LD A,(resolve_ball_sel)
A878 LD E,A
A879 ADD HL,DE
A87A EX AF,AF'
A87B LD (HL),A
A87C LD A,(resolve_ball_sel)
A87F LD (active_ball),A
A882 CALL set_ball_velocity
A885 CALL sfx_ball_bounce
A888 RET
← A75E Resolve both balls' bounces for the frame Map A889 → Point IX at an object-pool slot by index
Fork me on GitHub