'Error Trying to Draw Platforms in Lua/Love2D

New to Lua/Game dev in general here. I'm trying to write a code to draw the background of my game. I have four different spritesheets for things related to setting:

  • Background - which contains the drawn "background image" of the game
  • Platforms - which contain the platform sprites of the game
  • objectsBig - which contain the relatively bigger drawn objects in the background (example rocks, seaweed, etc)
  • objectsSmall - which contain the relatively smaller drawn objects (smaller rocks, plants, etc)

I made a function, called generateQuads() which is in my Util.lua file, which, given a spritesheet, splices it up into the different sprites in the spritesheet and returns those sprites. It is as follows:

-- Function to generate quads/cut the spritesheet
function generateQuads(atlas, tileWidth, tileHeight)
    local sheetWidth = atlas:getWidth() / tileWidth
    local sheetHeight = atlas:getHeight() / tileHeight
local sheetCounter = 1
local quads = {}

-- for every line of the sprite sheet
for y = 0, sheetHeight - 1 do
    -- for every piece in the width
    for x = 0, sheetWidth - 1 do
        -- quads generated will be the ones specified by tileWidth and tileHeight
        quads[sheetCounter] = love.graphics.newQuad(x * tileWidth, y * tileHeight, tileWidth, 
            tileHeight, atlas:getDimensions())
        sheetCounter = sheetCounter + 1
    end
end

return quads

end

I also have a class called Map, which is meant to contain information for the Map. The following are the functions in it:

FUNCTION TO SET UP THE CLASS

function Map:init()
    -- Load the background sprite into variable
    -- Each is 500x500, total is 1500x500
    self.background = love.graphics.newImage('Graphics/platform/background/full.png')

-- Load all the ground platforms into variable
-- Each is 60x30, total is 240x30
self.platforms = love.graphics.newImage('Graphics/platform/ground/all.png')

-- Load all the bigger misc objects into variable
-- Each is 15x20, total is 15x120
self.objectsBig = love.graphics.newImage('Graphics/platform/objects/15x20/all.png')

-- Load all the smaller misc objects into variable
-- Each is 15x15, total is 60x15
self.objectsSmall = love.graphics.newImage('Graphics/platform/objects/15x15/all.png')

-- Setting the size for each of the variables IN PIXELS
self.backgroundWidth = 500
self.backgroundHeight = 1500

self.platformWidth = 60
self.platformHeight = 30

self.objectsBigWidth = 15
self.objectsBigHeight = 20

self.objectsSmallWidth = 15
self.objectsSmallHeight = 15

-- Setting the map size IN TILES
-- EXPERIMENTAL, CHECK AGAIN
self.mapWidth = 432
self.mapHeight = 243

-- Setting the width of the map IN PIXELS (in relation to platforms)
self.mapWidthPixels = self.backgroundWidth
self.mapHeightPixels = self.backgroundHeight

-- Storing our map features
self.tiles = {}

-- Storing the camera points, starting from the bottom
-- The 243 is the VIRTUAL_HEIGHT, which we needed to subtract to account for the
-- offset of the screen
self.camX = 0
self.camY = self.backgroundHeight - 243

-- Cutting each of the spritesheets
self.backgroundSprite = generateQuads(self.background, self.backgroundWidth, self.backgroundHeight)
self.platformSprite = generateQuads(self.platforms, self.platformWidth, self.platformHeight)
self.objectsBigSprite = generateQuads(self.objectsBig, self.objectsBigWidth, self.objectsBigHeight)
self.objectsSmallSprite = generateQuads(self.objectsSmall, self.objectsSmallWidth, self.objectsSmallHeight)

-- 'Setting' the tiles for the map to be background 
for y = 1, self.mapHeight do
    for x = 1, self.mapWidth do
        self:setTile(x, y, BACKGROUND)
    end
end

-- 'Setting' the platform tiles for where we start
for x = 1, self.mapWidth do
    self:setTile(x, self.mapHeight - 303, GROUND_MIDDLE)
end
end

FUNCTION TO 'SET' WHERE IN THE X, Y COORDINATE THE TILES SHOULD BE

function Map:setTile(x, y, tile)
    -- The table 'tiles' is going to store what tile should be in what x and y position
    -- subtracting y by 1 so that it's 0 indexed, not 1 indexed
    self.tiles[(y - 1) * self.mapWidth + x] = tile
end

FUNCTION TO RETURN WHAT TILE IS IN THE X, Y COORDINATE

function Map:getTile(x, y, tile)
    -- This function is going to tell us what tile is set at this x and y position
    return self.tiles[(y - 1) * self.mapWidth + x]
end

FUNCTION TO UPDATE

function Map:update(dt)
    -- Moving the camera depending on the key being pressed
    if love.keyboard.isDown('w') then
        -- up movement, clamped between 0 and the other
        self.camY = math.max(0, math.floor(self.camY - SCROLL_SPEED * dt))
    elseif love.keyboard.isDown('a') then
        -- left movement
        self.camX = math.max(0, math.floor(self.camX - SCROLL_SPEED * dt))
    elseif love.keyboard.isDown('s') then
        -- down movement, subtracting VIRTUAL_HEIGHT to account for the screen offset
        self.camY = math.min(self.backgroundHeight - VIRTUAL_HEIGHT, math.floor(self.camY + SCROLL_SPEED * dt))
    elseif love.keyboard.isDown('d') then
        -- right movement
        self.camX = math.min(self.backgroundWidth - VIRTUAL_WIDTH, math.floor(self.camX + SCROLL_SPEED * dt))
    end
end

FUNCTION TO RENDER

function Map:render()
    for y = 1, self.mapHeight do
        for x = 1, self.mapWidth do
            -- Drawing the background first
            love.graphics.draw(self.background, self.backgroundSprite[self:getTile(x, y)],
                (x - 1) * self.backgroundWidth, (y - 1) * self.backgroundHeight)
            love.graphics.draw(self.platform, self.platformSprite[self:getTile(x, y)],
                (x - 1) * self.platformWidth, (y - 1) * self.platformHeight)
        end
    end
end

What I'm trying to do is splice up each spritesheet, and for set the background and bottom tiles so that I can see a bottom floor. I'm trying to do this through giving numbers to the components in my spritesheet, so that, for example, in a 1500x500 spritesheet for the background, the entire thing is considered 'one' sprite, and treated as such. Its number, 1, is given in a variable. Another example is a 240x30 platform spritesheet, where each 60x30 is considered 'one' sprite, and given a corresponding number, like so:

-- Know where the platforms are in the spritesheet
GROUND_LEFT = 1
GROUND_RIGHT = 2
GROUND_SMALL = 3
GROUND_MIDDLE = 4

-- Know where the backgrounds are in the spritesheet
BACKGROUND = 1

[...]

I want to then store each in the self.tiles list, so that I can access them at any time from the table (Do note that most of this is taken from the CS50 implementation of mario, and so I understand if I've gotten any concepts wrong). When I run this code, though, I get the following error:

Error

Error

Map.lua:135: bad argument #1 to 'draw' (Texture expected, got nil)


Traceback

[C]: in function 'draw'
Map.lua:135: in function 'render'
main.lua:48: in function 'draw'
[C]: in function 'xpcall'

Essentially, I just want to know a way in which I can set the bottom platform tiles, and then be able to iterate over the map and 'set' where the other object sprites should be. The background alone works fine, but once I added the:

-- 'Setting' the platform tiles for where we start
    for x = 1, self.mapWidth do
        self:setTile(x, self.mapHeight - 303, GROUND_MIDDLE)
    end

and

love.graphics.draw(self.platform, self.platformSprite[self:getTile(x, y)],
            (x - 1) * self.platformWidth, (y - 1) * self.platformHeight)

lines, the program wouldn't run.

Any help is appreciated!

EDIT: The line I'm getting an error on is the self.platform one.



Solution 1:[1]

i had the same problem before, and it turned out to be a typo when typing the variable. looking at your code, i saw that there was no self.platform, instead, there was self.platforms.

try:

love.graphics.draw(self.platforms, self.platformSprite[self:getTile(x, y)],
        (x - 1) * self.platformWidth, (y - 1) * self.platformHeight)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 freeve4