Error: attempt to index global 'playerBul' (a nil value) - lua

The error is saying:
game.lua:171: attempt to index global 'playerBul' (a nil value)
Sorry if I put too much unnecessary code, I just do not know what is causing this error.
here are all the files for this game:
menu.lua:
local menu = {}
local bannermenu;
local selection;
menu.name = 'Menu'
local function play()
mode = require('game')
mode.load()
end
local options = {
{['text'] = 'Play', ['action'] = play},
{['text'] = 'Exit', ['action'] = love.event.quit}
}
function menu.load()
bannermenu = love.graphics.newImage(BANNER)
selection = 1
pointer = love.graphics.newImage(POINTER)
mode = menu
end
function menu.update()
return mode
end
function menu.draw()
love.graphics.draw(bannermenu, 200,10)
for i = 1,#options do
if i == selection then
love.graphics.draw(pointer, 300, 200 + i *20)
end
love.graphics.printf(options[i].text,0,200 + i * 20, love.graphics.getWidth(), 'center')
end
end
function menu.keypressed(key)
if key == "up" then
selection = (selection - 2)%(#options) + 1
elseif key == "down" then
selection = (selection) % (#options) + 1
elseif key == "return" then
options[selection].action()
elseif key == "escape" then
love.event.quit()
end
end
return menu
main.lua
TITLE = 'Die Aliens Die!'
PLAYER_BULLET = 'Images/playerbullet.png'
ENEMY_BULLET = 'Images/enemybullet.png'
HEALTH_IMG = 'Images/life.png'
ENEMY_UFO = {
ENEMY_1 = 'Images/enemy1.png',
ENEMY_2 = 'Images/enemy2.png',
ENEMY_3 = 'Images/enemy3.png'
}
PLAYER_IMG = 'Images/spaceship.png'
YOU_WIN = 'Images/win.png'
BANNER = 'Images/banner.png'
POINTER = 'Images/pointer.png'
function love.load()
love.window.setTitle(TITLE)
mode = require "menu"
mode.load()
end
function love.draw()
mode.draw()
end
function love.keypressed(key, isrepeat)
mode.keypressed(key)
end
function love.update(dt)
mode.update(dt)
end
game.lua
local game = {}
local playerShip = {}
local alienUFO = {}
local bullets = {}
local alienBullets = {}
local playerBullets = {}
local aliens = {{},{},{},{},{},{},{},{},{},{}}
local health = 3
local score = 0
local level = 1
local alienMovement = true
local healthImage;
local alienQty = 0
local pause
--local function gameOver()
--local function gamwWin()
local function clearTable(t)
for i = #t,1,-1 do
table.remove(t,i)
end
end
local function clearAliens()
for i=#aliens,1,-1 do
for j = #aliens[i],1,-1 do
table.remove(aliens[i],j)
end
end
end
local function insertAliens()
alienQty = 0
for i=1,4 do
for j =1,10 do
local alien = {}
alien.x = (j-1) *alienUFO.width + 10
alien.y = (j-1) *alienUFO.width + 35
if level ==2 then
alien.life = 2
if level == 3 then
alien.life = 3
end
table.insert(aliens[j], alien)
alienQty = alienQty + 1
end
end
end
end
local function initGame()
clearTable(playerBullets)
clearTable(alienBullets)
clearAliens()
insertAliens()
playerShip.x = love.graphics.getWidth() / 2 - playerShip.width /2
end
local function playerShoot()
local bullet = {}
playerShip.x = playerShip.x + 32
playerShip.y = playerShip.y + 10
table.insert(playerBullets, bullet)
end
local function AlienShoot(x,y)
local bullet = {}
bullet.x = alienUFO.width/2
bullet.y = y -5
table.insert(alienBullets, bullet)
end
local function playerShots(dt)
if next(playerBullets) ~= nil then
for i = #playerBullets,1,-1 do
playerBullets[i].y = playerBullets[i].y - dt* playerBullets.bulletSpeed
if playerBullets[i].y < 0 then
table.remove(playerBullets,i)
else
for j = #aliens, 1,-1 do
for k = #aliens[j],1,-1 do
if next(playerBullets) ~= nil and playerBullets[i] ~= nil and
aliens[j][k].x <= playerBullets[i].x and aliens[j] [k].x + 50 >= playerBullets[i].x
and aliens[j][k].y <= playerBullets[i].y and aliens[j] [k].y + 47 >= playerBullets[i].y then
table.remove(playerBullets, i)
if level == 2 and aliens[j][k].life > 0 then
aliens[j][k].life = aliens[j][k].life - 1
if level == 3 and aliens[j][k].life > 0 then
aliens[j][k].life = aliens[j][k].life - 1
else
table.remove(aliens[j], k)
alienQty = alienQty - 1
score = score + 100
end
break
end
end
end
end
end
end
end
local function PlayerShot()
health = health - 1
if health == 0 then
love.event.quit() -- COME BACK HERE FOR LOSE
end
end
local function AlienShots(dt)
if next(alienBullets) ~= nil then
for i = #alienBullets,1,-1 do
alienBullets[i].y = alienBullets[i].y + dt * alienUFO.bulletSpeed
if alienBullets[i].y > love.graphics.getHeight() then
table.remove(alienBullets, i)
elseif playerShip.x <= alienBullets[i].x and playerShip.x + playerShip.width >= alienBullets[i].x
and playerShip.y <= alienBullets[i].y and playerShip.y + playerShip.height >- alienBullets[i].y then
table.remove(alienBullets, i)
PlayerShot()
end
end
end
end
local function nextLVL()
level = level + 1
if level == 2 then
alienUFO.image = love.graphics.newImage(alienUFO.ENEMY1)
alienUFO.speed = 100
alienUFO.shotProb = 20
alienUFO.bullet = alienBul.image
initGame()
elseif level == 3 then
alienUFO.image = love.graphics.newImage(alienUFO.ENEMY2)
initGame()
elseif level > 3 then
love.event.quit() -- COME BACK HERE FOR WIN
end
end
function game.load()
pause = false
level = 1
health = 3
score = 0
playerShip.speed = 300
playerShip.bulletSpeed = 300
playerShip.width = 75
playerShip.height = 71
alienUFO.speed = 70
alienUFO.width = 50
alienUFO.height = 47
alienUFO.ENEMY1 = ENEMY_UFO.ENEMY_1
alienUFO.ENEMY2 = ENEMY_UFO.ENEMY_2
alienUFO.ENEMY3 = ENEMY_UFO.ENEMY_3
alienUFO.bulletSpeed = 300
alienUFO.image = love.graphics.newImage(alienUFO.ENEMY3)
playerShip.IMAGE = PLAYER_IMG
playerShip.image = love.graphics.newImage(playerShip.IMAGE)
healthImage = love.graphics.newImage(HEALTH_IMG)
playerShip.x = love.graphics.getWidth() / 2 - playerShip.width/2
playerShip.y = love.graphics.getHeight() - 100
playerBul.image = love.graphics.newImage(PLAYER_BULLET)
alienBul.image = love.graphics.newImage(ENEMY_BULLET)
initGame()
end
function game.draw()
if pause then
love.graphics.print('GAME PAUSED',love.graphics.getWidth()/2 - 20,20)
end
if next(playerBullets) ~= nil then
for i = 1, #playerBullets do
love.graphics.draw(playerBul.image, playerBullets[i].x, playerBullets[i].y)
end
end
if next(alienBullets) ~= nil then
for i = 1, #alienBullets do
love.graphics.draw(alienBul.image, alienBullets[i].x, alienBullets[i].y)
end
end
if next(aliens) ~= nil then
for i = 1, #aliens do
for j = 1, #aliens[i] do
love.graphics.draw(alienUFO.image, aliens[i][j].x, aliens[i][j].y)
end
end
end
love.graphics.print('Score: '..score, love.graphics.getWidth() - 100,20)
love.graphics.draw(playership.image, playership.x, playerShip.y)
for i = 1, lives do
love.graphics.draw(healthImage, 10+ 1 * 15,20)
end
end
function game.update(dt)
if not pause then
if alienQty == 0 then
nextLVL()
end
if love.keyboard.isDown("right") then
playerShip.x = playerShip.x + dt * playerShip.speed
elseif love.keyboard.isDown("left") then
playerShip.x = playerShip.x - dt * playerShip.speed
end
if love.keyboard.isDown(" ") then
playerShoot()
end
playerShots(dt)
AlienShots(dt)
if love.math.random(1,100) < alienUFO.shotProb then
local r = love.math.random(1,#aliens)
if next(aliens[r]) ~= nil then
alienShoot(aliens[r][#aliens[r]].x, aliens[r][#aliens[r]].y)
end
end
if alienMovement then
for i = 1, #aliens do
for j = 1, #aliens[i] do
aliens[i][j].x = aliens[i][j].x + dt * alienUFO.speed
if aliens[i][j].x + alienUFO.width + 2 >= love.graphics.getWidth() then
alienMovement = false
end
end
end
else
for i =1, #aliens do
for j = 1, #aliens[i] do
aliens[i][j].x = aliens[i][j].x - dt * alienUFO.speed
if aliens[i][j].x - 2 <= 0 then
alienMovement = true
end
end
end
end
if playerShip.x < 0 then
playerShip.x = 0
elseif playerShip.x > love.graphics.getWidth() - 75 then
playerShip.x = love.graphics.getWidth() -75
end
end
end
end
function game.keypressed(key)
if key =='p' then
pause = not pause
end
end
return game

you haven't defined a load function on the game table you return in game.lua. it looks like you already wrote the load logic but wrote it as a local function named loadGame. to fix your issue update game.lua to export the load function and just have it call the load function you've already created, like this:
function game.load()
loadGame()
end
somewhere before you return the game table in game.lua, say after your definition of game.keypressed
or you could alternatively just change local function loadGame() to function game.load() to remove the local function and redefine it as exported functionality

Related

Cannot change the boolean in table lua love2d

I am creating a simple platformer with love2d in lua.
I want the player to stand on the ground so that it won't fall.
However I got some proablem that I cannot change the string of a table return from player.lua
(It is a table because the player.lua return m and the last sentance, and m is a table)
I tested that the isOnFloor function is work, but I just can't change the boolean in the player table.
Main.lua
local love = require("love")
local tileMapper = require("tile/tileMapper")
local player = require "player"
local isOnFloor = require("isOnFloor")
function love.load()
love.window.setMode(1080, 640)
love.window.setTitle("Simple Platformer")
tileMapper:spawn()
tiles = tileMapper.tiles
player:setValue()
love.keyboard.keyPressed = {}
end
function love.update(dt)
for i = 1, #tiles do
if isOnFloor(player.x, player.y, tiles[i].x, tiles[i].y, 32, 32 * 3, 72, 72) then
player.currentState = "ground" -- I wanna change it here but when I go back to
--player.lua and try to let it out put the self.currentState, nothing changed --
else
player.currentState = "air"
end
end
player:update(dt)
love.keyboard.keyPressed = {}
end
I try to print out the player.currentState the the line after I set the player.currentState = "ground". It printed out "ground"
But if I print it in player.lua, it is always "air"
player.lua(I didn't paste some of the code here)
m = {}
function m:setValue()
self.x = 400
self.y = 50
self.vtx = 0
self.y_input = 0
self.speed = 300
self.jumpForce = -800
self.gravity = 100
self.anim = {idle = {img = love.graphics.newImage("assets/Idle.png"), maxFrame = 10},
run = {img = love.graphics.newImage("assets/Run.png"), maxFrame = 11},
jump = {img = love.graphics.newImage("assets/Jump.png"), maxFrame = 0},
fall = {img = love.graphics.newImage("assets/Fall.png"), maxFrame = 0}}
self.currentAnim = nil
for i = 1, #self.anim do
self.anim[i]:setFilter("nearest", "nearest")
end
self.frame = 0
self.timer = 0
self.currentState = nil
end
function m:update(dt)
print(self.currentState)
---------------------- Player States Update ------------------------
self:getXInput()
if self.currentState == "ground" then
if self.vtx == 0 then
self.currentAnim = self.anim.idle
elseif not(self.vtx == 0) then
self.currentAnim = self.anim.run
end
elseif self.currentState == "air" then
self.y_input = self.y_input + self.gravity
if self.y_input > 0 then
self.currentAnim = self.anim.fall
elseif self.y_input < 0 then
self.currentAnim = self.anim.jump
end
end
------------------------ Anim --------------------
self:animUpdate(dt)
if love.keyboard.keyPressed["space"] == true then
self.y_input = self.jumpForce
end
self.x = self.x + self.speed * dt * self.vtx
self.y = self.y + self.y_input * dt
end
return m
If you have an idea of this porblem, please tell, thank you.

How to add more than one variable

function CountCops()
local xPlayers = ESX.GetPlayers()
CopsConnected = 0
for i=1, #xPlayers, 1 do
local xPlayer = ESX.GetPlayerFromId(xPlayers[i])
if xPlayer.job.name == 'police' then
CopsConnected = CopsConnected + 1
end
end
SetTimeout(120 * 1000, CountCops)
end
Does anyone know how would I have both if xPlayer.job.name == 'police' or xPlayer.job.name == 'sheriff' read for = 1 cop for each person.
So if one police was on then it = 1
and if one sheriff was on it would = 2.
local countingJobs = {
['police'] = true,
['sheriff'] = true
};
function CountCops()
local xPlayers = ESX.GetPlayers()
CopsConnected = 0
for i=1, #xPlayers, 1 do
local xPlayer = ESX.GetPlayerFromId(xPlayers[i])
if countingJobs[xPlayer.job.name] then
CopsConnected = CopsConnected + 1
end
end
SetTimeout(120 * 1000, CountCops)
end

Check Winner Naughts and Crosses game - Lua/Corona

I am quite new to the Lua language and am trying to create a simple Tic Tac Toe game. I am having difficulties figuring out how to check the winner. I have tried if-then statements but I think I am using them wrong. Not sure what the best way to check the winner is so any suggestions or assistance is greatly appreciated.
The code is -
local composer = require( "composer" )
local scene = composer.newScene()
d = display
w20 = d.contentWidth * .2
h20 = d.contentHeight * .2
w40 = d.contentWidth * .4
h40 = d.contentHeight * .4
w60 = d.contentWidth * .6
h60 = d.contentHeight * .6
w80 = d.contentWidth * .8
h80 = d.contentHeight * .8
----DRAW LINES FOR BOARD
local lline = d.newLine(w40,h20,w40,h80 )
lline.strokeWidth = 5
local rline = d.newLine(w60,h20,w60,h80 )
rline.strokeWidth = 5
local bline = d.newLine(w20,h40,w80,h40 )
bline.strokeWidth = 5
local tline = d.newLine(w20,h60,w80,h60 )
tline.strokeWidth = 5
--PLACE BOARD COMPARTMENT DIMENSIONS IN TABLE
board ={
{"tl",1,w20,h40,w40,h20,0},
{"tm",2,w40,h40,w60,h20,0},
{"tr",3,w60,h40,w80,h20,0},
{"ml",4,w20,h60,w40,h40,0},
{"mm",5,w40,h60,w60,h40,0},
{"mr",6,w60,h60,w80,h40,0},
{"bl",7,w20,h80,w40,h60,0},
{"bm",8,w40,h80,w60,h60,0},
{"br",9,w60,h80,w80,h60,0}
}
--
local EMPTY, X, O = 0, 1, 2
local whichTurn = 0
--FILL COMPARTMENT W/ COLOUR WHEN TOUCHED
local function fill(event)
if (event.phase == "ended") then
for t = 1,9 do
if event.x > board[t][3] and event.x < board[t][5] then
if event.y < board[t][4] and event.y > board[t][6] then
if board[t][7] == EMPTY then
if whichTurn == 1 then
whichTurn = 2
else
whichTurn = 1
end
board[t][7] = whichTurn
if board[t][7] == 1 then
local xText = display.newText("X", board[t][3], board[t][4], "Arial", 80)
xText.anchorX = 0
xText.anchorY = 100
elseif board[t][7] == 2 then
local oText = display.newText("O", board[t][3], board[t][4], "Arial", 80)
oText.anchorX = 0
oText.anchorY = 100
end
end
end
end
end
end
local function checkWinner()
for i = 1,9 do
if board[i][2] == 1 and board[i][7] == 1 then
boxOne = "x"
end
if board[i][2] == 2 and board[i][7] == 1 then
boxTwo = "x"
end
if board[i][2] == 3 and board[i][7] == 1 then
boxThree = "x"
end
if boxOne == "x" and boxTwo == "x" and boxThree == "x" then
display.newText("Winner", 10, 100, "Arial", 200)
end
end
end
end
Runtime:addEventListener ("touch", fill)
return scene
local All_Lines = {{1,5,9}, {3,5,7}, {1,2,3}, {4,5,6}, {7,8,9}, {1,4,7}, {2,5,8}, {3,6,9}}
local function checkWinner()
for _, Line in ipairs(All_Lines) do
local values = 0
for _, idx in ipairs(Line) do
values = values * 10 + board[idx][7]
end
if values == 111 then
display.newText("Winner", 10, 100, "Arial", 200)
return
elseif values == 222 then
display.newText("Loser", 10, 100, "Arial", 200)
return
end
end
end

Corona SDK / Lua : An table's property is nil, when accessed via event.other during collision event. But why?

So I have this module, where all of its activity during the game is in. In t.physics I add a collision event listener (differentiating if target is a group or a single object). When the concerning objects detect a collision though, the property col of the other object (event.other) seems to be nil, although I initially set it to a string representing a color in t.create. I just can't find the cause for that, can anyone?
Thanks for your help.
Greetings, Nils
local fence = require("lib.fence")
local physics = require("physics")
local t = {}
local stages = {yellow = 1, lila = 1, red = 1}
local sizes = {1, 3.625, 7.25}
t.colors = {"yellow", "lila", "red"}
t.growing = false
t.setSize = function(fill)
local tHeight = fill.contentHeight * sizes[stages[fill.col]]
local tScale = tHeight / fill.contentHeight
fill.yScale = tScale
end
t.grow = function(group, color, hero)
local counter = 0
stages[color] = stages[color] + 1
for i = 1, group.numChildren, 1 do
if group[i].col == color then
counter = counter + 1
local function newPhysics() t.physics(group) end
if counter == 1 then
local function reset() t.growing = false if stages[color] == 3 then stages[color] = 1; newPhysics(); end end
local function start() t.growing = true end
transition.to(group[i], {time = 260, yScale = sizes[stages[color]], onStart = start, onComplete = reset})
else
transition.to(group[i], {time = 250, yScale = sizes[stages[color]], onStart = start})
end
end
end
end
t.physics = function(target)
if target.numChildren == nil then
physics.removeBody(target)
local function add()
physics.addBody( target, "static", {isSensor = true} )
target.collision = function(self, event)
if event.phase == "began" then
target.count = target.count + 1
if target.count == 1 then
t.grow(target.parent, self.col, event.other)
end
elseif event.phase == "ended" then
target.count = 0
end
end
end
timer.performWithDelay(1, add, 1)
else
for i = 1, target.numChildren, 1 do
physics.removeBody( target[i] )
physics.addBody( target[i], "static", {isSensor = true} )
target[i].name = "fill"
local fill = target[i]
fill.count = 0
fill.collision = function(self, event)
if event.phase == "began" then
self.count = self.count + 1
if self.count == 1 and event.other.x ~= nil then
t.grow(target, self.col, event.other)
end
else
fill.count = 0
end
end
fill:addEventListener("collision")
end
end
end
t.setColor = function(fill)
local colors = {
{238 / 255, 228 / 255, 28 / 255},
{38 / 255, 33 / 255, 77 / 255},
{175 / 255, 24 / 255, 52 / 255},
}
local names = {"yellow", "lila", "red"}
local r = math.random(3)
fill.fill = colors[r]
fill.col = names[r]
end
t.create = function(fences, group, colors)
local fills = {}
for i = 1, #fences, 1 do
local rCol = math.random(3)
local col
if rCol == 1 then
col = colors.yellow
elseif rCol == 2 then
col = colors.lila
else
col = colors.red
end
fills[i] = display.newRect(
group, fences[i].x + fences[i].contentWidth * 0.125, fences[i].y,
fences[i].contentWidth * 0.9, (fences[i].contentHeight * 0.5 / 3)
)
fills[i].dPosX = fills[i].x
fills[i].y = display.contentHeight- fills[i].contentHeight / 2
fills[i].fill = col
fills[i].col = t.colors[rCol]
fills[i].increased = false
end
return fills
end
t.move = function(fills, fences, group)
for i = 1, #fills, 1 do
local fill = fills[i]
function fill:enterFrame()
self:translate(fence.speed, 0)
if t.growing == false then
t.setSize(self)
end
if self.x > display.contentWidth + 0.55 * fences[i].contentWidth then
local xT = {}
for i = 1, group.numChildren, 1 do
xT[i] = group[i].x
end
local function compare(a, b) return a < b end
table.sort(xT, compare)
self.x = xT[1] - fences[i].contentWidth * 0.98
t.setColor(self)
local function newPhysics() t.physics(self) end
timer.performWithDelay( 25, newPhysics, 1 )
self:toBack()
end
end
Runtime:addEventListener("enterFrame", fill)
end
end
return t
Solved. Ugh, sorry, I forgot to define the property on the other object involved (hero), that has its own module. What a stupid slip.
Thanks for your answers anyways!
You don't seem to have any dynamic bodies here. What is colliding with what? Could it be that the other object involved in the collision (the value of event.other) is not something initialized in t.create() and so doesn't have the col property?
From the Corona documentation on Collision Detection:
Some body types will — or will not — collide with other body types. In a collision between two physical objects, at least one of the objects must be dynamic, since this is the only body type which collides with any other type.
Also, in your fill.collision(), I think you want to pass event.target as the first argument to t.grow() rather than target. If you try things, please update the question with more information.

bad argument #1 to 'pairs' (table expected, got nil)

So I'm trying to program a space invaders like game in lua using löve2d, the first wave of enemies runs smoothly but once i try adding another wave to the levelctrl table i get this error: bad argument #1 to 'pairs' (table expected, got nil) on line 235 (even when i populate a second table)
function love.load()
hero = {}
hero.x = 400 - 16
hero.y = 450
hero.speedx = 300
hero.speedy = 50
hero.shots = {}
bgx = 0
bgs = .25
fleet1 = {}
f1x = 0
f1f = 0
lost = 0
score = 0
game = 0
menu = 1
startup = 1
--Images
bg = love.graphics.newImage("img/space.png")
bullet = love.graphics.newImage("img/shot.png")
player = love.graphics.newImage("img/player.png")
trail = love.graphics.newImage("img/trail.png")
ship1 = love.graphics.newImage("img/enemy1.png")
looser = love.graphics.newImage("img/looser.png")
boomp1 = love.graphics.newImage("img/boomp1.png")
boomp2 = love.graphics.newImage("img/boomp2.png")
boomp3 = love.graphics.newImage("img/boomp3.png")
boomp4 = love.graphics.newImage("img/boomp4.png")
boom1 = love.graphics.newImage("img/boom1.png")
boom2 = love.graphics.newImage("img/boom2.png")
boom3 = love.graphics.newImage("img/boom3.png")
boom4 = love.graphics.newImage("img/boom4.png")
winner = love.graphics.newImage("img/winner.png")
title = love.graphics.newImage("img/title.png")
message = love.graphics.newImage("img/message.png")
restart = love.graphics.newImage("img/restart.png")
icon = love.graphics.newImage("img/icon.gif")
boomtimer=0
isdead=0
boom={}
bgs = .25
bgx = 0
menublink = 0
menuf = 0
end
function love.update(dt)
if bgx < 600 then
bgx = bgx + bgs
else
bgx = -599
end
if bgs > .30 then
bgs = bgs - 2*dt
end
if menublink < 48 and menuf==0 then
menublink = menublink + 1
else
menuf=1
menublink = menublink -1
if menublink == 0 then
menuf=0
end
end
if menu == 1 then
hero = {}
hero.x = 400 - 16
hero.y = 450
hero.speedx = 300
hero.speedy = 50
hero.shots = {}
f1x = 0
f1f = 0
lost = 0
score = 0
boomtimer=0
isdead=0
won=0
boom={}
fleet1 = {}
for i=0,7 do
enemy = {}
enemy.width = 32
enemy.height = 16
enemy.img = ship1
enemy.x = i * (enemy.width + 64) + 48
if i<4 then
if i % 2 == 0 then
enemy.y = 0 - enemy.height
else
enemy.y = -16 - enemy.height
end
else
if i % 2 == 0 then
enemy.y = -16 - enemy.height
else
enemy.y = 0 - enemy.height
end
end
table.insert(fleet1, enemy)
end
boss = {}
level = 1
levelctrl = {}
table.insert(levelctrl, fleet1)
if love.keyboard.isDown(" ") then
menu = 0
game = 1
end
elseif game == 1 then
if isdead==0 then
if love.keyboard.isDown("left") then
if hero.x > 0 then
hero.x = hero.x - hero.speedx*dt
end
elseif love.keyboard.isDown("right") then
if hero.x < 800-32 then
hero.x = hero.x + hero.speedx*dt
end
end
if love.keyboard.isDown("up") then
if hero.y > 300 then
hero.y = hero.y - hero.speedy*dt
up=1
else
up=0
end
if bgs < 4 then
bgs = bgs + 5*dt
end
elseif love.keyboard.isDown("down") then
if hero.y < 600-64 then
hero.y = hero.y + hero.speedy*2*dt
end
else
up=0
end
end
for i,v in ipairs(hero.shots) do
v.y = v.y - dt * 300
end
if won == 0 then
local remShot = {}
local remEnemy = {}
for i,v in ipairs(hero.shots) do
if v.y < 0 then
table.insert(remShot, i)
end
for ii,vv in ipairs(levelctrl[1]) do
if CheckCollision(v.x,v.y,32,32,vv.x,vv.y,vv.width,vv.height) then
x = {}
x.x = vv.x
x.y = vv.y
x.t = 0
table.insert(boom, x)
table.insert(remEnemy, ii)
table.insert(remShot, i)
end
end
end
for i,v in ipairs(levelctrl[1]) do
if CheckCollision(hero.x,hero.y,32,64,v.x,v.y,v.width,v.height) then
lost = 1
end
end
for i,v in ipairs(remShot) do
table.remove(hero.shots, v)
end
for i,v in ipairs(remEnemy) do
table.remove(levelctrl[1], v)
score = score + 1
end
if level == 1 then
for i,v in ipairs(levelctrl[1]) do
v.y = v.y + dt * 12
if v.y > 512 then
lost = 1
end
if v.x>0 and v.x < 768 then
if f1f == 0 then
if f1x<3 then
f1x = f1x + 1 * dt
v.x = v.x + 1
else
f1f = 1
end
else
if f1x>-3 then
f1x = f1x - 1 * dt
v.x = v.x - 1
else
f1f = 0
end
end
end
end
end
end
if empty(levelctrl[1]) == true and won == 0 then
level = level + 1
table.remove(levelctrl, 1)
if remEnemy ~= nil then
for k in pairs (remEnemy) do
remEnemy[k] = nil
end
end
end
if won == 1 and love.keyboard.isDown("return") then
menu = 1
game = 0
elseif lost == 1 and love.keyboard.isDown("return") then
menu = 1
game = 0
end
end
end
function love.draw()
love.graphics.setIcon(icon)
love.graphics.setColor(255,255,255,255)
love.graphics.draw(bg, 0, bgx)
love.graphics.draw(bg, 0, bgx-1199)
if menu == 1 then
love.graphics.draw(title)
if menuf == 1 then
love.graphics.draw(message)
end
elseif game == 1 then
for i,v in ipairs(hero.shots) do
love.graphics.draw(bullet, v.x, v.y)
end
if up==1 then
love.graphics.draw(trail, hero.x, hero.y)
end
for i,v in ipairs(levelctrl[1]) do
love.graphics.draw(v.img, v.x, v.y)
end
if lost == 0 then
love.graphics.draw(player, hero.x, hero.y)
else
isdead=1
if boomtimer<8 then
love.graphics.draw(boomp1, hero.x-16, hero.y)
boomtimer = boomtimer + 1
elseif boomtimer<16 then
love.graphics.draw(boomp2, hero.x-16, hero.y)
boomtimer = boomtimer + 1
elseif boomtimer<24 then
love.graphics.draw(boomp3, hero.x-16, hero.y)
boomtimer = boomtimer + 1
elseif boomtimer<32 then
love.graphics.draw(boomp4, hero.x-16, hero.y)
boomtimer = boomtimer + 1
else
love.graphics.draw(looser)
if menuf == 1 then
love.graphics.draw(restart, 0, 20)
end
end
end
for i,v in ipairs(boom) do
if v.t<8 then
love.graphics.draw(boom1, v.x, v.y-8)
v.t = v.t + 1
elseif v.t<16 then
love.graphics.draw(boom2, v.x, v.y-8)
v.t = v.t + 1
elseif v.t<24 then
love.graphics.draw(boom3, v.x, v.y-8)
v.t = v.t + 1
elseif v.t<32 then
love.graphics.draw(boom4, v.x, v.y-8)
v.t = v.t + 1
else
table.remove(boom, i)
end
end
if won == 0 then
if empty(levelctrl) then
won = 1
end
end
if won == 1 then
love.graphics.draw(winner)
if menuf == 1 then
love.graphics.draw(restart, 0, 20)
end
end
end
end
function shoot()
local shot = {}
shot.x = hero.x
shot.y = hero.y - 4
table.insert(hero.shots, shot)
end
function CheckCollision(ax1,ay1,aw,ah, bx1,by1,bw,bh)
local ax2 = ax1 + aw
local ay2 = ay1 + ah
local bx2 = bx1 + bw
local by2 = by1 + bh
return ax1 < bx2 and ax2 > bx1 and ay1 < by2 and ay2 > by1
end
function love.keyreleased(key)
if isdead==0 then
if (key == " ") then
shoot()
end
end
end
function empty(self)
for _, _ in pairs(self) do
return false
end
return true
end
that's all the code and more specifically i get a problem with this:
for i,v in ipairs(levelctrl[1]) do
love.graphics.draw(v.img, v.x, v.y)
end
levelctrl initially has 2 tables inside so after i remove the first one to bump the second one down, I recieve the bad argument error
The problem seems to be around line 200:
if empty(levelctrl[1]) == true and won == 0 then
level = level + 1
table.remove(levelctrl, 1)
Here you remove the table from levelctrl when it's empty and increase the level. Since the table is empty already, can't you just re-use it instead of removing it (causing crashes on next rendering)? Removing the table.remove call should help.
I see
levelctrl = {}
table.insert(levelctrl, fleet1)
So levelctrl = {fleet1}
and some time later when you win,
if empty(levelctrl[1]) == true and won == 0 then
level = level + 1
table.remove(levelctrl, 1)
So levelctrl = {}
won is still 0, and game is still 1.
Then in your draw function
for i,v in ipairs(levelctrl[1]) do
love.graphics.draw(v.img, v.x, v.y)
end
At this point levelctrl = {} and levelctrl[1] = nil.
One solution would be to surround that bit of your draw function with
if not empty(levelctrl)
Also if you were trying to add fleet1 to levelctrl multiple times,
levelctrl = {}
table.insert(levelctrl, fleet1)
table.insert(levelctrl, fleet1)
table.insert(levelctrl, fleet1)
Then levelctrl would have three instances of the same table, and removing something from levelctrl[1] would remove it from fleet1 => all of the levels become empty at the same time.

Resources