breakout-pong/main.lua

1753 lines
70 KiB
Lua

-- 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