Page 1 of 1
I'm looking for help with making bullets in LÖVE
Posted: Wed Dec 23, 2015 10:52 pm
by The Lie
So I tried making bullets for a game by creating bodies and shapes and putting them into a table on keypress. After this step I wanted to put them together by a fixture. When I tried pressing the button though, löve told me that either the body was a shape or the shape was a body. Which was wrong dependet on what I put into the table first. The code in question:
Code: Select all
if love.keyboard.isDown('kp6') then
if sniggle == 1 then
newShape = love.physics.newRectangleShape( 2, 2)
table.insert(objects.bullets, newShape)
newBody = love.physics.newBody(world, objects.player.body:getX(), objects.player.body:getY())
table.insert(objects.bullets, newBody)
sniggle = sniggle-1
end
else
sniggle = 1
for i, Body in ipairs(objects.bullets) do
for j, Shape in ipairs(objects.bullets) do
if i == j and i > 0 then
newFixture = love.physics.newFixture(Body, Shape, 0)
table.insert(objects.bullets, newFixture)
Body:setLinearVelocity(400,0)
end
end
end
end
- Main.lua
- My Main.lua for additional info if necessary
- (5.02 KiB) Downloaded 149 times
thanks in advance for any help
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 5:38 am
by giantofbabil
It looks like you are making the bullet shape before making the body. A shape is attached to a body by a fixture. Look at your other physics objects when you make them it goes Body->Shape->Fixture.
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 10:29 am
by The Lie
giantofbabil wrote:It looks like you are making the bullet shape before making the body. A shape is attached to a body by a fixture. Look at your other physics objects when you make them it goes Body->Shape->Fixture.
First, thanks for the help. But If I change the order, the error just switches. when I write:
Code: Select all
newBody = love.physics.newBody(world, objects.player.body:getX(), objects.player.body:getY())
newShape = love.physics.newRectangleShape( 2, 2)
table.insert(objects.bullets, newBody)
table.insert(objects.bullets, newShape)
It says that it got a body when it expected a shape.
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 11:04 am
by bartbes
If we presume you insert the shape first, and then the body, and we rewrite the nested ipairs to a print, like this:
Code: Select all
for i, Body in ipairs(objects.bullets) do
for j, Shape in ipairs(objects.bullets) do
print(i, j, Body, Shape)
end
end
We'll see the output is:
Code: Select all
1, 1, Shape, Shape
1, 2, Shape, Body
2, 1, Body, Shape
2, 2, Body, Body
As you may now realise, the nested ipairs must not be doing what you expect them to, since this always means both 'Body' and 'Shape' will have a value of the other type at some point.
The best way to fix this is to not store the two together, perhaps by storing more structured data instead:
Code: Select all
local body = love.physics.newBody(world, objects.player.body:getX(), objects.player.body:getY())
local shape = love.physics.newRectangleShape(2, 2)
table.insert(objects.bullets, {body = body, shape = shape})
for i, bullet in ipairs(objects.bullets) do
bullet.fixture = love.physics.newFixture(bullet.body, bullet.shape, 0)
bullet.body:setLinearVelocity(400, 0)
end
Of course since you probably don't want to recreate fixtures for every bullet whenever a new one is fired, you're probably better off not using a loop just calling newFixture once.
As some extra explanation, the names given in the for loop for ipairs are
not filters of any sort. They simply represent the variable names used for the iteration values.
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 5:12 pm
by giantofbabil
bartbes wrote:Of course since you probably don't want to recreate fixtures for every bullet whenever a new one is fired, you're probably better off not using a loop just calling newFixture once.
A little confused by this, if he has multiple bullets on the screen at the same time doesn't each bullet need a fixture? That way they can be set as sensors to detect collision? I'm building a system like this right now as well about to start digging into some source to try to find something similar because putting in bullets and enemies is much more complicated when they are physics based and no tutorials seem to cover it
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 6:49 pm
by bartbes
giantofbabil wrote:
A little confused by this, if he has multiple bullets on the screen at the same time doesn't each bullet need a fixture?
Yes, but you don't need to create a fixture for every bullet every time you add one bullet, you only need to create the fixture for that bullet.
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 7:32 pm
by giantofbabil
I'm trying to do the same thing as OP with this and having an error when I press 'f'(my fire button) that says:
Error
assets/loaders/weapons.lua:49: attempt to index field 'body' (a nil value)
Code: Select all
function weaponsLoad()
local sprite = map.layers['Sprite Layer'].sprites.player
--set up table for Zapper
sprite.zapperGun = {canShoot = true,
canShootTimerMax = 0.2,
canShootTimer = 0.2,
zapImg = love.graphics.newImage('assets/particles/roundBlue.png'),
zapSound = love.audio.newSource('assets/sound/serglaser.wav', 'static'),
zapBullet = {}}
end
function weaponsUpdate(dt)
--timer for Zapper shot separation
local sprite = map.layers['Sprite Layer'].sprites.player
if playerStats.weaponEquip == 0 then
sprite.zapperGun.canShootTimer = sprite.zapperGun.canShootTimer - (1 * dt)
if sprite.zapperGun.canShootTimer <= 0 then
sprite.zapperGun.canShoot = true
end
end
--fire button response
local isDown = love.keyboard.isDown
if isDown('f') and playerStats.weaponEquip == 0 and sprite.zapperGun.canShoot == true then
--create zapper shot
local body = love.physics.newBody(world, sprite.body:getX(), sprite.body:getY(), 'dynamic')
local shape = love.physics.newRectangleShape(0, 0, 15, 15, 0)
table.insert(sprite.zapperGun.zapBullet, {body, shape})
sprite.zapperGun.zapSound:play()
sprite.zapperGun.canShoot = false
sprite.zapperGun.canShootTimer = sprite.zapperGun.canShootTimerMax
end
--update position for zapper shots
if playerStats.weaponEquip == 0 then
for i, bullet in ipairs(sprite.zapperGun.zapBullet) do
if sprite.lastdirection == 'right' then
bullet.fixture = love.physics.newFixture(bullet.body, bullet.shape)
bullet.body:setLinearVelocity(500, 0)
elseif sprite.lastdirection == 'left' then
bullet.fixture = love.physics.newFixture(bullet.body, bullet.shape)
bullet.body:setLinearVelocity(-500, 0)
end
if bullet.body:getX() < 0 or bullet.body:getX() > 7680 then
table.remove(sprite.zapperGun.zapBullet, i)
end
end
end
end
function weaponsDraw(dt)
local sprite = map.layers['Sprite Layer'].sprites.player
--update position for zapper shots
if playerStats.weaponEquip == 0 then
for i, bullet in ipairs(sprite.zapperGun.zapBullet) do
love.graphics.setColor(0, 255, 0, 255)
love.graphics.draw(sprite.zapperGun.zapImg, bullet.body:getX(), bullet.body:getY(), 0, 0.5, 0.5)
end
end
end
Github:
https://github.com/NeverHuman/Space-Chow.love
I'm using STI so I'm trying to create the bullet in a custom layer called 'Sprite Layer', I'm sure there's probably a syntax error or something... I'm guessing to fix the fixture thing you were talking about I would have to add fixture to the table.insert so it would be table.insert{body, shape, fixture} right?
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 7:45 pm
by bartbes
The actual error is that you're inserting {body, shape}, where it should be {body = body, shape = shape}, the first is equivalent to {[1] = body, [2] = shape} instead.
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 8:20 pm
by The Lie
bartbes wrote:If we presume you insert the shape first, and then the body, and we rewrite the nested ipairs to a print, like this:
Code: Select all
for i, Body in ipairs(objects.bullets) do
for j, Shape in ipairs(objects.bullets) do
print(i, j, Body, Shape)
end
end
We'll see the output is:
Code: Select all
1, 1, Shape, Shape
1, 2, Shape, Body
2, 1, Body, Shape
2, 2, Body, Body
As you may now realise, the nested ipairs must not be doing what you expect them to, since this always means both 'Body' and 'Shape' will have a value of the other type at some point.
The best way to fix this is to not store the two together, perhaps by storing more structured data instead:
Code: Select all
local body = love.physics.newBody(world, objects.player.body:getX(), objects.player.body:getY())
local shape = love.physics.newRectangleShape(2, 2)
table.insert(objects.bullets, {body = body, shape = shape})
for i, bullet in ipairs(objects.bullets) do
bullet.fixture = love.physics.newFixture(bullet.body, bullet.shape, 0)
bullet.body:setLinearVelocity(400, 0)
end
Of course since you probably don't want to recreate fixtures for every bullet whenever a new one is fired, you're probably better off not using a loop just calling newFixture once.
As some extra explanation, the names given in the for loop for ipairs are
not filters of any sort. They simply represent the variable names used for the iteration values.
Wow, thanks for all the work especially on christmas eve, have happy holidays.
Re: I'm looking for help with making bullets in LÖVE
Posted: Thu Dec 24, 2015 9:02 pm
by giantofbabil
The Lie wrote:Wow, thanks for all the work especially on christmas eve, have happy holidays.
If it helps at all my bullet code is now working, the github link is above if you want to look at the whole code for my engine but keep in mind you may need different values than me my game is a platformer and I have physics and variables flying around like crazy lol. Anyway here's my working weapon/bullet code:
Code: Select all
function weaponsLoad()
local sprite = map.layers['Sprite Layer'].sprites.player
--set up table for Zapper
sprite.zapperGun = {canShoot = true,
canShootTimerMax = 0.2,
canShootTimer = 0.2,
zapImg = love.graphics.newImage('assets/particles/roundBlue.png'),
zapSound = love.audio.newSource('assets/sound/serglaser.wav', 'static'),
zapBullet = {}}
end
function weaponsUpdate(dt)
--timer for Zapper shot separation
local sprite = map.layers['Sprite Layer'].sprites.player
if playerStats.weaponEquip == 0 then
sprite.zapperGun.canShootTimer = sprite.zapperGun.canShootTimer - (1 * dt)
if sprite.zapperGun.canShootTimer <= 0 then
sprite.zapperGun.canShoot = true
end
end
--fire button response
local isDown = love.keyboard.isDown
if isDown('f') and playerStats.weaponEquip == 0 and sprite.zapperGun.canShoot == true then
--create zapper shot
local body = love.physics.newBody(world, sprite.body:getX(), sprite.body:getY(), 'dynamic')
local shape = love.physics.newRectangleShape(7, 7, 13, 13, 0)
local fixture = love.physics.newFixture(body, shape)
table.insert(sprite.zapperGun.zapBullet, {body = body, shape = shape, fixture = fixture:setSensor(true), body:setBullet(true), speedSet = false})
sprite.zapperGun.zapSound:play()
sprite.zapperGun.canShoot = false
sprite.zapperGun.canShootTimer = sprite.zapperGun.canShootTimerMax
end
--update position for zapper shots
if playerStats.weaponEquip == 0 then
for i, bullet in ipairs(sprite.zapperGun.zapBullet) do
if sprite.lastDirection == 'right' and bullet.speedSet == false then -- THIS MIGHT NOT WORK
bullet.body:setLinearVelocity(2.5 * physicsMultiplier, -0.1 * physicsMultiplier)
bullet.speedSet = true
elseif sprite.lastDirection == 'left' and bullet.speedSet == false then
bullet.body:setLinearVelocity(-2.5 * physicsMultiplier, -0.1 * physicsMultiplier)
bullet.speedSet = true
end
if bullet.body:getX() < 0 or bullet.body:getX() > 7680 then
table.remove(sprite.zapperGun.zapBullet, i)
elseif bullet.body:getY() < 0 or bullet.body:getY() > 4352 then
table.remove(sprite.zapperGun.zapBullet, i)
end
end
end
end
function weaponsDraw(dt)
local sprite = map.layers['Sprite Layer'].sprites.player
--update position for zapper shots
if playerStats.weaponEquip == 0 then
for i, bullet in ipairs(sprite.zapperGun.zapBullet) do
love.graphics.setColor(0, 255, 0, 255)
love.graphics.draw(sprite.zapperGun.zapImg, bullet.body:getX(), bullet.body:getY(), 0, 0.5, 0.5)
love.graphics.setColor(255, 255, 255, 255)
end
end
end
I'm going to modify this to include multiple weapons, ammo, and add animations as well
but for now enemies is next on my list.
Happy holidays!