import "CoreLibs/keyboard" import "CoreLibs/animation" import "CoreLibs/math" local gfx = playdate.graphics local prevtext = "" local levelname = nil local inverted = false local tileTable = gfx.imagetable.new("gfx/tiles") local tilemapEditor = gfx.tilemap.new() tilemapEditor:setImageTable(tileTable) local tiles = {} local sawblades = {} local spins = {} tilemapEditor:setSize(1000,1000) local imgtiles = gfx.sprite.new(tilemapEditor) local w, h = imgtiles:getSize() imgtiles:moveTo(w/2,h/2) local bool2int = {[true]=1,[false]=0} local toolTipButton local altClrButton local pos1 = {x,y} local editor = "main" local editorSongs = {"song1","song2","song5", "song6"} local selSong = "song2" local songIndexSel = 10 local imgFloppy = gfx.imagetable.new("gfx/floppyT") local imgAdd = gfx.image.new("gfx/add") local imgMus = gfx.image.new("gfx/music") local imgLine = gfx.image.new("gfx/line") local imgSpin = gfx.image.new("gfx/spin") local imgCursor = gfx.image.new("gfx/cursor2") local imgCant = gfx.image.new("gfx/nothing") local imgSquare = gfx.image.new("gfx/square") local imgRocket = gfx.image.new("gfx/start") local imgExit = gfx.image.new("gfx/exit") local imgEye = gfx.image.new("gfx/eye") local imgPlayer = gfx.image.new("gfx/rocket") local imgPlayerExit = gfx.image.new("gfx/bigrocket") local imgExitMen = gfx.image.new("gfx/leave") local imgSaw = gfx.imagetable.new("gfx/sawblades") local imgTarget = gfx.image.new("gfx/target") local imgGrid = gfx.image.new("gfx/grid") assert(imgFloppy) assert(imgAdd) assert(imgMus) assert(imgLine) assert(imgSpin) assert(imgCursor) assert(imgSquare) assert(imgRocket) assert(imgEye) assert(imgPlayer) assert(imgPlayerExit) assert(imgSaw) assert(imgTarget) assert(imgGrid) local animFloppy = gfx.animation.loop.new(100, imgFloppy) local saveTime = 0 local playerPos = {x=1562,y=1564} local exitPos = {x = 1616, y = 1536} local position = {x=100,y=100} local positionLerp = {x=0,y=0} local powers = {} function newProject() mode = "newproj" playdate.keyboard.show("NEW LEVEL") end local createNewFont = gfx.font.new("gfx/bigVisibleSpaces") function updateNewproj() gfx.clear() processStars(-10,-10) gfx.drawText("LEVEL NAME:", 35, 100) gfx.drawTextInRect(playdate.keyboard.text:upper(),0,130, 210, 80,0,nil,kTextAlignment.center,createNewFont) end function editLoadName(name) song:stop() mode = "editor" local data = json.decodeFile("levels/"..name) powers = data.fuel sawblades = data.saws spins = data.rotators playerPos = {x = data.rocket.x, y = data.rocket.y} exitPos = {x = data.bigrocket.x, y = data.bigrocket.y} position = {x = (data.rocket.x + 6) / 16, y = (data.rocket.y + 4)/16} levelname = name:match("(.+)%..+$") inverted = data.inverted playdate.display.setInverted(data.inverted) saveTime = 0 -- loading tiles for tile = 1, #data.tiles, 1 do tilemapEditor:setTileAtPosition(data.tiles[tile].x,data.tiles[tile].y,data.tiles[tile].t) tiles[tile] = {x=data.tiles[tile].x,y=data.tiles[tile].y,t=data.tiles[tile].t} end altClrButton = playdate.getSystemMenu():addCheckmarkMenuItem("alt colours",inverted, function(value) playdate.display.setInverted(value) inverted = value end) toolTipButton = playdate.getSystemMenu():addMenuItem("save", function() editSave() end) imgtiles:add() end function playdate.keyboard.keyboardWillHideCallback(ok) if ok == false then page = 0 playdate.wait(0.3) editLoad() elseif #playdate.keyboard.text:upper() > 0 then song:stop() mode = "editor" position = {x=89,y=93} playerPos = {x=1562,y=1564} exitPos = {x = 1616, y = 1536} inverted = false playdate.display.setInverted(false) saveTime = 0 song:stop() playdate.getSystemMenu():addCheckmarkMenuItem("alt colours",false, function(value) playdate.display.setInverted(value) inverted = value end) playdate.getSystemMenu():addMenuItem("save",false, function() editSave() end) levelname = playdate.keyboard.text:upper() imgtiles:add() else page = 0 playdate.wait(0.3) editLoad() end end function playdate.keyboard.textChangedCallback() local newTex = playdate.keyboard.text:gsub("/", ""):gsub("\\", ""):gsub("|", ""):gsub(":", ""):gsub("*", ""):gsub("?", ""):gsub('"', ""):gsub("<", ""):gsub(">", "") if #newTex > 24 then newTex = prevtext end playdate.keyboard.text = newTex prevtext = newTex end local tileIndex = 0.0 local curY = math.floor( tileIndex ) * 28 + 3 local curYlerp = -32 function editSave() playdate.datastore.delete("levels/"..levelname..".json") saveTime = 5 playdate.datastore.write({song=selSong, tiles = tiles, inverted = inverted, rocket=playerPos, bigrocket=exitPos, fuel = powers,saws=sawblades,rotators=spins},"levels/"..levelname) end local traveltime = 1 local armamount = 1 local armlength = 1 function editUpdate() --print(math.floor( tileIndex ) ) local change, aChange = playdate.getCrankChange() tileIndex += change * 0.01 if editor == "main" then if tileIndex > 7.9 then tileIndex = 0 end if tileIndex < 0 then tileIndex = 7.9 end curY = math.floor( tileIndex ) * 28 +7 elseif editor == "tiles" then if tileIndex < 0 then tileIndex = #tileTable-.1 end if tileIndex > #tileTable then tileIndex = 0 end curY = (math.floor( tileIndex ) % 8) * 28 +7 elseif editor == "music" then if tileIndex > #editorSongs - 0.1 then tileIndex = 0 end if tileIndex < 0 then tileIndex = #editorSongs - 0.1 end curY = math.floor( tileIndex ) * 28 +7 if songIndexSel ~= math.floor(tileIndex) then songIndexSel = math.floor(tileIndex) song:stop() song:load("sfx/"..editorSongs[songIndexSel+1]) song:play() end elseif editor == "pos2Saw" then traveltime += change * 0.002 if traveltime < 0.2 then traveltime = 0.2 end traveltime = tonumber(string.format("%.2f", traveltime)) elseif editor == "pos2Spin" then traveltime += change * 0.001 traveltime = tonumber(string.format("%.2f", traveltime)) end curYlerp = playdate.math.lerp(curYlerp, curY, 0.4) positionLerp.x = playdate.math.lerp(positionLerp.x, position.x * 16, 0.5) positionLerp.y = playdate.math.lerp(positionLerp.y, position.y * 16, 0.5) if playdate.buttonJustPressed(playdate.kButtonA) then if editor == "pos2Saw" then sawblades[#sawblades+1] = {start={x=pos1.x,y=pos1.y},ends = {x=(position.x + 11) * 16,y=(position.y + 7) * 16}, speed = traveltime} editor = "main" tileIndex = 2 elseif editor == "music" then selSong = editorSongs[math.floor(tileIndex) + 1] editor = "main" song:stop() song:load("sfx/song1") tileIndex = 6 songIndexSel = #editorSongs + 1 elseif editor == "pos2Spin" then spins[#spins+1] = {middle=true,x=pos1.x,y=pos1.y,speed=traveltime,arms=armamount,armlen=armlength} editor = "main" tileIndex = 3 printTable(spins[#spins]) elseif editor == "tiles" then if math.floor( tileIndex ) == 0 then editor = "main" else tilemapEditor:setTileAtPosition(position.x+12,position.y+8,math.floor( tileIndex ) + 1) tiles[#tiles+1] = {x=position.x + 12, y=position.y + 8, t=math.floor( tileIndex ) + 1} imgtiles = gfx.sprite.new(tilemapEditor) end elseif editor == "main" then if math.floor( tileIndex ) == 0 then --[[ tilemapEditor:setTileAtPosition(position.x+12,position.y+8,2) tiles[#tiles+1] = {x=position.x + 12, y=position.y + 8, t=2} imgtiles = gfx.sprite.new(tilemapEditor) ]] editor = "tiles" elseif math.floor(tileIndex) == 1 then powers[#powers+1] = {x=((position.x + 11) * 16)-7, y=((position.y + 7) * 16)-5} elseif math.floor(tileIndex) == 2 then traveltime = 1 pos1.x,pos1.y=((position.x + 11) * 16), ((position.y + 7) * 16) editor = "pos2Saw" elseif math.floor( tileIndex ) == 3 then traveltime = .1 armamount = 1 armlength = 1 pos1.x,pos1.y=((position.x + 11) * 16), ((position.y + 7) * 16) editor = "pos2Spin" elseif math.floor(tileIndex) == 4 then playerPos = {x = ((position.x + 11) * 16) - 6, y = ((position.y + 7) * 16) - 4} elseif math.floor(tileIndex) == 5 then exitPos = {x = (position.x + 11) * 16, y = (position.y + 7) * 16} elseif math.floor(tileIndex) == 6 then editor = "music" elseif math.floor(tileIndex) == 7 then editor = "view" end end end if playdate.buttonJustPressed(playdate.kButtonB) then if editor == "tiles" then tilemapEditor:setTileAtPosition(position.x+12,position.y+8,0) for tile = 1, #tiles, 1 do if tiles[tile].x == position.x + 12 and tiles[tile].y == position.y+8 then table.remove(tiles,tile) break end end elseif editor == "pos2Saw" then tileIndex = 2 editor = "main" elseif editor == "pos2Spin" then tileIndex = 3 editor = "main" elseif editor == "main" then --[[if math.floor( tileIndex ) == 0 then tilemapEditor:setTileAtPosition(position.x+12,position.y+8,0) for tile = 1, #tiles, 1 do if tiles[tile].x == position.x + 12 and tiles[tile].y == position.y+8 then table.remove(tiles,tile) break end end imgtiles = gfx.sprite.new(tilemapEditor)]] if math.floor(tileIndex) == 1 then for power = 1, #powers, 1 do if powers[power].x == ((position.x + 11) * 16)-7 and powers[power].y == ((position.y + 7) * 16)-5 then table.remove(powers,power) break end end elseif math.floor( tileIndex ) == 2 then for saw= 1, #sawblades, 1 do if sawblades[saw].start.x == (position.x + 11) * 16 and sawblades[saw].start.y == (position.y + 7) * 16 then table.remove(sawblades, saw) break end end elseif math.floor( tileIndex ) == 3 then for saw= 1, #spins, 1 do if spins[saw].x == (position.x + 11) * 16 and spins[saw].y == (position.y + 7) * 16 then table.remove(spins, saw) break end end end elseif editor == "view" then editor = "main" tileIndex = 7.5 end end if playdate.buttonJustPressed(playdate.kButtonLeft) then if editor ~= "pos2Spin" then position.x -= 1 else armamount-=1 if armamount < 1 then armamount = 1 end end elseif playdate.buttonJustPressed(playdate.kButtonRight) then if editor ~= "pos2Spin" then position.x += 1 else armamount+=1 end end if playdate.buttonJustPressed(playdate.kButtonUp) then if editor ~= "pos2Spin" then position.y -= 1 else armlength += 1 end elseif playdate.buttonJustPressed(playdate.kButtonDown) then if editor ~= "pos2Spin" then position.y += 1 else armlength-=1 if armlength < 1 then armlength = 1 end end end if position.x + 11 < 0 then position.x = -11 end if position.y + 7 < 0 then position.y = -7 end gfx.clear() -- draw map gfx.setDrawOffset(-positionLerp.x, -positionLerp.y) imgtiles:update() imgPlayerExit:draw(exitPos.x, exitPos.y) imgPlayer:draw(playerPos.x,playerPos.y) for saw = 1, #sawblades, 1 do local b = sawblades[saw] imgSaw[1]:draw(b.start.x,b.start.y) imgTarget:draw(b.ends.x,b.ends.y) if editor == "main" and math.floor( tileIndex ) == 2 then playdate.graphics.setLineWidth(2) gfx.drawLine(b.start.x+8,b.start.y+8,b.ends.x+8,b.ends.y+8) gfx.drawText(b.speed,b.start.x+8 - (gfx.getTextSize(b.speed)/2),b.start.y-16) end end for saw = 1, #spins, 1 do local spin = spins[saw] imgSaw[2]:draw(spin.x,spin.y) for arm = 1, spin.arms do for blade = 1, spin.armlen do local degrees = 360 / spin.arms * arm local position = {x=math.sin(math.rad(degrees)) * 20 * blade,y=math.cos(math.rad(degrees)) * 20 * blade} imgSaw[2]:draw(spin.x+position.x,spin.y+position.y) end end --[[ for spinner = 1, #spinblades, 1 do for arm = 1, #spinblades[spinner].arms do for blade = 1, #spinblades[spinner].arms[arm] do spinblades[spinner].time += spinblades[spinner].speed local degrees = (360 / #spinblades[spinner].arms * arm + spinblades[spinner].time) if degrees % 360 == 0 then spinblades[spinner].time = 0 end local position = {x=math.sin(math.rad(degrees)) * 20 * blade,y=math.cos(math.rad(degrees)) * 20 * blade} spinblades[spinner].arms[arm][blade]:setImage(loopSaws:image()) spinblades[spinner].arms[arm][blade]:moveTo(spinblades[spinner].mid.x + position.x, spinblades[spinner].mid.y + position.y) end end end]] if editor == "main" and math.floor( tileIndex ) == 3 then gfx.drawText(spin.speed,spin.x+8 - (gfx.getTextSize(spin.speed)/2),spin.y-16) end end for power = 1, #powers, 1 do imgSquare:draw(powers[power].x,powers[power].y) end if editor ~= "view" then imgGrid:drawTiled((position.x-2)*16,(position.y-2)*16,416,288) imgCursor:draw((position.x + 11) * 16, (position.y + 7) * 16) end --[[ gfx.setColor(playdate.graphics.kColorXOR) gfx.fillRect(((position.x + 11) * 16) + 3, ((position.y + 7) * 16) + 3,10,10) ]] if position.y < 1 then imgCant:drawTiled((position.x-1) * 16,-112,400,112) end if position.x < 1 then imgCant:drawTiled(-176,(position.y-1) * 16,176,272) end if editor == "pos2Saw" then imgSaw[1]:draw(pos1.x,pos1.y) end -- draw ui/ if editor ~= "view" then gfx.setLineWidth(5) gfx.setDrawOffset(0,0) gfx.setColor(gfx.kColorBlack) gfx.fillRect(362,0,400,240) gfx.setColor(gfx.kColorWhite) gfx.drawLine(360,0,360,240) -- draw changes if editor == "tiles" then gfx.drawText("A TO PLACE \nB TO DELETE",0,0) local ind = math.floor( tileIndex / 8 ) * 8 if tileIndex < 8 then imgExitMen:draw(366,8) else tileTable[1+ind]:draw(373,13) end tileTable[2+ind]:draw(373,41) tileTable[3+ind]:draw(373,69) tileTable[4+ind]:draw(373,97) tileTable[5+ind]:draw(373,125) tileTable[6+ind]:draw(373,153) tileTable[7+ind]:draw(373,181) tileTable[8+ind]:draw(373,209) elseif editor == "music" then for i = 1, #editorSongs do gfx.drawText(i,374,12+(28*(i-1))) end elseif editor == "pos2Saw" then gfx.drawText("SELECT TARGET POSITION \nTRAVEL TIME: "..traveltime.."S",0,0) elseif editor == "pos2Spin" then gfx.drawText("< "..armamount.." > ARMS\nV "..armlength.." ^ BLADES PER ARM\nROTATION SPEED: "..traveltime,0,0) elseif editor == "main" then imgMus:draw(366, 176) imgAdd:draw(366,8) imgLine:draw(366,64) imgSpin:draw(366,92) imgSquare:draw(366,36) imgRocket:draw(366, 120) imgExit:draw(366,148) imgEye:draw(366,204) if math.floor( tileIndex ) == 0 then gfx.drawText("TILES",0,0) elseif math.floor( tileIndex ) == 1 then gfx.drawText("POWER",0,0) elseif math.floor( tileIndex ) == 2 then gfx.drawText("MOVERS",0,0) elseif math.floor( tileIndex ) == 3 then gfx.drawText("SPINNERS",0,0) elseif math.floor( tileIndex ) == 4 then gfx.drawText("PLAYER",0,0) elseif math.floor( tileIndex ) == 5 then gfx.drawText("EXIT",0,0) elseif math.floor( tileIndex ) == 6 then gfx.drawText("MUSIC",0,0) elseif math.floor( tileIndex ) == 7 then gfx.drawText("VIEW",0,0) end end gfx.setColor(playdate.graphics.kColorXOR) gfx.fillRect(365,curYlerp,33,28) end if saveTime > 0 then saveTime -= 0.1 animFloppy:draw(2,210) end end function editClose() for tile = 1, #tiles, 1 do tilemapEditor:setTileAtPosition(tiles[tile].x,tiles[tile].y,0) end tiles = {} powers = {} sawblades = {} editor = "main" tileIndex = 0 playdate.display.setInverted(false) imgtiles = gfx.sprite.new(tilemapEditor) imgtiles:remove() if #playdate.getSystemMenu():getMenuItems() > 1 then playdate.getSystemMenu():removeMenuItem(playdate.getSystemMenu():getMenuItems()[3]) playdate.getSystemMenu():removeMenuItem(playdate.getSystemMenu():getMenuItems()[2]) end end