Page 1 of 1

Attempt to index global player

Posted: Fri Jun 19, 2020 9:32 pm
by soulgirl2020
I'm building a very basic Zelda 1986 game. I'm trying to get my game to run again after switching to the box2D collision along with the windfield library. Initially, my world was created and tied back to a file name Map.lua. I had to change everything back to main since I want to use windfield along with box2D. My issue is every-time I try to update or render the player.lua file in main, it always returns nill at line 198. Why is this? Also, I am new to love2d.

main.lua

Code: Select all

Class = require 'class'
push = require 'push'

require 'Util'
player =require 'Player'
require 'Enemy1'
wf = require 'windfield_master/windfield'

TILE_EMPTY = -1

-- Tree tiles
TILE_TREE = 4

-- Top wall tiles
TILE_WALL = 2
SECRET_WALL = 6

TILE_HEART = 1

RED_OCTO_1 = 9
RED_OCTO_2 = 10
RED_OCTO_3 = 11
RED_OCTO_4 = 12
RED_OCTO_5 = 13
RED_OCTO_6 = 14
RED_OCTO_7 = 15
RED_OCTO_8 = 16


-- close resolution to NES but 16:9
VIRTUAL_WIDTH = 432
VIRTUAL_HEIGHT = 243

-- actual window resolution
WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720

local SCROLL_SPEED = 65

love.graphics.setDefaultFilter('nearest', 'nearest')

local tileWidth = 16
local tileHeight = 16
local mapWidth = 30
local mapHeight = 28
local xOffset = 8
local yOffset = 10
local tiles = {}


function love.load()

    world = wf.newWorld(0, 0, true)
    
    push:setupScreen(VIRTUAL_WIDTH, VIRTUAL_HEIGHT, WINDOW_WIDTH, WINDOW_HEIGHT, {
        fullscreen = false,
        resizable = true
    })
    
    spritesheet = love.graphics.newImage('hearts_tree_walls.png')
   
    
    -- camera offsets
    camX = 0
    camY = -3

    sprites = generateQuads(spritesheet, 16, 16)
    
    -- cache width and height of map in pixels
    mapWidthPixels = mapWidth * tileWidth
    mapHeightPixels = mapHeight * tileHeight


-- sets a tile at a given x-y coordinate to an integer value

    -- first, fill map with empty tiles
    for y = 1, mapHeight do
        for x = 1, mapWidth do
            
            -- support for multiple sheets per tile; storing tiles as tables 
            setTile(x, y, TILE_EMPTY)
        end
    end
    -- create wall tiles on the bottom of the screen
    for y = mapHeight / 2 + 1, mapHeight / 2 + 1  do
        for x = 0, 25 do
            setTile(x, y, TILE_WALL)
        end
    end
    -- Secret wall
    for y = mapHeight / 2 + 1, mapHeight / 2 + 1  do
        for x = 26, 26 do
            setTile(x, y, SECRET_WALL)
        end
    end
    --left hand side tile
    for y = 0, 25  do
        for x = 1, 1 do
            setTile(x, y, TILE_WALL)
        end
    end
    -- Upper right hand side tiles
    for y = 0, 25  do
        for x = 27, 27 do
            setTile(x, y, TILE_WALL)
        end
    end
    --Top screen tiles
    for y = 1, 1   do
        for x = 0, 26 do
            setTile(x, y, TILE_WALL)
        end
    end
    -- tree top left
    for y = 5, 5   do
        for x = 5, 15 do
            setTile(x, y, TILE_TREE)
        end
    end
    -- tree bottom-left
    for y = 9, 9   do
        for x = 5, 15 do
            setTile(x, y, TILE_TREE)
        end
    end
    -- tree right 
    for y = mapHeight / 2 - 10, mapHeight / 2 - 4   do
        for x = 22, 22 do
            setTile(x, y, TILE_TREE)
        end
    end
    for y = mapHeight / 2 - 12, mapHeight / 2 - 12   do
        for x = 26, 26 do
            setTile(x, y, TILE_HEART)
        end
    end

    love.window.setTitle('Legend of Zelda')

    love.keyboard.keysPressed = {}
    love.keyboard.keysReleased = {}

end

function setTile(x, y, id)
    tiles[(y - 1) * mapWidth + x] = id
end

-- gets the tile type at a given pixel coordinate
function tileAt(x, y)
    return {
        x = math.floor(x / tileWidth) + 1,
        y = math.floor(y / tileHeight) + 1,
        id = getTile(math.floor(x / tileWidth) + 1, math.floor(y / tileHeight) + 1)
    }
end

-- returns an integer value for the tile at a given x-y coordinate
function getTile(x, y)
    return tiles[(y - 1) * mapWidth + x]
end


function love.resize(w,h)
    push:resize(w,h)
end

function love.keyboard.wasReleased(key)
    if (love.keyboard.keysReleased[key]) then
        return true
    else
        return false
    end
end

function love.keypressed(key)
    if key == 'escape' then
        love.event.quit()
    end

    love.keyboard.keysPressed[key] = true
    player.collider:setPosition(0, 0)
        player.collider:setLinearVelocity(0, 0)
end

function love.keyreleased(key)
    love.keyboard.keysReleased[key] = true
end

function love.update(dt)

    if love.keyboard.isDown('w') then
        camY = math.max(0,camY - dt * SCROLL_SPEED)
    elseif love.keyboard.isDown('s') then
        camY = math.min(camY + dt * SCROLL_SPEED, mapHeightPixels - VIRTUAL_HEIGHT)
    end
    world:update(dt)
    player:update(dt)
    enemy1:update(dt)
    enemy2:update(dt)
    enemy3:update(dt)
  
    -- reset all keys pressed and released this frame
    love.keyboard.keysPressed = {}
    love.keyboard.keysReleased = {}
    
end

function love.draw()
    push:apply('start')
    world:draw()
    love.graphics.clear(252/255, 216/255, 169/255, 1)
    local scaleX = -1
    for y = 1, mapHeight do
        for x = 1, mapWidth do
            local tile = getTile(x, y)
            if tile ~= TILE_EMPTY then
                love.graphics.draw(spritesheet, sprites[tile],
                    (x - 1) * tileWidth, (y - 1) * tileHeight)
            end
        end
    end
    player:render()
    enemy:render()
    push:apply('end')
end



Player.lua

Code: Select all

--[[
    Represents our player in the game, with its own sprit
]]

Player = {}
require 'Animation'


local WALKING_SPEED = 140
local MOVE_SPEED = 80

local tileWidth = 16
local tileHeight = 16
local mapWidth = 30
local mapHeight = 28
local xOffset = 8
local yOffset = 10

WALKING_RIGHT_1 = 3
WALKING_RIGHT_2 = 4
WALKING_LEFT_1 = 7
WALKING_LEFT_2 = 8
WALKING_UP_1 = 5
WALKING_UP_2 = 6
WALKING_DOWN_1 = 1
WALKING_DOWN_2 = 2

function Player:init(main)
-- player physics collision 
--player.collider = world:newRectangleCollider(16,16,16,16)
--player.collider:setCollisionClass("player")
    self.width = 16
    player.height = 16

    -- offset refrence point from top left corner to center of sprite for X axis
    player.xOffset = 8
    player.yOffset = 16

    -- offset refrence point from top left corner to center of sprite for Y axis
    player.xOffset2 = 16
    player.yOffset2 = 8

    player.x = tileWidth * 10
    player.y = tileHeight * (mapHeight / 2 - 1) - player.height
    player.dx = 0
    player.dy =0
    player.direction = nil
    player.map = map

    player.currentFrame = nil
   

    player.texture = love.graphics.newImage('Link_movement.png')
    player.frames = {}

    player.state = 'idle_down'
    player.animations = {
        ['idle_right'] = Animation {
            texture = player.texture,
            frames = {
                love.graphics.newQuad(48,0,16,16,player.texture:getDimensions())
            },
            interval = 1
        },
        ['idle_left'] = Animation {
            texture = player.texture,
            frames = {
                love.graphics.newQuad(48,16,16,16,player.texture:getDimensions())
            },
            interval = 1
        },
        ['idle_up'] = Animation {
            texture = player.texture,
            frames = {
                love.graphics.newQuad(0,16,16,16,player.texture:getDimensions())
            },
            interval = 1
        },
        ['idle_down'] = Animation {
            texture = player.texture,
            frames = {
                love.graphics.newQuad(0,0,16,16,player.texture:getDimensions())
            },
            interval = 1
        },
        ['walking_right'] = Animation {
            texture = player.texture,
            frames = {
                --4 and 3
                love.graphics.newQuad(48,0,16,16,player.texture:getDimensions()),
                love.graphics.newQuad(32,0,16,16,player.texture:getDimensions())
            },
            interval = 0.15
        },
        ['walking_left'] = Animation {
            texture = player.texture,
            frames = {
                -- 7 and 8
                love.graphics.newQuad(32,16,16,16,player.texture:getDimensions()),
                love.graphics.newQuad(48,16,16,16,player.texture:getDimensions())
            },
            interval = 0.15
        },
        ['walking_up'] = Animation {
            texture = player.texture,
            frames = {
                --6 and 5
                love.graphics.newQuad(16,16,16,16,player.texture:getDimensions()),
                love.graphics.newQuad(0,16,16,16,player.texture:getDimensions())
            },
            interval = 0.15
        },
        ['walking_down'] = Animation {
            texture = player.texture,
            frames = { 
                -- 2 and 1
                love.graphics.newQuad(16,0,16,16,player.texture:getDimensions()),
                love.graphics.newQuad(0,0,16,16,player.texture:getDimensions())
            },
            interval = 0.15
        },
        ['sword_up'] = Animation {
            texture = player.texture,
            frames = {
                -- 10 and 14
                love.graphics.newQuad(16,64,16,-32,player.texture:getDimensions())
            },
            interval = 1
        },
        ['sword_down'] = Animation {
            texture = player.texture,
            frames = {
                -- 9 adn 13 FLIP FOR UP
                love.graphics.newQuad(0,32,16,32,player.texture:getDimensions())
            },
            interval = 1
        },
        ['sword_left'] = Animation {
            texture = player.texture,
            frames = {
                -- 15,16
                love.graphics.newQuad(32,48,32,16,player.texture:getDimensions())
            },
            interval = 1
        },
        ['sword_right'] = Animation {
            texture = player.texture,
            frames = {
                -- 11 and 12 FLIP FOR LEFT
                love.graphics.newQuad(32,32,32,16,player.texture:getDimensions())
            },
            interval = 1
        }
    }


    player.behaviors = {
        ['idle_down'] = function(dt)
            if love.keyboard.isDown('up') then
                player.y = player.y -MOVE_SPEED * dt
                player.animation = player.animations['walking_up']
                player.state = 'idle_up'
              
            elseif love.keyboard.isDown('down') then
                player.y = player.y + MOVE_SPEED * dt
                player.animation = player.animations['walking_down']
                player.state = 'idle_down'
             
            elseif love.keyboard.isDown('left') then
                player.x = player.x -MOVE_SPEED * dt
                player.animation = player.animations['walking_left']
                player.state = 'idle_left'
               
            elseif love.keyboard.isDown('right') then
                player.x = player.x + MOVE_SPEED * dt
                player.animation = player.animations['walking_right']
                player.state = 'idle_right'
            
            elseif love.keyboard.isDown('space')  then
                player.animation = player.animations['sword_down']
            else
                player.animation = player.animations['idle_down']
            
        end
              
        
        end,

      
        ['idle_up'] = function (dt)
            if love.keyboard.isDown('up') then
                player.y = player.y -MOVE_SPEED * dt
                player.animation = player.animations['walking_up']
                player.state = 'idle_up'
           
        
            elseif love.keyboard.isDown('down') then
                player.y = player.y + MOVE_SPEED * dt
                player.animation = player.animations['walking_down']
                player.state = 'idle_down'
              
            
            elseif love.keyboard.isDown('left') then
                player.x = player.x -MOVE_SPEED * dt
                player.animation = player.animations['walking_left']
                player.state = 'idle_left'
            
           
            elseif love.keyboard.isDown('right') then
                player.x = player.x + MOVE_SPEED * dt
                player.animation = player.animations['walking_right']
                player.state = 'idle_right'
               

            elseif love.keyboard.isDown('space')  then
                player.direction = 'up'
                player.animation = player.animations['sword_down']
            else
              
                player.animation = player.animations['idle_up']
            end

        end,

        ['idle_right'] = function (dt)
            if love.keyboard.isDown('up') then
                player.y = player.y -MOVE_SPEED * dt
                player.animation = player.animations['walking_up']
                player.state = 'idle_up'
               
            elseif love.keyboard.isDown('down') then
                player.y = player.y + MOVE_SPEED * dt
                player.animation = player.animations['walking_down']
                player.state = 'idle_down'
                
            elseif love.keyboard.isDown('left') then
                player.x = player.x -MOVE_SPEED * dt
                player.animation = player.animations['walking_left']
                player.state = 'idle_left'
               
            elseif love.keyboard.isDown('right') then
                player.x = player.x + MOVE_SPEED * dt
                player.animation = player.animations['walking_right']
                player.state = 'idle_right'
            
            elseif love.keyboard.isDown('space')  then
            
                player.animation = player.animations['sword_right']
            
            else
                player.animation = player.animations['idle_right']
            end
              
                
                        
        end,

            ['idle_left'] = function (dt)
                if love.keyboard.isDown('up') then
                    player.y = player.y -MOVE_SPEED * dt
                    player.animation = player.animations['walking_up']
                    player.state = 'idle_up'
              
                elseif love.keyboard.isDown('down') then
                    player.y = player.y + MOVE_SPEED * dt
                    player.animation = player.animations['walking_down']
                    player.state = 'idle_down'
                
                elseif love.keyboard.isDown('left') then
                    player.x = player.x -MOVE_SPEED * dt
                    player.animation = player.animations['walking_left']
                    player.state = 'idle_left'
                  
                elseif love.keyboard.isDown('right') then
                    player.x = player.x + MOVE_SPEED * dt
                    player.animation = player.animations['walking_right']
                    player.state = 'idle_right'
                 
                elseif love.keyboard.isDown('space')  then
                    player.direction = 'left'
                    player.animation = player.animations['sword_right']      
                else
                    player.animation = player.animations['idle_left']
                end
                 
        end
    }
    

    function Player:update(dt)
        -- Update behaviors, animations, and frames
        player.behaviors[player.state](dt)
        player.animation:update(dt) 
        player.currentFrame = player.animation:getCurrentFrame() 
       
    end

    function Player:render()
        -- Define scale variables
        local scaleX 
        local scaleY 

        -- If space is pressed and the state is left then it will take that current frame (sword_right) and flip it horizontally
        -- This was done since everything is drawn to its upper left corner and to keep consistency 
        if love.keyboard.isDown('space') and player.state == 'idle_left' then
            --Flips 180 degrees
            scaleX = -1
        else
            -- No flip
            scaleX = 1
        end
        -- If space is pressed and the state is up then it will take that current frame and flip it vertically
        if love.keyboard.isDown('space') and player.state == 'idle_up' then
            scaleY = -1
        else
            scaleY = 1
        end

        -- Change reference point from top left corner to the center so it can flip within the same position for both x and y axis flips
        if love.keyboard.isDown('space') and player.state == 'idle_left' then
            love.graphics.draw(player.texture, player.currentFrame, math.floor(player.x + player.xOffset),math.floor(player.y + player.yOffset),
            0,scaleX,1,player.xOffset,player.yOffset)

        elseif love.keyboard.isDown('space') and player.state == 'idle_up' then
            love.graphics.draw(player.texture, player.currentFrame, math.floor(player.x + player.xOffset2),math.floor(player.y + player.yOffset2),
            0,1,scaleY,player.xOffset2,player.yOffset2)
        else
            -- If the first two conditions does not appy, just render the current frames without any scaling or rotation
            love.graphics.draw(player.texture, player.currentFrame, math.floor(player.x),math.floor(player.y)) 
        end
    end
end

Re: Attempt to index global player

Posted: Fri Jun 19, 2020 10:14 pm
by Jeeper
You make a table named "Player", with a capital P. But then in most of the code you type "player.variable" with a lowercase p. Though I would recommend sticking to using "self" as you do when you declare the player width.

Re: Attempt to index global player

Posted: Sun Jun 21, 2020 5:57 pm
by soulgirl2020
Thanks for catching that, I switched back to using the "Class" library using self, which makes things much easier. Everything works now.