Попытка вызова global (нулевое значение) - PullRequest
0 голосов
/ 16 апреля 2019

Я пытаюсь порождать астероиды в этой игре каждые несколько секунд. Но всякий раз, когда я запускаю игру, я получаю сообщение об ошибке

stack traceback:
      main.lua:277: in function '_listener'
      ?: in function '?'
      ?: in function <?:172>

Я пытался переместить часть кода, но это не помогает. Мой профессор посмотрел на мой код и не знает точно, в чем проблема, но в цикле, который я использую, чего-то не хватает. Вот весь код, который включает в себя «createAsteroid»

РЕДАКТИРОВАТЬ: Я добавил весь мой файл main.lua к этому вопросу. Отдельные файлы, которые у меня есть в этом проекте, это символ и фоновое изображение, все остальное, кроме файла конфигурации, здесь. Я попытался удалить лишнюю end в функции gameLoop, но когда я это сделал, я получил ошибку, которая в основном говорила, что он ожидал end.


display.setStatusBar( display.HiddenStatusBar )

------------------------------
-- RENDER THE SAMPLE CODE UI
------------------------------
local sampleUI = require( "sampleUI.sampleUI" )
local physics = require( "physics" )
physics.start()

math.randomseed( os.time() )

------------------------------
-- CONFIGURE STAGE
------------------------------
local composer = require( "composer" )
local mainScene = display.newGroup()
display.getCurrentStage():insert( mainScene )

----------------------
-- BEGIN SAMPLE CODE
----------------------

-- Frequently used variables
local centerX = display.contentCenterX
local centerY = display.contentCenterY
local originX = display.screenOriginX
local originY = display.screenOriginY
local width = display.actualContentWidth
local height = display.actualContentHeight
local score = 0
local died = false

local asteroidsTable = {}

local player
local gameLoopTimer
local scoreText

local uiGroup = display.newGroup()    -- Display group for UI objects like the score

-- Load background and character from "background.lua" and "character.lua" respectively
local background = require( "background" )
mainScene:insert( background )

local character = require( "character" )
mainScene:insert( character )


local asteroid = display.newImage( "asteroid.png", 180, -50 )
asteroid.rotation = 5

physics.addBody( asteroid, { density=3.0, friction=0.5, bounce=0.3, radius=25 })



-------------------------
-- BEGIN MOVEMENT LOGIC
-------------------------

-- Movement logic variables
local movementSpeed = 1.5
local moving = false
local moveDirection = "down"

-- Sets if the character should move and updates sprite animation
local function setMoving( state )
    moving = state
    if ( moving ) then
        character:play()
    else
        character:pause()
        character:setFrame(2)
    end
end

-- Sets the direction that the player should move and updates the character's sprite facing
local function setMovementDirection( direction )
    -- Don't change anything if we haven't altered direction
    if ( moveDirection == direction ) then
        return
    end

    -- Update the sprite playback
    moveDirection = direction
    character:setSequence( "walk-" .. direction )

    -- Refresh animation playback, which can pause after changing the sprite sequence
    setMoving( moving )
end

-- Set movement magnitudes
local movementX = 0
local movementY = 0
local function setMovement( x, y )
    local updatedMovement = false

    -- Horizontal movement checks
    if ( movementX ~= x and nil ~= x ) then
        movementX = x
        updatedMovement = true
    end


    -- Abort if nothing is updating
    -- We do this since axis/key events can fire multiple times with the same values
    if ( not updatedMovement ) then
        return
    end

    -- Determine movement direction
    if ( 0 ~= movementX or 0 ~= movementY ) then
        -- Favor horizontal animations over vertical ones
        if ( math.abs( movementX ) >= math.abs( movementY ) ) then
            if ( 0 < movementX ) then
                setMovementDirection( "right" )
            else
                setMovementDirection( "left" )
            end
        else
            if ( 0 < movementY ) then
                setMovementDirection( "down" )
            else
                setMovementDirection( "up" )
            end
        end
    end

    -- Update moving animation/variable
    if ( 0 == movementX and 0 == movementY ) then
        setMoving( false )
    else
        setMoving( true )
    end
end

-- Handle character translation on the screen per frame
local function onFrameEnter()
    if ( 0 ~= movementX ) then
        character.x = character.x + ( movementSpeed * movementX )
        setMoving( true )
    end

    if ( 0 ~= movementY ) then
        character.y = character.y + ( movementSpeed * movementY )
        setMoving( true )
    end
end
Runtime:addEventListener( "enterFrame", onFrameEnter )


---------------------------
-- BEGIN INPUT CODE: TOUCH
---------------------------

local padGraphic, padButtonUp, padButtonDown, padButtonLeft, padButtonRight

-- Determine if we have a joystick connected or not
local inputDevices = system.getInputDevices()
local function getHasJoystick()
    for i = 1, #inputDevices do
        if ( "joystick" == inputDevices[i].type ) then
            return true
        end
    end
    return false
end

local hasJoystick = getHasJoystick()

-- If we don't have any controllers found, create a virtual D-pad controller
if ( not hasJoystick ) then

    -- Called when one of the virtual D-pad buttons are used
    local function onTouchEvent( event )
        local phase = event.phase
        local targetID = event.target.id

        if ( "began" == phase or "moved" == phase ) then
            if ( "up" == targetID ) then
                setMovement( 0, -1 )
            elseif ( "down" == targetID ) then
                setMovement( 0, 1 )
            elseif ( "left" == targetID ) then
                setMovement( -1, 0 )
            elseif ( "right" == targetID ) then
                setMovement( 1, 0 )
            elseif ( "padGraphic" == targetID ) then
                setMovement( 0, 0 )
            end

        elseif ( "ended" == phase or "cancelled"  == phase ) then
            -- An alternative to checking for "cancelled" is to set focus on the control
            -- However, we don't want an incoming phone call to bug out input
            if ( "up" == targetID or "down" == targetID ) then
                setMovement( nil, 0 )
            elseif ( "left" == targetID or "right" == targetID ) then
                setMovement( 0, nil )
            end
        end
        return true
    end

-- Display score
scoreText = display.newText( uiGroup, "Score: " .. score, 400, 40, native.systemFont, 36 )

-- Hide the status bar
display.setStatusBar( display.HiddenStatusBar )


local function updateText()
    scoreText.text = "Score: " .. score
end


local function createAsteroid()

    local newAsteroid = display.newImageRect( mainGroup, objectSheet, 1, 102, 85 )
    table.insert( asteroidsTable, newAsteroid )
    physics.addBody( newAsteroid, "dynamic", { radius=25, bounce=0.8 } )
    newAsteroid.myName = "asteroid"

    local whereFrom = math.random( 3 )

    if ( whereFrom == 1 ) then
         -- From the left
        newAsteroid.x = -60
        newAsteroid.y = math.random( 500 )
        newAsteroid:setLinearVelocity( math.random( 40,120 ), math.random( 20,60 ) )
        elseif ( whereFrom == 2 ) then
        -- From the top
        newAsteroid.x = math.random( display.contentWidth )
        newAsteroid.y = -60
        newAsteroid:setLinearVelocity( math.random( -40,40 ), math.random( 40,120 ) )
    elseif ( whereFrom == 3 ) then
        -- From the right
        newAsteroid.x = display.contentWidth + 60
        newAsteroid.y = math.random( 500 )
        newAsteroid:setLinearVelocity( math.random( -120,-40 ), math.random( 20,60 ) )
    end
        newAsteroid:applyTorque( math.random( -6,6 ) )
end

        -- Create the visuals for the on-screen D-pad
    local padSize = 200
    padGraphic = display.newImageRect( mainScene, "pad.png", padSize, padSize )
    padGraphic.x = originX + padSize/2 - 40
    padGraphic.y = height + originY - padSize/2 + 40
    padGraphic.alpha = 0.35
    padGraphic.id = "padGraphic"
    padGraphic:addEventListener( "touch", onTouchEvent )

    -- Creates one of the invisible virtual D-pad buttons
    local function createPadButton( buttonID, offsetX, offsetY )
        local btn = display.newRect( mainScene, padGraphic.x+offsetX, padGraphic.y+offsetY, padSize/5, padSize/5 )
        btn:addEventListener( "touch", onTouchEvent )
        btn.id = buttonID
        btn.isVisible = false
        btn.isHitTestable = true
        return btn
    end

    -- Create buttons for handling the D-pad input
    padButtonUp = createPadButton( "up", 0, padSize/-5 )
    padButtonDown = createPadButton( "down", 0, padSize/5 )
    padButtonLeft = createPadButton( "left", padSize/-5, 0 )
    padButtonRight = createPadButton( "right", padSize/5, 0 )
end

-----------------
--  GAME LOOP  --
-----------------

local function gameLoop()

    -- Create new asteroid
    createAsteroid()

    -- Remove asteroids which have drifted off screen
    for i = #asteroidsTable, 1, -1 do
        local thisAsteroid = asteroidsTable[i]

        if ( thisAsteroid.x < -100 or
             thisAsteroid.x > display.contentWidth + 100 or
             thisAsteroid.y < -100 or
             thisAsteroid.y > display.contentHeight + 100 )
        then
            display.remove( thisAsteroid )
            table.remove( asteroidsTable, i )
        end
        end
end

timer.performWithDelay(1000, gameLoop, 0)

--------------------------------------------------
-- BEGIN INPUT CODE: KEYBOARD & BASIC CONTROLLER
--------------------------------------------------

-- Detect if a joystick axis is being used
local joystickInUse = false

-- Keyboard input configuration
local keyUp = "up"
local keyDown = "down"
local keyLeft = "left"
local keyRight = "right"

-- Called when a key event has been received
local function onKeyEvent( event )
    local keyName = event.keyName
    local phase = event.phase

    -- Handle movement keys events; update movement logic variables
    if ( not joystickInUse ) then
        if ( "down" == phase ) then
            if ( keyUp == keyName ) then
                setMovement( nil, -1 )
            elseif ( keyDown == keyName ) then
                setMovement( nil, 1 )
            elseif ( keyLeft == keyName ) then
                setMovement( -1, nil )
            elseif ( keyRight == keyName ) then
                setMovement( 1, nil )
            end
        elseif ( "up" == phase ) then
            if ( keyUp == keyName ) then
                setMovement( nil, 0 )
            elseif ( keyDown == keyName ) then
                setMovement( nil, 0 )
            elseif ( keyLeft == keyName ) then
                setMovement( 0, nil )
            elseif ( keyRight == keyName ) then
                setMovement( 0, nil )
            end
        end
    end

    return false
end
Runtime:addEventListener( "key", onKeyEvent )


------------------------------------------
-- BEGIN INPUT CODE: ADVANCED CONTROLLER
------------------------------------------

-- We only support advanced controllers when one is detected
if ( getHasJoystick ) then
    -- Detect axis event updates
    local function onAxisEvent( event )
        local value = event.normalizedValue
        local axis = event.axis.type
        local descriptor = event.axis.descriptor

        -- We only care about "x" and "y" input events
        -- However, touch-screen events can fire these as well so we filter them out
        if ( ( "x" ~= axis and "y" ~= axis ) or ( string.find( descriptor, "Joystick" ) == nil ) ) then
            return
        end

        -- Detect zero movement at a certain cutoff so we don't get the character moving very, very slowly
        if ( math.abs(value) < 0.15 ) then
            value = 0
        end

        -- Based on which axis type we are dealing with, set movement variables
        if ( "x" == axis ) then
            setMovement( value, nil )
        elseif ( "y" == axis ) then
            setMovement( nil, value )
        end

        -- Some devices will send both up/down/left/right keys and the axis value
        -- We let our code know that we are using a joystick value so they do not conflict
        if ( 0 ~= value ) then
            joystickInUse = true
        else
            joystickInUse = false
        end
    end
    Runtime:addEventListener( "axis", onAxisEvent )
end

local function onCollision( event )

        if ( ( obj1.myName == "player" and obj2.myName == "asteroid" ) or
                 ( obj1.myName == "asteroid" and obj2.myName == "player" ) )
        then
            display.remove( player )
                else
                    ship.alpha = 0
                    timer.performWithDelay( 1000, restoreShip )
                end
            end

Runtime:addEventListener( "collision", onCollision )

1 Ответ

1 голос
/ 16 апреля 2019

Перейти к строке 277 в вашем файле main.lua

Вы найдете вызов функции createAsteroid().В этой области createAsteroid не определено.

Итак, давайте посмотрим, сможем ли мы найти определение для createAsteroid в этом файле.

Строка 218: local function createAsteroid() ...

Проверьте, находится ли вызов функции в рамках этой функции ...

Нет!Он находится внутри оператора if, а вызов функции находится вне этого оператора.Поскольку createAsteroid является локальным для этого оператора if, оно неизвестно (nil) внутри gameLoop и, следовательно, не может быть вызвано.

Найти такие проблемы с областью может быть очень легко, если у вас есть правильный отступ!

...