Log in
Please log in or register.
Pages: [1]
  Print  
Author Topic: Beat 'em Up collision checking (new question)  (Read 244 times)
AcetheSuperVillain
Newbie
*
Posts: 42


The one and only


View Profile WWW
« on: Wed, Jul 28, 2010 »

So, I'm thinking of doing a Beat 'em Up game like River City or Streets of Rage or they thang, and I'm wondering about the hitboxes during attacks.

The last time I did this, (not Flixel) I used a hitbox object that works sort of like an invisible, one-frame bullet.  It works, but the problem with this method is that the attacker can't tell if the hitbox hit anything, so I can't do important beat 'em up things like continue comboing only if something is getting hit, grab instead of attack something if they are close enough or playing a sound or making an effect only if something gets hit.  

What I think I'd like is something that goes if(hitbox(x,y,w,h,enemies)){/*do the attack*/}  (possibly thestate.hitbox() )

Does Flixel have a built-in way to do this, and if not, what are your recommendations for getting this done?  

(solved; see question 2 below)
« Last Edit: Sat, Jul 31, 2010 by AcetheSuperVillain » Logged

zyxstand
Jr. Member
**
Posts: 64


View Profile
« Reply #1 on: Wed, Jul 28, 2010 »

why don't you create your own class as a child of FlxObject (and call it HitBox or something), pass to it the owner (ie: the player casting the box), its x&y, width&height, override its parent-class update call, and manually do regular box-on-box collision detection.  You can also add a timer to make it disappear after 1/10 sec and if it collides with an enemy during an update call, call its owner's OnHit(.....) function to do your desired things (like combos) and you can also call the enemy it hit and deal damage and things...
this good?
Logged
zez
Full Member
***
Posts: 200



View Profile WWW
« Reply #2 on: Wed, Jul 28, 2010 »

zyxstand has the right general idea, but probably your best bet for getting the sort of callback you want is
Code:
//in the player class
if(frame > something && frame < something else)//check to see what attack animation and or where in the animation the player is
{
hitbox.x = player.x - whatever + (double whatever * facing);
hitbox.y = player.y + or - whatever;
hitbox.height = whatever;
hitbox.width = whatever;
}
else if(frame > sometihng else && frame < something else)//samething for another attack or part of attack
{
setup the hitbox again
}
else if (etcetc)
{
ditto
}
else //when the player is not doing any attacks
{
hitbox.height = hitbox.width = hitbox.x = hitbox.y = 0//make the hitbox have no dimensions and stick it in the top left corner of the game world
}

// then in the playstates update
FlxU.overlap(hitbox, enemy group, attack function);
// then the attack function
public function attack function(hitbox:flxObject, enemy:probably flxsprite, or your enemy class):void
{
if (player.y > enemy.y - some offset && player.y < enemy.y + some offset)//make sure the player and enemy are near the same Y axis, seeing as beatemups basically use Y for the Z axis. You need to modify this slightly if you plan on having jump attacks. You could get away with just having a shadow sprite that represents where the player is on the z axis and testing against that, or using an int that represents the players z cordinate and testing against that or something
{
enemy.hurt(something)
combo += 1;
//do whatever else you need to do when the player connects, including things like
if (player.frame > this && player.frame < that)
{
do the magic this particular attack just connected code
}
}
}

The key difference here, is you REALLY dont want to use collide, first off because overlap gives you a callback function, second, calling collide wont do anything but frustrate you if you are manually setting the x & y of the hitbox (you should be if you want it lined up with the player,) and third off, because calling collide with modify the velocity of the hitbox and the enemy you hit in ways you probably dont want. Not that knockback is bad, just that I imagine you want some control over it.
Logged

zyxstand
Jr. Member
**
Posts: 64


View Profile
« Reply #3 on: Wed, Jul 28, 2010 »

@zez
could you re-explain your last paragraph? i didn't quite follow.  what's wrong with making it a child of FlxObject. this way, he won't have to deal with calling update himself, and, since it overrides update, he won't call super.update to do any flixel-engine collision stuff.
thanks!
Logged
zez
Full Member
***
Posts: 200



View Profile WWW
« Reply #4 on: Wed, Jul 28, 2010 »

Nothing is wrong with it being an object extending FlxObject, I was operating under the assumption that it was. It could EVEN just be public var hitbox:FlxObject; in the player class. These are all being made in the overrides of update that Im assuming are already being used (given that to do pretty much anything with flixel, you want to override the update and stick your code in there,) with the exception of the callback function.

The problem with using collide, first and foremost, is that collide will never be called. The reason for this, is 'manually' placing two objects ontop of eachother DOES trigger overlap, but collide is only called when the collision boxes enter the same area as a result of changes in there velocity or thrust. The other problem, is that if you magically got the hitbox to collide with the enemy, by say placing it on the player and then modifying its velocity to make it move where you wanted it to, calling collide will trigger the usual collision correction code, pushing the enemy and hitbox away from each other, and that will prevent things like combo's and throws from being feasible.

... also, there is no reason any of the code I posted would force him to call update himself, or call super.update (isnt that the same thing?)
Logged

Richard Kain
Full Member
***
Posts: 182


View Profile
« Reply #5 on: Wed, Jul 28, 2010 »

This is actually quite easy. Just extend FlxSprite, as you would regularly do when creating an enemy. For your game logic, use an overlap check instead of a collision check. If the overlap evaluates to true, do an additional check to see if the enemy in question is within a predetermined Y value range of your player character. If that evaluates to true, then the enemy is in attackable range of your player.
Logged
AcetheSuperVillain
Newbie
*
Posts: 42


The one and only


View Profile WWW
« Reply #6 on: Sat, Jul 31, 2010 »

Alright, those sound like some reasonable techniques.

So next related question is this:  How would you program it so that once your grab an enemy, you can hold him by the ankle/wheel/tail and use him as a bludgeoning weapon?  River City Ransom and a few other games let you do this, and I like it, but I don't have a clue as to how it would work.
Logged

zyxstand
Jr. Member
**
Posts: 64


View Profile
« Reply #7 on: Sat, Jul 31, 2010 »

i'm guessing if you grab them by whatever part, you'd have to do new graphics for the victim being in a certain position.  the easiest way is to forget about the victim as being a unit:  I'm guessing since it's grabbed, it can no longer move or attack or do anything 'normal'.  i guess you'll need new animations for all victims in different positions along with whatever the grabber can do with it (i'm guessing swing and throw?).

does this answer your question well?  or you want more info?
Logged
AcetheSuperVillain
Newbie
*
Posts: 42


The one and only


View Profile WWW
« Reply #8 on: Sat, Jul 31, 2010 »

...yyyeah, that's kinda what I figured.  So basically the grabbee "goes away" and I just draw() it in "the victim position" onto the grabber's sprite, then it "comes back" and becomes a normal enemy again.

It's the "goes away" and "comes back" bits that sound troublesome.  I guess dead() might work, as long as it doesn't do anything to health.  I'd just have to change anything that says if(everyone_is_dead) to if(everyone_is_dead && !grabbing)

... something like that?
Logged

Hectate
Full Member
***
Posts: 192


View Profile
« Reply #9 on: Sat, Jul 31, 2010 »

...yyyeah, that's kinda what I figured.  So basically the grabbee "goes away" and I just draw() it in "the victim position" onto the grabber's sprite, then it "comes back" and becomes a normal enemy again.

It's the "goes away" and "comes back" bits that sound troublesome.  I guess dead() might work, as long as it doesn't do anything to health.  I'd just have to change anything that says if(everyone_is_dead) to if(everyone_is_dead && !grabbing)

... something like that?

You could set a status to "held" or "grabbed" using a boolean and then, if it's true, you basically completely ignore everything in the update loop and make it invisible - disabling the enemy in essence.
From there, you play the necessary sprites for the player to attack with it, and then when they release, you turn off the boolean for "held" or "grabbed" and reset the x.y (and any other properties) so it appears back where it needs to be and is active again.
Certainly, you could also add some velocity/acceleration to it if you'd like, if the player throws it instead of just letting go. Although you may want to throw a "fake" enemy that is actually a projectile class that can damage the other enemies (and then set the enemies x,y to the projectile's final location once it comes to rest). You could also alter it's health which might kill it, since I doubt you want to throw something without killing it along with anything it hits.
Logged

Patience is a Virtue,
But Haste is my Life.
AcetheSuperVillain
Newbie
*
Posts: 42


The one and only


View Profile WWW
« Reply #10 on: Sat, Jul 31, 2010 »

I gotcha, so something like

Code:
override ... update()
{
  if(!grabbed){
    super.update();
  }
}

I can probably slog through that projectile stuff too.

Thanks for all the help, guys. 
Logged

Richard Kain
Full Member
***
Posts: 182


View Profile
« Reply #11 on: Mon, Aug 2, 2010 »

Another method would be to provide an FlxObject or FlxSprite to your enemy. This could be used for the whenGrabbed boolean value. When your player grabs the enemy, you would provide the Player itself as the FlxObject or FlxSprite that the enemy would reference. That way you could adjust the position of the Enemy character relative to the Player character while it's being "held." So in the enemy update loop, if the "grabbed" variable evaluates to true, it will take the reference to the "grabbee" object and update the enemie's x and y values relative to the "grabees" position.

You don't always need an exact reference within an object. Often times a generic reference is more useful and flexible. Not only would this allow the player to pick up the enemy, but it could allow other enemies to pick up the enemy as well. All you really need to know is the position of the object in control. And every FlxObject has its own specific location information.
Logged
Pages: [1]
  Print  
 
Jump to: