I have run into a problem calculating attacks. If the player is attacking and an object intersects his attack hit box, I call the damage() function of the object.Problem is, this happens every loop, and the object is damaged several times during a single attack animation.

I searched the forums for a solution, but I didn't find anything. My ideas:

I thought I might end the attack after causing damage once, but that makes cleaving attacks impossible.

I thought of "tagging" the enemy as damaged, and testing for this before applying more damage, but I would have to reset each object between attack animations.

My best idea is to use a timer, allowing damage() to be called only so often, so there is a recovery period after being attacked, during which the object cannot take damage. Problem is, the recovery period cannot be shorter than the animation. If it is too short, the attack will still hit multiple times. If it is too long, the next attack might not cause damage. I don't want to use a set animation length. Maybe I can pass the animation length to the object when it is damaged...

The idea of a cooldown time looks appealing, this allows to have attacks which repeat faster or slwer.

But I'd just clear the player attack hit frame once every intersecting object has been damaged. Unless it is a cleaving attachh for which you seem to want to have just the effect of repeated attacks?

Myself, I handle attacks in the player input code, and if an attack is triggered once it will only execute once. That seemed simple enough and worked fairly well for melee attacks. If you have a flamethrower which does time-based damage it will be something different ...

My designer decides to give the player a slashing sword attack that can definitely hit multiple enemies. He sets the hit box of this attack so that it will hit anything in front of the player, where the sword will swing. It takes one full second for the sword to go from the initial position to the end of the swing.

The player is testing this, and two enemies are in front of him. One of the enemies is already within the hit box, and the other is fast approaching. So the player hits the attack button, and the sword swings. The second enemy steps into the hit box while the sword is swinging, exactly .5 sec after the attack is initiated. The pixels of the sword make clear contact with both enemies.

Currently, here is what happens: The game logic is updated at 60 frames per second. The first enemy, who was within the hit box for the entire length of the attack, is damaged 60 times. The second enemy, who is only present for half of the attack, is damaged 30 times. These numbers might be off, but that is essentially what happens.

Ideally, I would like to damage each enemy only once.

Quote

But I'd just clear the player attack hit frame once every intersecting object has been damaged

This is attractive to me, but in my example scenario the second enemy would not be damaged. Perhaps that is correct, and an enemy should not be damaged if they were not in range at the exact moment the attack begins. But visually, the player still sees the sword make contact.

....I think it would be much easier to just have a boolean in enemies that means they were hit or have the attack have a list (use your favorite data type) of enemies hit in this cycle and just check if an enemies is in the list, if so, don't damage.

So for every swing/animation cycle, reset , check for collision, if collision, damage() and set so we wont check this guy for the remainder of this animation, and at the end reset the list. You could easily add a int to cap the maximum enemies the weapon can hit at one time. That way a cleaver/greatsword would be much more useful for big mobs where a fast short sword or dagger would be great for a single target.

But what if two people attack at the same time? Surely monsters and allies will be able to cleave too. With a boolean per enemy that's impossible. You also have the performance problem of resetting the boolean on every single enemy after each attack.

You can save a list of damaged entities in your attack instance. If enemy is already in list, do not damage it again.

This. A HashSet can be used for it.

That's great! Thank you guys so much. I didn't think to create an instance of the attack. Rather, my attack consisted of a box that followed the player around and a player state that determined whether to check for objects within the box. Now I feel silly.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org