Posted May 02, 2024 by StealthC
#technical-overview
I’m resuming work on the project and would like to share some insights from my reverse engineering study. I haven’t settled on the best format for documentation yet, so I’ll be using my personal notes to describe the discoveries I make. Likewise, I’m starting up with the last feature implemented, the Juggernaut’s Skull Bullets.
Note: In the current release of the game (version 48), only the primary projectile function is simulated (activated by clicking the mouse on the screen). This functionality does not yet extend to the Juggernaut.
The Skull Bullet’s two frames are manually loaded in raw format by function 0x129d6:
It also utilizes the same explosion sprites and animation as the Maniaxe’s Axes, employing this graphics sheet:
The Skull Bullet ricochets off floors, ceilings, and walls, capable of bouncing up to four times. When the bullet’s position overlaps with a block, it is adjusted to align with the block’s margin, corresponding to its direction of movement. Upon contacting a wall, the bullet’s horizontal speed is reversed and reduced by 1.0; if this reduction would bring the speed to zero, it is simply reversed with no decrease. When hitting a floor or ceiling, the bullet’s vertical speed is inverted and reduced by 25%.
ActiveSkullBullets
by 1.availableHits
to 4 (the bullets can hit blocks exactly 4 times).newXPos = xPos + xSpd
# For performance reasons, only checks if the point is within a new block:
if isPointWithinNewBlock(xPos, yPos, newXPos, yPos) and isSolidBlock(newXPos, yPos):
# Align the point just outside the block according to direction:
xPos = alignPointWithBlockHorizontally(xPos, newXPos)
availableHits -= 1
if availableHits == 0:
# Skips the loop and goes to destroy subroutine:
return destroy()
# Decreases horizontal speed by 1.0:
if abs(xSpd) - 1.0 > 0:
xSpd = (abs(xSpd) - 1.0) * sign(xSpd)
xSpd *= -1.0
flipX = not flipX
else:
xPos = newXPos
newYPos = yPos + ySpd
# For performance reasons, only checks if the point is within a new block:
if isPointWithinNewBlock(xPos, yPos, xPos, newYPos) and isSolidBlock(xPos, newYPos):
# Align the point just outside the block according to direction:
yPos = alignPointWithBlockVertically(yPos, newYPos)
availableHits -= 1
if availableHits == 0:
# Skips the loop and goes to destroy subroutine:
return destroy()
# Invert the vertical speed and reduce it by 25%
ySpd *= -0.75
else:
yPos = newYPos