Last active
January 2, 2017 03:50
-
-
Save The0x539/d8b61708986f000976e56c31ce2a4362 to your computer and use it in GitHub Desktop.
A one-by-one layer toggle library for SMBX
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local poof = {} | |
--Version 0.2a | |
--By The0x539 | |
--To poof a layer, use poof.startPoof(layer, frames, freeze) in your LunaLua file after loading the API. | |
--layer specifies which layer gets poof'd | |
--frames specifies the number of frames (give or take one or two, somebody teach The0x539 some computer science) between poofing each thing. | |
--freeze specifies whether time should be frozen starting when the camera moves, and ending when it's back at the player. | |
--If freeze == true, time is frozen. If freeze == false, player input is locked instead. | |
--Moving NPCs work much better when freeze == true. Results not guaranteed for moving NPCs with freeze == false. | |
--Should this library get fancy particles, they will work much better with freeze == false. | |
--If the layer's center is such that the camera would go past where it normally would, the background won't extend properly. This is just a SMBX thing. | |
--Multiplayer is not currently officially supported due to requiring additional camera work. | |
local workingLayer = nil | |
local timer = 0 | |
local defaultInterval = 15 | |
local interval = nil | |
local poofOut = nil | |
local queue = nil | |
local goalX = nil | |
local goalY = nil | |
local camera = Camera.get()[1] | |
local currentX = nil | |
local currentY = nil | |
local lockInput = false | |
poof.status = "idle" | |
function poof.onInitAPI() | |
registerEvent(poof, "onDraw", "handleWorld") | |
registerEvent(poof, "onCameraUpdate", "handleCamera") | |
registerEvent(poof, "onInputUpdate", "handleInput") | |
end | |
local function thingsIn(layer) | |
--returns all the blocks, BGOs, and NPCs in a layer, in whatever order SMBX provides them, concatenated not collated | |
local contents = {} | |
local function insert(items) | |
for k,item in pairs(items) do | |
if tostring(item.layerName) == layer then | |
table.insert(contents,item) | |
end | |
end | |
end | |
insert(Block.get()) | |
insert(BGO.get()) | |
insert(NPC.get()) | |
return contents | |
end | |
local function bottomLeft(items) | |
--Gives the coordinates of the bottomleftmost point in a group of things | |
local x = math.huge | |
local y = -math.huge | |
for k,item in pairs(items) do | |
if item.x < x then x = item.x end | |
if item.y + item.height > y then y = item.y + item.height end | |
end | |
return {x,y} | |
end | |
local function topRight(items) | |
--Gives the coordinates of the upperrightmost point in a group of things | |
local x = -math.huge | |
local y = math.huge | |
for k,item in pairs(items) do | |
if item.x + item.width > x then x = item.x + item.width end | |
if item.y < y then y = item.y end | |
end | |
return {x,y} | |
end | |
local function between(a,b,c) | |
--quick inequality thing for readability in reorder | |
if a <= b and b <= c then return true else return false end | |
end | |
local function reorder(items) | |
--A bit of a misnomer, but gives, in rightward-then-upward order, the contents of the working layer in this context. | |
local foo = {} | |
for y = bottomLeft(items)[2], topRight(items)[2], -32 do | |
for x = bottomLeft(items)[1], topRight(items)[1], 32 do | |
local function conditionalInsert(group) | |
for k,item in pairs(group.getIntersecting(x,y-32,x+32,y)) do | |
if tostring(item.layerName) == workingLayer and between(x,item.x,x+32) and between(y-32,item.y+item.height,y) then | |
table.insert(foo,item) | |
end | |
end | |
end | |
conditionalInsert(Block) | |
conditionalInsert(BGO) | |
conditionalInsert(NPC) | |
end | |
end | |
return foo | |
end | |
function poof.startPoof(layer, frames, freeze) | |
--Kicks things into gear, filling up the item queue and telling the camera where to go | |
if Layer.get(layer) and queue == nil then | |
freeze = freeze or true | |
interval = frames or defaultInterval | |
workingLayer=layer | |
if freeze then | |
Misc.pause() | |
else | |
lockInput = true | |
end | |
poofOut = not(Layer.get(layer).isHidden) | |
queue = reorder(thingsIn(layer)) | |
goalX = math.floor((bottomLeft(queue)[1]+topRight(queue)[1])/2) - 400 | |
goalY = math.floor((bottomLeft(queue)[2]+topRight(queue)[2])/2) - 300 | |
poof.status = "moveTo" | |
end | |
end | |
function poof.handleWorld() | |
--Makes blocks appear/vanish and pauses/unpauses time as appropriate | |
if poof.status == "poofing" and type(queue) == "table" then | |
if timer < interval then timer = timer + 1 else | |
if table.getn(queue) > 0 then | |
if queue[1].isHidden ~= poofOut then | |
queue[1].isHidden = poofOut | |
timer = 0 | |
Audio.playSFX(27) | |
end | |
table.remove(queue,1) | |
elseif Layer.get(workingLayer).isHidden ~= poofOut then | |
Layer.get(workingLayer):toggle(true) | |
else | |
queue = nil | |
poof.status = "moveBack" | |
poofOut = nil | |
interval = nil | |
end | |
end | |
elseif poof.status == "idle" then | |
if Misc.isPausedByLua() then Misc.unpause() | |
elseif lockInput then lockInput = false end | |
end | |
end | |
function poof.handleCamera() | |
--Moves the camera and updates its status as appropriate | |
if poof.status == "moveTo" then | |
currentX = math.floor(camera.x) | |
currentY = math.floor(camera.y) | |
poof.status = "moving" | |
elseif poof.status == "moveBack" then | |
goalX = math.floor(camera.x) | |
goalY = math.floor(camera.y) | |
poof.status = "moving" | |
end | |
for i = 0,5 do | |
if poof.status == "moving" then | |
if currentX < goalX then currentX = currentX + 1 | |
elseif currentX > goalX then currentX = currentX - 1 end | |
if currentY < goalY then currentY = currentY + 1 | |
elseif currentY > goalY then currentY = currentY - 1 end | |
if currentX == goalX and currentY == goalY then | |
if queue then poof.status = "poofing" else poof.status = "idle" end | |
break | |
end | |
end | |
end | |
if poof.status ~= "idle" then | |
camera.x = currentX | |
camera.y = currentY | |
end | |
end | |
function poof.handleInput() | |
--Locks all player1 input as appropriate | |
if lockInput then | |
player.upKeyPressing = false | |
player.downKeyPressing = false | |
player.leftKeyPressing = false | |
player.rightKeyPressing = false | |
player.jumpKeyPressing = false | |
player.altJumpKeyPressing = false | |
player.runKeyPressing = false | |
player.altRunKeyPressing = false | |
player.dropItemKeyPressing = false | |
player.pauseKeyPressing = false | |
end | |
end | |
return poof |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment