Hitboxes and hurtboxes

Galdon2004

  • *
  • Posts: 313
So, I wasted most of the day tinkering with this before remembering that the "member of group" detection detects the actor's default group, and not the group the hitbox belongs to. This leaves me with difficulty figuring out how to make hitboxes and hurtboxes work.

I am trying to make combat for a platformer, where actors can touch each other without automatically dealing damage, and deal damage using their attack animations. The only way i can think to make it work without being able to identify to colliding hitbox's group would be to have invisible actors spawn in just to act as hitboxes, which feels like a very messy and unnecessarily complicated way to handle it.

Is there any cleaner way to handle detecting specific hitboxes, or is there any plan to allow them to work more intuitively at some point?

vicevicebingo

  • Posts: 80
You don't want 10000 hits (automatically)
you just want 1 hit
but MUST USE collision shape in animation

Eh, this is how to answer....

merrak

  • *
  • Posts: 2726
I started working on the same problem before getting sidetracked by StencylJam. Spawning invisible actors seemed to work well enough until I needed a better handle on precision. I ended up making custom hitboxes just by storing a list of coordinates. Every attack has a defined attack point (e.g. punch attack point is located on the player's fist in the punch animation). I can loop through each of the enemy hitboxes and figure out which one(s) the attack point landed in.

Galdon2004

  • *
  • Posts: 313
You don't want 10000 hits (automatically)
you just want 1 hit
but MUST USE collision shape in animation

Eh, this is how to answer....
You would have that issue with every kind of hitbox in the engine. You get around it by programming it to have a cooldown on being hit so it only triggers once.

I started working on the same problem before getting sidetracked by StencylJam. Spawning invisible actors seemed to work well enough until I needed a better handle on precision. I ended up making custom hitboxes just by storing a list of coordinates. Every attack has a defined attack point (e.g. punch attack point is located on the player's fist in the punch animation). I can loop through each of the enemy hitboxes and figure out which one(s) the attack point landed in.

Yeah, invisible actors can be hard to work with precisely.

merrak

  • *
  • Posts: 2726
Yeah, invisible actors can be hard to work with precisely.

I finished implementing hit/hurtboxes. This came together rather nicely. Each box has a name (e.g. "head", "body"). I can also define boxes for attacks: "fists", "feet", etc--anything that wouldn't make sense to implement as a separate actor. Collision is detected using AABB check. It even accounts for facing left/right. I can share the code/details if you'd like.

Below is a demonstration of how it works. The most complex parts of the code handle debug drawing. Purple boxes are the hitboxes, and orange the "attack boxes". The red enemies have placeholder graphics, so the fact that the hitboxes don't align with them very well isn't due to a code error.

<a href="https://www.youtube.com/v/JRn27-59LbU" target="_blank" class="new_win">https://www.youtube.com/v/JRn27-59LbU</a>

Galdon2004

  • *
  • Posts: 313
Yeah, details would be helpful. I think the thing that causes me the most confusion is how this would work if characters happen to be stationary when the attack happens; as I recall from a while ago when you create an actor, it doesn't count as colliding with hitboxes it overlaps until it moves.

merrak

  • *
  • Posts: 2726
I made a new class (HitBox) and an accompanying Actor behavior that lets me add them. I attached a couple of screenshots: the manager behavior and example usage for the player's punch attack. I haven't done anything too elaborate with it yet. In the example attack, the hitbox manager returns the name of the hitbox that was hit. I have this set up to only report a hit in one box at one moment in time, but it wouldn't be difficult to expand it to check for multiple hit boxes across multiple frames.

This setup is completely independent from the standard collision boxes. You can see in my example usage I just loop through all of the actors on screen and check if the player's attack point is inside any of the actor's hitboxes (those that have them, anyway).

Code: [Select]
/*
    Stencyl exclusively uses the Haxe programming language.
    Haxe is similar to ActionScript and JavaScript.
   
    Want to use native code or make something reusable? Use the Extensions Framework instead.
    http://www.stencyl.com/help/view/engine-extensions/
   
    Learn more about Haxe and our APIs
    http://www.stencyl.com/help/view/haxe/
*/

package scripts;

import com.stencyl.Engine;

class HitBox
{
public var name:String;

public var x0:Float;
public var y0:Float;
public var x2:Float;
public var y2:Float;

public var body_width:Float;
public var body_height:Float;

public function new( n:String, a:Float, b:Float, c:Float, d:Float, e:Float, f:Float )
{
this.name = n;

this.x0 = a;
this.y0 = b;
this.x2 = c;
this.y2 = d;

this.body_width = e;
this.body_height = f;
}

public function point_in_box( local_x:Float, local_y:Float, ?right:Bool = true )
{
if ( right )
return local_x >= x0 && local_x <= x2 && local_y >= y0 && local_y <= y2;
else
return local_x >= ( body_width - x2 ) && local_x <= ( body_width - x0 ) && local_y >= y0 && local_y <= y2;
}

public function box_in_box( hit_x:Float, hit_y:Float, hit_w:Float, hit_h:Float, right:Bool = true )
{
var hit_x0:Float, hit_x2:Float, hit_y0:Float, hit_y2:Float;

hit_x0 = hit_x;
hit_x2 = hit_x + hit_w;

hit_y0 = hit_y;
hit_y2 = hit_y + hit_h;

if ( right )
return VUtility.AABBOverlap( hit_x0, hit_y0, hit_x2, hit_y2, x0, y0, x2, y2 );
else
return VUtility.AABBOverlap( hit_x0, hit_y0, hit_x2, hit_y2, body_width - x2, y0, body_width - x0, y2 );
}

public function sided_x0( ?right:Bool = true ):Float
{
if ( right )
return x0;
else
return body_width - x2;
}

public function sided_x2( ?right:Bool = true ):Float
{
if ( right )
return x2;
else
return body_width - x0;
}
}