为什么我的道具没有出现在我的 LOVE2D 游戏中?
Why is my powerup not showing up in my LOVE2D game?
我目前正在制作名为 PlayBall 的 Pong 重制版,这是一个色彩丰富的版本,具有增强功能、模式和新增功能。我现在处于 Alpha 2.0(Powerup 概念),我想制作我的第一个名为 AddBall 的 powerup。
这个道具的作用是,当球与其碰撞时,会生成一个新球。
我在AddBall.lua
中设置了代码:
AddBall = Class{}
local spawner = math.random(10, 20)
function AddBall:init(x, y)
self.x = x
self.y = y
self.width = 8
self.height = 8
self.timer = 0
self.inPlay = false
end
function AddBall:collides(ball)
-- first, check to see if the left edge of either is farther to the right
-- than the right edge of the other
if self.x > ball.x + ball.width or ball.x > self.x + self.width then
return false
end
-- then check to see if the bottom edge of either is higher than the top
-- edge of the other
if self.y > ball.y + ball.height or ball.y > self.y + self.height then
return false
end
-- if the above aren't true, they're overlapping
return true
end
function AddBall:update(dt)
self.timer = self.timer + dt
if self.timer > spawner then
self.inPlay = true
end
if self.inPlay then
self:render()
end
end
function AddBall:render()
love.graphics.draw(textures['powerups'], frames['powerups'][1], self.x, self.y)
end
function AddBall:reset()
self.timer = 0
self.inPlay = false
spawner = math.random(10, 20)
end
这是我做的最好的。然后我在 main.lua
中分配了一大堆东西来加载道具和第二个球:
--[[
Called just once at the beginning of the game; used to set up
game objects, variables, etc. and prepare the game world.
]]
function love.load()
-- set love's default filter to "nearest-neighbor", which essentially
-- means there will be no filtering of pixels (blurriness), which is
-- important for a nice crisp, 2D look
love.graphics.setDefaultFilter('nearest', 'nearest')
-- set the title of our application window
love.window.setTitle('PlayBall')
-- seed the RNG so that calls to random are always random
math.randomseed(os.time())
-- initialize our nice-looking retro text fonts
smallFont = love.graphics.newFont('font.ttf', 8)
largeFont = love.graphics.newFont('font.ttf', 16)
scoreFont = love.graphics.newFont('font.ttf', 32)
love.graphics.setFont(smallFont)
-- set up our sound effects; later, we can just index this table and
-- call each entry's `play` method
sounds = {
['paddle_hit'] = love.audio.newSource('sounds/paddle_hit.wav', 'static'),
['score'] = love.audio.newSource('sounds/score.wav', 'static'),
['wall_hit'] = love.audio.newSource('sounds/wall_hit.wav', 'static')
}
textures = {
['powerups'] = love.graphics.newImage('graphics/powerups.png')
}
frames = {
['powerups'] = GenerateQuadsPowerups(textures['powerups'])
}
-- initialize our virtual resolution, which will be rendered within our
-- actual window no matter its dimensions
push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
fullscreen = false,
resizable = true,
vsync = true
})
-- initialize our player paddles; make them global so that they can be
-- detected by other functions and modules
player1 = Paddle(10, 30, 5, 20)
player2 = Paddle(VIRTUAL_WIDTH - 10, VIRTUAL_HEIGHT - 30, 5, 20)
-- place a ball in the middle of the screen
ball1 = Ball(VIRTUAL_WIDTH / 2 - 2, VIRTUAL_HEIGHT / 2 - 2, 4, 4, 1)
ball2 = Ball(ball1.x, ball1.y, 4, 4, 2)
powerup1 = AddBall(math.random(20, VIRTUAL_WIDTH - 20), math.random(0, VIRTUAL_HEIGHT - 8))
-- set up in play to ensure it is in game
ball1.inPlay = true
-- initialize score variables
player1Score = 0
player2Score = 0
-- either going to be 1 or 2; whomever is scored on gets to serve the
-- following turn
servingPlayer = 1
-- player who won the game; not set to a proper value until we reach
-- that state in the game
winningPlayer = 0
-- the state of our game; can be any of the following:
-- 1. 'start' (the beginning of the game, before first serve)
-- 2. 'serve' (waiting on a key press to serve the ball)
-- 3. 'play' (the ball is in play, bouncing between paddles)
-- 4. 'done' (the game is over, with a victor, ready for restart)
gameState = 'start'
end
然后游戏更新:
--[[
Called every frame, passing in `dt` since the last frame. `dt`
is short for `deltaTime` and is measured in seconds. Multiplying
this by any changes we wish to make in our game will allow our
game to perform consistently across all hardware; otherwise, any
changes we make will be applied as fast as possible and will vary
across system hardware.
]]
function love.update(dt)
if gameState == 'serve' then
-- before switching to play, initialize ball's velocity based
-- on player who last scored
ball1.dy = math.random(-50, 50)
if servingPlayer == 1 then
ball1.dx = math.random(140, 200)
else
ball1.dx = -math.random(140, 200)
end
elseif gameState == 'play' then
-- detect ball collision with paddles, reversing dx if true and
-- slightly increasing it, then altering the dy based on the position
-- at which it collided, then playing a sound effect
if ball1:collides(player1) then
ball1.dx = -ball1.dx * 1.03
ball1.x = player1.x + 5
-- keep velocity going in the same direction, but randomize it
if ball1.dy < 0 then
ball1.dy = -math.random(10, 150)
else
ball1.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
if ball1:collides(player2) then
ball1.dx = -ball1.dx * 1.03
ball1.x = player2.x - 4
-- keep velocity going in the same direction, but randomize it
if ball1.dy < 0 then
ball1.dy = -math.random(10, 150)
else
ball1.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
if ball2:collides(player1) then
ball2.dx = -ball2.dx * 1.03
ball2.x = player1.x + 5
-- keep velocity going in the same direction, but randomize it
if ball2.dy < 0 then
ball2.dy = -math.random(10, 150)
else
ball2.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
if ball2:collides(player2) then
ball2.dx = -ball2.dx * 1.03
ball2.x = player2.x - 4
-- keep velocity going in the same direction, but randomize it
if ball2.dy < 0 then
ball2.dy = -math.random(10, 150)
else
ball2.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
-- detect upper and lower screen boundary collision, playing a sound
-- effect and reversing dy if true
if ball1.y <= 0 then
ball1.y = 0
ball1.dy = -ball1.dy
sounds['wall_hit']:play()
end
-- -4 to account for the ball's size
if ball1.y >= VIRTUAL_HEIGHT - 4 then
ball1.y = VIRTUAL_HEIGHT - 4
ball1.dy = -ball1.dy
sounds['wall_hit']:play()
end
-- detect upper and lower screen boundary collision, playing a sound
-- effect and reversing dy if true
if ball2.y <= 0 then
ball2.y = 0
ball2.dy = -ball2.dy
sounds['wall_hit']:play()
end
-- -4 to account for the ball's size
if ball2.y >= VIRTUAL_HEIGHT - 4 then
ball2.y = VIRTUAL_HEIGHT - 4
ball2.dy = -ball2.dy
sounds['wall_hit']:play()
end
-- if we reach the left edge of the screen, go back to serve
-- and update the score and serving player
if ball1.x < 0 then
servingPlayer = 1
player2Score = player2Score + 1
sounds['score']:play()
-- if we've reached a score of 10, the game is over; set the
-- state to done so we can show the victory message
if player2Score == 10 then
winningPlayer = 2
gameState = 'done'
else
gameState = 'serve'
-- places the ball in the middle of the screen, no velocity
ball1:reset()
end
end
-- if we reach the right edge of the screen, go back to serve
-- and update the score and serving player
if ball1.x > VIRTUAL_WIDTH then
servingPlayer = 2
player1Score = player1Score + 1
sounds['score']:play()
-- if we've reached a score of 10, the game is over; set the
-- state to done so we can show the victory message
if player1Score == 10 then
winningPlayer = 1
gameState = 'done'
else
gameState = 'serve'
-- places the ball in the middle of the screen, no velocity
ball1:reset()
end
end
-- check if ball powerup is added
if powerup1:collides(ball1) then
ball2.inPlay = true
ball2:update(dt)
powerup1:reset()
end
-- ball 2 is resetted when it hits the edge
if ball2.x < 0 or ball2.x > VIRTUAL_WIDTH then
ball2.inPlay = false
end
end
--
-- paddles can move no matter what state we're in
--
-- player 1
if love.keyboard.isDown('w') then
player1.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('s') then
player1.dy = PADDLE_SPEED
else
player1.dy = 0
end
-- player 2
if aiMode == true then
player2.y = ball1.y
elseif aiMode == false then
if love.keyboard.isDown('up') then
player2.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('down') then
player2.dy = PADDLE_SPEED
else
player2.dy = 0
end
end
-- update our ball based on its DX and DY only if we're in play state;
-- scale the velocity by dt so movement is framerate-independent
if gameState == 'play' then
ball1:update(dt)
end
player1:update(dt)
player2:update(dt)
powerup1:update(dt)
end
我的问题是加电不会生成,使加电概念不完整。不知道是我渲染出了问题,还是时机不对。
我的猜测是我在 Ball.lua
:
上出了问题
Ball = Class{}
function Ball:init(x, y, width, height, num)
self.x = x
self.y = y
self.width = width
self.height = height
self.count = num
-- these variables are for keeping track of our velocity on both the
-- X and Y axis, since the ball can move in two dimensions
self.dy = 0
self.dx = 0
self.inPlay = false
end
--[[
Expects a paddle as an argument and returns true or false, depending
on whether their rectangles overlap.
]]
function Ball:collides(paddle)
-- first, check to see if the left edge of either is farther to the right
-- than the right edge of the other
if self.x > paddle.x + paddle.width or paddle.x > self.x + self.width then
return false
end
-- then check to see if the bottom edge of either is higher than the top
-- edge of the other
if self.y > paddle.y + paddle.height or paddle.y > self.y + self.height then
return false
end
-- if the above aren't true, they're overlapping
return true
end
--[[
Places the ball in the middle of the screen, with no movement.
]]
function Ball:reset()
self.x = VIRTUAL_WIDTH / 2 - 2
self.y = VIRTUAL_HEIGHT / 2 - 2
self.dx = 0
self.dy = 0
end
function Ball:update(dt)
self.x = self.x + self.dx * dt
self.y = self.y + self.dy * dt
end
function Ball:render()
if self.inPlay then
love.graphics.setFont(smallFont)
love.graphics.setColor(0/255, 0/255, 0/255, 255/255)
love.graphics.printf(tostring(self.count), 2, self.y - 8, VIRTUAL_WIDTH, 'center')
love.graphics.rectangle('fill', self.x + 2, self.y + 2, self.width, self.height)
love.graphics.setColor(255/255, 255/255, 255/255, 255/255)
love.graphics.printf(tostring(self.count), 0, self.y - 10, VIRTUAL_WIDTH, 'center')
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
end
end
或在 AddBall.lua
中,但我的道具不会生成。你能告诉我为什么吗?
我会 post GitHub 中的东西,如果你想仔细看的话,我的 AddBall powerup 是绿色十字。
我认为这是因为你只在 powerup 与 ball1 发生碰撞时才更新 ball2。由于您在更新方法中渲染了球,因此您只能在它更新时看到它(它没有更新)
我建议你这样做:
if ball2.inPlay then
ball2:update(dt)
end
你说你的道具没有出现。这可能是因为您没有出于该推理而在 love.draw
中调用 powerup1:render()
。尝试更新生成道具和球的概念,因为您需要以某种方式渲染它。
试试这样:
if powerup1.inPlay then
powerup1:render()
end
我目前正在制作名为 PlayBall 的 Pong 重制版,这是一个色彩丰富的版本,具有增强功能、模式和新增功能。我现在处于 Alpha 2.0(Powerup 概念),我想制作我的第一个名为 AddBall 的 powerup。
这个道具的作用是,当球与其碰撞时,会生成一个新球。
我在AddBall.lua
中设置了代码:
AddBall = Class{}
local spawner = math.random(10, 20)
function AddBall:init(x, y)
self.x = x
self.y = y
self.width = 8
self.height = 8
self.timer = 0
self.inPlay = false
end
function AddBall:collides(ball)
-- first, check to see if the left edge of either is farther to the right
-- than the right edge of the other
if self.x > ball.x + ball.width or ball.x > self.x + self.width then
return false
end
-- then check to see if the bottom edge of either is higher than the top
-- edge of the other
if self.y > ball.y + ball.height or ball.y > self.y + self.height then
return false
end
-- if the above aren't true, they're overlapping
return true
end
function AddBall:update(dt)
self.timer = self.timer + dt
if self.timer > spawner then
self.inPlay = true
end
if self.inPlay then
self:render()
end
end
function AddBall:render()
love.graphics.draw(textures['powerups'], frames['powerups'][1], self.x, self.y)
end
function AddBall:reset()
self.timer = 0
self.inPlay = false
spawner = math.random(10, 20)
end
这是我做的最好的。然后我在 main.lua
中分配了一大堆东西来加载道具和第二个球:
--[[
Called just once at the beginning of the game; used to set up
game objects, variables, etc. and prepare the game world.
]]
function love.load()
-- set love's default filter to "nearest-neighbor", which essentially
-- means there will be no filtering of pixels (blurriness), which is
-- important for a nice crisp, 2D look
love.graphics.setDefaultFilter('nearest', 'nearest')
-- set the title of our application window
love.window.setTitle('PlayBall')
-- seed the RNG so that calls to random are always random
math.randomseed(os.time())
-- initialize our nice-looking retro text fonts
smallFont = love.graphics.newFont('font.ttf', 8)
largeFont = love.graphics.newFont('font.ttf', 16)
scoreFont = love.graphics.newFont('font.ttf', 32)
love.graphics.setFont(smallFont)
-- set up our sound effects; later, we can just index this table and
-- call each entry's `play` method
sounds = {
['paddle_hit'] = love.audio.newSource('sounds/paddle_hit.wav', 'static'),
['score'] = love.audio.newSource('sounds/score.wav', 'static'),
['wall_hit'] = love.audio.newSource('sounds/wall_hit.wav', 'static')
}
textures = {
['powerups'] = love.graphics.newImage('graphics/powerups.png')
}
frames = {
['powerups'] = GenerateQuadsPowerups(textures['powerups'])
}
-- initialize our virtual resolution, which will be rendered within our
-- actual window no matter its dimensions
push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
fullscreen = false,
resizable = true,
vsync = true
})
-- initialize our player paddles; make them global so that they can be
-- detected by other functions and modules
player1 = Paddle(10, 30, 5, 20)
player2 = Paddle(VIRTUAL_WIDTH - 10, VIRTUAL_HEIGHT - 30, 5, 20)
-- place a ball in the middle of the screen
ball1 = Ball(VIRTUAL_WIDTH / 2 - 2, VIRTUAL_HEIGHT / 2 - 2, 4, 4, 1)
ball2 = Ball(ball1.x, ball1.y, 4, 4, 2)
powerup1 = AddBall(math.random(20, VIRTUAL_WIDTH - 20), math.random(0, VIRTUAL_HEIGHT - 8))
-- set up in play to ensure it is in game
ball1.inPlay = true
-- initialize score variables
player1Score = 0
player2Score = 0
-- either going to be 1 or 2; whomever is scored on gets to serve the
-- following turn
servingPlayer = 1
-- player who won the game; not set to a proper value until we reach
-- that state in the game
winningPlayer = 0
-- the state of our game; can be any of the following:
-- 1. 'start' (the beginning of the game, before first serve)
-- 2. 'serve' (waiting on a key press to serve the ball)
-- 3. 'play' (the ball is in play, bouncing between paddles)
-- 4. 'done' (the game is over, with a victor, ready for restart)
gameState = 'start'
end
然后游戏更新:
--[[
Called every frame, passing in `dt` since the last frame. `dt`
is short for `deltaTime` and is measured in seconds. Multiplying
this by any changes we wish to make in our game will allow our
game to perform consistently across all hardware; otherwise, any
changes we make will be applied as fast as possible and will vary
across system hardware.
]]
function love.update(dt)
if gameState == 'serve' then
-- before switching to play, initialize ball's velocity based
-- on player who last scored
ball1.dy = math.random(-50, 50)
if servingPlayer == 1 then
ball1.dx = math.random(140, 200)
else
ball1.dx = -math.random(140, 200)
end
elseif gameState == 'play' then
-- detect ball collision with paddles, reversing dx if true and
-- slightly increasing it, then altering the dy based on the position
-- at which it collided, then playing a sound effect
if ball1:collides(player1) then
ball1.dx = -ball1.dx * 1.03
ball1.x = player1.x + 5
-- keep velocity going in the same direction, but randomize it
if ball1.dy < 0 then
ball1.dy = -math.random(10, 150)
else
ball1.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
if ball1:collides(player2) then
ball1.dx = -ball1.dx * 1.03
ball1.x = player2.x - 4
-- keep velocity going in the same direction, but randomize it
if ball1.dy < 0 then
ball1.dy = -math.random(10, 150)
else
ball1.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
if ball2:collides(player1) then
ball2.dx = -ball2.dx * 1.03
ball2.x = player1.x + 5
-- keep velocity going in the same direction, but randomize it
if ball2.dy < 0 then
ball2.dy = -math.random(10, 150)
else
ball2.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
if ball2:collides(player2) then
ball2.dx = -ball2.dx * 1.03
ball2.x = player2.x - 4
-- keep velocity going in the same direction, but randomize it
if ball2.dy < 0 then
ball2.dy = -math.random(10, 150)
else
ball2.dy = math.random(10, 150)
end
sounds['paddle_hit']:play()
end
-- detect upper and lower screen boundary collision, playing a sound
-- effect and reversing dy if true
if ball1.y <= 0 then
ball1.y = 0
ball1.dy = -ball1.dy
sounds['wall_hit']:play()
end
-- -4 to account for the ball's size
if ball1.y >= VIRTUAL_HEIGHT - 4 then
ball1.y = VIRTUAL_HEIGHT - 4
ball1.dy = -ball1.dy
sounds['wall_hit']:play()
end
-- detect upper and lower screen boundary collision, playing a sound
-- effect and reversing dy if true
if ball2.y <= 0 then
ball2.y = 0
ball2.dy = -ball2.dy
sounds['wall_hit']:play()
end
-- -4 to account for the ball's size
if ball2.y >= VIRTUAL_HEIGHT - 4 then
ball2.y = VIRTUAL_HEIGHT - 4
ball2.dy = -ball2.dy
sounds['wall_hit']:play()
end
-- if we reach the left edge of the screen, go back to serve
-- and update the score and serving player
if ball1.x < 0 then
servingPlayer = 1
player2Score = player2Score + 1
sounds['score']:play()
-- if we've reached a score of 10, the game is over; set the
-- state to done so we can show the victory message
if player2Score == 10 then
winningPlayer = 2
gameState = 'done'
else
gameState = 'serve'
-- places the ball in the middle of the screen, no velocity
ball1:reset()
end
end
-- if we reach the right edge of the screen, go back to serve
-- and update the score and serving player
if ball1.x > VIRTUAL_WIDTH then
servingPlayer = 2
player1Score = player1Score + 1
sounds['score']:play()
-- if we've reached a score of 10, the game is over; set the
-- state to done so we can show the victory message
if player1Score == 10 then
winningPlayer = 1
gameState = 'done'
else
gameState = 'serve'
-- places the ball in the middle of the screen, no velocity
ball1:reset()
end
end
-- check if ball powerup is added
if powerup1:collides(ball1) then
ball2.inPlay = true
ball2:update(dt)
powerup1:reset()
end
-- ball 2 is resetted when it hits the edge
if ball2.x < 0 or ball2.x > VIRTUAL_WIDTH then
ball2.inPlay = false
end
end
--
-- paddles can move no matter what state we're in
--
-- player 1
if love.keyboard.isDown('w') then
player1.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('s') then
player1.dy = PADDLE_SPEED
else
player1.dy = 0
end
-- player 2
if aiMode == true then
player2.y = ball1.y
elseif aiMode == false then
if love.keyboard.isDown('up') then
player2.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('down') then
player2.dy = PADDLE_SPEED
else
player2.dy = 0
end
end
-- update our ball based on its DX and DY only if we're in play state;
-- scale the velocity by dt so movement is framerate-independent
if gameState == 'play' then
ball1:update(dt)
end
player1:update(dt)
player2:update(dt)
powerup1:update(dt)
end
我的问题是加电不会生成,使加电概念不完整。不知道是我渲染出了问题,还是时机不对。
我的猜测是我在 Ball.lua
:
Ball = Class{}
function Ball:init(x, y, width, height, num)
self.x = x
self.y = y
self.width = width
self.height = height
self.count = num
-- these variables are for keeping track of our velocity on both the
-- X and Y axis, since the ball can move in two dimensions
self.dy = 0
self.dx = 0
self.inPlay = false
end
--[[
Expects a paddle as an argument and returns true or false, depending
on whether their rectangles overlap.
]]
function Ball:collides(paddle)
-- first, check to see if the left edge of either is farther to the right
-- than the right edge of the other
if self.x > paddle.x + paddle.width or paddle.x > self.x + self.width then
return false
end
-- then check to see if the bottom edge of either is higher than the top
-- edge of the other
if self.y > paddle.y + paddle.height or paddle.y > self.y + self.height then
return false
end
-- if the above aren't true, they're overlapping
return true
end
--[[
Places the ball in the middle of the screen, with no movement.
]]
function Ball:reset()
self.x = VIRTUAL_WIDTH / 2 - 2
self.y = VIRTUAL_HEIGHT / 2 - 2
self.dx = 0
self.dy = 0
end
function Ball:update(dt)
self.x = self.x + self.dx * dt
self.y = self.y + self.dy * dt
end
function Ball:render()
if self.inPlay then
love.graphics.setFont(smallFont)
love.graphics.setColor(0/255, 0/255, 0/255, 255/255)
love.graphics.printf(tostring(self.count), 2, self.y - 8, VIRTUAL_WIDTH, 'center')
love.graphics.rectangle('fill', self.x + 2, self.y + 2, self.width, self.height)
love.graphics.setColor(255/255, 255/255, 255/255, 255/255)
love.graphics.printf(tostring(self.count), 0, self.y - 10, VIRTUAL_WIDTH, 'center')
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
end
end
或在 AddBall.lua
中,但我的道具不会生成。你能告诉我为什么吗?
我会 post GitHub 中的东西,如果你想仔细看的话,我的 AddBall powerup 是绿色十字。
我认为这是因为你只在 powerup 与 ball1 发生碰撞时才更新 ball2。由于您在更新方法中渲染了球,因此您只能在它更新时看到它(它没有更新)
我建议你这样做:
if ball2.inPlay then
ball2:update(dt)
end
你说你的道具没有出现。这可能是因为您没有出于该推理而在 love.draw
中调用 powerup1:render()
。尝试更新生成道具和球的概念,因为您需要以某种方式渲染它。
试试这样:
if powerup1.inPlay then
powerup1:render()
end