From KeenWiki
Jump to navigation Jump to search

Bounders are red, spherical creatures in Keen 4. They are harmless to Keen and can be ridden on by him. This effect is not due to anything in the Bounder's code but rather Keen's sprite collisions. As such patches that affect the finer points of this interaction (As opposed to whether or not the Bounder possesses that interaction) can be found at Patch:Keen (Keen 4).

Sprite Type

The Bounder uses sprite type 15, which means it can push Keen, and Keen can ride on it, much like a moving platform. Changing this will make it so Keen can't ride on or be pushed by Bounders. The second sprite type is that the Bounder changes to when stunned. The default values makes it such that Keen can't stand on the Bounder once it has been stunned.

Keen 4

#Bounder sprite type
%patch $110FE [$0F] #When spawned
%patch $11174 [$21] #When stunned

Bounder can still be stood on after being shot

This patch alter things so that the Bounder can still be stood on after they have been shot. This is important if the modder wants the Bounder to be shot multiple times.

Keen 4

#Bounder can still be stood on after being shot
%patch $11172 $EB $02

Sprite Actions

The Bounder has a number of interesting actions. When created it is bouncing vertically, a two-frame action loop. Randomly it will go to bouncing left or right, another two frame action loop. After bouncing left or right it will return to bouncing vertically.

If Keen is standing directly on top of the Bounder then it will alter its action to bouncing vertically. When shot it jumps into the air as a stunned Bounder, that changes to a landed stunned bounder when it hits the ground. This will then do nothing.

$2F12W #Bounder bouncing vertically
$2F30W #Bounder bouncing vertically
$2F4EW #Bounder bouncing left/right
$2F6CW #Bounder bouncing left/right
$2F8AW #Stunned Bounder in air
$2FA8W #Stunned Bounder on ground

Keen 4

#Bounder start -bounce vertically
%patch $1112A [$2F12W]

#Vertical bounce loop
%patch $31D9E [$2F30W]
%patch $31DBC [$2F12W]

#Randomly bounce left\right
%patch $1126E [$2F4EW]

#Bouncing left\right loop
%patch $31DDA [$2F6CW]
%patch $31DF8 [$2F4EW]

#After bouncing left\right bounce vertically
%patch $11221 [$2F12W]

#If Keen is on top of bounder bounce vertically
%patch $1127D [$2F12W]

#When shot, fly through air
%patch $11166 [$2F8AW]

#When stunned in air and landing go to stun
%patch $31E16 [$2FA8W]

#When stunned on ground do nothing
%patch $31E34 [$0000W]

Sprite Behavior

The Bounder does not have its own unique behavior. Instead it uses a generic 'stunned sprite' behavior, even while not stunned. This behavior lets it fly through the air and animate. (Bouncing it handled in its tile collision.)

Patches controlling how far left or right of the Bounder Keen must be to control it can be found in the sprite positioning section.

$09DC16C9RL #Shot sprite

Keen 4

#Bound u-d
%patch $31D92 $09DC16C9RL
%patch $31DB0 $09DC16C9RL

#Bound l-r
%patch $31DCE $09DC16C9RL
%patch $31DEC $09DC16C9RL

%patch $31E0A $09DC16C9RL
%patch $31E28 $09DC16C9RL

Bounder chases Keen

This patch changes things so that Bounders will always chase Keen. This is done by making it so that Keen doesn't have to be riding them to make them change direction, so they'll always head in his direction.

Bounders chase Keen

#Bounders chase Keen
%patch $111C2 $90 $90

Bounder doesn't obey Keen when he rides it

These patches make the Bounder ignore Keen; the first makes the Bounder continue to bounce in random directions whether or not Keen is on it. The second and third patches stop the Bounder moving left or right when Keen is on it.

Bounder doesn't obey Keen when he rides it

#Bounder doesn't obey Keen when he rides it
%patch $111C2 $EB

#Don't obey Keen...
%patch $111D6 $EB #Left
%patch $111EC $EB #Right

Speed and Jump Height

The Bounder does not use animation motion, its speed is defined entirely by its bounces, including the 'kick' it gets when it is shot by Keen. The Bounder has a set jump height, and two jump lengths (The same length left and right.), one for a 'free' Bounder, and one for a 'ridden' Bounder.

The Bounder also has a number of jump directions, that is, what directions to move. When being ridden by Keen these are quite obvious, it heads in the direction Keen is riding it. When 'free' they are random. (See the probability section below.) When riding Keen must be a certain number of pixels left or right of the Bounder's center to make it move in the direction he wishes.

Bounder jump height

#How high a bounder flies into the air when shot
%patch $11179 [$20]

%patch $111BC [$FFCEW] #Bounder's vertical jump height
%patch $111FE [$0018W] #Bounder's jump length (With Keen riding)
%patch $11260 [$0018W] #Bounder's jump length (Without Keen riding)

Bounder's jump directions:

#Direction bounder is set to after landing (Up)
%patch $11232 $0000W 

#Free bounce directions
%patch $11245 $FFFFW #Left
%patch $11253 $0001W #Right
%patch $1125A $0000W #Up

#How far left\right Keen must be to make Bounder move in that direction
%patch $111D1 [$0040W] #Left
%patch $111E7 [$0040W] #Right

#Ridden bounce directions
%patch $111DB $FFFFW  #Left (Keen riding l)
%patch $111F1 $0001W  #Right (Keen riding r)
%patch $111F8 $$0000W #Up (Keen on top)

Animation motion

#Bounder bouncing Vertically
%patch $31D8E $0000W $0000W #Speed 1
%patch $31DAC $0000W $0000W #Speed 2

#Bounder bouncing side to side
%patch $31DCA $0000W $0000W #Speed 1
%patch $31DE8 $0000W $0000W #Speed 2

%patch $31E06 $0000W $0000W #Speed 1 (In air)
%patch $31E24 $0000W $0000W #Speed 2 (On ground)

Bounder doesn't jump when shot

This patch stops the Bounder jumping when it is shot, it simply falls to the ground.

Keen 4

#Shot Bounder doesn't jump
%patch $11176 $5F $5E $5D $CB

Sprite Collision

Collision values

The Bounder has a unique collision that it uses when bounding left or right. Once it has been shot it has no collision, preventing it from being repeatedly stunnable.

Keen 4

#Bouncing vertical
%patch $31D96 $10800938RL
%patch $31DB4 $10800938RL

#Bouncing left\right
%patch $31DD2 $10800938RL
%patch $31DF0 $10800938RL

%patch $31E0E $00000000L #In air
%patch $31E2C $00000000L #On ground

Collision code

The collision code is notable in that it sets a number of variables to zero when shot. it is not known what these are at present. The Bounder responds only to Keen's shot by default; while Keen can ride the bounder, this does not relate to the bounder's collision code.

Keen 4

#Bounder collision
%patch $11138 $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $83 $3D {$03 $75} $32
              $C7 $44 $3E [$0000W]  $C7 $44 $40 [$0000W]  $C7 $44 $42 [$0000W]  $8B
              $04 $89 $44 $44 $57 $9A $0D8F0D43RL     $83 $C4 $02 $B8 [$2F8AW]
              $50 $56 $9A $09DC120ARL     $83 $C4 $04 $C7 $04 [$0021W]  $83 $6C
              $18 $20 $5F $5E $5D $CB

Bounder lethal but shootable

This patch adapts the Poison Slug's collision code for the Bounder. It does not require any extra space be created, but is incompatible with some of the patches on this page, such as the shot action and jump height when shot. (This patch removes the Bounder's ability to jump into the air when shot by Keen.)

Keen 4

#Bounder collision: Lethal, shootable
%patch $11138 $55 $8B $EC $56 $57 $8B $76 $06 $8B $7E $08 $83 $3D [$02] {$75} $09     #Check for Keen (Type 2)
              $9A $0B8013E9RL     $5F $5E $5D $CB $83 $3D [$03] {$75} $0E $B8         #If Keen, kill him; check for shot (Type 3)
              [$2F8AW]  $50 $57 $56 $9A $09DC1695RL     $83 $C4 $06 $5F $5E $5D $CB #If shot, become $2F8AW

Bounder can be shot multiple times

This patch makes the Bounder stun for a short time when shot, before resuming as normal. The blue value is how long the Bounder will remain stunned.

Bounder can be shot multiple times

#Bounder stuns temporarily
%patch $31E18 $01EFW $01F0W $0000W $0000W $0001W [$00A8W] $00000W $0000W
              $00000000L    $10800938RL   $09DC1847RL
%patch $31E34 $2F12W
%patch $11165 $C7 $44 $1C $2FA8W $5F $5E $5D $CB

Bounder jumps when touching Keen

This patch makes it so that the Bounder will jump into the air when Keen touches it in any way (Except from above, when he stands on it.) This means Keen can do things such as bounce the Bounder off of his head or launch it high in the air by jumping while under it.

Bounder jumps when touching Keen

#Bounder jumps when touching Keen:
%patch $11145 $02 $75 $04 $83 $6C $18 $20 $5F $5E $5D $CB


The Bounder has three cycles of animation. The first relates to whether the Bounder is moving left or right, using different animations depending on the direction. The second is for when the Bounder is moving straight up and down. The third cycle involves the shot and stunned Bounder.

Keen 4

%patch $30706 $01EBW #Bounder Cache start
%patch $30750 $01F1W #Bounder cache end

#Bouncing vertically
%patch $31D82 $01EFW $01EFW
%patch $31D8C $0014W        #Animation speed
%patch $31DA0 $01F0W $01F0W
%patch $31DAA $0014W        #Animation speed

#Bounder moving left/right
%patch $31DBE $01EBW $01EDW
%patch $31DC8 $0014W        #Animation speed
%patch $31DDC $01ECW $01EEW
%patch $31DE6 $0014W        #Animation speed

#Stunned Bounder in air
%patch $31DFA $01EFW $01EFW
%patch $31E04 $0000W        #Animation speed

#Stunned Bounder (Do nothing)
%patch $31E18 $01F1W $01F1W
%patch $31E22 $0000W        #Animation speed

Sprite positioning

The Bounder spawns 7 pixels higher then where it is placed in-level. This is not really important since the Bounder doesn't walk along the ground.

Keen 4

#Spawn height:
%patch $1111A [$FF80W] #7 pixels up

Keen control positions

Keen can control the Bounder if he is less than 4 pixels from either edge of the sprite. These limits can be changed, however it is wise not to make them so wide that they overlap.

Keen 4

#Bounder control limits
%patch $111D1 [$0040W] #Left -4 pixels
%patch $111E7 [$0040W] #Right -4 pixels


The Bounder has a distinct bouncing sound, this can be blocked.

Keen 4

#Bounder bounce sound
%patch $111AE [$10]

#Don't make Bounder bounce sound:
%patch $111AD $EB $0A

Clipping and foreground

The Bounder has a foreground variable of 0, meaning it appears behind all sprites and foreground tiles. This avoids graphics oddities when it bounces against walls and ceilings.

Keen 4

#Bounder foreground variable
%patch $11108 [$0000W]

Sprite-tile interaction

The Bounder's tile interaction is responsible for its actual bouncing, its bouncing sound and jump heights. (See above speed section.) It uses its tile collision whenever bouncing but of course uses a generic 'stunned sprite' tile collision after it has been shot.

Keen 4

%patch $31D9A $1080097ERL #Bounding up
%patch $31DB8 $1080097ERL #Bounding up

%patch $31DD6 $1080097ERL #Bounding l/r
%patch $31DF4 $1080097ERL #Bounding l/r

%patch $31E12 $09DC1913RL #Shot
%patch $31E30 $09DC1913RL #Stunned

Interaction code

This is the Bounder's tile interaction code. It is quite complex due to the fact that it controls not only the Bounder interacting with walls, floors and ceilings, but also Keen controlling it while riding and random bouncing.

The first line checks for ceilings; if found then the Bounder's vertical speed is set to zero. On the second line floors are checked for, if found a big jump over the following code is itself jumped.

Following this (That is, if floor is found) an unknown subroutine is called and if it returns a value of 0, sound $10 played (The Bounder bouncing sound.) On the same line the Bounder's jump height is set to $FFCEW. Next online 5 the Bounder checks to see if Keen is riding it, if so its Misc Variable C is set to 0 and Keen's position relative to it checked.

First Keen's left hitbox side is compared to the Bounder's, if less than 40 pixels from the Bounder's edge the Boudner's horizontal direction is set to -1 (Left). The same is then done for Keen's right hitbox side, turning the Bounder right. If neither is the case the Bounder's horizontal direction is set to 0. Finally at the start of line 9 the Bounder is given a horizontal speed, a jump width and the remaining 'random bounce' code skipped.

The random bounce code starts at the end of line 9. The first two lines check to see if the Bounder has been bounding left\right, if so it is 'reset' to bounding up and down. This acts as a restraint to stop the Bounder 'getting stuck' bouncing in a single direction. After this the random number generator is called. If the resulting number is less than $64 the Bounder will bound left, if it is between $64 and $00C8W then it will bound right, larger than $00C8W then it will bound up and down. This gives a roughly 33% chance for each option. After that the Bounder checks what direction it is moving in. If it is moving up and down it changes its action to bouncing up and down, otherwise it changes its action to bouncing left\right.

Finally walls are checked for. If left or right walls are found the Bounder simply reverses its current direction. The remaining code draws the sprite onscreen.

Keen 4

#Bounder tile collision
%patch $1117E $55 $8B $EC $83 $EC $02 $56 $57 $8B $7E $06 $83 $7D {$3A} [$00] {$74}
              $05 $C7 $45 $18 [$0000W]  $83 $7D {$36} [$00] {$75} $03 $E9 $00ECW  $FF
              $45 $40 $57 $9A $09DC1260RL     $83 $C4 $02 $0B $C0 $74 $0C $B8
              [$0010W]  $50 $9A $187409F1RL     $83 $C4 $02 $C7 $45 $18 [$FFCEW]
              $39 $3E [$7A6EW]  {$75} $43 $C7 $45 $40 [$0000W]  $8B $1E $D6 $A7 $8B
              $45 $22 $2D [$0040W]  $39 $47 [$22] {$73} $07 $C7 $45 $0E [$FFFFW]  $EB
              $1B $8B $1E $D6 $A7 $8B $45 $26 $05 [$0040W]  $39 $47 $26 $76 $07
              $C7 $45 $0E [$0001W]  $EB $05 $C7 $45 $0E [$0000W]  $8B $45 $0E $BA
              [$0018W]  $F7 $EA $89 $45 $16 $EB $60

#Randomly bounce
%patch $11207                                     $83 $7D $40 $02 $7E $06 $83
              $7D $3E [$00] {$75} $1C $C7 $45 $3E [$0001W]  $33 $C0 $89 $45 $16 $89
              $45 $0E $B8 [$2F12W]  $50 $57 $9A $09DC120ARL     $83 $C4 $04 $EB
              $38 $C7 $45 $3E $0000W  $9A $1D02002ARL     $89 $46 $FE $83 $7E
              $FE [$64] {$7D} $07 $C7 $45 $0E [$FFFFW]  $EB $13 $81 $7E $FE [$00C8W]
              {$7D} $07 $C7 $45 $0E [$0001W]  $EB $05 $C7 $45 $0E [$0000W]  $8B $45
              $0E $BA [$0018W]  $F7 $EA $89 $45 $16 $83 $7D $0E [$00] {$74} $0F $B8
              [$2F4EW]  $50 $57 $9A $09DC120ARL     $83 $C4 $04 $EB $0D $B8 [$2F12W]
                 $50 $57 $9A $09DC120ARL     $83 $C4 $04

#Check for walls and drawn sprite
%patch $11289                                             $83 $7D {$38} [$00] {$75}
              $06 $83 $7D {$3C} [$00] {$74} $10 $8B $45 $0E $F7 $D8 $89 $45 $0E $8B
              $45 $16 $F7 $D8 $89 $45 $16 $FF $75 $20 $33 $C0 $50 $FF $75 $1E
              $FF $75 $0C $FF $75 $0A $8B $C7 $05 $46 $00 $50 $9A $16541641RL
                  $83 $C4 $0C $5F $5E $8B $E5 $5D $CB

Action type

The Bounder uses action type 3 for all of its actions except when stunned. This allows it to respond to Keen while still moving smoothly through the air. Type 2 is used for both stunned actions as expected.

Keen 4

#Bouncing vertical
%patch $31D86 [$0003W]
%patch $31DA4 [$0003W]

#Bounder moving left/right
%patch $31DC2 [$0003W]
%patch $31DE0 [$0003W]

#Stunned Bounder in air
%patch $31DFE [$0002W]

#Stunned Bounder on ground
%patch $31E1C [$0002W]

Deprotect and stick to ground

The Bounder has no need for either of these variables and so has a value of 0 for both in all of its actions.

Keen 4

#Bouncing vertical
%patch $31D88 [$0000W $0000W]
%patch $31DA6 [$0000W $0000W]

#Bounder moving left/right
%patch $31DC4 [$0000W $0000W]
%patch $31DE2 [$0000W $0000W]

#Stunned in air
%patch $31E00 [$0000W $0000W]

#Stunned on ground
%patch $31E1E [$0000W $0000W]

Probability, randomness and jump directions

When the Bounder is not being ridden by Keen is randomly changes its bouncing directions. There are three directions it can bounce; left, right and vertical (Up and down.) This is handled via an unusual probability check. First the game takes a random number from 0-FF. Then it checks if the number is greater than $64. If not the Bounder bounds left. If it is then a second check is performed, this one seeing if the number if greater than $C8 ($64 + $64). If not the Bounder bounds right, otherwise it bounds vertically.

This means there is an equal chance of the Bounder bouncing left or right, but a smaller chance of it bouncing vertically. (0-100 is left, 101-200 is right, 201-255 is vertical. This is a ratio of about 2:2:1)

Keen 4

#Bounder bounce directions
%patch $11245 $FFFFW #Left
%patch $11253 $0001W #Right
%patch $1125A $0000W #Vertical

#Bounder bounce probabilities
%patch $1123F $64 #Left-right\vertical
%patch $1124C $C8 #Right-vertical

Sprite spawn code

In the initiation code notice the Bounder cache being set ($C7 $06 $CB71W $0001W.)

In the spawning code the last blue highlighted value is the sprite action the sprite uses as it proceeds to act in-level. $C7 $02 $xxxxW sets the sprite activity, $C7 $07 $xxxxW sets the sprite type, $C7 $20 $xxxxW sets the foreground value. Finally $D3 $E0 $05 $xxxx is how far down (Or more usually up) the sprite is spawned from where it is placed. This is necessary for sprites that walk on the ground as they can only be placed in the level at multiples of 16 pixels high while their actual height can be anything.

The Bounder always starts the level moving down and right. (Odd, it has no reason to.) $C7 $47 $10 $xxxxW is the vertical direction the sprite starts moving in, either $0001W (Facing down), $FFFFW (Facing up) or $0000W (Neither, never used.) $C7 $47 $0E $xxxxW is the horizontal direction.

Keen 4

#Location of initiation code
%patch $EE9B [$01FCW] #Bounder (At $EAEC)

#Bounder Initiation code
%patch $EAEC $FF $76 $FC $57 $9A {$108008EARL}     $83 $C4 $04 $C7 $06 $CB71W
             $0001W  $E9 $02FCW

#Bounder spawning code
%patch $110EA $55 $8B $EC $33 $C0 $50 $9A $06BD1E11RL     $83 $C4 $02 $8B $1E
              $D8 $A7 $C7 $07 [$000FW]  $C7 $47 $02 [$0001W]  $C7 $47 $20 [$0000W] 
              $8B $46 $06 $B1 $08 $D3 $E0 $89 $47 $0A $8B $46 $08 $D3 $E0 $05
              [$FF80W]  $89 $47 $0C $C7 $47 $10 [$0001W]  $C7 $47 $0E [$0000W]  $B8
              [$2F12W]  $50 $53 $9A $09DC118CRL     $83 $C4 $04 $5D $CB