local sti = require("sti") local inspect = require("inspect") love.graphics.setDefaultFilter("nearest", "nearest") local game = { SCREEN_WIDTH=320, SCREEN_HEIGHT=200, TILE_SIZE=16, -- NOTE: playfield dimensions in tiles PLAYFIELD_OFFSET_TOP=1.5, PLAYFIELD_WIDTH=20, PLAYFIELD_HEIGHT=10, playFieldTiles={}, map=sti("map.lua"), entities={ vehicles={}, floatdevs={}, }, default_speeds={ floatdev=8, vehicle=10, }, hazards={}, drawGrid=false, winState=false, big_font=love.graphics.newFont(48, "mono"), font=love.graphics.newFont(12, "mono"), } function t2p(tileDim) return tileDim*game.TILE_SIZE end function tilePos2Pixels(tilePos) return t2p(tilePos.x - 1), t2p(tilePos.y - 1) end function screenPixelToTilePos(pixelPos) return { x=math.floor(pixelPos.x/game.TILE_SIZE + 1), y=math.floor((pixelPos.y + t2p(game.PLAYFIELD_OFFSET_TOP))/game.TILE_SIZE) } end local player = { pos={x=t2p(0), y=t2p(0)}, turtlePos={x=t2p(0), y=t2p(1)}, turtleHit=false, lives=3, turtles=3, dead=false, deadTimer=2, float_speed=0, } function resetPlayer() player.pos = {x=t2p(0), y=t2p(0)} player.dead = false player.turtleHit = false player.turtlePos = {x=t2p(0), y=t2p(1)} end function love.load() local desktop_width, desktop_height = love.window.getDesktopDimensions() game.scaleW = desktop_width / game.SCREEN_WIDTH game.scaleH = desktop_height / game.SCREEN_HEIGHT for i, layer in ipairs(game.map.layers) do if layer.objects then layer.visible = false for j, mapObj in ipairs(layer.objects) do mapObj.visible = false local typekey = mapObj.type.."s" if game.entities[typekey] == nil then game.entities[typekey] = {} end local entity = { x=mapObj.x, y=mapObj.y, w=mapObj.width, h=mapObj.height, type=mapObj.type, gid=mapObj.gid, } if mapObj.type == "vehicle" or mapObj.type == "floatdev" then local tile = game.map.tiles[mapObj.gid] or game.map.tiles[game.map:setFlippedGID(mapObj.gid)] entity.collider = tile.objectGroup.objects[1] entity.speed = mapObj.properties.speed or game.default_speeds[mapObj.type] end table.insert(game.entities[typekey], entity) end end end player.sprites = love.graphics.newImage("player-sprites.png") player.quads = { dude=love.graphics.newQuad(17, 9, 15, 23, player.sprites), turtle=love.graphics.newQuad(0, 23, 17, 9, player.sprites), } end function love.keyreleased(key) if player.dead or player.turtleHit then return end if game.winState then if key == "space" or key == "return" then game.winState = false resetPlayer() end return end local newPos = screenPixelToTilePos(player.pos) local oldPos = screenPixelToTilePos(player.pos) if key == "up" or key == "w" then newPos.y = newPos.y - 1 end if key == "down" or key == "s" then newPos.y = newPos.y + 1 end if key == "right" or key == "d" then newPos.x = newPos.x + 1 end if key == "left" or key == "a" then newPos.x = newPos.x - 1 end player.turtlePos.x = t2p(oldPos.x - 1) player.turtlePos.y = t2p(oldPos.y - 1) if newPos.x < 1 then newPos.x = 1 end if newPos.x > game.PLAYFIELD_WIDTH then newPos.x = game.PLAYFIELD_WIDTH end if newPos.y < 1 then newPos.y = 1 end if newPos.y > game.PLAYFIELD_HEIGHT then newPos.y = game.PLAYFIELD_HEIGHT end player.pos.x = t2p(newPos.x - 1) player.pos.y = t2p(newPos.y - 1) end function tilePos2Rect(tilePos) return { x=t2p(tilePos.x - 1), y=t2p(tilePos.y - 1), w=game.TILE_SIZE, h=game.TILE_SIZE, } end function rectanglesIntersect(rect1, rect2) return (rect1.x < rect2.x + rect2.w and rect1.x + rect1.w > rect2.x and rect1.y < rect2.y + rect2.h and rect1.y + rect1.h > rect2.y) end function love.update(dt) if player.dead or player.turtleHit then player.deadTimer = player.deadTimer - dt if player.deadTimer <= 0 then player.deadTimer = 2 resetPlayer() end elseif not game.winState then if screenPixelToTilePos(player.turtlePos).x == game.PLAYFIELD_WIDTH then game.winState = true end local playerRect = tilePos2Rect(screenPixelToTilePos(player.pos)) local turtleRect = tilePos2Rect(screenPixelToTilePos(player.turtlePos)) if player.float_speed ~= 0 then player.pos.y = player.pos.y + player.float_speed*dt player.turtlePos.y = player.turtlePos.y + player.float_speed*dt if playerRect.y > t2p(game.PLAYFIELD_HEIGHT) or playerRect.y + playerRect.h< t2p(0) then player.dead = true end if turtleRect.y > t2p(game.PLAYFIELD_HEIGHT) or turtleRect.y + turtleRect.h< t2p(0) then player.turtleHit = true end end for i, vehicle in ipairs(game.entities.vehicles) do local colliderRect = {x=vehicle.x + vehicle.collider.x, y=vehicle.y + vehicle.collider.y, w=vehicle.collider.width, h=vehicle.collider.height} if rectanglesIntersect(playerRect, colliderRect) then player.dead = true player.lives = player.lives - 1 end if rectanglesIntersect(turtleRect, colliderRect) then player.turtleHit = true end vehicle.y = vehicle.y + vehicle.speed*dt if vehicle.y > t2p(game.PLAYFIELD_HEIGHT) then vehicle.y = -vehicle.h end if vehicle.y + vehicle.h < t2p(0) then vehicle.y = t2p(game.PLAYFIELD_HEIGHT) end end local was_floating = player.float_speed ~= 0 player.float_speed = 0 for i, floatdev in ipairs(game.entities.floatdevs) do local colliderRect = {x=floatdev.x + floatdev.collider.x, y=floatdev.y + floatdev.collider.y, w=floatdev.collider.width, h=floatdev.collider.height} if player.float_speed == 0 and rectanglesIntersect(playerRect, colliderRect) then if not was_floating then if math.abs(player.pos.y - colliderRect.y) > math.abs(player.pos.y - (colliderRect.y + colliderRect.h)) then player.pos.y = colliderRect.y player.turtlePos.y = player.pos.y + game.TILE_SIZE*2 else player.pos.y = colliderRect.y + colliderRect.h - game.TILE_SIZE player.turtlePos.y = player.pos.y - game.TILE_SIZE end end player.turtlePos.x = player.pos.x player.float_speed = floatdev.speed end floatdev.y = floatdev.y + floatdev.speed*dt if floatdev.y > t2p(game.PLAYFIELD_HEIGHT) then floatdev.y = -floatdev.h end if floatdev.y + floatdev.h < t2p(0) then floatdev.y = t2p(game.PLAYFIELD_HEIGHT) end end if player.float_speed == 0 then for i, water in ipairs(game.entities.waters) do if not player.dead and rectanglesIntersect(playerRect, water) then player.dead = true player.lives = player.lives - 1 end end if not player.dead and was_floating then player.turtlePos.x = player.pos.x player.turtlePos.y = player.pos.y - game.TILE_SIZE if player.turtlePos.y < t2p(0) then player.turtlePos.y = player.pos.y + game.TILE_SIZE end end end end end function love.draw() love.graphics.setColor(1, 1, 1) game.map:draw(0, t2p(game.PLAYFIELD_OFFSET_TOP), game.scaleW, game.scaleH) love.graphics.push() -- love.graphics.scale(game.scaleW, game.scaleH) love.graphics.translate(0, t2p(game.PLAYFIELD_OFFSET_TOP)) if game.drawGrid then love.graphics.setColor(0.4, 0.3, 0.1) for i=0, game.PLAYFIELD_WIDTH do love.graphics.line(t2p(i), 0, t2p(i), t2p(game.PLAYFIELD_HEIGHT)) end for i=0, game.PLAYFIELD_HEIGHT do love.graphics.line(0, t2p(i), t2p(game.PLAYFIELD_WIDTH), t2p(i)) end end for i, vehicle in ipairs(game.entities.vehicles) do local tile = game.map.tiles[vehicle.gid] or game.map:setFlippedGID(vehicle.gid) local tileset = game.map.tilesets[tile.tileset] local image = tileset.image love.graphics.setColor(1, 1, 1) love.graphics.draw(image, tile.quad, vehicle.x, vehicle.y) love.graphics.setColor(0.9, 0.1, 0) -- love.graphics.rectangle("line", vehicle.x + vehicle.collider.x, vehicle.y + vehicle.collider.y, vehicle.collider.width, vehicle.collider.height) end for i, floatdev in ipairs(game.entities.floatdevs) do local tile = game.map.tiles[floatdev.gid] or game.map:setFlippedGID(floatdev.gid) local tileset = game.map.tilesets[tile.tileset] local image = tileset.image love.graphics.setColor(1, 1, 1) love.graphics.draw(image, tile.quad, floatdev.x, floatdev.y) love.graphics.setColor(0.9, 0.1, 0) end if player.dead then love.graphics.setColor(0.8, 0.1, 0) else love.graphics.setColor(1, 1, 1) end love.graphics.setColor(0, 0, 0) love.graphics.rectangle("fill", 16, -t2p(game.PLAYFIELD_OFFSET_TOP), game.SCREEN_WIDTH, t2p(game.PLAYFIELD_OFFSET_TOP)) love.graphics.rectangle("fill", 0, game.SCREEN_HEIGHT - 40, game.SCREEN_WIDTH, 48) love.graphics.setColor(1, 1, 1) local x, y = player.pos.x, player.pos.y love.graphics.draw(player.sprites, player.quads.dude, x, y - 8) x, y = player.turtlePos.x, player.turtlePos.y if player.turtleHit then love.graphics.setColor(0.8, 0.1, 0) else love.graphics.setColor(1, 1, 1) end love.graphics.draw(player.sprites, player.quads.turtle, x, y + 4) if game.winState then love.graphics.setColor(0, 0, 0, 0.8) love.graphics.rectangle("fill", 0, -32, game.SCREEN_WIDTH, game.SCREEN_HEIGHT) love.graphics.setColor(0, 1, 0.2) love.graphics.printf("MADE IT!", game.big_font, 64, 12, 200, "center") love.graphics.printf("press return to play again", game.font, 64, 128, 200, "center") end -- love.graphics.pop() end