SimpleBreak
From OxeyeWiki
Contents |
Description
SimpleBreak is a very simple break-out game. Rendering is done with only rectangles, and all input is done with the mouse. A couple of sfxr sound effects have been added for some extra punch :)
Development time of this example was roughly one hour.
Download all files here: simplebreak.zip
Assets
Files
main.lua
math.randomseed( os.time() ) local gameData = { destructionCounter = 0, } local gameField = {} local player = { x = 0, y = 0, width = 100, height = 20, momentum = {}, momentumUpdate = 0 } local maxMomentum, momentumTime = 8, .05 local balls = {} local tileColors = { { a = 255, r = 160, g = 120, b = 120 }, { a = 255, r = 180, g = 160, b = 130 }, { a = 255, r = 240, g = 230, b = 160 }, { a = 255, r = 240, g = 235, b = 220 }, } local function addBall() local ball = { x = 0, y = 0, width = 10, height = 10, dx = 0, dy = 0, momentum = {}, momentumUpdate = 0, state = "locked" } table.insert(balls, ball) return ball end local function addTile(x, y, width, height, hits) local tile = {x = x, y = y, width = width, height = height, hits = hits} table.insert(gameField, tile) return tile end local function createLevel() gameField = {} -- clear old set local w,h = video.getScreenSize() local currentY = math.random(0, 5) while currentY < h / 2 do local tileHeight = math.random(30, 50) local currentX = math.random(0, 10) while currentX < w do local tileWidth = math.random(40, 80) if tileWidth + currentX > w then tileWidth = w - currentX end if tileWidth > 10 then addTile(currentX, currentY, tileWidth, tileHeight, math.random(1, 4)) end currentX = currentX + tileWidth + math.random(3, 4) end currentY = currentY + tileHeight + math.random(3, 4) end end --[[ INIT METHOD ]] local function mainInit() createLevel() addBall() end hook.add("gameInit", mainInit) local function updateMomentum(object, time) object.momentumUpdate = object.momentumUpdate + time if object.momentumUpdate > momentumTime then object.momentumUpdate = object.momentumUpdate - momentumTime table.insert(object.momentum, {x = object.x, y = object.y} ) while #object.momentum > maxMomentum do table.remove(object.momentum, 1) end end end --[[ UPDATE METHOD ]] local function mainUpdate(time) if time > .06 then time = .06 end local w, h = video.getScreenSize() -- update momentum updateMomentum(player, time) for index, ball in ipairs(balls) do updateMomentum(ball, time) end -- update player position local mx, my = daisy.getMousePosition() player.x = mx - player.width / 2 if player.x < 0 then player.x = 0 elseif player.x + player.width > w then player.x = w - player.width end player.y = h - player.height - 10 -- update balls for ballIndex, ball in ipairs(balls) do if ball.state == "locked" then ball.x = player.x + (player.width - ball.width) / 2 ball.y = player.y - ball.height if daisy.isMouseButtonPressed(0) then ball.state = "action" ball.dx, ball.dy = 0, -250 end elseif ball.state == "action" then ball.x, ball.y = ball.x + ball.dx * time, ball.y + ball.dy * time if ball.x + ball.width > w then ball.dx = -ball.dx ball.x = w - ball.width elseif ball.x < 0 then ball.dx = -ball.dx ball.x = 0 end if ball.y < 0 then ball.dy = -ball.dy ball.y = 0 end for index, tile in ipairs(gameField) do if ball.x + ball.width >= tile.x and ball.x <= tile.x + tile.width and ball.y + ball.height >= tile.y and ball.y <= tile.y + tile.height then if tile.hits > 1 then tile.hits = tile.hits - 1 if ball.y < tile.y or ball.y + ball.height > tile.y + tile.height then ball.dy = -ball.dy end if ball.x < tile.x or ball.x + ball.width > tile.x + tile.width then ball.dx = -ball.dx end audio.playSound("hit.wav") else table.remove(gameField, index) audio.playSound("break.wav") gameData.destructionCounter = gameData.destructionCounter + 1 if gameData.destructionCounter % 10 == 0 then addBall() end end break -- only allow one tile collision per update end end if ball.x + ball.width >= player.x and ball.x <= player.x + player.width and ball.y + ball.height >= player.y and ball.y <= player.y + player.height then if ball.dy > 0 then ball.dy = -(ball.dy + 1) audio.playSound("bounce.wav") end ball.dx = ((ball.x + ball.width / 2) - (player.x + player.width / 2)) * 3 end if ball.y > h then -- note, removing stuff inside a loop will mess up the loop index, so this is not best practise table.remove(balls, ballIndex) end end end end hook.add("frameUpdate", mainUpdate) --[[ RENDER METHOD ]] local function mainRender() local w,h = video.getScreenSize() video.renderRectangle(0, 0, w, h, 255, 40, 60, 80) for index, tile in ipairs(gameField) do local color = tileColors[tile.hits] video.renderRectangle(tile.x, tile.y, tile.width, tile.height, color.a, color.r, color.g, color.b) end -- render player local intensity = 1 for i=#player.momentum, 1, -1 do intensity = intensity * .8 local a, r, g, b = math.floor(intensity * 255), 255, 255, 255 video.renderRectangle(player.momentum[i].x, player.y, player.width, player.height, a, r, g, b) end video.renderRectangle(player.x, player.y, player.width, player.height, 255, 255, 255, 255) -- render balls for index, ball in ipairs(balls) do local intensity = 1 for i=#ball.momentum, 1, -1 do intensity = intensity * .8 local a, r, g, b = math.floor(intensity * 255), 230, 80, 20 video.renderRectangle(ball.momentum[i].x, ball.momentum[i].y, ball.width, ball.height, a, r, g, b) end video.renderRectangle(ball.x, ball.y, ball.width, ball.height, 255, 230, 80, 20) end if #gameField == 0 then video.renderText("VICTORY! - Press Ctrl+R to play again", w / 2, h - 100, 1) elseif #balls == 0 then video.renderText("GAME OVER - Press Ctrl+R to try again", w / 2, h - 100, 1) end end hook.add("frameRender", mainRender)