| ← CE5F | Map | CFB1 → |
CEB3: Hive behavior handler
|
Runs the hive each frame. It wanders sideways, homes on the bat's row and spawns bees above itself.
|
|||||||||||
|
|||||||||||
| update_hive | CEB3 | CALL inhabitant_react_state | Reaction-state machine first; carry means skip this frame. | ||||||||
| CEB6 | RET C | ||||||||||
| CEB7 | LD A,(IY+$0C) | Play the burst while the hive spawns a bee. | |||||||||
| CEBA | CP $03 | ||||||||||
| CEBC | JR NZ,hive_idle | ||||||||||
|
During the spawn, play the burst frames once. The animation step moves a frame every other call, so this spans 18 game frames. At anim frame 9 it returns to idle. Until then it returns without a move, so the hive holds still while the new bee spawns.
|
|||||||||||
| CEBE | LD HL,anim_hive_burst | Spawn-burst animation: one bitmap pointer per frame | |||||||||
| CEC1 | CALL advance_anim | ||||||||||
| CEC4 | LD A,(IY+$0B) | Hold until the burst completes. | |||||||||
| CEC7 | CP $09 | ||||||||||
| CEC9 | RET C | ||||||||||
| CECA | LD (IY+$0B),$00 | Burst done: reset the frame counter and return to idle. | |||||||||
| CECE | LD (IY+$0C),$00 | ||||||||||
| CED2 | RET | ||||||||||
|
In the idle state the hive wanders and homes on the bat's row.
|
|||||||||||
| hive_idle | CED3 | LD HL,anim_hive_idle | Idle animation | ||||||||
| CED6 | CALL advance_anim | ||||||||||
| CED9 | LD A,(IY+$0B) | Wrap the idle loop. | |||||||||
| CEDC | CP $09 | ||||||||||
| CEDE | JR C,hive_move | ||||||||||
| CEE0 | LD (IY+$0B),$00 | ||||||||||
|
Pick a horizontal wander heading, right or left, then home vertically on the bat's row. The bat's row is the Y byte of its sprite record. While the hive runs right or left, its row is compared against the bat's. The comparison tilts the heading one step up or down. The horizontal run becomes a diagonal that closes on the bat's row.
|
|||||||||||
| hive_move | CEE4 | LD A,$03 | Constrain the wander to a horizontal heading. | ||||||||
| CEE6 | CALL pick_wander_heading | ||||||||||
| CEE9 | LD HL,bat_y | The bat's row is the Y byte of its sprite record. | |||||||||
| CEEC | LD A,(IY+$00) | Only steer while the heading is horizontal. | |||||||||
| CEEF | CP $02 | ||||||||||
| CEF1 | JR NZ,hive_steer_left | ||||||||||
| CEF3 | LD A,(IX+$01) | Run to the right: tilt the heading one step up when the bat is level with or above the hive. | |||||||||
| CEF6 | CP (HL) | ||||||||||
| CEF7 | JR C,hive_nudge_a | ||||||||||
| CEF9 | DEC (IY+$00) | ||||||||||
| CEFC | JR hive_clamp_top | ||||||||||
| hive_nudge_a | CEFE | INC (IY+$00) | The bat sits below, so tilt the other way. | ||||||||
| CF01 | JR hive_clamp_top | ||||||||||
| hive_steer_left | CF03 | CP $06 | Run to the left: tilt the heading one step up when the bat is level with or above the hive. | ||||||||
| CF05 | JR NZ,hive_clamp_top | ||||||||||
| CF07 | LD A,(IX+$01) | ||||||||||
| CF0A | CP (HL) | ||||||||||
| CF0B | JR C,hive_nudge_b | ||||||||||
| CF0D | INC (IY+$00) | ||||||||||
| CF10 | JR hive_clamp_top | ||||||||||
| hive_nudge_b | CF12 | DEC (IY+$00) | The bat sits below, so tilt the other way. | ||||||||
|
Keep the hive out of the top strip. When the hive moves into the top strip of the play area, force the downward heading. That steers it back down.
|
|||||||||||
| hive_clamp_top | CF15 | LD A,(IX+$01) | Too near the top of the screen: force the downward vertical heading. | ||||||||
| CF18 | CP $30 | ||||||||||
| CF1A | JR NC,hive_apply_move | ||||||||||
| CF1C | LD A,$04 | ||||||||||
| CF1E | LD (IY+$00),A | ||||||||||
| hive_apply_move | CF21 | CALL object_avoid_walls | Steer away from walls. | ||||||||
| CF24 | CALL move_object | Advance one step along the heading. | |||||||||
| CF27 | CALL inhabitant_offscreen | Despawn once off the far edge; carry means gone. | |||||||||
| CF2A | RET C | ||||||||||
| CF2B | LD B,$0A | Award 100 points if a ball hits it, banked into the pending score. Carry means killed. | |||||||||
| CF2D | CALL ball_kill | ||||||||||
| CF30 | RET C | ||||||||||
| CF31 | CALL overlap_sweep | The sweep: non-zero means a hit. | |||||||||
| CF34 | OR A | ||||||||||
| CF35 | JR Z,hive_try_spawn | ||||||||||
| CF37 | LD (IY+$0B),$00 | On a hit, restart the animation and die. | |||||||||
| CF3B | LD (IY+$0C),$02 | ||||||||||
| CF3F | RET | ||||||||||
|
Spawn attempt, only on idle anim frame 0, so at most once per idle cycle. First scan the inhabitant records (inhabitant_records) for a bee already alive. A second bee is not spawned while one is. It is the only duplicate check a bee gets. The bee's entry in the singleton table (spawn_singleton_table) is clear, so the generic spawn process_wave_script_2 does not refuse a bee that a wave script places.
|
|||||||||||
| hive_try_spawn | CF40 | LD A,(IY+$0B) | Spawn only on idle frame 0. | ||||||||
| CF43 | OR A | ||||||||||
| CF44 | RET NZ | ||||||||||
| CF45 | PUSH IY | Set up to walk the inhabitant records. | |||||||||
| CF47 | LD IY,inhabitant_records | ||||||||||
| CF4B | LD B,$05 | ||||||||||
| hive_scan_bee | CF4D | LD A,(IY+$08) | A live bee already exists? | ||||||||
| CF50 | CP $07 | ||||||||||
| CF52 | JR Z,hive_bee_exists | ||||||||||
| CF54 | LD DE,$0010 | Step to the next logic record and continue the scan. | |||||||||
| CF57 | ADD IY,DE | ||||||||||
| CF59 | DJNZ hive_scan_bee | ||||||||||
| CF5B | JR hive_spawn_roll | No bee found in any slot, so a spawn is allowed. | |||||||||
| hive_bee_exists | CF5D | POP IY | Bee already alive: do not spawn. | ||||||||
| CF5F | RET | ||||||||||
|
Roll the RNG and proceed only when its low nibble is 0. Then find a free pool slot: walk the inhabitant records and the parallel inhabitant entries of the sprite records for an empty type. With no free slot, give up this frame.
|
|||||||||||
| hive_spawn_roll | CF60 | POP IY | Balance the scan's stack push. | ||||||||
| CF62 | CALL next_random | Roll the RNG: 1-in-16 chance to spawn this frame. | |||||||||
| CF65 | AND $0F | ||||||||||
| CF67 | RET NZ | ||||||||||
| CF68 | PUSH IY | Set up to scan the 5 records and object slots for a free one. | |||||||||
| CF6A | PUSH IX | ||||||||||
| CF6C | LD IX,inhabitant_objects | ||||||||||
| CF70 | LD IY,inhabitant_records | ||||||||||
| CF74 | LD B,$05 | ||||||||||
| hive_find_slot | CF76 | LD A,(IY+$08) | A free slot? | ||||||||
| CF79 | OR A | ||||||||||
| CF7A | JR Z,hive_emit_bee | ||||||||||
| CF7C | LD DE,$0009 | Step both records on and look again. | |||||||||
| CF7F | ADD IX,DE | ||||||||||
| CF81 | LD DE,$0010 | ||||||||||
| CF84 | ADD IY,DE | ||||||||||
| CF86 | DJNZ hive_find_slot | ||||||||||
| CF88 | POP IX | No free slot: give the saved registers back and drop the spawn. | |||||||||
| CF8A | POP IY | ||||||||||
| CF8C | RET | ||||||||||
|
Claim the free slot as a bee and place it at the hive's column, 14 pixels above the hive. The spawn initializer sets the bee's heading and timers. The hive then flashes the spawn burst.
|
|||||||||||
| hive_emit_bee | CF8D | LD (IY+$08),$07 | Claim the slot for a bee. | ||||||||
| CF91 | POP HL | Recover the hive's own sprite record. | |||||||||
| CF92 | LD A,(HL) | Put the bee in the hive's column. | |||||||||
| CF93 | LD (IX+$00),A | ||||||||||
| CF96 | INC HL | ||||||||||
| CF97 | LD A,(HL) | The bee spawns a fixed distance above the hive's row. | |||||||||
| CF98 | SUB $0E | ||||||||||
| CF9A | LD (IX+$01),A | ||||||||||
| CF9D | DEC HL | ||||||||||
| CF9E | PUSH HL | ||||||||||
| CF9F | LD B,$07 | The new object is a bee. | |||||||||
| CFA1 | CALL spawn_object_init | Initialize the new bee. | |||||||||
| CFA4 | POP IX | ||||||||||
| CFA6 | POP IY | ||||||||||
| CFA8 | LD (IY+$0C),$03 | Switch the hive to its spawn burst. | |||||||||
| CFAC | LD (IY+$0B),$00 | ||||||||||
| CFB0 | RET | ||||||||||
| ← CE5F | Map | CFB1 → |
