-- Import libraries local screen = require( "libraries/shack" ) screen:setDimensions( love.graphics.getWidth(), love.graphics.getHeight() ) local binser = require( "libraries/binser" ) -- Ensure that every play is different by changing the random number seed math.randomseed( os.time() ) -- Variables playerDistance = 40 playAreaHeight = love.graphics.getHeight() - 50 keyCounter = 0 menuList = {} currentMenu = "main" menuSelect = 1 menuScroll = 0 quitted = false -- Themes themes = { default = { name = "Default", red = { 0.9, 0, 0 }, lightRed = { 1, 0.5, 0.5 }, darkRed = { 0.5, 0, 0 }, blue = { 0, 0, 0.9 }, lightBlue = { 0.5, 0.5, 1 }, darkBlue = { 0, 0, 0.5 }, purple = { 1, 0, 1 }, black = { 0, 0, 0 }, gray = { 0.5, 0.5, 0.5 }, white = { 1, 1, 1 } }, light = { name = "Light", red = { 0.9, 0, 0 }, lightRed = { 1, 0.5, 0.5 }, darkRed = { 0.5, 0, 0 }, blue = { 0, 0, 0.9 }, lightBlue = { 0.5, 0.5, 1 }, darkBlue = { 0, 0, 0.5 }, purple = { 1, 0, 1 }, black = { 1, 1, 1 }, gray = { 0.5, 0.5, 0.5 }, white = { 0, 0, 0 }, }, gruvbox = { name = "Gruvbox", red = { 0.8, 0.1412, 0.1137 }, lightRed = { 0.9843, 0.2863, 0.2039 }, darkRed = { 0.6157, 0, 0.023529 }, blue = { 0.2706, 0.5216, 0.5333 }, lightBlue = { 0.5137, 0.6471, 0.5961 }, darkBlue = { 0.027451, 0.4, 0.4706 }, purple = { 0.6941, 0.3843, 0.5255 }, black = { 0.1569, 0.1569, 0.1569 }, gray = { 0.6588, 0.6, 0.5176 }, white = { 0.9216, 0.8588, 0.698 } } } currentTheme = themes.default -- Player coordinates and scores player1 = { x = playerDistance + 20, y = playAreaHeight - ( 120 + playerDistance ), score = 0, xImg = nil, yImg = nil, xVelocity = nil, yVelocity = nil, counter = 0 } player1Settings = { ai = false, aiDifficulty = 2 } player2 = { x = love.graphics.getWidth() - ( 120 + playerDistance ), y = playerDistance + 20, score = 0, xImg = nil, yImg = nil, xVelocity = nil, yVelocity = nil, counter = 0 } player2Settings = { ai = true, aiDifficulty = 2 } -- Keyboard definitions. If a player's key is not defined, it will fallback to -- the 'default' player. keys = { default = { left = { "left", "keyboard" }, right = { "right", "keyboard" }, up = { "up", "keyboard" }, down = { "down", "keyboard" }, pause = { "p", "keyboard" }, menuSelect = { "return", "keyboard" } }, player1 = { left = { "a", "keyboard" }, right = { "d", "keyboard" }, up = { "w", "keyboard" }, down = { "s", "keyboard" }, pause = { "e", "keyboard" }, menuSelect = nil }, player2 = { left = { "j", "keyboard" }, right = { "l", "keyboard" }, up = { "i", "keyboard" }, down = { "k", "keyboard" }, pause = { "o", "keyboard" }, menuSelect = nil } } -- Blocks - 10 for each side, positive if the block is there, zero if it is not leftBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } bottomBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } rightBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } topBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } leftBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } bottomBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } rightBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } topBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -- Ball ball = { x = ( love.graphics.getWidth() / 2 ) - 20, y = ( playAreaHeight / 2 ) - 20, prevX = { nil, nil, nil, nil, nil }, prevY = { nil, nil, nil, nil, nil }, velocity = 120, acceleration = 5, direction = math.random( 1, 360 ), img = nil, counter = 0, startCounter = 0, color = { currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] } } -- Function to redefine keys w/ user input function overrideKeys( player, key ) if player == "player1" then menuList.redKeyboard.keyboardOverride = getCurrentKey else menuList.blueKeyboard.keyboardOverride = getCurrentKey end if keys[ player ][ key ] ~= nil then keys[ player ][ key ][1] = "--" else keys[ player ][ key ] = { "--", "keyboard" } end keyCounter = 0 currentKey = nil settingKey = key settingPlayer = player end -- Function to test for a key function getCurrentKey() if currentKey ~= nil then keys[settingPlayer][settingKey] = currentKey if settingPlayer == "player1" then menuList.redKeyboard.keyboardOverride = nil else menuList.blueKeyboard.keyboardOverride = nil end end keyCounter = keyCounter + 1 end -- Get current key and save it in a variable function love.textinput(t) if t == " " then t = "space" end currentKey = { t, "keyboard" } end -- Arrow keys and return key (supplement to love.textinput) function extraKeys() if love.keyboard.isDown( "up" ) then currentKey = { "up", "keyboard" } elseif love.keyboard.isDown( "down" ) then currentKey = { "down", "keyboard" } elseif love.keyboard.isDown( "left" ) then currentKey = { "left", "keyboard" } elseif love.keyboard.isDown( "right" ) then currentKey = { "right", "keyboard" } elseif love.keyboard.isDown( "return" ) and keyCounter > 10 then currentKey = { "return", "keyboard" } end end -- Function to create the menus -- Usage: -- function another function -- \/ \/ -- newMenu( { name = "menu", title = "My Title!" items = { { "Item 1", doStuff }, { "Item 2", doMoreStuff } } } ) function newMenu( objectParameters ) local menuListLength = 0 for i in pairs( menuList ) do menuListLength = menuListLength + 1 end name = objectParameters.name or "menu" .. tostring( menuListLength ) title = objectParameters.title or "menu" .. tostring( menuListLength + 1 ) drawCode = objectParameters.drawCode or drawMenuBackground keyboardOverride = objectParameters.keyboardOverride or nil items = objectParameters.items or {} menuList[name] = items menuList[name].title = title menuList[name].drawCode = drawCode menuList[name].keyboardOverride = keyboardOverride end -- Function to save the game settings function saveSettings() settings = binser.serialize( keys, player1Settings, player2Settings ) love.filesystem.write( "settings.lua", settings ) end -- Function to increment a player's score function updateScore( player, score ) if player == "player1" then player1.score = score elseif player == "player2" then player2.score = score end end -- Function to reset the game after every point function reset() -- Reset the random number seed math.randomseed( os.time() ) -- Reset player 1 player1.x = playerDistance + 20 player1.y = playAreaHeight - ( 120 + playerDistance ) player1.counter = 0 player1.xVelocity = nil player1.yVelocity = nil -- Reset player 2 player2.x = love.graphics.getWidth() - ( 120 + playerDistance ) player2.y = playerDistance + 20 player2.counter = 0 player2.xVelocity = nil player2.yVelocity = nil -- Reset the ball ball.x = ( love.graphics.getWidth() / 2 ) - 20 ball.y = ( playAreaHeight / 2 ) - 20 ball.prevX = { nil, nil, nil, nil, nil } ball.prevY = { nil, nil, nil, nil, nil } ball.velocity = 120 + ( player1.score * ball.acceleration ) + ( player2.score * ball.acceleration ) local direction = math.random( 1, 360 ) while direction % 45 == 0 do direction = math.random( 1, 360 ) end ball.direction = direction ball.startCounter = 0 ball.color = { currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] } local blockNum = 0 for _, i in ipairs( leftBlocks ) do if i == 1 then blockNum = blockNum + 1 end end for _, i in ipairs( bottomBlocks ) do if i == 1 then blockNum = blockNum + 1 end end if blockNum < 11 then leftBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } bottomBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } end blockNum = 0 for _, i in ipairs( rightBlocks ) do if i == 1 then blockNum = blockNum + 1 end end for _, i in ipairs( topBlocks ) do if i == 1 then blockNum = blockNum + 1 end end if blockNum < 11 then rightBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } topBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } end end -- Function to restart the game function restart() -- Reset the random number seed math.randomseed( os.time() ) -- Variables playerDistance = 40 playAreaHeight = love.graphics.getHeight() - 50 keyCounter = 0 currentMenu = nil menuSelect = 1 menuScroll = 0 -- Player coordinates and scores player1 = { x = playerDistance + 20, y = playAreaHeight - ( 120 + playerDistance ), score = 0, xImg = nil, yImg = nil, xVelocity = nil, yVelocity = nil, counter = 0 } player2 = { x = love.graphics.getWidth() - ( 120 + playerDistance ), y = playerDistance + 20, score = 0, xImg = nil, yImg = nil, xVelocity = nil, yVelocity = nil, counter = 0 } -- Blocks - 10 for each side, positive if the block is there, zero if it is not leftBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } bottomBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } rightBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } topBlocks = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } leftBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } bottomBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } rightBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } topBlocksTransparency = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } -- Ball ball = { x = ( love.graphics.getWidth() / 2 ) - 20, y = ( playAreaHeight / 2 ) - 20, prevX = { nil, nil, nil, nil, nil }, prevY = { nil, nil, nil, nil, nil }, velocity = 120, acceleration = 5, direction = math.random( 1, 360 ), img = nil, counter = 0, startCounter = 0, color = { currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] } } -- Graphics -- Player 1 paddles player1.xImg = love.graphics.newImage( "assets/graphics/red-x.png" ) player1.yImg = love.graphics.newImage( "assets/graphics/red-y.png" ) -- Player 2 paddles player2.xImg = love.graphics.newImage( "assets/graphics/blue-x.png" ) player2.yImg = love.graphics.newImage( "assets/graphics/blue-y.png" ) -- Ball ball.img = love.graphics.newImage( "assets/graphics/ball.png" ) end -- Test if key is down function getKeyDown( player, key ) -- If the key is not set for the player, use the default settings if keys[player][key] == nil or keys[player][key][1] == "--" then -- Keyboard test for key input, joystick for gamepad input if keys["default"][key][2] == "keyboard" then return( love.keyboard.isDown( keys["default"][key][1] ) ) end -- If the key is set for the player, use the player's settings else -- Keyboard test for key input, joystick for gamepad input if keys[player][key][2] == "keyboard" then return( love.keyboard.isDown( keys[player][key][1] ) ) end end end function love.load() -- Player 1 paddles player1.xImg = love.graphics.newImage( "assets/graphics/red-x.png" ) player1.yImg = love.graphics.newImage( "assets/graphics/red-y.png" ) -- Player 2 paddles player2.xImg = love.graphics.newImage( "assets/graphics/blue-x.png" ) player2.yImg = love.graphics.newImage( "assets/graphics/blue-y.png" ) -- Ball ball.img = love.graphics.newImage( "assets/graphics/ball.png" ) -- Font merriweatherTitle = love.graphics.newFont( "assets/fonts/merriweather.italic.ttf", 40 ) merriweatherSelected = love.graphics.newFont( "assets/fonts/merriweather.italic.ttf", 35 ) merriweatherUnselected = love.graphics.newFont( "assets/fonts/merriweather.italic.ttf", 30 ) merriweatherSmall = love.graphics.newFont( "assets/fonts/merriweather.italic.ttf", 25 ) -- Load settings if love.filesystem.getInfo( "settings.lua" ) ~= nil then local settings = love.filesystem.read( "settings.lua" ) keys = binser.deserialize( settings )[1] player1Settings = binser.deserialize( settings )[2] player2Settings = binser.deserialize( settings )[3] end -- Create menus -- Main menu newMenu( { name = "main", title = "Breakout Pong", items = { { "Play", function() currentMenu = "start" end }, { "Settings", function() currentMenu = "settings" menuSelect = 1 end }, { "Quit", function() love.event.push( "quit" ) end } } } ) -- Start menu newMenu( { name = "start", title = "Breakout Pong", items = { { "Red: ${1}", function() player1Settings.ai = not player1Settings.ai end, function() return player1Settings.ai and "AI" or "Human" end }, { "Blue: ${1}", function() player2Settings.ai = not player2Settings.ai end, function() return player2Settings.ai and "AI" or "Human" end }, { "Start", function() currentMenu = nil end } } } ) -- Settings menu newMenu( { name = "settings", title = "Settings", items = { { "Red AI Difficulty: ${1}", function() player1Settings.aiDifficulty = player1Settings.aiDifficulty + 1 if player1Settings.aiDifficulty > 4 then player1Settings.aiDifficulty = 1 end end, function() return ( player1Settings.aiDifficulty == 1 ) and "Easy" or ( player1Settings.aiDifficulty == 2 ) and "Medium" or ( player1Settings.aiDifficulty == 3 ) and "Hard" or ( player1Settings.aiDifficulty == 4 ) and "Impossible" end }, { "Blue AI Difficulty: ${1}", function() player2Settings.aiDifficulty = player2Settings.aiDifficulty + 1 if player2Settings.aiDifficulty > 4 then player2Settings.aiDifficulty = 1 end end, function() return ( player2Settings.aiDifficulty == 1 ) and "Easy" or ( player2Settings.aiDifficulty == 2 ) and "Medium" or ( player2Settings.aiDifficulty == 3 ) and "Hard" or ( player2Settings.aiDifficulty == 4 ) and "Impossible" end }, { "Red Keyboard Settings", function() currentMenu = "redKeyboard" menuSelect = 1 menuScroll = 0 end }, { "Blue Keyboard Settings", function() currentMenu = "blueKeyboard" menuSelect = 1 menuScroll = 0 end }, { "Back", function() currentMenu = "main" menuSelect = 2 menuScroll = 0 end } } } ) -- Red keyboard menu newMenu( { name = "redKeyboard", title = "Red Keyboard Settings", items = { { "Left: ${1}", function() overrideKeys( "player1", "left" ) end, function() return keys.player1.left[1] end }, { "Right: ${1}", function() overrideKeys( "player1", "right" ) end, function() return keys.player1.right[1] end }, { "Up: ${1}", function() overrideKeys( "player1", "up" ) end, function() return keys.player1.up[1] end }, { "Down: ${1}", function() overrideKeys( "player1", "down" ) end, function() return keys.player1.down[1] end }, { "Pause: ${1}", function() overrideKeys( "player1", "pause" ) end, function() return keys.player1.pause[1] end }, { "Select: ${1}", function() overrideKeys( "player1", "menuSelect" ) end, function() if keys.player1.menuSelect ~= nil then return keys.player1.menuSelect[1] else return keys.default.menuSelect[1] end end }, { "Back", function() currentMenu = "settings" menuSelect = 3 menuScroll = 0 end } } } ) -- Blue keyboard menu newMenu( { name = "blueKeyboard", title = "Blue Keyboard Settings", items = { { "Left: ${1}", function() overrideKeys( "player2", "left" ) end, function() return keys.player2.left[1] end }, { "Right: ${1}", function() overrideKeys( "player2", "right" ) end, function() return keys.player2.right[1] end }, { "Up: ${1}", function() overrideKeys( "player2", "up" ) end, function() return keys.player2.up[1] end }, { "Down: ${1}", function() overrideKeys( "player2", "down" ) end, function() return keys.player2.down[1] end }, { "Pause: ${1}", function() overrideKeys( "player2", "pause" ) end, function() return keys.player2.pause[1] end }, { "Select: ${1}", function() overrideKeys( "player2", "menuSelect" ) end, function() if keys.player2.menuSelect ~= nil then return keys.player2.menuSelect[1] else return keys.default.menuSelect[1] end end }, { "Back", function() currentMenu = "settings" menuSelect = 3 menuScroll = 0 end } } } ) -- Pause menu newMenu( { name = "pause", title = "Paused", items = { { "Resume", function() currentMenu = nil end }, { "Quit", function() love.event.push( "quit" ) end } }, drawCode = function() drawMenuBackground() -- Player 1 score scoreFont = love.graphics.newFont( 40 ) love.graphics.setFont( scoreFont ) love.graphics.printf( player1.score, 10, playAreaHeight, ( love.graphics.getWidth() / 2 ) - 60, "left" ) -- Player 2 score love.graphics.printf( player2.score, ( love.graphics.getWidth() / 2 ) + 50, playAreaHeight, ( love.graphics.getWidth() / 2 ) - 60, "right" ) end } ) -- End menu newMenu( { name = "end", title = "Game over!", items = { { "Restart", function() restart() currentMenu = nil end }, { "Quit", function() love.event.push( "quit" ) end } }, drawCode = function() drawCorners() if winner == "red" then love.graphics.setColor( currentTheme.darkRed ) else love.graphics.setColor( currentTheme.darkBlue ) end love.graphics.rectangle( "fill", 0, playAreaHeight, love.graphics.getWidth(), 50 ) love.graphics.setColor( currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] ) local menuFont = love.graphics.newFont( 40 ) love.graphics.setFont( menuFont ) love.graphics.printf( "Winner: " .. winner, 10, playAreaHeight, love.graphics.getWidth() - 20, "center" ) end } ) end function menuUpdate() -- Default to item 1 if a non-valid item is selected menuLength = 0 for i in ipairs( menuList[ currentMenu ] ) do menuLength = menuLength + 1 end if menuSelect > menuLength then menuSelect = 1 elseif menuSelect < 1 then menuSelect = 1 end -- Redirect to an override function if specified if menuList.redKeyboard.keyboardOverride ~= nil and keyCounter > 10 then menuList.redKeyboard.keyboardOverride() keyCounter = 0 end if menuList.blueKeyboard.keyboardOverride ~= nil and keyCounter > 10 then menuList.blueKeyboard.keyboardOverride() keyCounter = 0 end -- Down/up keys if ( getKeyDown( "player1", "down" ) or getKeyDown( "player2", "down" ) or getKeyDown( "default", "down" ) ) and keyCounter > 10 then menuSelect = menuSelect + 1 if menuSelect > menuLength then menuSelect = 1 menuScroll = 0 end -- Scroll down if not visible if menuSelect > 4 + menuScroll then menuScroll = menuScroll + 1 end keyCounter = 0 elseif ( getKeyDown( "player1", "up" ) or getKeyDown( "player2", "up" ) or getKeyDown( "default", "up" ) ) and keyCounter > 10 then menuSelect = menuSelect - 1 if menuSelect < 1 then menuSelect = menuLength menuScroll = ( menuLength - 4 > -1 ) and menuLength - 4 or 0 end -- Scroll up if not visible if menuSelect < menuScroll + 1 then menuScroll = menuScroll - 1 end keyCounter = 0 end -- Select the current item if ( getKeyDown( "player1", "menuSelect" ) or getKeyDown( "player2", "menuSelect" ) ) and keyCounter > 10 then menuList[ currentMenu ][ menuSelect ][2]() keyCounter = 0 return end -- Increment the key counter keyCounter = keyCounter + 1 end function love.update( dt ) -- Update shack screen:update( dt ) -- Extra non-alphanumeric characters extraKeys() -- End the game if one player's score is 10 or if the sum of the two players' -- scores is negative if player1.score >= 10 or player2.score >= 10 then currentMenu = "end" menuSelect = 1 if player1.score >= 10 then winner = "red" else winner = "blue" end player1.score = 0 player2.score = 0 end if player1.score + player2.score < 0 then currentMenu = "end" menuSelect = 1 if player1.score > player2.score then winner = "red" else winner = "blue" end player1.score = 0 player2.score = 0 end -- Show menus, if there are any if currentMenu ~= nil then menuUpdate() return end if ( getKeyDown( "player1", "pause" ) or getKeyDown( "player2", "pause" ) ) and keyCounter > 10 then currentMenu = "pause" menuSelect = 1 keyCounter = 0 return end if not player1Settings.ai then -- Left and right movement for player 1 if getKeyDown( "player1", "left" ) then player1.x = player1.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.x < playerDistance + 20 then player1.x = playerDistance + 20 end elseif getKeyDown( "player1", "right" ) then player1.x = player1.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player1.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end else -- Left and right movement for player 1 if player1.xVelocity == nil then if player1Settings.aiDifficulty == 4 then -- Ahhh, Algebra <3 -- Solve for x!!! -- y = playAreaHeight - ( 40 + playerDistance ) -- x1 = ball.prevX[1] -- y1 = ball.prevY[1] -- x2 = ball.x -- y2 = ball.y -- x = ? local y = playAreaHeight - ( 20 + playerDistance ) local x1 = ball.prevX[1] or ball.x local y1 = ball.prevY[1] or ball.y + 5 local x2 = ball.x local y2 = ball.y local x = ( ( y * ( x2 - x1 ) ) / ( y2 - y1 ) ) - ( ( y1 * ( x2 - x1 ) ) / ( y2 - y1 ) ) + x1 if player1.x + 10 > x then player1.x = player1.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.xVelocity = "left" if player1.x < playerDistance + 20 then player1.x = playerDistance + 20 end elseif player1.x + 70 < x then player1.x = player1.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.xVelocity = "right" if player1.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player1.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end else if player1.x - 10 > ball.x then player1.x = player1.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.xVelocity = "left" if player1.x < playerDistance + 20 then player1.x = playerDistance + 20 end elseif player1.x + 90 < ball.x then player1.x = player1.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.xVelocity = "right" if player1.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player1.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end end else if player1.xVelocity == "left" then player1.x = player1.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.x < playerDistance + 20 then player1.x = playerDistance + 20 end elseif player1.xVelocity == "right" then player1.x = player1.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player1.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end end end if not player1Settings.ai then -- Up and down movement for player 1 if getKeyDown( "player1", "up" ) then player1.y = player1.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.y < playerDistance + 20 then player1.y = playerDistance + 20 end elseif getKeyDown( "player1", "down" ) then player1.y = player1.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.y > playAreaHeight - ( 120 + playerDistance ) then player1.y = playAreaHeight - ( 120 + playerDistance ) end end else -- Up and down movement for player 1 if player1.yVelocity == nil then if player1Settings.aiDifficulty == 4 then -- And they said I would never use algebra outside of school... local x = playerDistance local x1 = ball.prevX[1] or ball.x + 5 local y1 = ball.prevY[1] or ball.y local x2 = ball.x local y2 = ball.y local y = ( ( x * ( y2 - y1 ) ) / ( x2 - x1 ) ) - ( ( x1 * ( y2 - y1 ) ) / ( x2 - x1 ) ) + y1 if player1.y + 10 > y then player1.y = player1.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.yVelocity = "up" if player1.y < playerDistance + 20 then player1.y = playerDistance + 20 end elseif player1.y + 70 < y then player1.y = player1.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.yVelocity = "down" if player1.y > playAreaHeight - ( 120 + playerDistance ) then player1.y = playAreaHeight - ( 120 + playerDistance ) end end else if player1.y - 10 > ball.y then player1.y = player1.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.yVelocity = "up" if player1.y < playerDistance + 20 then player1.y = playerDistance + 20 end elseif player1.y + 90 < ball.y then player1.y = player1.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player1.yVelocity = "down" if player1.y > playAreaHeight - ( 120 + playerDistance ) then player1.y = playAreaHeight - ( 120 + playerDistance ) end end end else if player1.yVelocity == "up" then player1.y = player1.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.y < playerDistance + 20 then player1.y = playerDistance + 20 end elseif player1.yVelocity == "down" then player1.y = player1.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player1.y > playAreaHeight - ( 120 + playerDistance ) then player1.y = playAreaHeight - ( 120 + playerDistance ) end end end end if not player2Settings.ai then -- Left and right movement for player 2 if getKeyDown( "player2", "left" ) then player2.x = player2.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.x < playerDistance + 20 then player2.x = playerDistance + 20 end elseif getKeyDown( "player2", "right" ) then player2.x = player2.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player2.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end else -- Left and right movement for player 2 if player2.xVelocity == nil then if player2Settings.aiDifficulty == 4 then -- Q: Why did the ball cross the road? -- A: Because someone threw it, *obviously*. The ball can't move -- itself -- or can it? local y = playerDistance local x1 = ball.prevX[1] or ball.x local y1 = ball.prevY[1] or ball.y + 5 local x2 = ball.x local y2 = ball.y local x = ( ( y * ( x2 - x1 ) ) / ( y2 - y1 ) ) - ( ( y1 * ( x2 - x1 ) ) / ( y2 - y1 ) ) + x1 if player2.x + 10 > x then player2.x = player2.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.xvelocity = "left" if player2.x < playerDistance + 20 then player2.x = playerDistance + 20 end elseif player2.x + 70 < x then player2.x = player2.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.xvelocity = "right" if player2.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player2.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end else if player2.x - 10 > ball.x then player2.x = player2.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.xVelocity = "left" if player2.x < playerDistance + 20 then player2.x = playerDistance + 20 end elseif player2.x + 90 < ball.x then player2.x = player2.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.xVelocity = "right" if player2.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player2.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end end else if player2.xVelocity == "left" then player2.x = player2.x - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.x < playerDistance + 20 then player2.x = playerDistance + 20 end elseif player2.xVelocity == "right" then player2.x = player2.x + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.x > love.graphics.getWidth() - ( 120 + playerDistance ) then player2.x = love.graphics.getWidth() - ( 120 + playerDistance ) end end end end if not player2Settings.ai then -- Up and down movement for player 2 if getKeyDown( "player2", "up" ) then player2.y = player2.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.y < playerDistance + 20 then player2.y = playerDistance + 20 end elseif getKeyDown( "player2", "down" ) then player2.y = player2.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.y > playAreaHeight - ( 120 + playerDistance ) then player2.y = playAreaHeight - ( 120 + playerDistance ) end end else -- Up and down movement for player 2 if player2.yVelocity == nil then if player2Settings.aiDifficulty == 4 then -- Algebra, truly the most useful branch of mathematics local x = love.graphics.getWidth() - ( 20 + playerDistance ) local x1 = ball.prevX[1] or ball.x + 5 local y1 = ball.prevY[1] or ball.y local x2 = ball.x local y2 = ball.y local y = ( ( x * ( y2 - y1 ) ) / ( x2 - x1 ) ) - ( ( x1 * ( y2 - y1 ) ) / ( x2 - x1 ) ) + y1 if player2.y + 10 > y then player2.y = player2.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.yVelocity = "up" if player2.y < playerDistance + 20 then player2.y = playerDistance + 20 end elseif player2.y + 70 < y then player2.y = player2.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.yVelocity = "down" if player2.y > playAreaHeight - ( 120 + playerDistance ) then player2.y = playAreaHeight - ( 120 + playerDistance ) end end else if player2.y - 10 > ball.y then player2.y = player2.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.yVelocity = "up" if player2.y < playerDistance + 20 then player2.y = playerDistance + 20 end elseif player2.y + 90 < ball.y then player2.y = player2.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) player2.yVelocity = "down" if player2.y > playAreaHeight - ( 120 + playerDistance ) then player2.y = playAreaHeight - ( 120 + playerDistance ) end end end else if player2.yVelocity == "up" then player2.y = player2.y - ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.y < playerDistance + 20 then player2.y = playerDistance + 20 end elseif player2.yVelocity == "down" then player2.y = player2.y + ( ( ( 3 * ball.velocity ) / 2 ) * dt ) if player2.y > playAreaHeight - ( 120 + playerDistance ) then player2.y = playAreaHeight - ( 120 + playerDistance ) end end end end -- Reset the counter(s) and allow the ai(s) to move twice a second local speed = nil if player1Settings.aiDifficulty == 4 then speed = 10 else speed = player1Settings.aiDifficulty end if player1.counter > love.timer.getFPS() / ( speed - 0.03 ) then player1.counter = 0 player1.xVelocity = nil player1.yVelocity = nil end if player2Settings.aiDifficulty == 4 then speed = 8 else speed = player2Settings.aiDifficulty end if player2.counter > love.timer.getFPS() / ( speed + 0.03 ) then player2.counter = 0 player2.xVelocity = nil player2.yVelocity = nil end if ball.startCounter > 60 then -- Save the ball's current position as previous position for i = 5,1,-1 do if i ~= 1 and ball.prevX[i - 1] ~= nil and ball.prevY[i - 1] ~= nil then ball.prevX[i] = ball.prevX[i - 1] ball.prevY[i] = ball.prevY[i - 1] elseif i == 1 then ball.prevX[i] = ball.x ball.prevY[i] = ball.y end end -- Move the ball ball.x = ball.x + ( dt * ball.velocity * math.cos( ( ball.direction * math.pi ) / 180 ) ) ball.y = ball.y + ( dt * ball.velocity * math.sin( ( ball.direction * math.pi ) / 180 ) ) -- Accelerate the ball ball.velocity = ball.velocity + ( ball.acceleration * dt ) else ball.startCounter = ball.startCounter + 1 end -- Check collision with the left blocks if ball.x < 15 then local blockLength = ( playAreaHeight - ( 2 * math.sqrt( 2 ) * playerDistance ) ) / 10 for i = 1,10,1 do if leftBlocks[i] > 0 then local blockY = ( math.sqrt( 2 ) * playerDistance ) + ( blockLength * ( i - 1 ) ) if ball.y > blockY - 20 and ball.y < blockY + blockLength then if ball.y < ( blockY - 15 ) or ball.y > ( blockY + blockLength - 5 ) then ball.direction = 360 - ball.direction if ball.y < ( blockY - 15 ) then ball.y = blockY - 20 else ball.y = blockY + blockLength end else ball.direction = 180 - ball.direction ball.x = 15 end leftBlocks[i] = leftBlocks[i] - 1 updateScore( "player2", player2.score + 1 ) break end end end end -- Check collision with the right blocks if ball.x > love.graphics.getWidth() - 35 then local blockLength = ( playAreaHeight - ( 2 * math.sqrt( 2 ) * playerDistance ) ) / 10 for i = 1,10,1 do if rightBlocks[i] > 0 then local blockY = ( math.sqrt( 2 ) * playerDistance ) + ( blockLength * ( i - 1 ) ) if ball.y > blockY - 20 and ball.y < blockY + blockLength then if ball.y < ( blockY - 15 ) or ball.y > ( blockY + blockLength - 5 ) then ball.direction = 360 - ball.direction if ball.y < ( blockY - 15 ) then ball.y = blockY - 20 else ball.y = blockY + blockLength end else ball.direction = 180 - ball.direction ball.x = love.graphics.getWidth() - 35 end rightBlocks[i] = rightBlocks[i] - 1 updateScore( "player1", player1.score + 1 ) break end end end end -- Check collision with the top blocks if ball.y < 15 then local blockLength = ( love.graphics.getWidth() - ( 2 * math.sqrt( 2 ) * playerDistance ) ) / 10 for i = 1,10,1 do if topBlocks[i] > 0 then local blockX = ( math.sqrt( 2 ) * playerDistance ) + ( blockLength * ( i - 1 ) ) if ball.x > blockX - 20 and ball.x < blockX + blockLength then if ball.x < blockX - 15 or ball.x > blockX + blockLength - 5 then ball.direction = 180 - ball.direction if ball.x < blockX - 15 then ball.x = blockX - 20 else ball.x = blockX + blockLength end else ball.direction = 360 - ball.direction ball.y = 15 end topBlocks[i] = topBlocks[i] -1 updateScore( "player1", player1.score + 1 ) break end end end end -- Check collision with the bottom blocks if ball.y > playAreaHeight - 35 then local blockLength = ( love.graphics.getWidth() - ( 2 * math.sqrt( 2 ) * playerDistance ) ) / 10 for i = 1,10,1 do if bottomBlocks[i] > 0 then blockX = ( math.sqrt( 2 ) * playerDistance ) + ( blockLength * ( i - 1 ) ) if ball.x > blockX - 20 and ball.x < blockX + blockLength then if ball.x < blockX - 15 or ball.x > blockX + blockLength - 5 then ball.direction = 180 - ball.direction if ball.x < blockX - 15 then ball.x = blockX - 20 else ball.x = blockX + blockLength end else ball.direction = 360 - ball.direction ball.y = playAreaHeight - 35 end bottomBlocks[i] = bottomBlocks[i] -1 updateScore( "player2", player2.score + 1 ) break end end end end -- Check collision with the edge -- Corners if ( ball.x > love.graphics.getWidth() - 20 or ball.x < 0 ) and ( ball.y > playAreaHeight - 20 or ball.y < 0 ) then ball.direction = ball.direction + 180 if ball.x > love.graphics.getWidth() - 20 then ball.x = love.graphics.getWidth() - 20 else ball.x = 0 end if ball.y > playAreaHeight - 20 then ball.y = playAreaHeight - 20 else ball.y = 0 end ball.color = { currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] } elseif ball.x > love.graphics.getWidth() - 20 or ball.x < 0 then ball.direction = 180 - ball.direction -- Right edge if ball.x > love.graphics.getWidth() - 20 then if ball.y > math.sqrt( 2 ) * playerDistance and ball.y < playAreaHeight - ( math.sqrt( 2 ) * playerDistance ) - 20 then updateScore( "player2", player2.score - 1 ) screen:setShake( 40 ) reset() else ball.color = { currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] } ball.x = love.graphics.getWidth() - 20 end else -- Left edge if ball.y > math.sqrt( 2 ) * playerDistance and ball.y < playAreaHeight - ( math.sqrt( 2 ) * playerDistance ) - 20 then updateScore( "player1", player1.score - 1 ) screen:setShake( 40 ) reset() else ball.color = { currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] } ball.x = 0 end end elseif ball.y > playAreaHeight - 20 or ball.y < 0 then ball.direction = 360 - ball.direction -- Bottom edge if ball.y > playAreaHeight - 20 then if ball.x > math.sqrt( 2 ) * playerDistance and ball.x < love.graphics.getWidth() - ( math.sqrt( 2 ) * playerDistance ) - 20 then updateScore( "player1", player1.score - 1 ) screen:setShake( 40 ) reset() else ball.color = { currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] } ball.y = playAreaHeight - 20 end else -- Top edge if ball.x > math.sqrt( 2 ) * playerDistance and ball.x < love.graphics.getWidth() - ( math.sqrt( 2 ) * playerDistance ) - 20 then updateScore( "player2", player2.score - 1 ) screen:setShake( 40 ) reset() else ball.color = { currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] } ball.y = 0 end end end -- Check collision with player 1's x paddle if ball.x > ( player1.x - 20 ) and ball.x < ( player1.x + 100 ) and ball.y > playAreaHeight - ( 40 + playerDistance ) and ball.y < playAreaHeight - playerDistance then ball.color = { currentTheme.lightRed[1], currentTheme.lightRed[2] - 0.05, currentTheme.lightRed[3] - 0.05 } if ball.x < ( player1.x - 15 ) or ball.x > ( player1.x + 95 ) then ball.direction = 180 - ball.direction if ball.x < ( player1.x - 15 ) then ball.x = player1.x - 20 else ball.x = player1.x + 100 end elseif ball.y > playAreaHeight - ( 40 + playerDistance ) and ball.y < playAreaHeight - playerDistance then ball.direction = 360 - ball.direction if ball.y < playAreaHeight - ( 20 + playerDistance ) then ball.y = playAreaHeight - ( 40 + playerDistance ) else ball.y = playAreaHeight - playerDistance end end end -- Check collision with player 1's y paddle if ball.y > ( player1.y - 20 ) and ball.y < ( player1.y + 100 ) and ball.x > playerDistance - 20 and ball.x < playerDistance + 20 then ball.color = { currentTheme.lightRed[1], currentTheme.lightRed[2] + 0.05, currentTheme.lightRed[3] + 0.05 } if ball.y < ( player1.y - 15 ) or ball.y > ( player1.y + 95 ) then ball.direction = 360 - ball.direction if ball.y < ( player1.y - 15 ) then ball.y = player1.y - 20 else ball.y = player1.y + 100 end elseif ball.x > playerDistance - 20 and ball.x < playerDistance + 20 then ball.direction = 180 - ball.direction if ball.x < playerDistance then ball.x = playerDistance - 20 else ball.x = playerDistance + 20 end end end -- Check collision with player 2's x paddle if ball.x > ( player2.x - 20 ) and ball.x < ( player2.x + 100 ) and ball.y > playerDistance - 20 and ball.y < playerDistance + 20 then ball.color = { currentTheme.lightBlue[1] + 0.05, currentTheme.lightBlue[2] + 0.05, currentTheme.lightBlue[3] } if ball.x < ( player2.x - 15 ) or ball.x > ( player2.x + 95 ) then ball.direction = 180 - ball.direction if ball.x < ( player2.x - 15 ) then ball.x = player2.x - 20 else ball.x = player2.x + 100 end elseif ball.y > playerDistance - 20 and ball.y < playerDistance + 20 then ball.direction = 360 - ball.direction if ball.y < playerDistance then ball.y = playerDistance - 20 else ball.y = playerDistance + 20 end end end -- Check collision with player 2's y paddle if ball.y > ( player2.y - 20 ) and ball.y < ( player2.y + 100 ) and ball.x > love.graphics.getWidth() - ( 40 + playerDistance ) and ball.x < love.graphics.getWidth() - playerDistance then ball.color = { currentTheme.lightBlue[1] - 0.05, currentTheme.lightBlue[2] - 0.05, currentTheme.lightBlue[3] } if ball.y < ( player2.y - 15 ) or ball.y > ( player2.y + 95 ) then ball.direction = 360 - ball.direction if ball.y < ( player2.y - 15 ) then ball.y = player2.y - 20 else ball.y = player2.y + 100 end elseif ball.x > love.graphics.getWidth() - ( 40 + playerDistance ) and ball.x < love.graphics.getWidth() - playerDistance then ball.direction = 180 - ball.direction if ball.x < love.graphics.getWidth() - ( 20 + playerDistance ) then ball.x = love.graphics.getWidth() - ( 40 + playerDistance ) else ball.x = love.graphics.getWidth() - playerDistance end end end -- Increase player 2's counter player2.counter = player2.counter + 1 player1.counter = player1.counter + 1 -- Key counter keyCounter = keyCounter + 1 -- Increase the transparency of blocks that have been hit -- and decrease the transparency of blocks that have regenerated for i = 1,10,1 do if leftBlocks[i] == 0 and leftBlocksTransparency[i] < 1 then leftBlocksTransparency[i] = leftBlocksTransparency[i] + 0.05 elseif leftBlocks[i] == 1 and leftBlocksTransparency[i] > 0 then leftBlocksTransparency[i] = leftBlocksTransparency[i] - 0.02 end if rightBlocks[i] == 0 and rightBlocksTransparency[i] < 1 then rightBlocksTransparency[i] = rightBlocksTransparency[i] + 0.05 elseif rightBlocks[i] == 1 and rightBlocksTransparency[i] > 0 then rightBlocksTransparency[i] = rightBlocksTransparency[i] - 0.02 end if topBlocks[i] == 0 and topBlocksTransparency[i] < 1 then topBlocksTransparency[i] = topBlocksTransparency[i] + 0.05 elseif topBlocks[i] == 1 and topBlocksTransparency[i] > 0 then topBlocksTransparency[i] = topBlocksTransparency[i] - 0.02 end if bottomBlocks[i] == 0 and bottomBlocksTransparency[i] < 1 then bottomBlocksTransparency[i] = bottomBlocksTransparency[i] + 0.05 elseif bottomBlocks[i] == 1 and bottomBlocksTransparency[i] > 0 then bottomBlocksTransparency[i] = bottomBlocksTransparency[i] - 0.02 end end -- Reset playAreaHeight ( In case of window resize ) playAreaHeight = love.graphics.getHeight() - 50 end function love.draw( dt ) -- Draw background love.graphics.setColor( currentTheme.black ) love.graphics.rectangle( "fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight() ) -- Draw quit screen if exited and in lovejs if quitted then drawMenuBackground() love.graphics.setColor( currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] ) love.graphics.setFont( merriweatherTitle ) love.graphics.printf( "Thanks for playing!", 10, 240, love.graphics.getWidth() - 20, "center" ) return end -- Draw menus if currentMenu ~= nil then menuList[currentMenu].drawCode() love.graphics.setFont( merriweatherTitle ) love.graphics.setColor( currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] ) love.graphics.printf( menuList[currentMenu].title, 10, 160, love.graphics.getWidth() - 20, "center" ) for i, menuItem in ipairs(menuList[currentMenu]) do if i > menuScroll and i < 5 + menuScroll then if menuSelect == i then love.graphics.setFont( merriweatherSelected ) love.graphics.setColor( currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] ) else love.graphics.setFont( merriweatherUnselected ) love.graphics.setColor( currentTheme.gray ) end local itemText = menuItem[1] for j, f in ipairs( menuItem ) do if j > 2 then local functionResult = tostring(f()) itemText = itemText:gsub( "${" .. tostring( j - 2 ) .. "}", functionResult ) end end love.graphics.printf( "> " .. itemText, 10, 160 + ( i * 80 ) - ( menuScroll * 80 ), love.graphics.getWidth() - 20, "center" ) elseif i == menuScroll then love.graphics.setFont( merriweatherSmall ) love.graphics.setColor( currentTheme.gray ) local itemText = menuItem[1] for j, f in ipairs( menuItem ) do if j > 2 then local functionResult = tostring(f()) itemText = itemText:gsub( "${" .. tostring( j - 2 ) .. "}", functionResult ) end end love.graphics.printf( ". . .", 10, 200, love.graphics.getWidth() - 20, "center" ) elseif i == 5 + menuScroll then love.graphics.setFont( merriweatherSmall ) love.graphics.setColor( currentTheme.gray ) local itemText = menuItem[1] for j, f in ipairs( menuItem ) do if j > 2 then local functionResult = tostring(f()) itemText = itemText:gsub( "${" .. tostring( j - 2 ) .. "}", functionResult ) end end love.graphics.printf( ". . .", 10, 520, love.graphics.getWidth() - 20, "center" ) end end return end -- Apply shack effects screen:apply() -- Left blocks local blockLength = ( playAreaHeight - ( 2 * math.sqrt( 2 ) * playerDistance ) ) / 10 for i = 1,10,1 do if leftBlocks[i] == 1 then love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 ) love.graphics.rectangle( "fill", 0 - ( leftBlocksTransparency[i] * 15 ), ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) love.graphics.setColor( currentTheme.black ) love.graphics.rectangle( "line", 0 - ( leftBlocksTransparency[i] * 15 ), ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) else love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 - leftBlocksTransparency[i] ) love.graphics.rectangle( "fill", 0, ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) love.graphics.setColor( currentTheme.black[1], currentTheme.black[2], currentTheme.black[3], 1 - leftBlocksTransparency[i] ) love.graphics.rectangle( "line", 0, ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) end end -- Right blocks for i = 1,10,1 do if rightBlocks[i] == 1 then love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 ) love.graphics.rectangle( "fill", love.graphics.getWidth() - 15 + ( rightBlocksTransparency[i] * 15 ), ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) love.graphics.setColor( currentTheme.black ) love.graphics.rectangle( "line", love.graphics.getWidth() - 15 + ( rightBlocksTransparency[i] * 15 ), ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) else love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 - rightBlocksTransparency[i] ) love.graphics.rectangle( "fill", love.graphics.getWidth() - 15, ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) love.graphics.setColor( currentTheme.black[1], currentTheme.black[2], currentTheme.black[3], 1 - rightBlocksTransparency[i] ) love.graphics.rectangle( "line", love.graphics.getWidth() - 15, ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 15, blockLength ) end end -- Top blocks local blockLength = ( love.graphics.getWidth() - ( 2 * math.sqrt( 2 ) * playerDistance ) ) / 10 for i = 1,10,1 do if topBlocks[i] == 1 then love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 ) love.graphics.rectangle( "fill", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 0 - ( topBlocksTransparency[i] * 15 ), blockLength, 15 ) love.graphics.setColor( currentTheme.black ) love.graphics.rectangle( "line", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 0 - ( topBlocksTransparency[i] * 15 ), blockLength, 15 ) else love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 - topBlocksTransparency[i] ) love.graphics.rectangle( "fill", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 0, blockLength, 15 ) love.graphics.setColor( currentTheme.black[1], currentTheme.black[2], currentTheme.black[3], 1 - topBlocksTransparency[i] ) love.graphics.rectangle( "line", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), 0, blockLength, 15 ) end end -- Bottom blocks for i = 1,10,1 do if bottomBlocks[i] == 1 then love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 ) love.graphics.rectangle( "fill", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), playAreaHeight - 15 + ( bottomBlocksTransparency[i] * 15 ), blockLength, 15 ) love.graphics.setColor( currentTheme.black ) love.graphics.rectangle( "line", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), playAreaHeight - 15 + ( bottomBlocksTransparency[i] * 15 ), blockLength, 15 ) else love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3], 1 - bottomBlocksTransparency[i] ) love.graphics.rectangle( "fill", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), playAreaHeight - 15, blockLength, 15 ) love.graphics.setColor( currentTheme.black[1], currentTheme.black[2], currentTheme.black[3], 1 - bottomBlocksTransparency[i] ) love.graphics.rectangle( "line", ( ( i - 1 ) * blockLength ) + ( math.sqrt( 2 ) * playerDistance ), playAreaHeight - 15, blockLength, 15 ) end end drawBackground() -- Ball for i = 5,1,-1 do if ball.prevX[i] ~= nil and ball.prevY ~= nil then love.graphics.setColor( 1, 1, 1, 0.125 - ( ( 1 / 48 ) * i ) ) love.graphics.draw( ball.img, ball.prevX[i], ball.prevY[i] ) end end love.graphics.setColor( ball.color[1], ball.color[2], ball.color[3] ) love.graphics.draw( ball.img, ball.x, ball.y ) love.graphics.setColor( currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] ) drawCorners() drawScore() -- Player 1 paddles love.graphics.setColor( currentTheme.red ) love.graphics.setLineWidth( 4 ) love.graphics.rectangle( "line", player1.x + 4, playAreaHeight - ( 20 + playerDistance ) + 4, 92, 12 ) love.graphics.setColor( currentTheme.red[1], currentTheme.red[2], currentTheme.red[3], 0.5 ) love.graphics.setLineWidth( 5 ) love.graphics.rectangle( "line", player1.x + 3, playAreaHeight - ( 20 + playerDistance ) + 3, 94, 14 ) love.graphics.setColor( currentTheme.red ) love.graphics.setLineWidth( 4 ) love.graphics.rectangle( "line", playerDistance + 4, player1.y + 4, 12, 92 ) love.graphics.setColor( currentTheme.red[1], currentTheme.red[2], currentTheme.red[3], 0.5 ) love.graphics.setLineWidth( 5 ) love.graphics.rectangle( "line", playerDistance + 3, player1.y + 3, 14, 94 ) -- Player 2 paddles love.graphics.setColor( currentTheme.blue ) love.graphics.setLineWidth( 4 ) love.graphics.rectangle( "line", player2.x + 4, playerDistance + 4, 92, 12 ) love.graphics.setColor( currentTheme.blue[1], currentTheme.blue[2], currentTheme.blue[3], 0.5 ) love.graphics.setLineWidth( 5 ) love.graphics.rectangle( "line", player2.x + 3, playerDistance + 3, 94, 14 ) love.graphics.setColor( currentTheme.blue ) love.graphics.setLineWidth( 4 ) love.graphics.rectangle( "line", love.graphics.getWidth() - ( 20 + playerDistance ) + 4, player2.y + 4, 12, 92 ) love.graphics.setColor( currentTheme.blue[1], currentTheme.blue[2], currentTheme.blue[3], 0.5 ) love.graphics.setLineWidth( 5 ) love.graphics.rectangle( "line", love.graphics.getWidth() - ( 20 + playerDistance ) + 3, player2.y + 3, 14, 94 ) love.graphics.setLineWidth( 1 ) love.graphics.setColor( 1, 1, 1 ) end -- Draw the background function drawBackground() -- Background local linePoints = { playerDistance / math.sqrt( 2 ), playerDistance / math.sqrt( 2 ), love.graphics.getWidth() - ( playerDistance / math.sqrt( 2 ) ), playAreaHeight - ( playerDistance / math.sqrt( 2 ) ), } love.graphics.setColor( currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3], 0.5 ) love.graphics.setLineWidth( 5 ) love.graphics.line( linePoints ) love.graphics.setColor( currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] ) love.graphics.setLineWidth( 1 ) love.graphics.line( linePoints ) love.graphics.setColor( 1, 1, 1 ) end -- Draw the corners function drawCorners() -- Corners love.graphics.setColor( currentTheme.red[1], currentTheme.red[2], currentTheme.red[3], 0.75 ) local trianglePoints = { 0, playAreaHeight - ( math.sqrt( 2 ) * playerDistance ), ( math.sqrt( 2 ) * playerDistance ), playAreaHeight, 0, playAreaHeight } love.graphics.polygon( "fill", trianglePoints ) trianglePoints = { 0, 0, playerDistance / math.sqrt( 2 ), playerDistance / math.sqrt( 2 ), 0, math.sqrt( 2 ) * playerDistance } love.graphics.polygon( "fill", trianglePoints ) trianglePoints = { love.graphics.getWidth() - ( playerDistance / math.sqrt( 2 ) ), playAreaHeight - ( playerDistance / math.sqrt( 2 ) ), love.graphics.getWidth(), playAreaHeight, love.graphics.getWidth() - ( math.sqrt( 2 ) * playerDistance ), playAreaHeight } love.graphics.polygon( "fill", trianglePoints ) love.graphics.setColor( currentTheme.blue[1], currentTheme.blue[2], currentTheme.blue[3], 0.75 ) trianglePoints = { love.graphics.getWidth() - ( math.sqrt( 2 ) * playerDistance ), 0, love.graphics.getWidth(), 0, love.graphics.getWidth(), math.sqrt( 2 ) * playerDistance } love.graphics.polygon( "fill", trianglePoints ) trianglePoints = { 0, 0, playerDistance / math.sqrt( 2 ), playerDistance / math.sqrt( 2 ), math.sqrt( 2 ) * playerDistance, 0 } love.graphics.polygon( "fill", trianglePoints ) trianglePoints = { love.graphics.getWidth() - ( playerDistance / math.sqrt( 2 ) ), playAreaHeight - ( playerDistance / math.sqrt( 2 ) ), love.graphics.getWidth(), playAreaHeight, love.graphics.getWidth(), playAreaHeight - ( math.sqrt( 2 ) * playerDistance ) } love.graphics.polygon( "fill", trianglePoints ) love.graphics.setColor( currentTheme.red[1], currentTheme.red[2], currentTheme.red[3], 0.375 ) love.graphics.setLineWidth( 5 ) local linePoints = { 0, playAreaHeight - ( math.sqrt( 2 ) * playerDistance ), ( math.sqrt( 2 ) * playerDistance ), playAreaHeight } love.graphics.line( linePoints ) linePoints = { playerDistance / math.sqrt( 2 ), playerDistance / math.sqrt( 2 ), 0, math.sqrt( 2 ) * playerDistance } love.graphics.line( linePoints ) linePoints = { love.graphics.getWidth() - ( playerDistance / math.sqrt( 2 ) ), playAreaHeight - ( playerDistance / math.sqrt( 2 ) ), love.graphics.getWidth() - ( math.sqrt( 2 ) * playerDistance ), playAreaHeight } love.graphics.line( linePoints ) love.graphics.setColor( currentTheme.blue[1], currentTheme.blue[2], currentTheme.blue[3], 0.375 ) linePoints = { love.graphics.getWidth() - ( math.sqrt( 2 ) * playerDistance ), 0, love.graphics.getWidth(), math.sqrt( 2 ) * playerDistance } love.graphics.line( linePoints ) linePoints = { playerDistance / math.sqrt( 2 ), playerDistance / math.sqrt( 2 ), math.sqrt( 2 ) * playerDistance, 0 } love.graphics.line( linePoints ) linePoints = { love.graphics.getWidth() - ( playerDistance / math.sqrt( 2 ) ), playAreaHeight - ( playerDistance / math.sqrt( 2 ) ), love.graphics.getWidth(), playAreaHeight - ( math.sqrt( 2 ) * playerDistance ) } love.graphics.line( linePoints ) linePoints = { 0, 0, playerDistance / math.sqrt( 2 ), playerDistance / math.sqrt( 2 ) } love.graphics.setColor( currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3], 0.5 ) love.graphics.setLineWidth( 5 ) love.graphics.line( linePoints ) love.graphics.setColor( currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] ) love.graphics.setLineWidth( 1 ) love.graphics.line( linePoints ) linePoints = { love.graphics.getWidth() - ( playerDistance / math.sqrt( 2 ) ), playAreaHeight - ( playerDistance / math.sqrt( 2 ) ), love.graphics.getWidth(), playAreaHeight } love.graphics.setColor( currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3], 0.5 ) love.graphics.setLineWidth( 5 ) love.graphics.line( linePoints ) love.graphics.setColor( currentTheme.purple[1], currentTheme.purple[2], currentTheme.purple[3] ) love.graphics.setLineWidth( 1 ) love.graphics.line( linePoints ) love.graphics.setColor( 1, 1, 1 ) end function drawScore() -- Scoring background love.graphics.setColor( currentTheme.darkRed ) local rectanglePoints = { 0, playAreaHeight, ( love.graphics.getWidth() / 2 ) - 25, playAreaHeight, ( love.graphics.getWidth() / 2 ) + 25, love.graphics.getHeight(), 0, love.graphics.getHeight() } love.graphics.polygon( "fill", rectanglePoints ) love.graphics.setColor( currentTheme.darkBlue ) rectanglePoints = { ( love.graphics.getWidth() / 2 ) - 25, playAreaHeight, love.graphics.getWidth(), playAreaHeight, love.graphics.getWidth(), love.graphics.getHeight(), ( love.graphics.getWidth() / 2 ) + 25, love.graphics.getHeight() } love.graphics.polygon( "fill", rectanglePoints ) love.graphics.setColor( currentTheme.white[1], currentTheme.white[2], currentTheme.white[3] ) -- Player 1 score scoreFont = love.graphics.newFont( 40 ) love.graphics.setFont( scoreFont ) love.graphics.printf( player1.score, 10, playAreaHeight, ( love.graphics.getWidth() / 2 ) - 60, "left" ) -- Player 2 score love.graphics.printf( player2.score, ( love.graphics.getWidth() / 2 ) + 50, playAreaHeight, ( love.graphics.getWidth() / 2 ) - 60, "right" ) end function drawMenuBackground() drawCorners() love.graphics.setColor( currentTheme.darkRed ) local rectanglePoints = { 0, playAreaHeight, ( love.graphics.getWidth() / 2 ) - 25, playAreaHeight, ( love.graphics.getWidth() / 2 ) + 25, love.graphics.getHeight(), 0, love.graphics.getHeight() } love.graphics.polygon( "fill", rectanglePoints ) love.graphics.setColor( currentTheme.darkBlue ) rectanglePoints = { ( love.graphics.getWidth() / 2 ) - 25, playAreaHeight, love.graphics.getWidth(), playAreaHeight, love.graphics.getWidth(), love.graphics.getHeight(), ( love.graphics.getWidth() / 2 ) + 25, love.graphics.getHeight() } love.graphics.polygon( "fill", rectanglePoints ) love.graphics.setColor( 1, 1, 1 ) end -- Save game settings when exiting function love.quit() saveSettings() if love.system.getOS() == "Web" then quitted = true return true end end