Page 1 of 1

[SOLVED] Attack system based on DT

Posted: Thu Oct 19, 2023 5:21 am
by Ladniy
Hello everyone!
I'm working on my first small game and I need some help from the community.
Here's the deal, I need to implement an enemy attack system with support for attack speed.
At the moment it looks like this:

Code: Select all

CurrentDelta = 0

function EnemiesAttack(object)
    local sumOfDamage = 0
    if GetItemsCount(Enemies) ~= 0 then
      for enemyIndex, enemy in pairs(Enemies) do
      	sumOfDamage = sumOfDamage + enemy:getDamage()
      end
    	object.health = object.health - sumOfDamage
    end
end

function love.update(dt)
  CurrentDelta = math.ceil(CurrentDelta + (dt * 100))
    if CurrentDelta % 100 == 1 then
      EnemiesAttack(Player)
    end
end
It is a bit junky and doesn't do what i need.

What do i need exactly:
Some system that will allow me automatically execute attack on player. E.g. First enemy will attack twice in a sec. and second enemy will attack once in a sec.

Full code of the game - GitHub

Any help would be appreciated, thanks!

Re: Attack system based on DT

Posted: Thu Oct 19, 2023 5:39 pm
by BrotSagtMist
If they have different speeds each enemy needs to have its own timecheck.
Further using % and == here can cause attack skips so its not suitable.

I would:
On enemy init save the global time value love.timer.getTime() + the waiting time for each attack.
Then check during the game when the global time succeeds the saved value, act and repeat setting a new time mark.
Using < instead == means no skips, no double acts during slowdowns etc.

Re: Attack system based on DT

Posted: Fri Oct 20, 2023 11:58 am
by Ladniy
BrotSagtMist wrote: Thu Oct 19, 2023 5:39 pm I would:
On enemy init save the global time value love.timer.getTime() + the waiting time for each attack.
Then check during the game when the global time succeeds the saved value, act and repeat setting a new time mark.
Using < instead == means no skips, no double acts during slowdowns etc.
Thank you for your idea! It was interesting and helpful :neko:

Solved with this code:

Code: Select all

  -- Attack player with given damage and attack speed
  for enemyIndex, enemy in ipairs(Enemies) do
    if AttackTime and GetItemsCount(Enemies) > 0 then
      AttackTime = AttackTime + dt
      if AttackTime >= enemy:getAttackSpeed() then
        EnemiesAttack(Player, enemy:getDamage())
        AttackTime = 0
      end
    end
  end
For current state of game's development this will be enough.
Perhaps in the future I'll rework the system as the game becomes more complex

Re: [SOLVED] Attack system based on DT

Posted: Sat Oct 21, 2023 7:33 am
by Ladniy
UPDATE

Code in previous post was not working completely.
I notice it this morning and was a bit upset, but i found solution pretty quick.

Code:

Code: Select all

-- Attack player with given damage and attack speed
for enemyIndex, enemy in pairs(Enemies) do
  enemy.timer = enemy.timer + dt
  if enemy:getTimer() >= enemy:getAttackSpeed() then
    EnemiesAttack(Player, enemy:getDamage())
    enemy.timer = 0
  end
end
I added a timer field for each enemy, so now i can change and compare it with any other timers!

Re: [SOLVED] Attack system based on DT

Posted: Sat Oct 21, 2023 9:20 am
by BrotSagtMist
Note that you are reassigning enemy.timer new 60 times per second per enemy. Thats a bit of a cpu waster.
I would rather change it to something like
enemy.timer = Time+ enemy:getAttackSpeed()
So time is only updated if its actually been used.

Re: [SOLVED] Attack system based on DT

Posted: Sat Oct 21, 2023 11:12 am
by Ladniy
BrotSagtMist wrote: Sat Oct 21, 2023 9:20 am
I would rather change it to something like
enemy.timer = Time+ enemy:getAttackSpeed()
Thank you! I'll keep that in mind.