momenimum Posted July 20, 2018 Share Posted July 20, 2018 Hi I know there is a hitTest against another container, but how can I hitTest a single x,y point? My sprite is a circle hit area. Thanks! Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted July 20, 2018 Share Posted July 20, 2018 What object would you like your container to hitTest with? with a point ? The built in physics module makes collisions very simple, and you don't need to use any physics at all. You just set all the physics parameters to 0. That's what I do in my game - I have my own physics, but I use built-in physics for collisions. You just collide bodies, which can be of circular or rectangular shape. Quote Link to comment Share on other sites More sharing options...
enpu Posted July 20, 2018 Share Posted July 20, 2018 Hi @momenimum Welcome to Panda 2 forum! So you want to hit test point against sprite that has circle hit area? You should be able to do that by just calculating the distance between the point and your sprite. If the distance is same or lower than the radius of your circle, then your point is inside the circle. var point = new game.Vector(100, 100); var dist = point.distance(sprite.position); if (dist <= sprite.hitArea.radius) { // Point is inside the circle } Quote Link to comment Share on other sites More sharing options...
momenimum Posted July 20, 2018 Author Share Posted July 20, 2018 Hi thanks for the replies. I am not using physics, I have a sprite and set the hitArea as a circle. I have a mouse down with an X, Y coordinate. Just wondering if there was something like sprite.hitTest(x,y) type function already there. I will just use the distance formula you suggested, thanks! Wolfsbane 1 Quote Link to comment Share on other sites More sharing options...
Wolfsbane Posted July 20, 2018 Share Posted July 20, 2018 The sprite.click() method won't work for you? Quote Link to comment Share on other sites More sharing options...
momenimum Posted July 20, 2018 Author Share Posted July 20, 2018 Correct me if I'm wrong, but I think click() is only mouse down then up. I want an event on mouse down only. I have a bunch of sprite targets, I want to know if just 1 hits with the mouse, or if the mouse misses. So instead of putting a listener on every sprite, I want to loop through all of them. If a hit is detected it would leave the loop, and if nothing hit it would be considered it a miss. I think if I put a listener on every sprite it would get a bit tricky. Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted July 20, 2018 Share Posted July 20, 2018 1 hour ago, momenimum said: Correct me if I'm wrong, but I think click() is only mouse down then up. I want an event on mouse down only. I have a bunch of sprite targets, I want to know if just 1 hits with the mouse, or if the mouse misses. So instead of putting a listener on every sprite, I want to loop through all of them. If a hit is detected it would leave the loop, and if nothing hit it would be considered it a miss. I think if I put a listener on every sprite it would get a bit tricky. Do you create those sprites all manually or they are created in a loop an have the same properties ? You could create a class that extends Sprite and have the mousedown event handled there and then create objects of this class and set the parameters with the constructor. No additional loop for checking hit would be needed then. Quote Link to comment Share on other sites More sharing options...
momenimum Posted July 20, 2018 Author Share Posted July 20, 2018 Hi @pstrejczek they are created in a loop with the same properties. My goal is to know at the moment the mouse is down, if any sprites were hit or it was a miss. For example there are 10 targets, if the mouse clicks a target, a hit sound is played, if the mouse hit nothing, a miss sound is played. I'm not sure how to do that without looping through all of them, especially with the miss and only 1 target can be hit at a time. Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted July 21, 2018 Share Posted July 21, 2018 Hi @enpu @momenimum Quote Just wondering if there was something like sprite.hitTest(x,y) type function I really think something like this would be a brilliant idea for Panda, and would really speed some tasks up. Having a circle against point, circle to circle + similar hitTest functions would be really cool. Flash had something similar back in the day and made things really straightforward Wolfsbane 1 Quote Link to comment Share on other sites More sharing options...
momenimum Posted July 21, 2018 Author Share Posted July 21, 2018 Yes I'm from the old flash games world Maybe sprite.hitTestPoint(pt) or sprite.hitTestPoint(x,y) that uses the current hitArea for testing. Quote Link to comment Share on other sites More sharing options...
Wolfsbane Posted July 21, 2018 Share Posted July 21, 2018 Yeah, I went through the code fully expecting there would be some kind of sprite collide with point method. I'd like to see. How do you think, @enpu ? ? Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted July 21, 2018 Share Posted July 21, 2018 This was actually an interesting topic for me, so I decided to give it a shot. Here is how I did it without update function and looping when checking collisions: game.module( 'game.main' ) .body(function() { game.addAsset('panda.png') game.createScene('Main', { init: function() { var bckg = new game.Graphics(); bckg.fillAlpha = 0; bckg.drawRect(0, 0, game.width, game.height); bckg.hitarea = new game.Rectangle(0, 0, game.width, game.height); bckg.interactive = true; bckg.mousedown = function() { console.log('Not sprite sound'); } bckg.addTo(this.stage); for(i = 0; i < 5; i++) { var sprt = new game.MyClass(i * 100 + 1, i* 100 + 1, 'panda.png'); sprt.sprite.addTo(this.stage); } }, }); game.createClass('MyClass', { init: function(posx, posy, texture) { this.sprite = new game.Sprite(texture, { x: posx, y: posy, interactive: true }); this.sprite.hitarea = new game.Rectangle(posx, posy, this.sprite.width, this.sprite.height), this.sprite.mousedown = function() { console.log('Sprite sound'); } } }); }); Maybe not the best solution in the world - but it works! I personally see no need for additional collision functions - everything I have encountered so far can be easily done with what we have. Wolfsbane 1 Quote Link to comment Share on other sites More sharing options...
momenimum Posted July 21, 2018 Author Share Posted July 21, 2018 @pstrejczek Very nice, I understand what you are saying now. A slight issue is that I wanted the hit or miss code in the same place. But it does 2 more things I needed, it picks based on the depth sort and it uses the existing hitareas of the sprite. So it works well for me, thanks! Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted July 21, 2018 Share Posted July 21, 2018 8 minutes ago, momenimum said: @pstrejczek Very nice, I understand what you are saying now. A slight issue is that I wanted the hit or miss code in the same place. But it does 2 more things I needed, it picks based on the depth sort and it uses the existing hitareas of the sprite. So it works well for me, thanks! Yes. There is a container in the background which is invisible and it takes the "miss" mousedown events. When it is covered with containers with sprites - those containers pick the event as "hit". The container concept is, in my opinion, one of the best ideas in Panda 2 engine. It makes a lot of things very easy to do. This way you don't have to iterate over all the sprites in update function. You could also add the sprites to the stage inside MyClass, so you could keep all the sprites code in one place. Quote Link to comment Share on other sites More sharing options...
enpu Posted July 23, 2018 Share Posted July 23, 2018 @pstrejczek is absolutely correct here. In your case just using mousedown events should be enough. Though there is some things wrong in your code example. bckg.hitarea = new game.Rectangle(0, 0, game.width, game.height); Correct property name is hitArea, not hitarea. First two parameters of Rectangle constructor are width and height, so you are creating rectangle with size of 0x0 pixels. Here is full example with one scene and two classes, where i'm creating 20 circles that move to the right. You remove them by clicking on them, and if you miss the background will flash red (by changing the background color of the scene): game.module( 'game.main' ) .body(function() { game.createScene('Main', { init: function() { var bg = new game.Background(); bg.addTo(this.stage); for (var i = 0; i < 20; i++) { var target = new game.TargetCircle(game.width.random(), game.height.random()); target.circle.addTo(this.stage); } } }); game.createClass('Background', 'Container', { init: function() { this.interactive = true; this.hitArea = new game.Rectangle(game.width, game.height); }, mousedown: function() { game.scene.backgroundColor = '#ff0000'; game.Timer.add(100, function() { game.scene.backgroundColor = '#000000'; }); } }); game.createClass('TargetCircle', { init: function(x, y) { this.radius = Math.random(20, 100); this.circle = new game.Graphics(); this.circle.drawCircle(0, 0, this.radius); this.circle.position.set(x, y); this.circle.hitArea = new game.Circle(this.radius); this.circle.interactive = true; this.circle.mousedown = this.mousedown.bind(this); }, mousedown: function() { this.circle.remove(); }, update: function() { this.circle.x += this.radius * 2 * game.delta; if (this.circle.x > game.width + this.radius) this.circle.x = -this.radius; } }); }); As you can see, to detect if i miss a circle or not, i'm using empty container with custom hitArea, in size of game.width x game.height. Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted July 23, 2018 Share Posted July 23, 2018 @enpu You are totally right - I have made those two mistakes - this code was actually a quick shot. It's interesting why this correctly worked with those mistakes ... If it wouldn't work, I would probably check this with the API. Anyway .. I work with the editor and engine almost every day in my free time, and still make that small mistakes ... Thanks for the example - I'm still learning proper use of the engine Quote Link to comment Share on other sites More sharing options...
Wolfsbane Posted July 24, 2018 Share Posted July 24, 2018 @enpu You put something in new in Dev? That sample code works in Dev branch, but not main branch. (FYI). Quote Link to comment Share on other sites More sharing options...
enpu Posted July 24, 2018 Share Posted July 24, 2018 @Wolfsbane Yeah there was a small bug, when using Circle as hitArea. That's fixed on dev branch. Wolfsbane 1 Quote Link to comment Share on other sites More sharing options...
enpu Posted July 24, 2018 Share Posted July 24, 2018 @pstrejczek The reason why your code worked was because this line bckg.hitarea = new game.Rectangle(0, 0, game.width, game.height); You are actually doing nothing. And if there is no custom hitArea defined, it will automatically use the container's dimensions for the hit area, when interactive is set to true. And this part var bckg = new game.Graphics(); bckg.fillAlpha = 0; bckg.drawRect(0, 0, game.width, game.height); bckg.hitarea = new game.Rectangle(0, 0, game.width, game.height); bckg.interactive = true; Would work exactly same as empty Container with custom hitArea: var bckg = new game.Container(); bckg.hitArea = new game.Rectangle(game.width, game.height); bckg.interactive = true; pstrejczek, Ninjadoodle and Wolfsbane 3 Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted July 24, 2018 Share Posted July 24, 2018 @enpu - Thanks for the explanations ... It's great we have so many interesting code-related engine topics on the forums. I'm learning a lot from them Wolfsbane and Ninjadoodle 2 Quote Link to comment Share on other sites More sharing options...
enpu Posted July 24, 2018 Share Posted July 24, 2018 On 7/21/2018 at 3:23 AM, Ninjadoodle said: Having a circle against point, circle to circle + similar hitTest functions would be really cool. I can't just create "circle to point" or "circle to circle" functions, because there are many things that can be circle. Sprite texture, hit area, graphics shape, shape of physics body etc. I have modified hitTest function in Container, so that you can also use Vector as a target parameter. Also there is now second parameter, which if you set to true, will calculate the hit as if the container was a circle (and also the target if it's a container too). So there are now 4 different ways to use hitTest function: sprite1.hitTest(sprite2) sprite1.hitTest(sprite2, true); // Hit test as circles sprite1.hitTest(game.input.mouse); // Hit test against Vector sprite1.hitTest(game.input.mouse, true); // Hit test against Vector as a circle Ninjadoodle and pstrejczek 2 Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted July 24, 2018 Share Posted July 24, 2018 Hi @enpu That's very cool! Thank you very much for these additions, these will definitely come in handy Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted July 24, 2018 Share Posted July 24, 2018 Awesome work @enpu ! Could you please put this in the examples section? This is quite important and I'm sure many people in the future will ask about this. I see there is a polygon hitArea in the roadmap for the next engine version (2.10). Does it mean detecting a collision of (for example) circle with polygon will be possible? This would be awesome! Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
momenimum Posted July 24, 2018 Author Share Posted July 24, 2018 Hi @enpu thanks very much for these new functions! Just want to make sure, when you say "circle" you mean whatever hitArea (Circle or Rectangle) the sprite was set to? Quote Link to comment Share on other sites More sharing options...
enpu Posted July 24, 2018 Share Posted July 24, 2018 @pstrejczek Yeah i will update the examples in the website as soon as those new changes are merged into the master branch, which means releasing next version of engine (2.10.0). @momenimum Now that you asked, i think i made things a bit too complicated. hitTest function should really use the container's hitArea for the hit testing (not bounds like it currently uses). That would mean that you could do this: sprite1.hitTest(sprite2); Which would mean that it does hit test for sprite1's hitArea against sprite2's hitArea, which both could be either Rectangle or Circle (or even Polygon in future). Then if the parameter is Vector instead of Container, it would make the hit test against that. I think that would be a lot cleaner and easier to understand solution. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.