Hi! I'm new to love2d and coding in general and only started a couple of months ago. I'm having an issue where attacking one enemy, and it taking damage and running the remove function ends up removing all enemies on screen. I've tried countless of different ways to approach this and I'm not sure if it's my collision that's causing this issue, or something in my enemy code. I'm using box2d world callbacks for my collisions.
Press G while walking left or right (with the arrow keys or WASD) to attack, after selecting the available characters.
Feedback would be greatly appreciated!
All Enemies are deleted when one dies
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
All Enemies are deleted when one dies
- Attachments
-
- beat em up test .zip
- (2.42 MiB) Downloaded 204 times
Re: All Enemies are deleted when one dies
Can you provide the relevant code, e.g. where the deletion happens? Probably you are creating enemy instances as a reference, not a copy.
My boat driving game demo: https://dusoft.itch.io/captain-bradley- ... itius-demo
Re: All Enemies are deleted when one dies
Code: Select all
function Enemy:checkRemove()
for i, instance in ipairs(ActiveEnemys) do
if instance.health <= 0 then
instance.toBeRemoved = true
end
if instance.toBeRemoved == true then
instance:remove()
end
end
end
function Enemy:remove()
for i, instance in ipairs(ActiveEnemys) do
if instance.health <= 0 then
instance.toSpawnNew = true
instance.physics.body:destroy()
table.remove(ActiveEnemys,i)
return true
else
return false
end
end
end
Re: All Enemies are deleted when one dies
Should probably also include this as well:
Code: Select all
function Hitbox.beginContact_PlayerToEnemy(a,b,collision)
for i,instance in ipairs(ActiveHitboxes) do
if a == instance.physics.fixture or b == instance.physics.fixture then
for v = 1, #ActiveEnemys do
if a == ActiveEnemys[v].physics.fixture or b == ActiveEnemys[v].physics.fixture then
return ActiveEnemys[v], true
end
end
end
end
end
function beginContact(a, b, collision)
if Enemy.beginContact(a,b,collision) then Enemy:getIntent() return end
if Hitbox.beginContact_PlayerToEnemy(a,b,collision) then --if player's hitbox contacts with enemy returns true then,
Enemy:takeDamage(Hitbox.beginContact_PlayerToEnemy(a,b,collision)) return end --Enemy takes damage
Player:beginContact(a, b, collision)
end
function Enemy:takeDamage()
for i,instance in ipairs(ActiveEnemys) do
instance.health = instance.health - Player.damageOutput
instance:checkRemove()
end
end
-
- Party member
- Posts: 559
- Joined: Wed Oct 05, 2016 11:53 am
Re: All Enemies are deleted when one dies
In your posted code, the enemy takeDamage function makes every enemy instance take damage at once, so that's likely your issue.
Re: All Enemies are deleted when one dies
I originally had a conditional (after the for loop in the take damage function) in hopes that it would make it so that if the Enemy that calls the function is equal to the instance to run the code on the single enemy, but it never passes the check and I don't know why. Using the self keyword returns nil here and I also don't understand why that's the case.
Code: Select all
function Enemy:takeDamage()
for i,instance in ipairs(ActiveEnemys) do
if instance == self then -- never passes this check
self.health = self.health - Player.damage --"a nil value?"
instance:checkRemove()
hoverSFX:play()
end
end
end
-
- Party member
- Posts: 559
- Joined: Wed Oct 05, 2016 11:53 am
Re: All Enemies are deleted when one dies
Looks like you've got a bit of a fundamental misunderstanding regarding the "self" keyword and instances of your enemy class.
Lets run through this example:
As you see, the colon (":") is just syntactic sugar, that reduces some amount of typing. Because in lua you are decently commonly passing tables around, or calling functions contained in tables (that act on those tables' contents), this kind of shorthand can be helpful -- just at the cost of causing some confusion for beginner programmers.
As such, when you have code like...
That means that you are not passing an enemy instance to the function, but rather the enemy class itself. This is why in your code the "instance == self" check would never equate to true, because your class and its instances are different tables.
So, as you can see, you'll need to modify your "beginContact" function to instead act on your instances, rather than the enemy class itself. You may similarly want to do so on player class too, in case you ever want to spawn more than one copy of the player.
So...
I'll leave fixing up the code as an exercise for you to solve.
Lets run through this example:
Code: Select all
local myTable = { x = 0 }
function myTable:myFunction ( )
-- just increment table's x value
self.x = self.x + 1 -- self is inferred from the colon syntax
end
myTable:myFunction ( )
-- is functionally equivalent to
local myTable = { x = 0 }
function myTable.myFunction ( tab ) -- "tab" could be named "self" or whatever you want
tab.x = tab.x + 1
end
myTable.myFunction ( myTable )
myTable:myFunction () -- can mix and match too, just need to be careful!
As such, when you have code like...
Code: Select all
Enemy:takeDamage(...)
So, as you can see, you'll need to modify your "beginContact" function to instead act on your instances, rather than the enemy class itself. You may similarly want to do so on player class too, in case you ever want to spawn more than one copy of the player.
So...
Code: Select all
-- instead of this...
Enemy:takeDamage ( param1, param2, ... )
-- do this
Enemy.takeDamage (instanceOfEnemy, param1, param2, ... )
-- or this, assuming instances of your enemy class contain the takeDamage function
instanceOfEnemy:takeDamage ( param1, param2, ... )
Re: All Enemies are deleted when one dies
What I struggle with understanding is if "self" refers to the entire class of individual instances.
Also thank you for the response, I don't understand it entirely but I think it'll push me in the right direction!
Also thank you for the response, I don't understand it entirely but I think it'll push me in the right direction!
Re: All Enemies are deleted when one dies
If you're not yet familiar with metatables, trying to simulate classes and instances in Lua using the metatable __index trick can be a lot.
You can perfectly make your game by defining functions outside of any tables, and explicitly writing the table parameter, like with:
You can perfectly make your game by defining functions outside of any tables, and explicitly writing the table parameter, like with:
Code: Select all
local function enemyCheckRemove(enemy)
if enemy.health <= 0 then
(...)
end
end
Who is online
Users browsing this forum: Amazon [Bot], Google [Bot] and 5 guests