"Attempt to index local 'self' (a nil value)" cant index variables of my classes - lua

I know this question already exists a couple of times on this site, BUT my problem is a little different! So... see my problem is that im trying to get a value in a draw function i wrote for my player class but when im trying to get anything with self.such'n'such it says attempt to index local 'self' (a nil value) the functions arent important for my problem (I hope)
require"functions"
Acc = 2000
Decel = 2500
Maxspd = 900
Player = {}
Player.__index = Player
function Player:new(x,y)
local play = {}
setmetatable(play, Player)
play.inx = 0
play.iny = 0
play.dirx = 0
play.diry = 0
play.x = x
play.y = y
play.speedx = 0
play.speedy = 0
play.velx = 0
play.vely = 0
play.clr = "red"
play.hp = 100
play.rot = 0
play.size = 40
play.hoehe = math.sqrt(3) * (40 / 2)
return play
end
function love.load()
Main = Player:new(100,100)
end
function Player:update(d)
if love.keyboard.isDown("w") then self.iny = -1
elseif love.keyboard.isDown("s") then self.iny = 1 else self.iny = 0 end
if love.keyboard.isDown("d") then self.inx = 1
elseif love.keyboard.isDown("a") then self.inx = -1 else self.inx = 0 end
if self.inx == -self.dirx then self.speedx = self.speedx / 5 end
if self.iny == -self.diry then self.speedy = self.speedy / 5 end
self.dirx = self.inx
self.diry = self.iny
if self.inx ~= 0 then self.speedx = self.speedx + Acc * d
else self.speedx = self.speedx - Decel * d end
if self.iny ~= 0 then self.speedy = self.speedy + Acc * d
else self.speedy = self.speedy - Decel * d end
self.speedx = clamp(self.speedx,0,Maxspd)
self.speedy = clamp(self.speedy,0,Maxspd)
self.velx = self.speedx * d * self.dirx
self.vely = self.speedy * d * self.diry
self.x = self.x * d
self.y = self.y * d
end
function Player:getX() return self.x end
function Player:getY() return self.y end
function Player:switch()
if self.clr == "red" then self.clr = "blue" end
if self.clr == "blue" then self.clr = "red" end
end
function Player:draw()
local x1,x2,x3,y1,y2,y3 = 0,0,0,0,0,0
x1 = self.x - self.size / 2
y1 = self.y + self.hoehe / 2
x2 = self.x + self.size/2
y2 = self.y + self.hoehe / 2
x3 = self.x
y3 = self.y - self.hoehe / 2
x1, y1 = rotate_around_point(x1, y1, self.x, self.y, self.rot)
x2, y2 = rotate_around_point(x2, y2, self.x, self.y, self.rot)
x3, y3 = rotate_around_point(x3, y3, self.x, self.y, self.rot)
local verts = {x1,y1,x2,y2,x3,y3}
if self.clr == "blue" then love.graphics.setColor(0,255,0,1) end
if self.clr == "red" then love.graphics.setColor(255,0,0,1) end
love.graphics.polygon("fill",verts)
end
function love.keypressed(key,scancode,isrepeat)
if key == "space" then Main:switch() end
end
function love.update(d)
Main:update(d)
end
function love.draw()
Main.draw()
end

I had the same problem and #EgorSkriptunoff's answer was dead on; going to post here as an answer rather than a comment for posterity.
Probably, you are invoking your functions as x.f() instead of x:f()

Related

Love2D trying to generate a chunk that has blocks inside it, but after moving a few chunks away it renders more chunks then intended

I have created a basic chunk generator, a chunk is area filled with squares, when the player moves a few blocks away from 0,0 it works correctly but after moving 4 chunks away it renders more then one chunk instead of one, I am not sure what I am doing wrong, I have given it a go changing some values, but I am left head scratching.
here is the full code, you can copy and paste into VSCODE with love2D to see what happens.
I think the main issue is somewhere around check_boarders function since that is what checks if the player is inside a chunk.
function Key_input(key)
if love.keyboard.isDown(key) then
return 1
else
return 0
end
end
function love.load()
Camera = require "camera"
Cam = Camera()
Basic_Player = {}
Basic_Player.X = 100
Basic_Player.Y = 100
Basic_Player.Speed = 15
Movement = {}
end
function love.update(dt)
Movement.X = Key_input("d") - Key_input("a")
Movement.Y = Key_input("s") - Key_input("w")
Basic_Player.X = Basic_Player.X + Movement.X * Basic_Player.Speed
Basic_Player.Y = Basic_Player.Y + Movement.Y * Basic_Player.Speed
Cam:lookAt(Basic_Player.X,Basic_Player.Y)
X, Y = Cam:position() -- Set cam position to global values
end
function love.draw()
love.graphics.setBackgroundColor(0.5,0.5,0.9)
Cam:attach() -- Renders the player and world inside its own scene
generate_world(10,0)
love.graphics.setColor( 0,0,1, 1 )
love.graphics.rectangle("fill",Basic_Player.X,Basic_Player.Y,30,30)
love.graphics.setColor( 1,1,1, 1 )
Cam:detach()
love.graphics.setColor( 1,0,0, 1 ) --Stays on the screen
love.graphics.print(X .. " / " .. Y ,300,400)
love.graphics.print(love.timer.getFPS( ) ,300,450)
love.graphics.setColor( 1,1,1, 1 )
end
function old_generate_world(_world_size, _seed) -- Before optimization
local _chunk_size = 30
local _block_size = 30
for i = 0, _world_size - 1 do
for f = 0, _world_size - 1 do
local x_val = (_chunk_size * _block_size) * i -- Position value for actually building the chunks
local y_val = (_chunk_size * _block_size) * f
gen_chunk(_chunk_size,_block_size,_seed,{X = x_val ,Y = y_val })
end
end
end
function generate_world(_world_size, _seed)
local _chunk_size = 10 -- Chunk size width and height
local _block_size = 30 -- block size inside the chunk
for i = 0, _world_size - 1 do -- loop through world size
for f = 0, _world_size - 1 do
local x_val = (_chunk_size * _block_size) * i -- Position value for actually building the chunks
local y_val = (_chunk_size * _block_size) * f
local chunk_x_local_size = 0 -- To make sure we get a length for when i and f = 0
local chunk_y_local_size = 0
if i == 0 then -- To make sure the size of the chunk isnt zero
chunk_x_local_size = _chunk_size * _block_size -- Get length of chunk when i = 0
else
chunk_x_local_size = x_val
end
if f == 0 then -- ditto
chunk_y_local_size = _chunk_size * _block_size
else
chunk_y_local_size = y_val
end
-- Checks if the player is inside a chunk if true draw it.
if Check_boarders({X = X,Y = Y},{X = x_val,Y = y_val}, {X = chunk_x_local_size, Y = chunk_y_local_size}) then
gen_chunk(_chunk_size,_block_size,_seed,{X = x_val ,Y = y_val }) -- Actually generate the chunk
end
love.graphics.setColor( 0,1,0, 1 )
love.graphics.rectangle("fill",x_val,y_val,15,15)
love.graphics.setColor( 1,1,1, 1 )
end
end
end
function Check_boarders(player_pos, boarder_pos, chunk_length) -- Checks player position is inside the boarder of the currently generated chunk
if player_pos.X > boarder_pos.X and player_pos.X < boarder_pos.X + chunk_length.X then -- Check if the player is greater then top left and less then top right
if player_pos.Y > boarder_pos.Y and player_pos.Y < boarder_pos.Y + chunk_length.Y then -- check if player is greater then top and less then bottom left
return true
end
end
return false
end
function gen_chunk(chunk_size,block_size,seed,position) -- chunk size is how many blocks inside the chunk, block size is self explain, seed n/a, pos starting chunk position
for i = 0, chunk_size - 1 do
for e = 0, chunk_size - 1 do -- loop until chunk size is met this is the amount of blocks being created
love.graphics.rectangle("fill",position.X + i * block_size,position.Y + e * block_size,block_size - 1,block_size - 1)
end
end
love.graphics.setColor( 1,0,0, 1 )
love.graphics.rectangle("fill",position.X ,position.Y,6,6)
love.graphics.setColor( 1,1,1, 1 )
end
You will need this camera.lua script just create it and paste this into it:
local _PATH = (...):match('^(.*[%./])[^%.%/]+$') or ''
local cos, sin = math.cos, math.sin
local camera = {}
camera.__index = camera
-- Movement interpolators (for camera locking/windowing)
camera.smooth = {}
function camera.smooth.none()
return function(dx,dy) return dx,dy end
end
function camera.smooth.linear(speed)
assert(type(speed) == "number", "Invalid parameter: speed = "..tostring(speed))
return function(dx,dy, s)
-- normalize direction
local d = math.sqrt(dx*dx+dy*dy)
local dts = math.min((s or speed) * love.timer.getDelta(), d) -- prevent overshooting the goal
if d > 0 then
dx,dy = dx/d, dy/d
end
return dx*dts, dy*dts
end
end
function camera.smooth.damped(stiffness)
assert(type(stiffness) == "number", "Invalid parameter: stiffness = "..tostring(stiffness))
return function(dx,dy, s)
local dts = love.timer.getDelta() * (s or stiffness)
return dx*dts, dy*dts
end
end
local function new(x,y, zoom, rot, smoother)
x,y = x or love.graphics.getWidth()/2, y or love.graphics.getHeight()/2
zoom = zoom or 1
rot = rot or 0
smoother = smoother or camera.smooth.none() -- for locking, see below
return setmetatable({x = x, y = y, scale = zoom, rot = rot, smoother = smoother}, camera)
end
function camera:lookAt(x,y)
self.x, self.y = x, y
return self
end
function camera:move(dx,dy)
self.x, self.y = self.x + dx, self.y + dy
return self
end
function camera:position()
return self.x, self.y
end
function camera:rotate(phi)
self.rot = self.rot + phi
return self
end
function camera:rotateTo(phi)
self.rot = phi
return self
end
function camera:zoom(mul)
self.scale = self.scale * mul
return self
end
function camera:zoomTo(zoom)
self.scale = zoom
return self
end
function camera:attach(x,y,w,h, noclip)
x,y = x or 0, y or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
self._sx,self._sy,self._sw,self._sh = love.graphics.getScissor()
if not noclip then
love.graphics.setScissor(x,y,w,h)
end
local cx,cy = x+w/2, y+h/2
love.graphics.push()
love.graphics.translate(cx, cy)
love.graphics.scale(self.scale)
love.graphics.rotate(self.rot)
love.graphics.translate(-self.x, -self.y)
end
function camera:detach()
love.graphics.pop()
love.graphics.setScissor(self._sx,self._sy,self._sw,self._sh)
end
function camera:draw(...)
local x,y,w,h,noclip,func
local nargs = select("#", ...)
if nargs == 1 then
func = ...
elseif nargs == 5 then
x,y,w,h,func = ...
elseif nargs == 6 then
x,y,w,h,noclip,func = ...
else
error("Invalid arguments to camera:draw()")
end
self:attach(x,y,w,h,noclip)
func()
self:detach()
end
-- world coordinates to camera coordinates
function camera:cameraCoords(x,y, ox,oy,w,h)
ox, oy = ox or 0, oy or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
-- x,y = ((x,y) - (self.x, self.y)):rotated(self.rot) * self.scale + center
local c,s = cos(self.rot), sin(self.rot)
x,y = x - self.x, y - self.y
x,y = c*x - s*y, s*x + c*y
return x*self.scale + w/2 + ox, y*self.scale + h/2 + oy
end
-- camera coordinates to world coordinates
function camera:worldCoords(x,y, ox,oy,w,h)
ox, oy = ox or 0, oy or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
-- x,y = (((x,y) - center) / self.scale):rotated(-self.rot) + (self.x,self.y)
local c,s = cos(-self.rot), sin(-self.rot)
x,y = (x - w/2 - ox) / self.scale, (y - h/2 - oy) / self.scale
x,y = c*x - s*y, s*x + c*y
return x+self.x, y+self.y
end
function camera:mousePosition(ox,oy,w,h)
local mx,my = love.mouse.getPosition()
return self:worldCoords(mx,my, ox,oy,w,h)
end
-- camera scrolling utilities
function camera:lockX(x, smoother, ...)
local dx, dy = (smoother or self.smoother)(x - self.x, self.y, ...)
self.x = self.x + dx
return self
end
function camera:lockY(y, smoother, ...)
local dx, dy = (smoother or self.smoother)(self.x, y - self.y, ...)
self.y = self.y + dy
return self
end
function camera:lockPosition(x,y, smoother, ...)
return self:move((smoother or self.smoother)(x - self.x, y - self.y, ...))
end
function camera:lockWindow(x, y, x_min, x_max, y_min, y_max, smoother, ...)
-- figure out displacement in camera coordinates
x,y = self:cameraCoords(x,y)
local dx, dy = 0,0
if x < x_min then
dx = x - x_min
elseif x > x_max then
dx = x - x_max
end
if y < y_min then
dy = y - y_min
elseif y > y_max then
dy = y - y_max
end
-- transform displacement to movement in world coordinates
local c,s = cos(-self.rot), sin(-self.rot)
dx,dy = (c*dx - s*dy) / self.scale, (s*dx + c*dy) / self.scale
-- move
self:move((smoother or self.smoother)(dx,dy,...))
end
-- the module
return setmetatable({new = new, smooth = camera.smooth},
{__call = function(_, ...) return new(...) end})

How do I use lerp correctly, making sure it reaches the target value

I am trying to create a player in love2D, and I have a lerp function that brings the players speed to 0 , but I know I am not using the lerp function correctly because it never reaches the end value and starts acting funky and crazy, how do I use the lerp function correctly.
function love.load()
moon = require "Library/moon_light"
position = {x = 0, y = 0}
H = 0
V = 0
new_H = 0
new_V = 0
position["x"] = moon.Mid_point(0,0,1280,720)[1]
position["y"] = moon.Mid_point(0,0,1280,720)[2]
accel = 8
max_speed = 80
fps = 60
friction = 6
end
function love.update(dt)
if love.keyboard.isDown('escape') then
love.event.push('quit')
end
if love.keyboard.isDown("d") then
H = 1
elseif love.keyboard.isDown("a") then
H = -1
else
H = 0
end
if love.keyboard.isDown("w") then
V = -1
elseif love.keyboard.isDown("s") then
V = 1
else
V = 0
end
if H ~= 0 then -- use a new value and give it acceleration
new_H = H * accel * dt * fps
end
if H == 0 then -- Check if the player isnt moving lerp it to 0 so stopping the movement
new_H = moon.Lerp(new_H,0,friction * dt)
end
if V ~= 0 then
new_V = V * accel * dt * fps
end
if V == 0 then
new_V = moon.Lerp(new_V,0,friction * dt)
end
position["x"] = position["x"] + new_H -- Set the motion to the position
position["y"] = position["y"] + new_V
end
function love.draw()
love.graphics.rectangle("fill",position["x"] - 25,position["y"] - 25,50,50)
love.graphics.print("Horiztonal value : " .. H .. "\nVertical value : " .. V,100,400)
love.graphics.print("new_H value : " .. new_H .. "\nnew_V value : " .. new_V,100,440)
end
The lerp function, I think nothing is wrong with it, but just in case.
function moon_light.Lerp(start_v,end_v,percent)
return start_v + (end_v - start_v) * percent
end
EDIT I changed the lerp to be time based, from the suggestion and I also made a new variable called motion it seems setting the lerp to its self caused a weird issue, making it never reach 0:
if H ~= 0 then -- use a new value and give it acceleration
H_counter = 0
new_H = H * accel * dt * fps
motion_H = new_H
end
if H == 0 then -- Check if the player isnt moving lerp it to 0 so stopping the movement
if H_counter < slow_down_duration then
motion_H = moon.Lerp(new_H,0,H_counter/slow_down_duration)
H_counter = H_counter + dt
else
new_H = 0
motion_H = 0
end
end
if V ~= 0 then
V_counter = 0
new_V = V * accel * dt * fps
motion_V = new_V
end
if V == 0 then
if V_counter < slow_down_duration then
motion_V = moon.Lerp(new_V,0,V_counter/slow_down_duration)
V_counter = V_counter + dt
else
new_V = 0
motion_V = 0
end
end
position["x"] = position["x"] + motion_H -- Set the motion to the position
position["y"] = position["y"] + motion_V

Trying to add horizontal movement to my game in love2d

I have tried to add horizontal movement into my game in love, but I haven't found a way yet. This is my code.
PADDLE_SPEED = 200
player1 = Paddle(10, 30, 5, 20)
player1 = Paddle(10, 30, 5, 20)
player2 = Paddle(VIRTUAL_WIDTH - 15, VIRTUAL_HEIGHT - 30, 5, 20)
player3 = Paddle(30, 10, 20, 5)
player4 = Paddle(VIRTUAL_WIDTH - 30, VIRTUAL_HEIGHT - 15, 20, 5)
ball = Ball(VIRTUAL_WIDTH / 2 - 2, VIRTUAL_HEIGHT / 2 - 2, 4, 4)
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
if love.keyboard.isDown('a') then
player1.dx = PADDLE_SPEED
elseif love.keyboard.isDown('d') then
player1.dx = -PADDLE_SPEED
else
player1.dx = 0
end
if love.keyboard.isDown('a') then
player1.dx = -PADDLE_SPEED
elseif love.keyboard.isDown('d') then
player1.dy = PADDLE_SPEED
else
player1.dx = 0
end
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
if love.keyboard.isDown('i') then
player3.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('k') then
player3.dy = PADDLE_SPEED
else
player3.dy = 0
end
if love.keyboard.isDown('g') then
player4.dy = -PADDLE_SPEED
elseif love.keyboard.isDown('b') then
player4.dy = PADDLE_SPEED
else
player4.dy = 0
end
This is my class that I call Paddle
Paddle = Class{}
function Paddle:init(x, y, width, height)
self.x = x
self.y = y
self.width = width
self.height = height
self.dy = 0
self.dx = 0
end
function Paddle:update(dt)
if self.dy < 0 then
self.y = math.max(0, self.y + self.dy * dt)
else
self.y = math.min(VIRTUAL_HEIGHT - self.height, self.y + self.dy * dt)
end
end
function Paddle:render()
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
end
I would try drawing the rectangles individually, but I would have to remove all the code that includes player1-4. Is there any way that I can set a variable like PADDLE_SPEED to a number?
So your not quite instantiating your Paddle class correctly. Based on Lua's documentation, I changed some things in your paddle class.
Paddle.lua
Paddle={x=0,y=0,width=0,height=0}
function Paddle:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Paddle:update(dt)
if self.dy < 0 then
self.y = math.max(0, self.y + self.dy * dt)
else
self.y = math.min(VIRTUAL_HEIGHT - self.height, self.y + self.dy * dt)
end
end
function Paddle:render()
love.graphics.rectangle('fill', self.x, self.y, self.width, self.height)
end
Also I'm not sure what you just didn't include in you question, but I set up your core 3 functions (love.load(), love.update(dt), and love.draw()), set values for VIRTUAL_WIDTH AND VIRTUAL_HEIGHT, and instantiated your player classes according to how the Lua documentation specifies
The main thing that might be your problem is that your assigning the speeds to your player objects dy and dx values. These are made up values that you've created for your player object. They don't do anything unless you later access them and use them somehow. I think what you are trying to do is change the x and y position of your player objects. You can do this by taking the players current x or y position and adding or subtracting the PADDLE_SPEED * dt(the number of seconds that have passed since the last execution of love.update(dt)
main.lua
require('Paddle')
function love.load()
--initial graphics setup
love.graphics.setBackgroundColor(0.41, 0.53, 0.97)
love.window.setMode(1000, 600)
PADDLE_SPEED = 200
VIRTUAL_WIDTH = 30
VIRTUAL_HEIGHT = 30
player1 = Paddle:new{x=10, y=30, width=5, height=20}
player2 = Paddle:new{x=VIRTUAL_WIDTH-15, y=VIRTUAL_HEIGHT-30, width=5, height=20}
player3 = Paddle:new{x=30, y=10, width=20, height=5}
player4 = Paddle:new{x=VIRTUAL_WIDTH-30, y=VIRTUAL_HEIGHT-15, width=20, height=5}
-- ball = Ball(VIRTUAL_WIDTH / 2 - 2, VIRTUAL_HEIGHT / 2 - 2, 4, 4)
end
function love.update(dt)
if love.keyboard.isDown('w') then
player1.y = player1.y + PADDLE_SPEED * dt
elseif love.keyboard.isDown('s') then
player1.y = player1.y - PADDLE_SPEED * dt
end
if love.keyboard.isDown('a') then
player1.x = player1.x + PADDLE_SPEED * dt
elseif love.keyboard.isDown('d') then
player1.x = player1.x - PADDLE_SPEED * dt
end
if love.keyboard.isDown('a') then
player2.x = player2.x - PADDLE_SPEED * dt
elseif love.keyboard.isDown('d') then
player2.x = player2.x + PADDLE_SPEED * dt
end
if love.keyboard.isDown('up') then
player2.y = player2.y - PADDLE_SPEED * dt
elseif love.keyboard.isDown('down') then
player2.y = player2.y + PADDLE_SPEED * dt
end
if love.keyboard.isDown('i') then
player3.y = player3.y - PADDLE_SPEED * dt
elseif love.keyboard.isDown('k') then
player3.y = player3.y + PADDLE_SPEED * dt
end
if love.keyboard.isDown('g') then
player4.y = player4.y - PADDLE_SPEED * dt
elseif love.keyboard.isDown('b') then
player4.y = player4.y + PADDLE_SPEED * dt
end
end
function love.draw()
player1:render()
player2:render()
player3:render()
player4:render()
end
So your ball won't work, because I don't know exactly what you want with it, and your Paddle:update(dt) still won't work because I don't know exactly what you want. When you do get Paddle:update(dt) working make sure you include player1:update(dt), player2:update(dt) ... inside your love:update(dt) function or else none of your players will update.
You should get horizontal and vertical movement of your blocks though
P.S. If you post a question a again, you should make sure that you specify exactly what isn't working. Some of your details were missing, and I wasn't sure if that was the part you were asking about, or you had those details in your original code and were asking about something else.
It seems like you probably want to deal with collisions. Here's another answer where i kind of explain collisions, but I would probably recommend love.physics for this type of scenario

ERROR: "attempt to index global 'self' (a nil value)

I'm very slowly working my way through the games track of cs50, and I am stuck on Mario3. In the video he just talks about the code, but I wanted to write it into my own that I am writing alongside the video. I have the exact same code that he does, but I keep getting this error and I cannot figure out why. I will post the code below, but as far as I can tell, I have already assigned self.mapWidth = 30, so I don't know why it keeps saying that it is a nil value.
Here is the error
Error code
Here is the map.lua code
require 'Util'
Map = Class{}
TILE_BRICK = 1
TILE_EMPTY = 4
--cloud tiles
CLOUD_LEFT = 6
CLOUD_RIGHT = 7
SCROLL_SPEED = 62
function Map:init()
self.spritesheet = love.graphics.newImage('graphics/spritesheet.png')
self.tileWidth = 16
self.tileHeight = 16
self.mapWidth = 30
self.mapHeight = 28
self.tiles = {}
self.camX = 0
self.camY = 0
self.mapWidthPixels = self.mapWidth * self.tileWidth
self.mapHeightPixels = self.mapHeight * self.tileHeight
self.tileSprites = generateQuads(self.spritesheet, self.tileWidth, self.tileHeight)
--fill map with empty tiles--
for y = 1, self.mapHeight do
for x = 1, self.mapWidth do
self:setTile(x, y, TILE_EMPTY)
end
end
for y =self.mapHeight / 2, self.mapHeight do
for x = 1, self.mapWidth do
self:setTile(x, y, TILE_BRICK)
end
end
end
function Map:setTile(x, y, tile)
self.tiles[(y - 1) * self.mapWidth + x] = tile
end
function Map:getTile(x, y)
return self.tiles[(y -1) * self.mapWidth + x]
end
local x = 1
while x < self.mapWidth do
if math.random(20) == 1 then
local cloudStart = math.random(self.mapHeight / 2 -6)
self.setTile(x, cloudStart, CLOUD_LEFT)
self:setTile(x + 1, cloudStart, CLOUD_RIGHT)
end
end
function Map:update(dt)
if love.keyboard.isDown('w') then
self.camY = math.max(0, math.floor(self.camY - SCROLL_SPEED * dt))
elseif love.keyboard.isDown('s') then
self.camY = math.min(self.mapHeightPixels - VIRTUAL_HEIGHT, math.floor(self.camY + SCROLL_SPEED * dt))
elseif love.keyboard.isDown('a') then
self.camX = math.max(0, math.floor(self.camX - SCROLL_SPEED *dt))
elseif love.keyboard.isDown('d') then
self.camX = math.min(self.mapWidthPixels - VIRTUAL_WIDTH, math.floor(self.camX + SCROLL_SPEED * dt))
end
end
function Map:render()
for y = 1, self.mapHeight do
for x = 1, self.mapWidth do
love.graphics.draw(self.spritesheet, self.tileSprites[self:getTile(x, y)],
(x - 1) * self.tileWidth, (y - 1) * self.tileHeight)
end
end
end
and in case you need it, here is my main.lua code
WINDOW_WIDTH = 1200
WINDOW_HEIGHT = 720
VIRTUAL_WIDTH = 432
VIRTUAL_HEIGHT = 243
Class = require 'class'
push = require 'push'
require 'Util'
require 'Map'
function love.load()
map = Map()
love.graphics.setDefaultFilter('nearest', 'nearest')
push:setupScreen(VIRTUAL_WIDTH,VIRTUAL_HEIGHT,WINDOW_WIDTH,WINDOW_HEIGHT, {
fullscreen = false,
resizable = false,
vsync = true
})
end
function love.update(dt)
map:update(dt)
if love.keyboard.isDown('escape') then
love.event.quit()
end
end
function love.draw()
push:apply('start')
love.graphics.translate(math.floor(-map.camX),math.floor(-map.camY))
love.graphics.clear(108/255, 140/255, 1, 1)
map:render()
push:apply('end')
end
Thanks in advance for any and all help.
function Map:SomeFunction() end is syntactic sugar for Map["SomeFunction"] = function(self) end
Therefor you can use self inside a function defined with the colon syntax.
Outside of such a function self is nil.
Yet you index self several times in this while loop where self is nil.
local x = 1
while x < self.mapWidth do
if math.random(20) == 1 then
local cloudStart = math.random(self.mapHeight / 2 -6)
self.setTile(x, cloudStart, CLOUD_LEFT)
self:setTile(x + 1, cloudStart, CLOUD_RIGHT)
end
end
which is an infinite loop btw.

Flawed game logic in Lua code

The code is for a simple snake clone and I don't want to let the snake me able to go left if it's going right already.
It works if I just press LEFT when going RIGHT but if I for example presses UP then LEFT within the time frame it starts to move left.
function self.update(dt)
if love.keyboard.isDown(self.left) and self.prevvelocity.x ~= 1 then
self.velocity.x = -1
self.velocity.y = 0
end
if love.keyboard.isDown(self.right) and self.prevvelocity.x ~= -1 then
self.velocity.x = 1
self.velocity.y = 0
end
if love.keyboard.isDown(self.up) and self.prevvelocity.y ~= 1 then
self.velocity.x = 0
self.velocity.y = -1
end
if love.keyboard.isDown(self.down) and self.prevvelocity.y ~= -1 then
self.velocity.x = 0
self.velocity.y = 1
end
if self.timeSinceLastMove < self.speedinverted then
self.timeSinceLastMove = self.timeSinceLastMove + dt
else
table.remove(self.tail, 1)
tail = { x = self.position.x, y = self.position.y }
table.insert(self.tail, tail)
self.position.x = self.position.x + self.velocity.x * tileSize
self.position.y = self.position.y + self.velocity.y * tileSize
self.prevvelocity = self.velocity
self.timeSinceLastMove = 0;
end
end
function self.update(dt)
if love.keyboard.isDown(self.left) and self.prevvelocity.x ~= 1 then
self.velocity.x = -1
self.velocity.y = 0
end
if love.keyboard.isDown(self.right) and self.prevvelocity.x ~= -1 then
self.velocity.x = 1
self.velocity.y = 0
end
if love.keyboard.isDown(self.up) and self.prevvelocity.y ~= 1 then
self.velocity.x = 0
self.velocity.y = -1
end
if love.keyboard.isDown(self.down) and self.prevvelocity.y ~= -1 then
self.velocity.x = 0
self.velocity.y = 1
end
self.timeSinceLastMove = self.timeSinceLastMove + dt
if self.timeSinceLastMove >= self.speedinverted then
self.timeSinceLastMove = self.timeSinceLastMove - self.speedinverted
self.position.x = self.position.x + self.velocity.x * tileSize
self.position.y = self.position.y + self.velocity.y * tileSize
table.remove(self.tail, 1)
local head = { x = self.position.x, y = self.position.y }
table.insert(self.tail, head)
self.prevvelocity = { x = self.velocity.x, y = self.velocity.y }
end
end

Resources