Forums → Programming Forum → How to make a perfect hitTest in as2?
32 | 29402 |
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
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"
}
}
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.
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.
@arobegamr
onClipEvent(enterFrame){
if(this.hitTest(_root._xmouse,_root._ymouse,true)){
trace("hit"
}
}
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"" right? You need to add the function there?
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" with all the stuff that you want to happen if the collision is happening.
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.
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)
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;
}
}
?
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
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
}
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.
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).
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:
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!
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?
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
Here is the link of my image:
http://kepfeltoltes.hu/view/110530/ma_www.kepfeltoltes.hu_.jpg
You must be logged in to post a reply!