Page 1 of 1

Need help with an nil error please..

Posted: Tue Dec 21, 2021 1:59 pm
by dsk031
Alright so, I have been following a tutorial on youtube for a pong game, I came across a different problem than this one that I am posting about and accidently did Ctrl+Z too many times and ended up messing my code up more than it already is.. Here is what I am getting.. Any help is appreciated.. I did go back through the video some to see if anything looks out of place and still can't find it..

Error

main.lua:109: attempt to index global 'player2' (a nil value)


Traceback

main.lua:109: in main chunk
[C]: in function 'require'
[C]: in function 'xpcall'
[C]: in function 'xpcall'

If main.lua:109 I'm guessing this is the line it's at? I marked where 109 is in bold if that's the case..

---------------------------------------------------------------------
here is code.. ---------------------------------------
---------------------------------------------------------------------

-- push is a library that will allow us to draw our game at a virtual
-- resolution, instead of however large our window is; used to provide
-- a more retro aesthetic
--
push = require 'push'

-- the "Class" library we're using will allow us to represent anything in
-- our game as code, rather than keeping track of many disparate variables and
-- methods
--
Class = require 'class'

-- our Paddle class, which stores position and dimensions for each Paddle
-- and the logic for rendering them
require 'Paddle'

-- our Ball class, which isn't much different than a Paddle structure-wise
--but which will mechanically function very differently
require 'Ball'

WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720

VIRTUAL_WIDTH = 432
VIRTUAL_HEIGHT = 243

-- speed at which we will move our paddle; multiplied by dt in update
PADDLE_SPEED = 200

--[[
Runs when the game first starts up
]]
-- use nearest-neighbor filtering on upscaling and downscaling
function love.load()
love.graphics.setDefaultFilter('nearest', 'nearest')

-- set the title of our application window
love.window.setTitle('Pong')

--"seed" the RNG so that calls to random are always random
-- use the current time, since that will vary on startup every time.
math.randomseed(os.time())

-- more "Retro-looking" font object we can use for any text
smallFont = love.graphics.newFont('font.ttf', 13)

-- larger font for drawing the score on screen
scoreFont = love.graphics.newFont('font.ttf', 32)

-- set LOVE2D active font to the smallFont object
love.graphics.setFont(smallFont)

push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
fullscreen = false,
resizable = false,
vsync = true
})

-- initialize score variables, used for rendering on the screen and keeping
-- track of the winner
player1Score = 0
player2Score = 0

-- paddle positions on the Y axis (They can only move up or down)
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
ball = Ball(VIRTUAL_WIDTH / 2 - 2, VIRTUAL_HEIGHT / 2 - 2, 4, 4)

-- game state variable used to transition between different parts of the game
-- (used for beginning, menus, main game, high score list, ect.)
-- we will use this to determine behavior during render and update
gameState = 'start'
end


--[[
Runs every frame, with "dt" pressed in, our delta in seconds
since the last frame, which LOVE2D supplies us.
]]

function love.update(dt)
-- player 1 movement
if love.keyboard.isDown('w') then
-- add negative paddle speed to current Y scaled by deltaTime
-- now, we clamp our position between the bounds of the screen
-- math.max returns the greater of the two values; 0 and player Y
-- will ensure we don't go above it
player1.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('s') then
-- add positive paddle to current Y scaled by deltaTime
-- math.min returns the lesser of two values; bottom of the edge
-- and player Y will ensure we don't go below it
player1.dy = PADDLE_SPEED
else
player1.dy = 0
end
end

-- player 2 movement
if love.keyboard.isDown('up') then
-- add negative paddle speed to current Y scaled by deltaTime
player2.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('down') then
-- add positive paddle to current Y scaled by deltaTime
player2.dy = PADDLE_SPEED
else
--109?-- player2.dy = 0
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
function love.update(dt)
if gameState == 'play' then
ball:update(dt)
end

player1:update(dt)
player2:update(dt)
end


--function love.update(dt)
--if gameState == 'play' then
-- detect ball collision with paddles, reversing dx if true and
-- slightly increasing it, then altering the dy based on the position of the ball
--if ball:collides(player1) then
--ball.dx = -ball.dx * 1.03
--ball.x = player1.x + 5
--end

-- keep velocity going in the same direction, but randomize it
--if ball.dy < 0 then
--ball.dy = -math.random(10, 150)
--else
--ball.dy = math.random(10, 150)
--end
--end
--if ball:collides(player2) then
--ball.dx = -ball.dx * 1.03
--ball.x = player2.x - 4

-- keep velocity going in the same direction, but randomize it
--if ball.dy < 0 then
--ball.dy = -math.random(10, 150)
--else
--ball.dy = math.random(10, 150)
--end
--end

-- detect upper and lower screen boundary collision and reverse if collides
--if ball.y <= 0 then
--ball.y = 0
--ball.dy = -ball.dy
--end

-- -4 to account for the balls size
--if ball.y >= VIRTUAL_HEIGHT - 4 then
--ball.y = VIRTUAL_HEIGHT - 4
--ball.dy = -ball.dy
--end
--end



--[[
Keyboard handling, called by LOVE2D each frame;
passes in the key we pressed so we can access.
]]

function love.keypressed(key)
-- keys can be accessed by string name
if key == 'escape' then
-- function LOVE gives us to terminate application
love.event.quit()
-- if we press enter during the start state of the game, we'll go into play state
-- during play mode, the ball will move in a random direction
elseif key == 'enter' or key == 'return' then
if gameState == 'start' then
gameState = 'play'
else
gameState = 'start'

-- ball's new reset method
ball:reset()
end
end
end

--[[
Called after update by LOVE2D, used to draw anything to the screen, updated
]]

--begin rendering at virtual resolution
function love.draw()
push:apply('start')

-- clear the screen with a specific color; in this case, a color similar
-- to some versions of the original Pong
love.graphics.clear(40/255, 45/255, 52/255, 1)

-- draw score on the left and right center of the screen
-- need to switch font to draw before actually printing
love.graphics.setFont(scoreFont)
love.graphics.print(tostring(player1Score), VIRTUAL_WIDTH / 2 - 50,
VIRTUAL_HEIGHT / 3)
love.graphics.print(tostring(player2Score), VIRTUAL_WIDTH / 2 + 30,
VIRTUAL_HEIGHT / 3)

--
-- paddles are simply rectangles we draw on the screen at certain points
-- as is the ball
--

-- draw different things based on the state of the game
love.graphics.setFont(smallFont)

if gameState == 'start' then
love.graphics.printf('Hello Start State!', 0, 20, VIRTUAL_WIDTH, 'center')
else
love.graphics.printf('Hello Play State!', 0, 20, VIRTUAL_WIDTH, 'center')
end

-- render paddles, now using their class's render method
player1:render()
player2:render()

-- render ball using its class's render method
ball:render()

-- new function just to demonstrate how to see FPS in Love2D
displayFPS()


-- end rendering at virtual resolution
push:apply('end')
end

--[[
Renders the current FPS.
]]
function displayFPS()
-- simple FPS display across all states
love.graphics.setFont(smallFont)
love.graphics.setColor(0, 255, 0, 255)
love.graphics.print('FPS: ' .. tostring(love.timer.getFPS()), 10, 10)
end

Re: Need help with an nil error please..

Posted: Tue Dec 21, 2021 3:00 pm
by Nikki

Code: Select all

function love.update(dt)
   -- player 1 movement
   if love.keyboard.isDown('w') then
      -- add negative paddle speed to current Y scaled by deltaTime
      -- now, we clamp our position between the bounds of the screen
      -- math.max returns the greater of the two values; 0 and player Y
      -- will ensure we don't go above it
      player1.dy = -PADDLE_SPEED
   elseif love.keyboard.isDown('s') then
      -- add positive paddle to current Y scaled by deltaTime
      -- math.min returns the lesser of two values; bottom of the edge
      -- and player Y will ensure we don't go below it
      player1.dy = PADDLE_SPEED
   else
      player1.dy = 0
   end
end

-- player 2 movement
if love.keyboard.isDown('up') then
   -- add negative paddle speed to current Y scaled by deltaTime
   player2.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('down') then
   -- add positive paddle to current Y scaled by deltaTime
   player2.dy = PADDLE_SPEED
else
   --109?-- player2.dy = 0
end
your -- player 2 movement code is outside the love.update() function, it looks like an extra

Code: Select all

end
is there

Re: Need help with an nil error please..

Posted: Tue Dec 21, 2021 3:50 pm
by pgimeno
What Nikki said, and also there are two love.update() functions. The second one will overwrite the first, which will be ignored. Maybe that code should be part of Paddle:update?

By the way, being very rigorous with indentation helps a lot with preventing problems like that. Here's that section of the code, properly indented:

Code: Select all

function love.update(dt)
	-- player 1 movement
	if love.keyboard.isDown('w') then
		-- add negative paddle speed to current Y scaled by deltaTime
		-- now, we clamp our position between the bounds of the screen
		-- math.max returns the greater of the two values; 0 and player Y
		-- will ensure we don't go above it
		player1.dy = -PADDLE_SPEED
	elseif love.keyboard.isDown('s') then
		-- add positive paddle to current Y scaled by deltaTime
		-- math.min returns the lesser of two values; bottom of the edge
		-- and player Y will ensure we don't go below it
		player1.dy = PADDLE_SPEED
	else
		player1.dy = 0
	end
end

-- player 2 movement
if love.keyboard.isDown('up') then
	-- add negative paddle speed to current Y scaled by deltaTime
	player2.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('down') then
	-- add positive paddle to current Y scaled by deltaTime
	player2.dy = PADDLE_SPEED
else
	--109?--		player2.dy = 0
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
function love.update(dt)
	if gameState == 'play' then
		ball:update(dt)
	end

	player1:update(dt)
	player2:update(dt)
end
edited to fix typo

Re: Need help with an nil error please..

Posted: Tue Dec 21, 2021 4:47 pm
by dsk031
Thank you both very much :)

Re: Need help with an nil error please..

Posted: Wed Dec 22, 2021 3:25 pm
by dsk031
Alright on to another smaller problem.. The tutorial that I am following he has only 7 ends in this line of code but now when I try and run this code on LOVE it wants me to put another end after line 83 which is in bold, which would make this 8 Ends in my code.. Also, once I do put an End at line 83 to close off function, game runs and I have another problem after that.. The collision does not work when it goes off of boundaries (Top and bottom screen) it is suppose to bounce back off of the screen.


I apologize, I am quite new to programming, I am trying to learn Lua for the sake of trying to make my on game on Core Games..

Code: Select all

function love.update(dt)
	if gameState == 'play' then
		-- detect ball collision with paddles, reversing dx if true and
		-- slightly increasing it, then altering the dy based on the position of the ball
		if ball:collides(player1) then
			ball.dx = -ball.dx * 1.03
			ball.x = player1.x + 5
--> [b]End?[/b]
			-- keep velocity going in the same direction, but randomize it
			if ball.dy < 0 then
				ball.dy = -math.random(10, 150)
			else
				ball.dy = math.random(10, 150)
			end
		end
		if ball:collides(player2) then
			ball.dx = -ball.dx * 1.03
			ball.x = player2.x - 4

			-- keep velocity going in the same direction, but randomize it
		    if ball.dy < 0 then
				ball.dy = -math.random(10, 150)
			else
				ball.dy = math.random(10, 150)
			end
		end

		-- detect upper and lower screen boundary collision and reverse if collides
		if ball.y <= 0 then
			ball.y = 0
			ball.dy = -ball.dy
		end

		-- -4 to account for the balls size
		if ball.y >= VIRTUAL_HEIGHT - 4 then
			ball.y = VIRTUAL_HEIGHT - 4
			ball.dy = -ball.dy
		end
	end

Re: Need help with an nil error please..

Posted: Wed Dec 22, 2021 5:05 pm
by dsk031
I have created a new topic for the other error on the forums.. Sorry about that..