2

I wanted to make a 2D-Platformer (with the Love2D-Framework) and have a main.lua-file select random maps from a states folder. To start with that, i just said that the main-main.lua should open the main.lua-file in /states/map1/. But every time I try to run it, i get this Error-Message:

Error

states/map1/main.lua:169: attempt to call method 'update' (a nil value)

Traceback

states/map1/main.lua:169: in function 'update' [C]: in function 'xpcall'

The main-main.lua-code:

function clearLoveCallbacks()
    love.draw = nil
    love.joystickpressed = nil
    love.joystickreleased = nil
    love.keypressed = nil
    love.keyreleased = nil
    --love.load = nil
    love.mousepressed = nil
    love.mousereleased = nil
    love.update = nil
end

state = {}
function loadState(name)
    state = {}
    clearLoveCallbacks()
    local path = "states/" .. name
    require(path .. "/main")
    load()
    local player
end

function load()
end

function love.load()
    loadState("map1")
end

The main.lua in the /states/map1/-file:

player = table
local AdvTiledLoader = require("AdvTiledLoader.Loader")
require("camera")

function love.load()
    love.graphics.setBackgroundColor( 198, 220, 255 )
    song1 = love.audio.newSource("sound/Brightly_Fancy.mp3", true)
    song1:setVolume(0.1)
    song1:play()

    imgPlayer = love.graphics.newImage("textures/player.png") 
    AdvTiledLoader.path = "maps/"
    map = AdvTiledLoader.load("map1.tmx") 
    map:setDrawRange(0, 0, map.width * map.tileWidth, map.height * map.tileHeight)

    camera:setBounds(0, 0, map.width * map.tileWidth - love.graphics.getWidth(), map.height * map.tileHeight - love.graphics.getHeight() )

    world =     {
                gravity = 1536,  --1536
                ground = 512,
                }

    player =    {
                x = 256,
                y = 256,
                x_vel = 0,
                y_vel = 0,
                jump_vel = -1024,
                speed = 512, --512
                flySpeed = 700,
                state = "",
                h = 32,
                w = 32,
                standing = false,
                }
    function player:jump()
        if self.standing then
            self.y_vel = self.jump_vel
            self.standing = false
        end
    end

    function player:right()
        self.x_vel = self.speed
    end

    function player:left()
        self.x_vel = -1 * (self.speed)
    end

    function player:stop()
        self.x_vel = 0
    end

    function player:collide(event)
        if event == "floor" then
            self.y_vel = 0
            self.standing = true
        end
        if event == "cieling" then
            self.y_vel = 0
        end
    end

    function player:update(dt)
        local halfX = self.w / 2
        local halfY = self.h / 2

        self.y_vel = self.y_vel + (world.gravity * dt)

        self.x_vel = math.clamp(self.x_vel, -self.speed, self.speed)
        self.y_vel = math.clamp(self.y_vel, -self.flySpeed, self.flySpeed)

        local nextY = self.y + (self.y_vel*dt)
        if self.y_vel < 0 then
            if not (self:isColliding(map, self.x - halfX, nextY - halfY))
                and not (self:isColliding(map, self.x + halfX - 1, nextY - halfY)) then
                self.y = nextY
                self.standing = false
            else
                self.y = nextY + map.tileHeight - ((nextY - halfY) % map.tileHeight)
                self:collide("cieling")
            end
        end
        if self.y_vel > 0 then
            if not (self:isColliding(map, self.x-halfX, nextY + halfY))
                and not(self:isColliding(map, self.x + halfX - 1, nextY + halfY)) then
                    self.y = nextY
                    self.standing = false
            else
                self.y = nextY - ((nextY + halfY) % map.tileHeight)
                self:collide("floor")
            end
        end

        local nextX = self.x + (self.x_vel * dt)
        if self.x_vel > 0 then
            if not(self:isColliding(map, nextX + halfX, self.y - halfY))
                and not(self:isColliding(map, nextX + halfX, self.y + halfY - 1)) then
                self.x = nextX
            else
                self.x = nextX - ((nextX + halfX) % map.tileWidth)
            end
        elseif self.x_vel < 0 then
            if not(self:isColliding(map, nextX - halfX, self.y - halfY))
                and not(self:isColliding(map, nextX - halfX, self.y + halfY - 1)) then
                self.x = nextX
            else
                self.x = nextX + map.tileWidth - ((nextX - halfX) % map.tileWidth)
            end
        end

        self.state = self:getState()
    end

    function player:isColliding(map, x, y)
        local layer = map.tl["Solid"]
        local tileX, tileY = math.floor(x / map.tileWidth), math.floor(y / map.tileHeight)
        local tile = layer.tileData(tileX, tileY)
        return not(tile == nil)
    end

    function player:getState()
        local tempState = ""
        if self.standing then
            if self.x_vel > 0 then
                tempState = "right"
            elseif self.x_vel < 0 then
                tempState = "left"
            else
                tampState = "stand"
            end
        end
        if self.y_vel > 0 then
            tempState = "fall"
        elseif self.y_vel < 0 then
            tempState = "jump"
        end
        return tempState
    end
end

function love.draw()
    camera:set()

    love.graphics.setColor( 255, 255, 255, 255 )
    love.graphics.draw( imgPlayer, player.x - player.w/2, player.y - player.h/2, 0, 1, 1, 0, 0)
    love.graphics.setColor( 255, 255, 255 )
    map:draw()

    camera:unset()
end

function love.update(dt)
    if dt > 0.05 then
        dt = 0.05
    end
    if love.keyboard.isDown("d") then
        player:right()
    end
    if love.keyboard.isDown("a") then
        player:left()
    end
    if love.keyboard.isDown("w") then --and not (hasJumped) then
        player:jump()   
    end

    player:update(dt) 

    camera:setPosition( player.x - (love.graphics.getWidth()/2), player.y - (love.graphics.getHeight()/2))
end

function love.keyreleased(key)
    if (key == "a") or (key == "d") then
        player.x_vel = 0
    end
end

I really dont know what the problem is :/

2
  • 1
    You are going to have to reduce the size of the code base to something more minimal to get good answers on stack overflow. It looks like either the update method is being called before the load is called, or the player is being erased/overwritten between the load and the call. That might be a good place to start investigating. Commented Apr 10, 2015 at 4:08
  • Or it could be the update method does not exist under xpcall. Commented Apr 10, 2015 at 4:12

1 Answer 1

1

Your code is not going to work the way you think it works. You call love.load that then loads map specific file that sets its own love.load and love.update. This overwrites love.load you had before, but that change has no effect as love.load is called only once, so the map-specific initialization you have there is not executed, but map-specific love.update code is executed, but fails as it's missing the initialization part. You need to restructure your code such that you only have one love.load and love.update, but they call map-specific functions as needed. I suggest you look at examples of some love2d games to see how they are organized.

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

Comments

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.