639 lines
15 KiB
Lua
639 lines
15 KiB
Lua
|
SCRIPT_TITLE = "Super Mario Bros. 3 Rainbow Riding"
|
||
|
SCRIPT_VERSION = "0.1"
|
||
|
|
||
|
require "m_utils"
|
||
|
m_require("m_utils",0)
|
||
|
|
||
|
--[[
|
||
|
Super Mario Bros. 3 Rainbow Riding
|
||
|
version 0.1 by miau
|
||
|
|
||
|
Visit http://morphcat.de/lua/ for the most recent version and other scripts.
|
||
|
|
||
|
This script turns smb3 into a new game very similar to Kirby's Canvas Curse.
|
||
|
It's still incomplete, messy and full of bugs, so don't expect too much. Next version
|
||
|
will fix most of that... hopefully.
|
||
|
Probably slow on old computers, you may want to turn down emulator speed anyway to
|
||
|
decrease difficulty.
|
||
|
|
||
|
Controls
|
||
|
Left-click on mario - jump
|
||
|
Middle-click anywhere - run
|
||
|
Draw vertical lines to make mario change his walking direction
|
||
|
Draw horizontal lines to help mario move over obstacles
|
||
|
|
||
|
Supported roms
|
||
|
Super Mario Bros 3 (J), Super Mario Bros 3 (U) (PRG 0), Super Mario Bros 3 (U) (PRG 1),
|
||
|
Super Mario Bros 3 (E)
|
||
|
|
||
|
Known Bugs/TODO list
|
||
|
Too many to list em all, actually...
|
||
|
- game objects are occasionally catapulted out of screen - bad divisions!?
|
||
|
- mario falling through lines (clean up collision detection)
|
||
|
- long vertically scrolling levels won't work
|
||
|
- boss battles are glitchy
|
||
|
- disable auto move in mini games?
|
||
|
- option to disable auto move?
|
||
|
- make collision detection work with fire balls (fire mario or fire piranha plants)
|
||
|
- improve map screen check
|
||
|
- add easy mode: decrease mario's speed
|
||
|
- improve enemy hit boxes
|
||
|
- (add suicide button in case mario gets stuck)
|
||
|
-]]
|
||
|
|
||
|
--configurable vars
|
||
|
local show_cursor = false
|
||
|
--------------------------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
|
||
|
local Z_LSPAN = 400 --240
|
||
|
local Z_MAX = 128 --256 --maximum amount of lines on screen
|
||
|
local NUM_SPRITES = 20
|
||
|
|
||
|
local zbuf = {}
|
||
|
local zindex = 1
|
||
|
local timer = 0
|
||
|
local zprev = 0
|
||
|
local last_inp={}
|
||
|
local spr = {} --game's original sprites
|
||
|
local mario = {}
|
||
|
local clickbox={x1=-4,y1=4,x2=18,y2=32}
|
||
|
local collx = 0
|
||
|
local colly = 0
|
||
|
--local coll = {} --debug
|
||
|
local paintmeter = 0
|
||
|
local lastpaint = -100
|
||
|
local jp = {}
|
||
|
|
||
|
|
||
|
--accepts two tables containing these elements [1]=x1, [2]=y1, [3]=x2, [4]=y2
|
||
|
function get_line_intersection(a,b)
|
||
|
local Asx,Asy,Bsx,Bsy,s,t
|
||
|
local Ax1,Ay1,Ax2,Ay2
|
||
|
local Bx1,By1,Bx2,By2
|
||
|
Ax1 = a[1]
|
||
|
Ay1 = a[2]
|
||
|
Ax2 = a[3]
|
||
|
Ay2 = a[4]
|
||
|
Bx1 = b[1]
|
||
|
By1 = b[2]
|
||
|
Bx2 = b[3]
|
||
|
By2 = b[4]
|
||
|
Asx = Ax2 - Ax1
|
||
|
Asy = Ay2 - Ay1
|
||
|
Bsx = Bx2 - Bx1
|
||
|
Bsy = By2 - By1
|
||
|
|
||
|
s = (-Asy * (Ax1 - Bx1) + Asx * (Ay1 - By1)) / (-Bsx*Asy + Asx*Bsy)
|
||
|
t = (Bsx * (Ay1 - By1) - Bsy * (Ax1 - Bx1)) / (-Bsx*Asy + Asx*Bsy)
|
||
|
if(s>=0 and s<=1 and t>=0 and t<=1) then
|
||
|
local Ix,Iy
|
||
|
Ix = Ax1 + t * Asx
|
||
|
Iy = Ay1 + t * Asy
|
||
|
return Ix,Iy
|
||
|
else
|
||
|
return nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function close_to_line(Px,Py,a,range) --a[4] line segment
|
||
|
local Ax=a[1]
|
||
|
local Ay=a[2]
|
||
|
local Bx=a[3]
|
||
|
local By=a[4]
|
||
|
local APx = Px - Ax
|
||
|
local APy = Py - Ay
|
||
|
local ABx = Bx - Ax
|
||
|
local ABy = By - Ay
|
||
|
local absq = ABx*ABx + ABy*ABy
|
||
|
local apab = APx*ABx + APy*ABy
|
||
|
local t = apab / absq
|
||
|
|
||
|
if (t < 0.0) then
|
||
|
t = 0.0
|
||
|
elseif (t > 1.0) then
|
||
|
t = 1.0
|
||
|
end
|
||
|
local Cx,Cy
|
||
|
Cx = Ax + ABx * t
|
||
|
Cy = Ay + ABy * t
|
||
|
if(getdistance(Px,Py,Cx,Cy)<=range) then
|
||
|
return true
|
||
|
else
|
||
|
return false
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function ride_line(s,xoffs,yoffs)
|
||
|
|
||
|
local function move(zx1,zy1,zx2,zy2)
|
||
|
local avx,avy,cvx,cvy
|
||
|
cvx,cvy = getvdir(zx1,zy1,zx2,zy2)
|
||
|
if(math.abs(spr[s].vx)<math.abs(spr[s].vy)) then
|
||
|
avx = spr[s].vx
|
||
|
avy = spr[s].vx
|
||
|
else
|
||
|
avx = spr[s].vy
|
||
|
avy = spr[s].vy
|
||
|
end
|
||
|
if(spr[s].movetimer) then
|
||
|
avx = cvx*5
|
||
|
avy = cvy*5
|
||
|
else
|
||
|
avx = cvx*2.5
|
||
|
avy = cvy*3
|
||
|
end
|
||
|
|
||
|
set_sprite_velocity(s,avx,avy)
|
||
|
--coll.a = {spr[s].x+xoffs,spr[s].y+yoffs-1,spr[s].x+xoffs+avx*64,spr[s].y+yoffs+avy*64-1}
|
||
|
end
|
||
|
|
||
|
local function getcoords(i)
|
||
|
local j
|
||
|
j = i - 1
|
||
|
if(j < 1) then
|
||
|
j = Z_MAX
|
||
|
end
|
||
|
if(zbuf[i] and zbuf[j]) then
|
||
|
return zbuf[j].x,zbuf[j].y,zbuf[i].x,zbuf[i].y
|
||
|
else
|
||
|
return nil
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function domovemagic(x,y,firstline)
|
||
|
local zx1,zy1,zx2,zy2 = getcoords(spr[s].riding)
|
||
|
if(zx1 and close_to_line(x,y,{zx1,zy1,zx2,zy2},5)) then
|
||
|
move(zx1,zy1,zx2,zy2)
|
||
|
else
|
||
|
--get next line.. check for collision
|
||
|
spr[s].riding = spr[s].riding + 1
|
||
|
if(spr[s].riding > Z_MAX) then
|
||
|
spr[s].riding = 1
|
||
|
end
|
||
|
if(spr[s].riding==firstline) then
|
||
|
spr[s].riding=nil
|
||
|
return
|
||
|
end
|
||
|
domovemagic(x,y,firstline)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if(spr[s].riding==nil) then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
local x = spr[s].x+xoffs
|
||
|
local y = spr[s].y+yoffs
|
||
|
domovemagic(x,y,spr[s].riding)
|
||
|
end
|
||
|
|
||
|
function collisioncheck(s)
|
||
|
local c=false
|
||
|
local cvx,cvy
|
||
|
local avx,avy
|
||
|
|
||
|
local function checkpixel(xoffs,yoffs,i,j)
|
||
|
local x = spr[s].x+xoffs
|
||
|
local y = spr[s].y+yoffs
|
||
|
local px2 = x+spr[s].vx
|
||
|
local py2 = y+spr[s].vy
|
||
|
local px1 = x
|
||
|
local py1 = y
|
||
|
local zx = zbuf[i].x
|
||
|
local zy = zbuf[i].y
|
||
|
local zx2 = zbuf[j].x
|
||
|
local zy2 = zbuf[j].y
|
||
|
if(spr[s].vx~=0 or spr[s].vy~=0) then
|
||
|
if(spr[s].vx>0) then --we need at least one pixel!!?
|
||
|
px2 = px2 + 2
|
||
|
elseif(spr[s].vx<0) then
|
||
|
px2 = px2 - 2
|
||
|
end
|
||
|
if(spr[s].vy>0) then
|
||
|
py2 = py2 + 2
|
||
|
elseif(spr[s].vy<0) then
|
||
|
py2 = py2 - 2
|
||
|
end
|
||
|
|
||
|
local cx,cy = get_line_intersection({px1,py1,px2,py2},{zx,zy,zx2,zy2})
|
||
|
if(cx~=nil) then
|
||
|
cx = math.floor(cx)
|
||
|
cy = math.floor(cy)
|
||
|
local avx,avy,cvx,cvy
|
||
|
|
||
|
--coll = {--[[a={px1,py1,px2+spr[s].vx*64,py2+spr[s].vy*64},-]]b={zbuf[i].x,zbuf[i].y,zbuf[j].x,zbuf[j].y}} --debug
|
||
|
collx = cx
|
||
|
colly = cy
|
||
|
|
||
|
avx,avy = getvdir(px1,py1,px2,py2)
|
||
|
cvx,cvy = getvdir(zbuf[j].x,zbuf[j].y,zbuf[i].x,zbuf[i].y)
|
||
|
|
||
|
|
||
|
local x,y
|
||
|
x = cx-xoffs
|
||
|
y = cy-yoffs
|
||
|
if(spr[s].x==x and spr[s].y==y) then
|
||
|
--FCEU.message("boo"..timer)
|
||
|
else
|
||
|
set_sprite_pos(s,x,y)
|
||
|
end
|
||
|
if(s==0) then --mario/luigi
|
||
|
if(math.abs(cvy)==1 and math.abs(cvx) < 0.5) then
|
||
|
change_sprite_dir(s)
|
||
|
set_sprite_velocity(s,-avx,nil)
|
||
|
else
|
||
|
spr[s].riding = i
|
||
|
set_sprite_velocity(s,0,0)
|
||
|
end
|
||
|
else --enemies, moving platforms
|
||
|
end
|
||
|
|
||
|
|
||
|
return true
|
||
|
end
|
||
|
else
|
||
|
if(close_to_line(x,y,{zx,zy,zx2,zy2},4)) then
|
||
|
if(s==0) then
|
||
|
spr[s].riding = i
|
||
|
set_sprite_velocity(s,0,0)
|
||
|
end
|
||
|
return true
|
||
|
else
|
||
|
spr[s].riding = nil
|
||
|
end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
if(spr[s].riding) then
|
||
|
ride_line(s,8,30)
|
||
|
return
|
||
|
end
|
||
|
|
||
|
for i=1,Z_MAX do
|
||
|
if(zbuf[i] and zbuf[i].connected) then
|
||
|
--if(zbuf[i].x >= spr[s].x+hitbox.x1 and zbuf[i].y >= spr[s].y+hitbox.y1
|
||
|
-- and zbuf[i].x <= spr[s].x+hitbox.x2 and zbuf[i].y <= spr[s].y+hitbox.y2) then
|
||
|
--local px = spr[s].x-spr[s].vx
|
||
|
--local py = spr[s].y-spr[s].vy
|
||
|
local j
|
||
|
j = i - 1
|
||
|
if(j < 1) then
|
||
|
j = Z_MAX
|
||
|
end
|
||
|
|
||
|
if(zbuf[j]) then --check if line is still valid (if nil, node disappeared)
|
||
|
if(s==0) then --mario
|
||
|
if(checkpixel(8,30,i,j)) then
|
||
|
return
|
||
|
end
|
||
|
else
|
||
|
if(checkpixel(0,0,i,j) or checkpixel(8,8,i,j)
|
||
|
--[[or checkpixel(0,8,i,j) or checkpixel(8,0,i,j)-]]) then
|
||
|
destroy_sprite(s)
|
||
|
return
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
--end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
|
||
|
function screen_to_game_pos(x,y)
|
||
|
return x+scroll_x,y+scroll_y
|
||
|
end
|
||
|
|
||
|
function game_to_screen_pos(x,y)
|
||
|
return x-scroll_x,y-scroll_y
|
||
|
end
|
||
|
|
||
|
|
||
|
function destroy_sprite(s)
|
||
|
if(s<10) then
|
||
|
memory.writebyte(0x660+s,0x06)
|
||
|
--memory.writebyte(0x660+s,0x00)
|
||
|
--set_sprite_velocity(s,10,10)
|
||
|
else
|
||
|
memory.writebyte(0x6C7+s-10,0x01)
|
||
|
--set_sprite_pos(s,0,0)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function set_sprite_velocity(s,vx,vy)
|
||
|
if(s<10) then
|
||
|
if(s==0) then
|
||
|
memory.writebyte(0xD8,1) --air flag?
|
||
|
end
|
||
|
if(vx) then
|
||
|
memory.writebyte(0xBD+s,vx*16)
|
||
|
spr[s].vx = vx
|
||
|
end
|
||
|
if(vy) then
|
||
|
memory.writebyte(0xCF+s,vy*16)
|
||
|
spr[s].vy = vy
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function set_sprite_pos(i,x,y)
|
||
|
memory.writebyte(0x90+i,AND(x,255))
|
||
|
memory.writebyte(0x75+i,math.floor(x/256))
|
||
|
memory.writebyte(0xA2+i,AND(y,255))
|
||
|
memory.writebyte(0x87+i,math.floor(y/256))
|
||
|
spr[i].x = x
|
||
|
spr[i].y = y
|
||
|
spr[i].sx,spr[i].sy = game_to_screen_pos(spr[i].x,spr[i].y)
|
||
|
end
|
||
|
|
||
|
function change_sprite_dir(s)
|
||
|
if(spr[s].dir == 1) then
|
||
|
spr[s].dir = -1
|
||
|
elseif(spr[s].dir == -1) then
|
||
|
spr[s].dir = 1
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function add_rainbow_coord(cx,cy,connected)
|
||
|
zbuf[zindex] = {t=timer,x=cx,y=cy,connected=connected}
|
||
|
zprev = zbuf[zindex]
|
||
|
zindex = zindex + 1
|
||
|
if(zindex>Z_MAX) then
|
||
|
zindex = 1
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function drawrainbow(x1,y1,x2,y2,coloffs)
|
||
|
local cx,cy
|
||
|
local vx,vy
|
||
|
local color = coloffs
|
||
|
vx,vy = getvdir(x1,y1,x2,y2)
|
||
|
cx = x1
|
||
|
cy = y1
|
||
|
|
||
|
for i=1,200 do
|
||
|
if(cx>=0 and cy>=0 and cx<=253 and cy<=253) then
|
||
|
local rcolor = color/1.8+161 --165
|
||
|
gui.drawpixel(cx,cy,rcolor)
|
||
|
gui.drawpixel(cx,cy+1,rcolor)
|
||
|
gui.drawpixel(cx+1,cy,rcolor)
|
||
|
gui.drawpixel(cx+1,cy+1,rcolor)
|
||
|
|
||
|
gui.drawpixel(cx+2,cy,rcolor)
|
||
|
gui.drawpixel(cx,cy+2,rcolor)
|
||
|
gui.drawpixel(cx+2,cy+1,rcolor)
|
||
|
gui.drawpixel(cx+1,cy+2,rcolor)
|
||
|
gui.drawpixel(cx+2,cy+2,rcolor)
|
||
|
end
|
||
|
if((x2>x1 and cx>x2) or (x2<x1 and cx<x2) or (y2>y1 and cy>y2) or (y2<y1 and cy<y2)) then
|
||
|
break
|
||
|
end
|
||
|
cx = cx + vx
|
||
|
cy = cy + vy
|
||
|
color = color + 17
|
||
|
color = AND(color,15)
|
||
|
end
|
||
|
return color
|
||
|
end
|
||
|
|
||
|
|
||
|
function initialize()
|
||
|
for i=0,NUM_SPRITES-1 do
|
||
|
spr[i] = {
|
||
|
a=0,
|
||
|
id=0,
|
||
|
id2=0,
|
||
|
x=0,
|
||
|
y=0,
|
||
|
hp=0,
|
||
|
}
|
||
|
end
|
||
|
spr[0].dir = 1
|
||
|
spr[0].lastposchange = -999
|
||
|
end
|
||
|
|
||
|
|
||
|
function update_sprites()
|
||
|
mario = spr[0]
|
||
|
--also change dir when colliding with game objects
|
||
|
local x = memory.readbyte(0x90)+memory.readbyte(0x75)*256
|
||
|
local y = memory.readbyte(0xA2)+memory.readbyte(0x87)*256
|
||
|
if(x~=mario.x or y~=mario.y) then
|
||
|
mario.lastposchange = timer
|
||
|
end
|
||
|
if(mario.dir~=0 and mario.riding==nil and timer-mario.lastposchange>60) then
|
||
|
mario.lastposchange = timer
|
||
|
change_sprite_dir(0)
|
||
|
end
|
||
|
|
||
|
--load game sprites from ram
|
||
|
for i=0,NUM_SPRITES-1 do
|
||
|
if(i<10) then
|
||
|
spr[i].x = memory.readbyte(0x90+i)+memory.readbyte(0x75+i)*256
|
||
|
spr[i].y = memory.readbyte(0xA2+i)+memory.readbyte(0x87+i)*256
|
||
|
spr[i].vx = memory.readbytesigned(0xBD+i)/16
|
||
|
spr[i].vy = memory.readbytesigned(0xCF+i)/16
|
||
|
spr[i].a = (memory.readbytesigned(0x660+i)~=0)
|
||
|
spr[i].id = memory.readbytesigned(0x670+i)
|
||
|
spr[i].sx,spr[i].sy = game_to_screen_pos(spr[i].x,spr[i].y)
|
||
|
else
|
||
|
--TODO: 0x5D3?
|
||
|
local xcomp = memory.readbyte(0xFD)
|
||
|
local ycomp = memory.readbyte(0xFC)
|
||
|
spr[i].x = memory.readbyte(0x5C9+i-10)
|
||
|
spr[i].y = memory.readbyte(0x5BF+i-10)
|
||
|
spr[i].a = true
|
||
|
spr[i].vx = 0
|
||
|
spr[i].vy = 0
|
||
|
spr[i].sx = AND(spr[i].x-xcomp+256,255)
|
||
|
spr[i].sy = AND(spr[i].y-ycomp+256,255)
|
||
|
spr[i].x = spr[i].sx + scroll_x
|
||
|
spr[i].y = spr[i].sy + scroll_y
|
||
|
end
|
||
|
if(spr[i].a) then
|
||
|
collisioncheck(i)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
function update_vars()
|
||
|
--disabling input not possible anymore in FCEUX 2.1?
|
||
|
jp = {}
|
||
|
if(mario.riding==nil) then
|
||
|
if(mario.movetimer) then
|
||
|
jp.B = 1
|
||
|
mario.movetimer = mario.movetimer - 1
|
||
|
if(mario.movetimer == 0) then
|
||
|
mario.movetimer = nil
|
||
|
end
|
||
|
end
|
||
|
if(mario.dir==1) then
|
||
|
jp.right=1
|
||
|
elseif(mario.dir==-1) then
|
||
|
jp.left=1
|
||
|
end
|
||
|
--if(AND(timer,1)==0) then --automatically enter doors and pipes... not a very good idea actually :P
|
||
|
--jp.up=1
|
||
|
--if(memory.readbyte(0xD8)==1) then --air flag set? try to stay in air as long as possible... makes it easier to rescue mario if collision detection screws up.. sucks in water levels
|
||
|
-- jp.A=1
|
||
|
--end
|
||
|
--else
|
||
|
-- jp.down=1 --automatically enter pipes
|
||
|
--end
|
||
|
end
|
||
|
|
||
|
inp = input.get()
|
||
|
|
||
|
scroll_x = memory.readbyte(0xFD)+memory.readbyte(0x12)*256
|
||
|
scroll_y = memory.readbyte(0xFC)--+memory.readbyte(0x13)*256 --not quite right, long vertical scrolling levels won't work
|
||
|
|
||
|
--0xD8 = 0 -> touch ground, 1 -> air
|
||
|
|
||
|
update_sprites()
|
||
|
|
||
|
|
||
|
if(inp.middleclick) then
|
||
|
mario.movetimer = 30
|
||
|
end
|
||
|
|
||
|
if(inp.leftclick==nil) then
|
||
|
mario.jumping=false
|
||
|
end
|
||
|
if(inp.leftclick and last_inp.leftclick==nil and
|
||
|
inp.xmouse>=mario.sx+clickbox.x1 and inp.xmouse<=mario.sx+clickbox.x2 and
|
||
|
inp.ymouse>=mario.sy+clickbox.y1 and inp.ymouse<=mario.sy+clickbox.y2)
|
||
|
then
|
||
|
jp.A = 1
|
||
|
mario.jumping = true
|
||
|
elseif(inp.leftclick and mario.jumping) then
|
||
|
jp.A = 1
|
||
|
elseif(inp.leftclick) then
|
||
|
if(paintmeter>0) then
|
||
|
local x,y=screen_to_game_pos(inp.xmouse,inp.ymouse)
|
||
|
if(last_inp.leftclick==nil) then
|
||
|
add_rainbow_coord(x,y,false)
|
||
|
outofpaint = nil
|
||
|
elseif(outofpaint==nil) then
|
||
|
if(zprev and getdistance(x,y,zprev.x,zprev.y)>8) then
|
||
|
add_rainbow_coord(x,y,true)
|
||
|
paintmeter = paintmeter - 2
|
||
|
lastpaint = timer
|
||
|
end
|
||
|
end
|
||
|
else
|
||
|
outofpaint = true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
joypad.set(1,jp)
|
||
|
|
||
|
last_mario = mario
|
||
|
last_inp = inp
|
||
|
end
|
||
|
|
||
|
function render()
|
||
|
--bctext(0,20,string.format("Memory usage: %.2f KB",collectgarbage("count")))
|
||
|
|
||
|
|
||
|
local j = 0
|
||
|
for i=1,Z_MAX do
|
||
|
if(zbuf[i]) then
|
||
|
j = j + 1
|
||
|
end
|
||
|
end
|
||
|
--bctext(0,20,"Lines: "..j)
|
||
|
--bctext(0,20,mario.x..","..mario.y)
|
||
|
--bctext(0,30,mario.sx..","..mario.sy)
|
||
|
--bctext(0,40,mario.vx..","..mario.vy)
|
||
|
--bctext(0,50,"D "..mario.dir)
|
||
|
|
||
|
--bctext(0,70,"scroll_x: "..scroll_x)
|
||
|
--bctext(0,80,"scroll_y: "..scroll_y)
|
||
|
--bctext(0,90,AND(mario.x,255))
|
||
|
--if(mario.riding) then
|
||
|
-- bctext(0,100,"R")
|
||
|
--end
|
||
|
bcbox(mario.sx+clickbox.x1,mario.sy+clickbox.y1,mario.sx+clickbox.x2,mario.sy+clickbox.y2,"white")
|
||
|
|
||
|
local prev_x, prev_y, prev_connected
|
||
|
local i=zindex
|
||
|
local color = AND(timer/2,15)
|
||
|
for j=1,Z_MAX do
|
||
|
if(zbuf[i]) then
|
||
|
local ltime = timer-zbuf[i].t
|
||
|
if(ltime<Z_LSPAN) then
|
||
|
local x,y=game_to_screen_pos(zbuf[i].x,zbuf[i].y)
|
||
|
if(prev_x and prev_connected) then
|
||
|
color = drawrainbow(prev_x,prev_y,x,y,color)
|
||
|
end
|
||
|
prev_x = x
|
||
|
prev_y = y
|
||
|
prev_connected = zbuf[i].connected
|
||
|
else
|
||
|
zbuf[i] = nil
|
||
|
end
|
||
|
end
|
||
|
i = i - 1
|
||
|
if(i<1) then
|
||
|
i = Z_MAX
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
local cx,cy = game_to_screen_pos(mario.x+8,mario.y+30)
|
||
|
bcpixel(cx,cy,string.format("#%02X%02X%02X",math.random(0,255),math.random(0,255),math.random(0,255)))
|
||
|
|
||
|
local pmx=78
|
||
|
local pmy=226
|
||
|
if(paintmeter>0) then
|
||
|
drawrainbow(pmx+paintmeter,pmy,pmx,pmy,timer/6)
|
||
|
end
|
||
|
bcbox(pmx-2,pmy-1,pmx+102,pmy+3,"white")
|
||
|
|
||
|
if(timer-lastpaint>60) then
|
||
|
paintmeter = paintmeter + 1
|
||
|
if(paintmeter>100) then
|
||
|
paintmeter=100
|
||
|
end
|
||
|
end
|
||
|
|
||
|
if(show_cursor) then
|
||
|
local col2
|
||
|
if(inp.leftclick) then
|
||
|
col2 = "#FFAA00"
|
||
|
elseif(inp.rightclick) then
|
||
|
col2 = "#0099EE"
|
||
|
elseif(inp.middleclick) then
|
||
|
col2 = "#AACC00"
|
||
|
else
|
||
|
col2 = "white"
|
||
|
end
|
||
|
drawcursor(inp.xmouse,inp.ymouse,"black",col2)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function domagic()
|
||
|
if(memory.readbyte(0x73)==0x20) then --map screen(?)
|
||
|
update_vars()
|
||
|
render()
|
||
|
else
|
||
|
bcpixel(1,10,"clear")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
initialize()
|
||
|
gui.register(domagic)
|
||
|
|
||
|
while(true) do
|
||
|
FCEU.frameadvance()
|
||
|
timer = timer + 1
|
||
|
end
|