106 lines
3.8 KiB
Lua
106 lines
3.8 KiB
Lua
-- shows the player - enemy collision boxes
|
|
-- does not show the player bullet - enemy collision boxes
|
|
-- doesn't currently handle collision code f (rising spiked walls and fire beams)
|
|
|
|
function check_player_x_collision(player_index)
|
|
local PLAYER_STATE = emu.read(0x90 + player_index, emu.memType.nesMemory)
|
|
if PLAYER_STATE ~= 0x01 then
|
|
-- exit if player not in normal state
|
|
return nil
|
|
end
|
|
|
|
-- @check_in_water_crouched
|
|
local collision_box = 0x00
|
|
local LEVEL_LOCATION_TYPE = emu.read(0x40 + player_index, emu.memType.nesMemory)
|
|
local PLAYER_WATER_STATE = emu.read(0xb2 + player_index, emu.memType.nesMemory)
|
|
if LEVEL_LOCATION_TYPE & 0xfe == 0x00 then
|
|
-- outdoor
|
|
local PLAYER_SPRITE_SEQUENCE = emu.read(0xbc + player_index, emu.memType.nesMemory)
|
|
if PLAYER_WATER_STATE ~= 0x00 and PLAYER_SPRITE_SEQUENCE == 0x02 then
|
|
-- exit if player crouched in water, no collision can happen with player
|
|
return nil
|
|
end
|
|
end
|
|
|
|
if PLAYER_WATER_STATE == 0x00 then
|
|
collision_box = collision_box + 1
|
|
end
|
|
|
|
-- not checking for crouched while on indoor level, because non-bullets can
|
|
-- collide when crouching player on indoor levels
|
|
|
|
local PLAYER_JUMP_STATUS = emu.read(0xa0 + player_index, emu.memType.nesMemory)
|
|
local PLAYER_SPRITE_CODE = emu.read(0xd6 + player_index, emu.memType.nesMemory)
|
|
if PLAYER_JUMP_STATUS == 0x00 then
|
|
-- player not jumping
|
|
collision_box = collision_box + 1
|
|
if PLAYER_SPRITE_CODE ~= 0x17 then
|
|
collision_box = collision_box + 1
|
|
end
|
|
end
|
|
|
|
-- draw player collision point
|
|
local SPRITE_Y_POS = emu.read(0x031a + player_index, emu.memType.nesMemory)
|
|
local SPRITE_X_POS = emu.read(0x0334 + player_index, emu.memType.nesMemory)
|
|
emu.drawRectangle(SPRITE_X_POS, SPRITE_Y_POS, 1, 1, 0x0000ff, false)
|
|
|
|
for i = 0,0xf do
|
|
local ENEMY_ROUTINE = emu.read(0x04b8 + i, emu.memType.nesMemory)
|
|
local ENEMY_ROUTINE = emu.read(0x04b8 + i, emu.memType.nesMemory)
|
|
local ENEMY_STATE_WIDTH = emu.read(0x0598 + i, emu.memType.nesMemory)
|
|
local should_test_collision = ENEMY_STATE_WIDTH & 0x01 == 0x00
|
|
if ENEMY_ROUTINE ~= 0x00 and should_test_collision then
|
|
set_enemy_collision_box(player_index, i, collision_box)
|
|
end
|
|
end
|
|
end
|
|
|
|
function set_enemy_collision_box(player_index, i, collision_box)
|
|
local ENEMY_SCORE_COLLISION = emu.read(0x0588 + i, emu.memType.nesMemory) & 0x0f
|
|
|
|
if ENEMY_SCORE_COLLISION == 0x0f then
|
|
-- todo handle (fire beam and rising spiked wall)
|
|
return
|
|
end
|
|
|
|
local collision_box_addr = emu.readWord(0xe4e8 + (collision_box * 2), emu.memType.nesMemory) -- collision_box_codes_tbl
|
|
local offset = ENEMY_SCORE_COLLISION * 4
|
|
local y0 = emu.read(collision_box_addr + offset, emu.memType.nesMemory)
|
|
local x0 = emu.read(collision_box_addr + offset + 1, emu.memType.nesMemory)
|
|
local height = emu.read(collision_box_addr + offset + 2, emu.memType.nesMemory)
|
|
local width = emu.read(collision_box_addr + offset + 3, emu.memType.nesMemory)
|
|
local ENEMY_Y_POS = emu.read(0x0324 + i, emu.memType.nesMemory)
|
|
local ENEMY_X_POS = emu.read(0x033e + i, emu.memType.nesMemory)
|
|
|
|
local topY = ENEMY_Y_POS
|
|
if y0 > 0x80 then
|
|
y0 = negateInt(y0)
|
|
topY = ENEMY_Y_POS - y0
|
|
else
|
|
topY = ENEMY_Y_POS + y0
|
|
end
|
|
|
|
local topX = ENEMY_X_POS
|
|
if x0 > 0x80 then
|
|
x0 = negateInt(x0)
|
|
topX = ENEMY_X_POS - x0
|
|
else
|
|
topX = ENEMY_X_POS + x0
|
|
end
|
|
|
|
emu.drawRectangle(topX, topY, width, height, 0x0000ff, false)
|
|
end
|
|
|
|
function negateInt(num)
|
|
if(num > 0x80) then
|
|
num = (~num + 1) & 0xff
|
|
end
|
|
|
|
return num
|
|
end
|
|
|
|
function Main()
|
|
check_player_x_collision(0)
|
|
end
|
|
|
|
emu.addEventCallback(Main, emu.eventType.endFrame) |