ForumsProgramming ForumHow to make a perfect hitTest in as2?

32 29979
Oseb
offline
Oseb
29 posts
Nomad

Hi everybody!
Im working on a game, but when i make a hitTest its not work perfectly (stops before reach the object). I use this code:

onClipEvent (enterFrame) {
if (_root.MC1.hitTest(this)) {
_root.MC1._y-= 5;
}
}

Any idea how to make it? Please explain it please.

  • 32 Replies
arobegamr
offline
arobegamr
130 posts
Nomad

The reason is that in flash, the hitTest function only detects collisions between bounding boxes, which are perfect rectangles which encompass the entire clips.
The only way to create perfect collisions between objects without going through an in-depth math-based engine is to check one specific point with a full movie clip.

Example:
onClipEvent(enterFrame){
if(this.hitTest(_root._xmouse,_root._ymouse,true)){
trace("hit&quot
}
}


The function hitTest can be used in two ways:
mc1.hitTets(mc2)
or
mc1.hitTest(pointx,pointy,true)
The third parameter in the second method tells flash whether to use just the bounding box, or evaluate the exact shape of the clip, which only works if flash is working with a point rather than a second full movie clip.

gaboloth
offline
gaboloth
1,612 posts
Peasant

Yeah, but remember that you can find loads of nice perfect hit test classes for free with google. For now, it's not fundamental that you understand how they work before using them.

Oseb
offline
Oseb
29 posts
Nomad

@arobegamr

onClipEvent(enterFrame){
if(this.hitTest(_root._xmouse,_root._ymouse,true)){
trace("hit&quot
}
}

You mean in the example that: mouse is an object which you give the intance name: mouse?
and in the code you dont need "trace("hit&quot" right? You need to add the function there?

gaboloth
offline
gaboloth
1,612 posts
Peasant

no, _xmouse e _ymouse are the two built-in flash variables for the mouse coordinates, but you can replace them with the coordinates of the point you want to hitTest.
and yes, you have to replace trace("hit&quot with all the stuff that you want to happen if the collision is happening.

Oseb
offline
Oseb
29 posts
Nomad

but if a write "_xmouse" then which object will my hero hits?
can you write me the code: my character (which i move with tehe arrows) called hero, the object that my hero hits called wall? I would be really glad if you would do that for me.

arobegamr
offline
arobegamr
130 posts
Nomad

Perfect hitTests cannot refer to a second movieclip, only a point. In the second example, _xmouse is not a clip, but a coordinate. By specifying _xmouse,_ymouse, you are telling flash to detect a collision with the mouse cursor.

It is, however, possible to check all corners of the hero's bounding box, while using the full second movie clip. For an example of how to do this, check out tonypa's tutorial: [url=http://www.tonypa.pri.ee/tbw/start.html]

(The tutorial covers much more than just that, and there is a lot more useful information)

Oseb
offline
Oseb
29 posts
Nomad

Thanks now i get it, but still dont understand xmouse and ymouse.
BTW is this code ok:

onClipEvent(enterFrame){
if(this.hitTest(_root._x=200,_root._y=200,true)){
this._y-= 5;
}
}

?

PixelSmash
offline
PixelSmash
566 posts
Nomad

Oseb: Your code isn't ok, what you're effectively doing is setting variables in your hittest coding - _root._x = 200. Depending on the outcome of setting this it will return either true or false I believe, but not any usable Number. Either remove the =200, or try getting your x and y values from somewhere else

arobegamr
offline
arobegamr
130 posts
Nomad

I think I know what you're trying to do, Oseb, but if you want to detect collision between the object and the coordinate (200,200), then you need to remove the _root._x=

Just have this as you're code:
onClipEvent(enterFrame){
if(this.hitTest(200,200,true)){
this._y-=5
}

Oseb
offline
Oseb
29 posts
Nomad

Thanks arobegamr!
But i have problem with the tird line: this._y-=5 if i add this then when my character reach the point he will be bounce back and if i hold the button then he will hit the wall perfectly, now i want to do the same. I mean don't dounce back just hit it.

Oseb
offline
Oseb
29 posts
Nomad

onClipEvent(enterFrame){
if(this.hitTest(200,200,true)){
this._y-=5
}

Now i want this code with only y cordinate in. Then how is it writen?
Because i deleted the first 200 but then the second one became the firts one (its became from Y to X coordinate). I want that my char wont go under Y 200 (its like a floor).

Programpro
offline
Programpro
562 posts
Nomad

onClipEvent(enterFrame){
if(this.hitTest(_root._x=200,_root._y=200,true)){
this._y-= 5;
}
}


Okay, firstly, _root is simply a Movie Clip. It refers to the stage itself. You know how you can place symbols within symbols? Well, all of the flash game's symbols are being placed inside _root. So if you say _root._x = 200, you're going to move EVERYTHING over by 200, because you're changing the origin (anchor point) of the stage.

I think you may have meant "this._x", or just "_x"; in most cases both mean the same thing, and refer to the x-coordinate of which movie clip your function is written for. Or better yet, just use numbers:

this.hitTest(200,200,true);

That will check against the point at x=200, y=200.

Also, what specifically are you trying to collide? Sometimes, a bounding circle (a circle around the object that collides with other objects) can be MUCH better than a bounding box. It's also much easier to write yourself and much more efficient:

Say that every object has a radius r that you assign them. This is the radius of their bounding circle. To check whether two bodies overlap, all you need to do is check the distance between them against the sum of their radii; if the radii add up to more than the distance between them, then there's no way for them not to overlap. Sorry, this diagram should make it clearer:

https://lh6.googleusercontent.com/-2o3uJx1a8U0/TeO7mUWdpCI/AAAAAAAAAA8/DWpFsTksgH4/BoundingCircle_Diagram.jpg

You could also set the radius up arbitrarily as half of the width of the MovieClip, so that you don't have to define variables. If you had one MovieClip named my_mc (I should say "if you had one reference to a MovieClip", but that's more technical Object-Oriented talk) and another named enemy_mc, the collision code within the my_mc object would look like:

onClipEvent(enterFrame) {

if(Math.sqrt((_x-_root.enemy_mc._x)^2 + (_y-_root.enemy_mc._y)^2) > (_width/2 + _root.enemy_mc._width/2)) {
//do this stuff if we overlap
}

}


This is pretty sloppy code; some easy optimizations would be to use ( )*( ) instead of ( )^2, because the exponent operator is slower than the multiplication one. Also, instead of ( )/2 + ( )/2 it could have been (( ) + ( ))/2. I just wrote it out so it would be easier to read.

So yeah, this uses a simple Pythagorean distance equation and checks it against the sum of their "radii". Circular bounding-boxes can provide some of the easiest and smoothest collisions you'd need, although they don't work in all occasions. If you want me to continue expounding on their use, let me know!
Oseb
offline
Oseb
29 posts
Nomad

http://kepfeltoltes.hu/view/110530/ma_www.kepfeltoltes.hu_.jpg


I want that my blue circle stops on the black wall. If my wall intance name is wall and my character's is char. Then with this code how is it sounds like?

onClipEvent(enterFrame) {
if(Math.sqrt((_x-_root.wall_char._x)^2 + (_y-_root.wall_char._y)^2) > (_width/2 + _root.wall_char._width/2)) {
_root.char._y-= 5;
}
}

this?

Programpro
offline
Programpro
562 posts
Nomad

Then with this code how is it sounds like?

onClipEvent(enterFrame) {
if(Math.sqrt((_x-_root.wall_char._x)^2 + (_y-_root.wall_char._y)^2) > (_width/2 + _root.wall_char._width/2)) {
_root.char._y-= 5;
}
}

this?


Sorry, sorry, I was unclear. My code works only for circle-on-circle collisions.

For circle-rectangle or rectangle-rectangle something more will be needed. Hmm...

Could you describe what you want in more detail? I can't see the picture
Oseb
offline
Oseb
29 posts
Nomad

Here is the link of my image:

http://kepfeltoltes.hu/view/110530/ma_www.kepfeltoltes.hu_.jpg

Showing 1-15 of 32