Score & UI
Let's improve our game's user interface with a proper score display, lives, and a win condition.
Better Text Display
Love2D allows custom fonts and positioning. For now, we'll make the most of the default font:
lualove.graphics.print(text, x, y) love.graphics.printf(text, x, y, width, alignment) -- "left", "center", "right"
Game States
Games typically have different states: menu, playing, game over, win. Let's add a simple win screen:
luafunction love.load() player = { x = 50, y = 100, width = 30, height = 40, speed = 200, velocityY = 0, gravity = 800, jumpForce = -350, onGround = false } platforms = { {x = 0, y = 250, width = 400, height = 50}, {x = 100, y = 180, width = 80, height = 15}, {x = 220, y = 130, width = 100, height = 15}, {x = 50, y = 80, width = 70, height = 15}, } coins = { {x = 130, y = 155, radius = 8, collected = false}, {x = 260, y = 105, radius = 8, collected = false}, {x = 80, y = 55, radius = 8, collected = false}, {x = 350, y = 225, radius = 8, collected = false}, } score = 0 totalCoins = #coins gameWon = false end function love.update(dt) if gameWon then return end -- Stop updating if won -- Movement if love.keyboard.isDown("left") or love.keyboard.isDown("a") then player.x = player.x - player.speed * dt end if love.keyboard.isDown("right") or love.keyboard.isDown("d") then player.x = player.x + player.speed * dt end -- Gravity player.velocityY = player.velocityY + player.gravity * dt player.y = player.y + player.velocityY * dt player.onGround = false -- Platform collisions for i, plat in ipairs(platforms) do if checkCollision(player, plat) then local overlapTop = (player.y + player.height) - plat.y if overlapTop > 0 and player.velocityY > 0 then player.y = plat.y - player.height player.velocityY = 0 player.onGround = true end end end -- Coin collection local collected = 0 for i, coin in ipairs(coins) do if not coin.collected then if checkCoinCollision(player, coin) then coin.collected = true score = score + 10 end end if coin.collected then collected = collected + 1 end end -- Check win condition if collected == totalCoins then gameWon = true end -- Screen bounds if player.x < 0 then player.x = 0 end if player.x + player.width > 400 then player.x = 400 - player.width end end function checkCollision(a, b) return a.x < b.x + b.width and a.x + a.width > b.x and a.y < b.y + b.height and a.y + a.height > b.y end function checkCoinCollision(player, coin) local closestX = math.max(player.x, math.min(coin.x, player.x + player.width)) local closestY = math.max(player.y, math.min(coin.y, player.y + player.height)) local distX, distY = coin.x - closestX, coin.y - closestY return (distX * distX + distY * distY) < (coin.radius * coin.radius) end function love.keypressed(key) if gameWon and key == "r" then love.load() -- Restart game return end if (key == "space" or key == "w" or key == "up") and player.onGround then player.velocityY = player.jumpForce end end function love.draw() -- Sky love.graphics.setColor(0.4, 0.7, 1) love.graphics.rectangle("fill", 0, 0, 400, 300) -- Platforms love.graphics.setColor(0.4, 0.8, 0.4) for i, plat in ipairs(platforms) do love.graphics.rectangle("fill", plat.x, plat.y, plat.width, plat.height) end -- Coins for i, coin in ipairs(coins) do if not coin.collected then love.graphics.setColor(1, 0.8, 0) love.graphics.circle("fill", coin.x, coin.y, coin.radius) love.graphics.setColor(1, 1, 0.5) love.graphics.circle("fill", coin.x - 2, coin.y - 2, 3) end end -- Player love.graphics.setColor(1, 0.3, 0.3) love.graphics.rectangle("fill", player.x, player.y, player.width, player.height) love.graphics.setColor(1, 1, 1) love.graphics.circle("fill", player.x + 10, player.y + 12, 5) love.graphics.circle("fill", player.x + 22, player.y + 12, 5) love.graphics.setColor(0, 0, 0) love.graphics.circle("fill", player.x + 12, player.y + 12, 2) love.graphics.circle("fill", player.x + 24, player.y + 12, 2) -- UI Background love.graphics.setColor(0, 0, 0, 0.5) love.graphics.rectangle("fill", 5, 5, 120, 25) -- Score love.graphics.setColor(1, 1, 1) love.graphics.print("Score: " .. score .. " Coins: " .. score/10 .. "/" .. totalCoins, 10, 10) -- Win screen if gameWon then love.graphics.setColor(0, 0, 0, 0.7) love.graphics.rectangle("fill", 0, 0, 400, 300) love.graphics.setColor(1, 0.8, 0) love.graphics.printf("YOU WIN!", 0, 100, 400, "center") love.graphics.setColor(1, 1, 1) love.graphics.printf("Final Score: " .. score, 0, 140, 400, "center") love.graphics.printf("Press R to restart", 0, 180, 400, "center") end end
Try it! Collect all coins to win, then press R to play again!