I'm asking this here because even though there is another board dealing specifically with the course this game is from, hardly anyone ever responds to questions on that board. I'm hoping that those of you familiar with Lua can explain it to me.
The question has to do with with the pause function in a Breakout game that is part of game development course. The issue only concerns two files (I think), both of which are short. The first file is a Lua class called Paddle that generates a paddle for the Breakout game. The second file is part of a state machine called PlayState, which is the state for when the game is being played (obviously).
Here is the code for Paddle.lua:
Paddle = Class{}
function Paddle:init()
self.x = VIRTUAL_WIDTH / 2 - 32
self.y = VIRTUAL_HEIGHT - 32
self.dx = 0
self.width = 64
self.height = 16
self.skin = 1
self.size = 2
end
function Paddle:update(dt)
if love.keyboard.isDown('left') then
self.dx = -PADDLE_SPEED
elseif love.keyboard.isDown('right') then
self.dx = PADDLE_SPEED
else
self.dx = 0
end
if self.dx < 0 then
self.x = math.max(0, self.x + self.dx * dt)
else
self.x = math.min(VIRTUAL_WIDTH - self.width, self.x + self.dx * dt)
end
end
function Paddle:render()
love.graphics.draw(gTextures['main'], gFrames['paddles'][self.size + 4 * (self.skin - 1)],
self.x, self.y)
end
Here is the code for PlayState.lua:
PlayState = Class{__includes = BaseState}
function PlayState:init()
self.paddle = Paddle()
self.paused = false
end
function PlayState:update(dt)
if self.paused then
if love.keyboard.wasPressed('space') then
self.paused = false
gSounds['pause']:play()
else
return
end
elseif love.keyboard.wasPressed('space') then
self.paused = true
gSounds['pause']:play()
return
end
self.paddle:update(dt)
if love.keyboard.wasPressed('escape') then
love.event.quit()
end
end
function PlayState:render()
self.paddle:render()
if self.paused then
love.graphics.setFont(gFonts['large'])
love.graphics.printf("PAUSED", 0, VIRTUAL_HEIGHT / 2 - 16, VIRTUAL_WIDTH, 'center')
end
end
So here's what I understand: the PlayState creates a paddle. self.paused is false. Then PlayState:update starts. If the space bar is hit, the code regarding the space bar doesn't execute. After that, self.paddle:update is called, which checks if the left or right arrow keys are pushed and then sets an x-velocity based on which one is pushed. Once PlayState:update is done, PlayState:render starts, which calls self.paddle:render. self.paddle:render draws the paddle at a new position based on the x-velocity.
Now back to PlayState:update. If the spacebar is hit, self.paused becomes true (and a sound plays). But then self.paddle:update still executes. Now since space was hit, left and right weren't hit, so x-velocity is 0. Then PlayState:render runs again, which calls self.paddle:render, which draws the paddle in the same place as before because there is no x-velocity. Then because self.paused is true, the word PAUSED is drawn on the screen.
Now here's where I'm confused: on the next frame, nothing happens with the paddle if you press left or right. Of course, that's how it's supposed to work, but I don't know why it works. If you press the left key the next time PlayState:update runs, of course self.paused won't change, but self.paddle:update is still called, isn't it? And shouldn't self.paddle:update still register that the left key was pressed? Which would give us an x-velocity, so that when PlayState:render calls self.paddle:render, the paddle would be drawn at the new location based on the x-velocity, even though the word PAUSED will be redrawn on the screen?
I guess what I mean is that I don't understand how setting self.paused to true keeps self.paddle:update from registering a key event and keeps self.paddle:render from drawing the paddle at a new location.
The key is in the first return
statement in PlayState:update
. If the game is paused, and if the spacebar was not pressed, we reach the else
clause, which simply returns from the function before reaching self.paddle:update(dt)
, so all that paddle math never happens.
To make it clear, this simplified code should be equivalent:
function PlayState:update(dt)
if love.keyboard.wasPressed('space') then
self.paused = not self.paused
gSounds['pause']:play()
end
if not self.paused then
self.paddle:update(dt)
if love.keyboard.wasPressed('escape') then
love.event.quit()
end
end
end