Attempt to index global player
Posted: Fri Jun 19, 2020 9:32 pm
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
Player.lua
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