1

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.

1
  • 2
    In the while loop, you reference self outside of any function. I'm assuming that's line 54. Commented Jul 14, 2020 at 16:08

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much, I get it now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.