Okay. Here’s a big chunk. Not sure if it’ll be of any help without explanation, but if you’d like to check it out, go ahead and feel free to ask questions:
hero.frameLoop = function(event) local touching = touching -- compute potential horizontal motion for next frame --print(editor.state) if hero.dead == false then if touching == "left" then hero.xVel = hero.xVel - hero.xAccel elseif touching == "right" then hero.xVel = hero.xVel + hero.xAccel elseif touching == false then hero.xVel = hero.xVel \* hero.friction end end if hero.xVel \> hero.xMaxVel then hero.xVel = hero.xMaxVel elseif hero.xVel \< -hero.xMaxVel then hero.xVel = -hero.xMaxVel end hero.xPosNext = hero.xPos + hero.xVel if hero.platform ~= false then -- add platform xOffset to hero.xPosNext hero.xPosNext = hero.xPosNext + platformList[hero.platform].xOffset end -- compute potential vertical motion for next frame if hero.jumpState == "falling" then hero.yVel = hero.yVel + hero.yAccel jumpTouch = false elseif hero.jumpState == "grounded" then if jumpTouch == true then jumpTouch = false hero.jump() end end if hero.yVel \> hero.yMaxVel then hero.yVel = hero.yMaxVel elseif hero.yVel \< -hero.yMaxVel then hero.yVel = -hero.yMaxVel end -- set yPosNext if hero.platform == false then -- move hero with velocity hero.yPosNext = hero.yPos + hero.yVel else -- move along with platform hero.yPosNext = platformList[hero.platform].image.y end -- reevaluate next position for hero based on collisions! local levelMap = levelMap -- first correct the vertical movement, based on current X and next Y position !!! local bottomRow = math.floor((hero.yPosNext)/94) -- first row = row 0 which is good for row multiplier 0\*mapwidth for Arraypos's local topRow = math.floor((hero.yPosNext-252)/94) -- first row = row 0 which is good for row multiplier 0\*mapwidth for Arraypos's local leftColumn = math.floor((hero.xPos-62)/126) -- first column = column 0 so add 1 for Arraypos's local rightColumn = math.floor((hero.xPos+62)/126) -- first column = column 0 so add 1 for Arraypos's if (hero.jumpState == "falling") or (hero.platform ~= false) then if hero.yVel \> 0 then -- moving down -- check if bottom points are in a platform if hero.platform == false then for i = 1, #platformList do local vDistance = hero.yPosNext - platformList[i].image.y local hDistance = math.abs(hero.xPosNext - platformList[i].image.x) if (vDistance \> 0) and (vDistance \< 64) then -- 64 for platform height if platformList[i].type == 3 then if (hDistance \< 236) then hero.jumpState = "grounded" hero.platform = i hero.yPosNext = platformList[i].image.y if platformList[i].dropform == true then platformList[i]:startTimer() end end elseif platformList[i].type == 2 then if (hDistance \< 156) then hero.jumpState = "grounded" hero.platform = i hero.yPosNext = platformList[i].image.y if platformList[i].dropform == true then platformList[i]:startTimer() end end end end -- if end -- for platformList end -- repeat check for bottom points in a dropform!!! local botLeftTile = levelMap.physics[leftColumn+1+bottomRow\*levelMap.width] local botRightTile = levelMap.physics[rightColumn+1+bottomRow\*levelMap.width] if (botLeftTile ~= 1) or (botRightTile ~= 1) then -- one or more bottom corners will be on a solid tile audio.play(landSound) hero.yVel = 0 hero.yPos = (math.floor(hero.yPosNext/94)\*94)-1 hero.jumpState = "grounded" hero.platform = false else hero.yPos = hero.yPosNext end elseif hero.yVel \< 0 then -- moving up local topLeftTile = levelMap.physics[leftColumn+1+topRow\*levelMap.width] local topRightTile = levelMap.physics[rightColumn+1+topRow\*levelMap.width] if (topLeftTile == 2) or (topRightTile == 2) then -- one or more top corners will be on a solid tile hero.yVel = 0 -- WRONG!!! hero.yPos = (math.floor(hero.yPosNext/94)\*94)+64 else hero.yPos = hero.yPosNext end elseif hero.yVel == 0 then -- no vertical movement hero.yPos = hero.yPosNext end -- if (hero.jumpState == "falling" or platform is true) else -- if hero == "grounded" end -- then correct the horizontal movement, based on corrected Y and next X position !!! bottomRow = math.floor((hero.yPos)/94) -- first row = row 0 which is good for row multiplier 0\*mapwidth for Arraypos's local midRow = math.floor((hero.yPos-126)/94) -- first row = row 0 which is good for row multiplier 0\*mapwidth for Arraypos's topRow = math.floor((hero.yPos-252)/94) -- first row = row 0 which is good for row multiplier 0\*mapwidth for Arraypos's leftColumn = math.floor((hero.xPosNext-62)/126) -- first column = column 0 so add 1 for Arraypos's rightColumn = math.floor((hero.xPosNext+62)/126) -- first column = column 0 so add 1 for Arraypos's local xSpeedWithPlatform = hero.xVel if hero.platform ~= false then xSpeedWithPlatform = hero.xVel + platformList[hero.platform].xOffset end if xSpeedWithPlatform \> 0 then -- moving right local topRightTile = levelMap.physics[rightColumn+1+topRow\*levelMap.width] local midRightTile = levelMap.physics[rightColumn+1+midRow\*levelMap.width] local botRightTile = levelMap.physics[rightColumn+1+bottomRow\*levelMap.width] if (topRightTile == 2) or (midRightTile == 2) or (botRightTile == 2) then -- one or more right corners will be on a solid tile -- check wether on platform and only bottom point colliding if (hero.platform ~= false) and (topRightTile ~= 2) and (midRightTile ~= 2) then -- hitting only bottom point to get off platform! hero.xPos = hero.xPosNext else hero.xVel = 0 hero.xPos = (math.floor(hero.xPosNext/126)\*126)+63 end else hero.xPos = hero.xPosNext end elseif xSpeedWithPlatform \< 0 then -- moving left local topLeftTile = levelMap.physics[leftColumn+1+topRow\*levelMap.width] local midLeftTile = levelMap.physics[leftColumn+1+midRow\*levelMap.width] local botLeftTile = levelMap.physics[leftColumn+1+bottomRow\*levelMap.width] if (topLeftTile == 2) or (midLeftTile == 2) or (botLeftTile == 2) then -- one or more top corners will be on a solid tile -- check wether on platform and only bottom point colliding if (hero.platform ~= false) and (topLeftTile ~= 2) and (midLeftTile ~= 2) then -- hitting only bottom point to get off platform! hero.xPos = hero.xPosNext else hero.xVel = 0 hero.xPos = (math.floor(hero.xPosNext/126)\*126)+64 end else hero.xPos = hero.xPosNext end elseif hero.xVel == 0 then -- no horizontal movement hero.xPos = hero.xPosNext end -- gate check here! for i = 1, #gateList do local gate = gateList[i] if gate.state == "closed" then -- start checking stuff -- if gate is OPEN we do nothing at all! :-) -- CHECK wether hero is IN gate rect if math.abs(gate.group.x - hero.xPos) \< 128 then -- in horizontal area so check V overlap if (gate.group.y - hero.yPos) \< 192 and (gate.group.y - hero.yPos) \> - 444 then -- Y also within gate if hero.holdingKey == false then -- hero is blocked because gate is closed and hero is not holding a key -- BLOCK HERO!!! if hero.xVel \< 0 then -- moving left hero.xVel = 0 hero.xPos = gate.group.x + 128 elseif hero.xVel \> 0 then -- moving right hero.xVel = 0 hero.xPos = gate.group.x - 128 end else -- HERO is HOLDING A KEY! -- So check if it is the RIGHT KEY index for this gate if keyList[hero.holdingKey].group.index == gate.group.index then -- hero opens door and moves through gate.open(gate) -- is equal to gate:open() keyList[hero.holdingKey].group.y = -1000 keyList[hero.holdingKey].state = "used" hero.holdingKey = false else -- hero is holding a key with the wrong index -- BLOCK HERO!!! if hero.xVel \< 0 then -- moving left hero.xVel = 0 hero.xPos = gate.group.x + 128 elseif hero.xVel \> 0 then -- moving right hero.xVel = 0 hero.xPos = gate.group.x - 128 end end -- check if holding the right key end -- hero holding key or not check ends end -- if hero is in vertical rect check ends end -- if hero is in horizontal rect check ends end -- if gate.state == CLOSED or OPEN check ends end -- for loop over all gates ENDS -- finally, check to see if hero is still standing on solid tiles or on finish -- if not on solid or cloud, set jumpState to "falling" -- if on finish tile, level is completed! bottomRow = math.floor(((hero.yPos)/94)+1) -- first row = row 0 which is good for row multiplier 0\*mapwidth for Arraypos's leftColumn = math.floor((hero.xPos-62)/126) -- first column = column 0 so add 1 for Arraypos's rightColumn = math.floor((hero.xPos+62)/126) -- first column = column 0 so add 1 for Arraypos's local botLeftTile = levelMap.physics[leftColumn+1+bottomRow\*levelMap.width] local botRightTile = levelMap.physics[rightColumn+1+bottomRow\*levelMap.width] if hero.platform ~= false then -- hero is standing on a platform local hDistance = math.abs(hero.xPosNext - platformList[hero.platform].image.x) if platformList[hero.platform].type == 3 then if hDistance \> 236 then hero.platform = false hero.jumpState = "falling" hero.yVel = -10 end elseif platformList[hero.platform].type == 2 then if hDistance \> 156 then hero.platform = false hero.jumpState = "falling" hero.yVel = -10 end end else -- hero is not on a platform if (botLeftTile == 1) and (botRightTile == 1) and (hero.jumpState == "grounded") then -- both bottom corners will be on an air tile hero.yVel = -10 hero.jumpState = "falling" elseif (botLeftTile == 8) and (botRightTile == 8) and (hero.jumpState == "grounded") then if hero.finished == false then --print("finished!") audio.stop(1) audio.play(victorySound) -- write unlocked and score into levelTable data and SAVE! -- set current level unlocked from PLAYABLE to PLAYED levelTable.data[levelMap.number][3]=2 -- set next level unlocked from LOCKED to PLAYABLE levelTable.data[levelMap.number+1][3]=1 -- set scores (temp to Gold Silver Bronze!) levelTable.data[levelMap.number][7]=3 levelTable.data[levelMap.number][8]=2 levelTable.data[levelMap.number][9]=1 -- then SAVE the levelTable levelTable.save() hero.finished = true UI.closeShutterLevelFinished() end elseif (botLeftTile == 4) or (botRightTile == 4) and (hero.jumpState == "grounded") then -- hero is on death tile with one or two corners if hero.dead == false then hero.die() end else -- hero is still standing on solid, cloud, ice or jump with one or both bottom corners end end



Set it before you load any tile images and / or make sprite sheets from tiles (and don’t forget to reset it afterwards).