Skip to content

Commit

Permalink
Merge pull request #12 from JeremyLoh/breakout-11
Browse files Browse the repository at this point in the history
breakout-11: Paddle Select Update
  • Loading branch information
JeremyLoh authored Jan 5, 2021
2 parents f05f129 + 3cc1c8b commit 4303960
Show file tree
Hide file tree
Showing 45 changed files with 2,004 additions and 0 deletions.
204 changes: 204 additions & 0 deletions breakout-11/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# breakout-11: Paddle Select Update

Add ability for users to select a paddle before starting the game

## `main.lua` changes

```Lua
function love.load()
-- ...
-- Quads generated from our textures
gQuadsTable = {
["paddles"] = GenerateQuadPaddles(gGraphics["main"]),
["balls"] = GenerateQuadBalls(gGraphics["main"]),
["bricks"] = GenerateQuadBricks(gGraphics["main"]),
["hearts"] = generateQuads(gGraphics["hearts"], 16, 16),
["arrows"] = generateQuads(gGraphics["arrows"], 16, 16),
}

states = {
["start"] = function() return StartState() end,
["highscores"] = function() return HighscoreState() end,
["play"] = function() return PlayState() end,
["serve"] = function() return ServeState() end,
["game-over"] = function() return GameOverState() end,
["victory"] = function() return VictoryState() end,
["enter-highscores"] = function() return EnterHighscoreState() end,
["paddle-select"] = function() return PaddleSelectState() end,
}
end
```

## `constants.lua` changes

```Lua
HIGHEST_PADDLE_SKIN = 4
HIGHEST_PADDLE_SIZE = 4
LOWEST_PADDLE_SKIN = 1
LOWEST_PADDLE_SIZE = 1

PADDLE_SIZES = {
-- small (size 1)
[1] = {
["width"] = 32,
["height"] = 16,
},
-- medium (size 2)
[2] = {
["width"] = 64,
["height"] = 16,
},
-- large (size 3)
[3] = {
["width"] = 96,
["height"] = 16,
},
-- extra-large (size 4)
[4] = {
["width"] = 128,
["height"] = 16,
},
}
```

## `Dependencies.lua` changes

```Lua
require "src/states/PaddleSelectState"
```

## `Paddle.lua` changes

```Lua
function Paddle:init(skin, size)
-- Color of paddle (skin), used to offset gPaddleSkins
self.skin = skin
-- Paddle size (small (1), medium (2), large (3), extra-large (4))
self.size = size
-- Paddle dimensions
self.width = PADDLE_SIZES[self.size]["width"]
self.height = PADDLE_SIZES[self.size]["height"]
self.x = (VIRTUAL_WIDTH / 2) - (self.width / 2)
self.y = VIRTUAL_HEIGHT - 30
-- Keep track of paddle velocity
self.dx = 0
end
```

## `PaddleSelectState.lua`

```Lua
PaddleSelectState = Class{__includes = BaseState}

function PaddleSelectState:init()
-- Color of paddle
self.skin = 1
-- Paddle size (small (1), medium (2), large (3), extra-large (4))
self.size = 1
end

function PaddleSelectState:update(dt)
if love.keyboard.wasPressed("enter") or love.keyboard.wasPressed("return") then
gStateMachine:change("serve", {
["paddle"] = Paddle(self.skin, self.size),
["bricks"] = LevelMaker.createMap(1),
["ball"] = Ball(1),
["lives"] = MAX_LIVES,
["score"] = 0,
["level"] = 1,
})
elseif love.keyboard.wasPressed("escape") then
gStateMachine:change("start")
elseif love.keyboard.wasPressed("left") then
if self.skin == LOWEST_PADDLE_SKIN and self.size == LOWEST_PADDLE_SIZE then
gSounds["no-select"]:play()
else
gSounds["select"]:play()
self.size = self.size - 1
if self.size < 1 then
self.skin = self.skin - 1
self.size = HIGHEST_PADDLE_SIZE
end
end
elseif love.keyboard.wasPressed("right") then
if self.skin == HIGHEST_PADDLE_SKIN and self.size == HIGHEST_PADDLE_SIZE then
gSounds["no-select"]:play()
else
gSounds["select"]:play()
self.size = self.size + 1
if self.size > 4 then
self.size = LOWEST_PADDLE_SIZE
self.skin = self.skin + 1
end
end
end
end

function PaddleSelectState:render()
love.graphics.setFont(gFonts["medium"])
love.graphics.printf("Select your paddle with the left and right arrow keys", 0, 20, VIRTUAL_WIDTH, "center")
love.graphics.setFont(gFonts["small"])
love.graphics.printf("Press \"Enter\" to continue", 0, 40, VIRTUAL_WIDTH, "center")

local arrowHeight = gGraphics["arrows"]:getHeight()
local arrowWidth = gGraphics["arrows"]:getWidth()
local arrowX = (VIRTUAL_WIDTH / 3) - (arrowWidth / 2)
local arrowY = (VIRTUAL_HEIGHT / 2) - (arrowHeight / 2)
local rightArrowOffset = (VIRTUAL_WIDTH / 2 - arrowX) - arrowWidth / 2

-- Left select arrow
if self.skin == LOWEST_PADDLE_SKIN and self.size == LOWEST_PADDLE_SIZE then
-- Give grey tint to indicate no further selection possible
love.graphics.setColor(40/255, 40/255, 40/255, 128/255)
else
-- Reset drawing color to full white for proper rendering
love.graphics.setColor(1, 1, 1, 1)
end
love.graphics.draw(gGraphics["arrows"], gQuadsTable["arrows"][1], arrowX, arrowY)

-- Right select arrow
if self.skin == HIGHEST_PADDLE_SKIN and self.size == HIGHEST_PADDLE_SIZE then
-- Give grey tint to indicate no further selection possible
love.graphics.setColor(40/255, 40/255, 40/255, 128/255)
else
-- Reset drawing color to full white for proper rendering
love.graphics.setColor(1, 1, 1, 1)
end
love.graphics.draw(gGraphics["arrows"], gQuadsTable["arrows"][2],
(VIRTUAL_WIDTH / 2) + rightArrowOffset, arrowY)

-- Reset drawing color to full white for proper rendering
love.graphics.setColor(1, 1, 1, 1)
-- Draw paddle
local paddleWidth = PADDLE_SIZES[self.size]["width"]
local paddleHeight = PADDLE_SIZES[self.size]["height"]
love.graphics.draw(gGraphics["main"],
gQuadsTable["paddles"][(self.skin - 1) * 4 + self.size],
VIRTUAL_WIDTH / 2 - paddleWidth / 2,
VIRTUAL_HEIGHT / 2 - paddleHeight / 2)
end
```

## `StartState.lua` changes

```Lua
function StartState:update(dt)
if love.keyboard.wasPressed("up") or love.keyboard.wasPressed("down") then
selectedOption = selectedOption == 1 and 2 or 1
gSounds["paddle-hit"]:play()
elseif love.keyboard.wasPressed("enter") or love.keyboard.wasPressed("return") then
gSounds["confirm"]:play()
if selectedOption == 1 then
-- Start game, select paddle
gStateMachine:change("paddle-select")
elseif selectedOption == 2 then
-- Highscores
gStateMachine:change("highscores", {
["highscores"] = highscores
})
end
elseif love.keyboard.wasPressed("escape") then
love.event.quit()
end
end
```
Binary file added breakout-11/fonts/font.ttf
Binary file not shown.
Binary file added breakout-11/graphics/Breakout.aseprite
Binary file not shown.
Binary file added breakout-11/graphics/Icons.aseprite
Binary file not shown.
Binary file added breakout-11/graphics/arrows.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added breakout-11/graphics/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added breakout-11/graphics/blocks.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added breakout-11/graphics/breakout.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added breakout-11/graphics/breakout_big.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added breakout-11/graphics/hearts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added breakout-11/graphics/particle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 94 additions & 0 deletions breakout-11/lib/class.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
--[[
Copyright (c) 2010-2013 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
]]--

local function include_helper(to, from, seen)
if from == nil then
return to
elseif type(from) ~= 'table' then
return from
elseif seen[from] then
return seen[from]
end

seen[from] = to
for k,v in pairs(from) do
k = include_helper({}, k, seen) -- keys might also be tables
if to[k] == nil then
to[k] = include_helper({}, v, seen)
end
end
return to
end

-- deeply copies `other' into `class'. keys in `other' that are already
-- defined in `class' are omitted
local function include(class, other)
return include_helper(class, other, {})
end

-- returns a deep copy of `other'
local function clone(other)
return setmetatable(include({}, other), getmetatable(other))
end

local function new(class)
-- mixins
class = class or {} -- class can be nil
local inc = class.__includes or {}
if getmetatable(inc) then inc = {inc} end

for _, other in ipairs(inc) do
if type(other) == "string" then
other = _G[other]
end
include(class, other)
end

-- class implementation
class.__index = class
class.init = class.init or class[1] or function() end
class.include = class.include or include
class.clone = class.clone or clone

-- constructor call
return setmetatable(class, {__call = function(c, ...)
local o = setmetatable({}, c)
o:init(...)
return o
end})
end

-- interface for cross class-system compatibility (see https://github.com/bartbes/Class-Commons).
if class_commons ~= false and not common then
common = {}
function common.class(name, prototype, parent)
return new{__includes = {prototype, parent}}
end
function common.instance(class, ...)
return class(...)
end
end


-- the module
return setmetatable({new = new, include = include, clone = clone},
{__call = function(_,...) return new(...) end})
Loading

0 comments on commit 4303960

Please sign in to comment.