简体   繁体   English

Lua错误“尝试调用方法”(nil值)

[英]Lua Error "Attempt to call method '' (a nil Value)

I wanted to make a 2D-Platformer (with the Love2D-Framework) and have a main.lua-file select random maps from a states folder. 我想制作一个2D平台(带有Love2D-Framework),并有一个main.lua文件从状态文件夹中选择随机映射。 To start with that, i just said that the main-main.lua should open the main.lua-file in /states/map1/. 首先,我只是说main-main.lua应该在/ states / map1 /中打开main.lua文件。 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) States / map1 / main.lua:169:尝试调用方法“ update”(一个nil值)

Traceback 追溯

states/map1/main.lua:169: in function 'update' [C]: in function 'xpcall' States / map1 / main.lua:169:在函数“ update”中[C]:在函数“ xpcall”中

The main-main.lua-code: main-main.lua代码:

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: / states / map1 /-文件中的main.lua:

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 :/ 我真的不知道问题出在哪里:/

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 . 您调用love.load ,然后加载设置其自己的love.loadlove.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. 这将覆盖您之前的love.load ,但是该更改没有效果,因为love.load仅被调用一次,因此您所拥有的地图特定的初始化不会执行,但是地图特定的love.update代码执行,但是失败因为它缺少初始化部分。 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. 您需要重组代码,以便只有一个love.loadlove.update ,但是它们会根据需要调用特定于地图的函数。 I suggest you look at examples of some love2d games to see how they are organized. 我建议您看一些love2d游戏的示例,以了解它们的组织方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM