kristof

How to update hitArea of a sprite

Recommended Posts

Hy everyone, 

My question is about the hitArea of a sprite. First of all I am not quite sure if I understood the definition correctly, so I would really appreciate a clear explanation about it. 

What I want to do is: I have sprites in my game and I would test collision between them, but the sprite's width and height is not perfectly accurate to its 'actual appearance' so I would reduce the hitArea to improve my collision detection algorithm (but sometimes setting the hitArea is making it worse than using just the regular .getBounds() function).

This is how I did it for the first time but collision didn't occur.

let player = new PIXI.Sprite(texture); 
player.position.set(75, app.stage.view.height / 2);
player.anchor.set(0.5);

player.hitArea = new PIXI.Rectangle(player.x, player.y, 60, 20);

Later I found out that it is because the enemy that I am checking the collision against, is not being compared to my player object, but the initial coordinates of the PIXI.Rectangle that I use to modify hitArea with.

I have found out that if I want to compare the player.hitArea of the current position of my player object to enemy.getBounds(), in my game loop I update the hitArea of player like: 

app.ticker.add( () =>{
player.x += player.velocityX;
player.y += player.velocityY;
player.hitArea = new PIXI.Rectangle(player.x, player.y, 75, 85);
};

 I feel like this is a poor solution that I have came up with. Is there a better way of always updating hitArea coordinates to the player object's current coordinates? 

Share this post


Link to post
Share on other sites

Here is Sprite default area: https://github.com/pixijs/pixi.js/blob/dev/packages/sprite/src/Sprite.js#L433 , Pixi converts coords to local and then it checks rect (-anchor.x * w, -anchor.y * h, (1-anchor.x)*w, (1-anchor.y) * h)

If you want different w,h , your hitArea has to be relative that (0,0) that is CENTER of your sprite because you specified anchor=0.5. It'll be like (-30, -10, 60, 20) 

Share this post


Link to post
Share on other sites

So if I did not set anchor of the sprite I would always just use (0,0, widthValue, heightValue) and no need to ever update it? 

And when anchor is set to center of the sprite as 0.5 then it is (-widthValue/2, -heightValue/2, widthValue, heightValue)? 

Sorry for asking silly questions I just want to make sure that I understand it :)

Share this post


Link to post
Share on other sites

Exactly. But sprite checks that rectangle anyway in `containsPoint`. you are not sure that its different from your sprite dimensions.

However, hitArea behaviour is different if element has children, I cant explain it, just give you the code: 

https://github.com/pixijs/pixi.js/blob/dev/packages/interaction/src/InteractionManager.js#L1030

https://github.com/pixijs/pixi.js/blob/dev/packages/interaction/src/InteractionManager.js#L1105

So, why do you need hitArea?

Share this post


Link to post
Share on other sites

I used hitArea because coming from it's name I thought it would solve my issue. I have used the bounding box collision detection algorithm in my game, but when I tested it for some reason I had some gaps between my 2 objects when I already got the collision alert. For this reason I thought if I reduce the size of my target sprite (its hitArea) the algorithm would work fine. Am I approaching the problem in a bad way? Do you have any suggestions? 

Share this post


Link to post
Share on other sites

yeah, its a good idea, but getBounds() is not related to hitArea and to get collisions you have to convert that hitArea to global coords first... Maybe you need you own field there , and convert it every frame? I don't know , there are so many ways to do that, and its just general JS game implementation problem, not pixi problem. And if you start rotations there , getBounds() will still get you normal and not rotated rectangle, so it'll collide on corners where its not supposed to.. Its a big topic, I don't believe I have time to discuss it.

What I can is to give you the references, but you have to look in docs and sources yourself. "Bounds.addFrame(transform, x0, y0, x1, y1)" can convert local bounds to global using element transform, of course if you understand what `Bounds` is and why did we make that class. You have to store your stuff in different field, because hitArea exists for interaction and not for collision. In general, NOTHING in pixi exists for collision, collision has to be your engine problem, the engine you are building on top of pixi.

Share this post


Link to post
Share on other sites

My objects do not rotate, they only move on the x axis so I guess I do not have to worry about the 'Bound' class, or do I? 

What I intended to do is: 

if(doCollied(player.getBounds(), enemy.hitArea)){
   //collision handling
}

Are you telling me that I cannot compare these 2 even though they both have their width, height, x, y properties?

I have checked the toGlobal() method in the docs, do I just apply on enemy.hitArea or what did you mean by that? 

Share this post


Link to post
Share on other sites

yeah, because hitArea is supposed to be local. If you want it to be global, name it something else , or it will affect interaction. toGlobal() wont work on rectangle, you have to develop your own method (THE HORROR!) of transforming stuff. I think I gave you enough links to source code to get some info from it ;)

We are talking about intersection of two rectangles each with their own transform, that's a 1st grade college material, I dont know how to explain simple things, I just sit and write them like they are nothing special :(

Share this post


Link to post
Share on other sites

Thank you for the answers, and the codepen link as well, the way I have solved the issue is that I was playing around with replacing my sprites with pure rectangles with the height and width of the player and the enemy sprites, and compared them to the actual sprites' appearance. I found out that the height of my player sprite is approximately twice as big as the player's sprite's height, so what I did was in the collision checking algorithm I divided height by 2 and I got an approximately perfect solution without the need of using hitArea :)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Recently Browsing   0 members

    No registered users viewing this page.