require("tiny-debug") tiny = require("lib/tiny") require("lib/inspect") require("utils") require("tiny-tools") World = tiny.world() require("generated/filter-types") require("generated/assets") require("generated/all-systems") local width, height = love.graphics.getWidth(), love.graphics.getHeight() local squareSide = 80 local tileSize = math.floor(squareSide * 1.2) local squareSize = { x = squareSide, y = squareSide } CursorMask = 1 BallMask = 2 local function emptyTile(unhighlightSiblings, gridPosition) return { unhighlightSiblings = unhighlightSiblings, canBeCollidedBy = CursorMask, highlightOnMouseOver = T.marker, size = squareSize, gridPosition = gridPosition, drawAsRectangle = { size = squareSize }, } end local function replaceAt(grid, y, x, entity) local current = grid[y][x] grid[y][x] = entity current.highlighted = nil entity.parentGrid = grid current.unhighlightSiblings[entity] = true current.unhighlightSiblings[current] = nil entity.unhighlightSiblings = current.unhighlightSiblings -- entity.position = current.position entity.gridPosition = current.gridPosition entity.toLeft = current.toLeft entity.toRight = current.toRight entity.above = current.above entity.below = current.below current.toLeft.toRight = current.toRight current.toRight.toLeft = current.toLeft current.above.below = current.below current.below.above = current.above -- print("replacement: " .. Inspect(entity, { depth = 1 })) World:removeEntity(current) World:addEntity(entity) end function Replace(toReplace, replacement) replaceAt(toReplace.parentGrid, toReplace.gridPosition.y, toReplace.gridPosition.x, replacement) end function PositionAtGridXy(x, y) return { x = 20 + ((x - 1) * tileSize), y = 60 + ((y - 1) * tileSize), } end Scenarios = { ---@return table xyGrid Where grid[y][x] is an Entity emptyGrid = function() local cursorSize = { x = 5, y = 5 } World:addEntity({ size = cursorSize, moveWithCursor = T.marker, isCursor = T.marker, canCollideWith = bit.bor(CursorMask, BallMask), position = { x = -999, y = -999 }, highlightsCollided = T.marker, -- drawAsRectangle = { -- size = cursorSize, -- mode = "fill", -- }, }) World:addEntity({ position = { x = 0, y = 0 }, drawAsSprite = Grass, z = 0, }) -- Temporary storages for connecting grid items local previous local unhighlightSiblings = {} local yxGrid = {} local xCount = 8 local yCount = 5 for y = 1, yCount do yxGrid[y] = {} for x = 1, xCount do local current = World:addEntity(emptyTile(unhighlightSiblings, { x = x, y = y })) current.parentGrid = yxGrid yxGrid[y][x] = current unhighlightSiblings[current] = true current.toLeft = previous if previous ~= nil then if previous.toRight == nil then previous.toRight = current end else current.canReceiveButtons = T.marker current.highlighted = T.marker end if yxGrid[y - 1] and yxGrid[y - 1][x] then current.above = yxGrid[y - 1][x] yxGrid[y - 1][x].below = current end if y == yCount then -- Connect last row to first row yxGrid[1][x].above = current current.below = yxGrid[1][x] end if x == xCount then -- Connect last column to first column current.toRight = yxGrid[y][1] yxGrid[y][1].toLeft = current end previous = current end end local startButtonX, startButtonY = StartButton:getDimensions() World:addEntity({ canBeCollidedBy = CursorMask, drawAsSprite = StartButton, addOnActivate = { { roundState = "active" }, }, z = 3, size = { x = startButtonX, y = startButtonY }, position = { x = width - 120, y = height - 50, }, }) return yxGrid end, firstLevel = function() local yxGrid = Scenarios.emptyGrid() local clickables = 0 ---@param entity table | { effectsToApply: BallEffects } local function addClickable(entity) entity.canBeCollidedBy = bit.bor(CursorMask, entity.canBeCollidedBy or 0) entity.pickedUpOnClick = T.marker entity.size = squareSize entity.z = 1 entity.position = { x = 20 + (clickables * squareSide), y = height - 80 } clickables = clickables + 1 return World:addEntity(entity) end replaceAt(yxGrid, 4, 7, { drawAsSprite = Flag, z = 1, effectsToApply = { endOfRound = T.marker, movement = { x = 0, y = 0 }, }, }) replaceAt(yxGrid, 2, 5, { drawAsSprite = SmallSandTrap, z = 1, spriteAfterEffect = SmallSandTrapActivated, effectsToApply = { slowsTo = { x = 1, y = 1 }, --movement = { x = 0, y = 0 }, }, }) replaceAt(yxGrid, 3, 1, { drawAsSprite = SmallSandTrap, z = 1, spriteAfterEffect = SmallSandTrapActivated, effectsToApply = { slowsTo = { x = 1, y = 1 }, --movement = { x = 0, y = 0 }, }, }) addClickable({ drawAsSprite = GolferRight, spriteAfterEffect = GolferRightActivated, effectsToApply = { movement = { x = 8, y = 0 }, } }) addClickable({ drawAsSprite = ConveyerDownRight, spriteAfterEffect = ConveyerDownRight, effectsToApply = { movement = { x = 1, y = 1 }, } }) addClickable({ drawAsText = { text = "ROCK", }, effectsToApply = { slowsTo = { x = -1, y = -1 }, } }) addClickable({ drawAsText = { text = "RAMP", }, effectsToApply = { fliesFor = 1, slowsBy = { x = 3, y = 3 }, } }) addClickable({ drawAsSprite = GolferRight, spriteAfterEffect = GolferRightActivated, effectsToApply = { movement = { x = 5, y = 0 }, }, }) addClickable({ drawAsSprite = GolferDown, spriteAfterEffect = GolferRightActivated, effectsToApply = { movement = { x = 0, y = 6 }, }, }) local teleporterA = addClickable({ drawAsSprite = Teleporter, spriteAfterEffect = TeleporterInactive, effectsToApply = {} }) local teleporterB = addClickable({ drawAsSprite = Teleporter, spriteAfterEffect = TeleporterInactive, effectsToApply = {} }) teleporterA.effectsToApply.teleportTo = teleporterB teleporterB.effectsToApply.teleportTo = teleporterA addClickable({ drawAsSprite = SmallSandTrap, spriteAfterEffect = SmallSandTrapActivated, effectsToApply = { slowsTo = { x = 1, y = 1 }, }, }) addClickable({ drawAsSprite = SmallSandTrap, spriteAfterEffect = SmallSandTrapActivated, effectsToApply = { slowsTo = { x = 1, y = 1 }, }, }) World:addEntity({ ballEffects = {}, drawAsSprite = Ball, gridPosition = { x = 1, y = 1 }, endAnimating = T.marker, z = 2, }) end, } local bail = false local currentLevel = Scenarios.firstLevel function love.load() -- World:setSystemIndex(LiveForNFrames, 1) love.graphics.setBackgroundColor(1, 1, 1) love.graphics.setFont(EtBt7001Z0xa(32)) currentLevel() end function love.draw() local dt = love.timer.getDelta() if love.keyboard.isDown("r") then World:clearEntities() currentLevel() bail = false end if love.keyboard.isDown("f") then bail = not bail end if not bail then World:update(dt, function(_, system) return not system.isDrawSystem end) end World:update(dt, function(_, system) return system.isDrawSystem end) end