Related
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.
I am making a simulator game on roblox and it has a pet system. I revamped how the hatch works, and for some reason it started to glitch out, and always give the same pet, and the pet was always the rarest one. I don't know what the problem is, here is the script. The Weight system worked perfectly before, but now it isnt working. I compared it to the old version of the game and the only difference is what the variables are called.
game.ReplicatedStorage.OpenEgg.OnServerInvoke = (function(player, amount, egg)
print("Fired")
if not player:FindFirstChild("Debounce") then
if amount == "One" then
local CC = player.leaderstats.CloudCoins
local EO = player.leaderstats.EggsOpened
local EGGS = require(game.ReplicatedStorage.EGGS)
local Data = EGGS[egg]
local Price = Data["Cost"]
local Pets = Data["Pets"]
local TotalWeight = 0
for i,v in pairs(Pets) do
TotalWeight = TotalWeight + v[1]
end
local function ChoosePet(player)
local Chance = math.random(1,TotalWeight)
local Counter = 0
for d,c in pairs(Pets)do
Counter = Counter + c[1]
if Chance >= Counter then
return d
end
end
end
local function GetChance(ChosenPet)
for i, v in pairs(Pets)do
for o,b in pairs(Pets) do
if o == ChosenPet then
return b[1]
end
end
end
end
if CC.Value >= Price then
local ChosenPet = ChoosePet(player)
local Chance = GetChance(ChosenPet)
CC.Value = CC.Value - Price
EO.Value = EO.Value + 1
local Pet = Instance.new("BoolValue")
Pet.Name = ChosenPet
Pet.Parent = player.Pets
if not player.PetsA:FindFirstChild(Pet.Name.." Amount") then
local AmountA = Instance.new("IntValue")
AmountA.Name = Pet.Name.." Amount"
AmountA.Value = 1
else
local AmountA = player.PetsA[Pet.Name.." Amount"]
AmountA.Value = AmountA.Value + 1
end
local Level = Instance.new("IntValue")
local Xp = Instance.new("IntValue")
local Number = Instance.new("IntValue")
Number.Name = "Number"
Number.Value = player.PetsA[Pet.Name.." Amount"].Value
Number.Parent = Pet
Level.Name = "Level"
Xp.Name = "XP"
Level.Value = 1
Xp.Value = 0
Level.Parent = Pet
Xp.Parent = Pet
return("Hatched")
else
return("NotEnoughCoins")
end
end
if amount == "Triple" then
local CC = player.leaderstats.CloudCoins
local EO = player.leaderstats.EggsOpened
local EGGS = require(game.ReplicatedStorage.EGGS)
local Data = EGGS[egg]
local Price = Data["Cost"]
local Pets = Data["Pets"]
local TotalWeight = 0
for i,v in pairs(Pets) do
TotalWeight = TotalWeight + v[1]
end
local function ChoosePet(player)
local Chance = math.random(1,TotalWeight)
local Counter = 0
for d,c in pairs(Pets)do
Counter = Counter + c[1]
if Chance >= Counter then
return d
end
end
end
local function GetChance(ChosenPet)
for i, v in pairs(Pets)do
for o,b in pairs(Pets) do
if o == ChosenPet then
return b[1]
end
end
end
end
if CC.Value >= Price*3 then
local ChosenPet1,ChosenPet2,ChosenPet3 = ChoosePet(player),ChoosePet(player),ChoosePet(player)
local Chance1,Chance2,Chance3 = GetChance(ChosenPet1),GetChance(ChosenPet2),GetChance(ChosenPet3)
CC.Value = CC.Value - Price*3
EO.Value = EO.Value + 3
local Pet1 = Instance.new("BoolValue")
Pet1.Name = ChosenPet1
Pet1.Parent = player.Pets
local Level1 = Instance.new("IntValue")
local Xp1 = Instance.new("IntValue")
local Number1 = Instance.new("IntValue")
Number1.Name = "Number"
if not player.PetsA:FindFirstChild(Pet1.Name.." Amount") then
local AmountA = Instance.new("IntValue")
AmountA.Name = Pet1.Name.." Amount"
AmountA.Value = 1
else
local AmountA = player.PetsA[Pet1.Name.." Amount"]
AmountA.Value = AmountA.Value + 1
end
Number1.Value = player.PetsA[Pet1.Name.." Amount"].Value
Number1.Parent = Pet1
Level1.Name = "Level"
Xp1.Name = "XP"
Level1.Value = 1
Xp1.Value = 0
Level1.Parent = Pet1
Xp1.Parent = Pet1
local Pet2 = Instance.new("BoolValue")
Pet2.Name = ChosenPet2
Pet2.Parent = player.Pets
local Level2 = Instance.new("IntValue")
local Xp2 = Instance.new("IntValue")
local Number2 = Instance.new("IntValue")
Number2.Name = "Number"
if not player.PetsA:FindFirstChild(Pet2.Name.." Amount") then
local AmountA = Instance.new("IntValue")
AmountA.Name = Pet2.Name.." Amount"
AmountA.Value = 1
else
local AmountA = player.PetsA[Pet2.Name.." Amount"]
AmountA.Value = AmountA.Value + 1
end
Number2.Value = player.PetsA[Pet2.Name.." Amount"].Value
Number2.Parent = Pet2
Level2.Name = "Level"
Xp2.Name = "XP"
Level2.Value = 1
Xp2.Value = 0
Level2.Parent = Pet2
Xp2.Parent = Pet2
local Pet3 = Instance.new("BoolValue")
Pet3.Name = ChosenPet3
Pet3.Parent = player.Pets
local Level3 = Instance.new("IntValue")
local Xp3 = Instance.new("IntValue")
local Number3 = Instance.new("IntValue")
Number3.Name = "Number"
if not player.PetsA:FindFirstChild(Pet3.Name.." Amount") then
local AmountA = Instance.new("IntValue")
AmountA.Name = Pet3.Name.." Amount"
AmountA.Value = 1
else
local AmountA = player.PetsA[Pet3.Name.." Amount"]
AmountA.Value = AmountA.Value + 1
end
Number3.Value = player.PetsA[Pet3.Name.." Amount"].Value
Number3.Parent = Pet3
Level3.Name = "Level"
Xp3.Name = "XP"
Level3.Value = 1
Xp3.Value = 0
Level3.Parent = Pet3
Xp3.Parent = Pet3
return("Hatched")
else
return("NotEnoughCoins")
end
end
end
end)
take a closer look at these lines of code.
local TotalWeight = 0
for i,v in pairs(Pets) do
TotalWeight = TotalWeight + v[1]
end
local function ChoosePet(player)
local Chance = math.random(1,TotalWeight)
local Counter = 0
for d,c in pairs(Pets)do
Counter = Counter + c[1]
if Chance >= Counter then
return d
end
end
end
the next time we see this function it is to assign the chosen pet to the player. I would suggest playing around with the Chance value. Set it to something crazy and see if you get another pet instead.
I really need help..
I have this code for fly, as a backpack item:
Name = "Fly"
pi = 3.141592653589793238462643383279502884197163993751
a = 0
s = 0
ndist = 13
rs = 0.025
siz = Vector3.new(1, 1, 1)
form = 0
flow = {}
function CFC(P1,P2)
local Place0 = CFrame.new(P1.CFrame.x,P1.CFrame.y,P1.CFrame.z)
local Place1 = P2.Position
P1.Size = Vector3.new(P1.Size.x,P1.Size.y,(Place0.p - Place1).magnitude)
P1.CFrame = CFrame.new((Place0.p + Place1)/2,Place0.p)
end
function checktable(table, parentneeded)
local i
local t = {}
for i = 1, #table do
if table[i] ~= nil then
if string.lower(type(table[i])) == "userdata" then
if parentneeded == true then
if table[i].Parent ~= nil then
t[#t + 1] = table[i]
end
else
t[#t + 1] = table[i]
end
end
end
end
return t
end
if script.Parent.Name ~= Name then
User = game:service("Players").Nineza
HB = Instance.new("HopperBin")
HB.Name = Name
HB.Parent = User.StarterGear
script.Parent = HB
User.Character:BreakJoints()
end
speed = 50
script.Parent.Selected:connect(function(mar)
s = 1
torso = script.Parent.Parent.Parent.Character.Torso
LeftShoulder = torso["Left Shoulder"]
RightShoulder = torso["Right Shoulder"]
LeftHip = torso["Left Hip"]
RightHip = torso["Right Hip"]
human = script.Parent.Parent.Parent.Character.Humanoid
bv = Instance.new("BodyVelocity")
bv.maxForce = Vector3.new(0,math.huge,0)
bv.velocity = Vector3.new(0,0,0)
bv.Parent = torso
bg = Instance.new("BodyGyro")
bg.maxTorque = Vector3.new(0,0,0)
bg.Parent = torso
connection = mar.Button1Down:connect(function()
a = 1
bv.maxForce = Vector3.new(math.huge,math.huge,math.huge)
bg.maxTorque = Vector3.new(900000,900000,900000)
bg.cframe = CFrame.new(torso.Position,mar.hit.p) * CFrame.fromEulerAnglesXYZ(math.rad(-90),0,0)
bv.velocity = CFrame.new(torso.Position,mar.hit.p).lookVector * speed
moveconnect = mar.Move:connect(function()
bg.maxTorque = Vector3.new(900000,900000,900000)
bg.cframe = CFrame.new(torso.Position,mar.hit.p) * CFrame.fromEulerAnglesXYZ(math.rad(-90),0,0)
bv.velocity = CFrame.new(torso.Position,mar.hit.p).lookVector * speed
end)
upconnect = mar.Button1Up:connect(function()
a = 0
moveconnect:disconnect()
upconnect:disconnect()
bv.velocity = Vector3.new(0,0,0)
bv.maxForce = Vector3.new(0,math.huge,0)
torso.Velocity = Vector3.new(0,0,0)
bg.cframe = CFrame.new(torso.Position,torso.Position + Vector3.new(torso.CFrame.lookVector.x,0,torso.CFrame.lookVector.z))
wait(1)
end)
end)
while s == 1 do
wait(0.02)
flow = checktable(flow, true)
local i
for i = 1,#flow do
flow[i].Transparency = flow[i].Transparency + rs
if flow[i].Transparency >= 1 then flow[i]:remove() end
end
if a == 1 then
flow[#flow + 1] = Instance.new("Part")
local p = flow[#flow]
p.formFactor = form
p.Size = siz
p.Anchored = true
p.CanCollide = false
p.TopSurface = 0
p.BottomSurface = 0
if #flow - 1 > 0 then
local pr = flow[#flow - 1]
p.Position = torso.Position - torso.Velocity/ndist
CFC(p, pr)
else
p.CFrame = CFrame.new(torso.Position - torso.Velocity/ndist, torso.CFrame.lookVector)
end
p.BrickColor = BrickColor.new("Cyan")
p.Transparency = 1
p.Parent = torso
local marm = Instance.new("BlockMesh")
marm.Scale = Vector3.new(1.9, 0.9, 1.725)
marm.Parent = p
local amplitude
local frequency
amplitude = pi
desiredAngle = amplitude
RightShoulder.MaxVelocity = 0.4
LeftShoulder.MaxVelocity = 0.4
RightHip.MaxVelocity = pi/10
LeftHip.MaxVelocity = pi/10
RightShoulder.DesiredAngle = desiredAngle
LeftShoulder.DesiredAngle = -desiredAngle
RightHip.DesiredAngle = 0
LeftHip.DesiredAngle = 0
end
end
end)
script.Parent.Deselected:connect(function()
a = 0
s = 0
bv:remove()
bg:remove()
if connection ~= nil then
connection:disconnect()
end
if moveconnect ~= nil then
moveconnect:disconnect()
end
if upconnect ~= nil then
upconnect:disconnect()
end
while s == 0 do
wait()
if #flow > 0 then
flow = checktable(flow, true)
local i
for i = 1,#flow do
flow[i].Transparency = flow[i].Transparency + rs
if flow[i].Transparency >= 1 then flow[i]:remove() end
end
end
end
end)
while true do
wait()
if s == 1 then
return
end
end
script:remove()
The script is in a HopperBin Object in the game's StarterPack Folder.
Now if you try it on your own, you'll see that it will work, BUT if you publish the game, play it via ROBLOX(not the studio) and try to use the item, you won't fly.
Any ideas why?
It's been a long time since I haven't played ROBLOX, so my answer might be inaccurate.
First, you need to understand the difference between a Script and a Localscript. In a nutshell, a script runs server-side whereas a Localscript runs client-side. Your fly script is expected to run on a player's client, thus you have to use a Localscript.
Your regular script works in build-mode because scripts are run on your client, and thus are considered as Localscripts. When you publish your game and play it, your computer doesn't work as a server anymore, but as a client.
In addition to this, as you use a localscript, you may have to change the following line :
-- gets the client (local player) on which the script is running
User = Game:GetService("Players").LocalPlayer
Also, avoid relative paths such as script.Parent.Parent.Parent..... You want to get the client's torso, so just use your User variable as per : User.Character.Torso. Do the same for the character's Humanoid object.
I think it's because the time to load not existing try this at line1:
repeat wait() until game.Players.LocalPlayer.Character
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
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.