Ninjadoodle Posted March 29, 2018 Share Posted March 29, 2018 Hi @enpu I'm having a bit of an issue with collision detection, as I'm in need of a circle vs rotated square collision. I know there are some libraries out there, that handle this sort of thing (for games that don't require physics). I'm not really sure tho, if there is an easy way to do something like this in panda without using physics or having to resort to coding your own classes. I know it's a different story, but in Construct this is handled by setting up collision shapes for each object. The hit-test is then done on these collision shapes - even without physics. Is something like this possible in Panda to make collision a little easier to implement? Quote Link to comment Share on other sites More sharing options...
pstrejczek Posted March 29, 2018 Share Posted March 29, 2018 I'm actually also interested in that. I couldn't find anything built in into the engine except hitTest for sprite or container. The collision shapes are one thing, but also more data would be great (f.ex. direction of collision - was the object hitted from above, below, left or right). I can see I can do everything that with P2 plugin, but when I'm not interested in advanced physics or want to do my own simple one, P2 is a little overkill. Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
enpu Posted March 29, 2018 Share Posted March 29, 2018 Hit detection in the built-in physics are only for non-rotated rectangles and circles. I want to keep the built-in physics engine as simple as possible and adding hit detection for rotated rectangles would mean that it should then also include collision solving for those, which would make it a lot more complicated. As @pstrejczek said, this can be done with P2, but if you are only looking for the hit detection and nothing more, P2 might be a bit overkill. I found this JavaScript function for circle vs rotated rectangle hit detection: https://gist.github.com/snorpey/8134c248296649433de2 Should be pretty easy to implement that to your needs. Let me know if you need help with that one. Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted March 31, 2018 Author Share Posted March 31, 2018 Hi @enpu Thank you for the link! I managed to get the function working, but it still doesn't seem to be very precise. Not too sure if I'm using all the values correctly, but the ships still seem to be getting hit quite a few pixels off (visibly). Any chance of getting a simpler way of doing this implemented in Panda (if you want to avoid P2)? Thanks heaps! Quote Link to comment Share on other sites More sharing options...
enpu Posted April 3, 2018 Share Posted April 3, 2018 @Ninjadoodle I also tried that hit test function and you are right, it's not working properly. I will take a closer look on it asap, or then try to find another one. Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
enpu Posted April 6, 2018 Share Posted April 6, 2018 @Ninjadoodle & @pstrejczek Finally got it working, here is live example: https://www.panda2.io/examples#misc-hittest (use mouse to move the circle, click to change rectangle position) As you can see the hit test function is actually pretty simple Note that this version only works on sprites with anchor point at center. Ninjadoodle and pstrejczek 2 Quote Link to comment Share on other sites More sharing options...
enpu Posted April 6, 2018 Share Posted April 6, 2018 https://www.panda2.io/examples#misc-hittest2 And here is version that works with any anchor points Ninjadoodle 1 Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 7, 2018 Author Share Posted April 7, 2018 @enpu - Legend, thank you for figuring it out! Just curious - these 'misc' examples - I can't seem to find them in the menu on the left, only through the links you post here. They would be really useful to include for reference Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 7, 2018 Author Share Posted April 7, 2018 @enpu - I'm looking through the functions and I can't see anywhere you're actually setting up the circle and rectangle sizes etc. It's late and I might be missing something Quote Link to comment Share on other sites More sharing options...
enpu Posted April 8, 2018 Share Posted April 8, 2018 @Ninjadoodle https://www.panda2.io/examples Just added the misc examples in the bottom of the list. I modified the hit test function, so you can define rectangle width and height as well as the circle radius. Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 9, 2018 Author Share Posted April 9, 2018 @enpu For some reason I'm still not getting precise collision with moving bullets. I'm using the function as in the example, but for some reason, my bullets seem to be hitting / destroying the enemy 'visibly' off by quite a few pixels (visually it looks like 20-40 pixels). I'm not really sure what I'm doing wrong tho. Any ideas on what could be a cause of something like this? PS. My bullets are moving pretty slow but my circular enemies are constantly rotating. Quote Link to comment Share on other sites More sharing options...
enpu Posted April 9, 2018 Share Posted April 9, 2018 Really hard to say without any code example Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 9, 2018 Author Share Posted April 9, 2018 Hi @enpu Here is my laser class and my enemy class - I've tried different sizes for the circle and rectangle, like in your updated function, but things still seem very off for me. I'm doing the hitTest in the bottom of the Laser class game.createClass('Spinvader', { rot: 2, init: function(x, y) { this.sprite = new game.Sprite('spinvader.png'); this.sprite.position.set(x, y); this.sprite.anchorCenter(); this.sprite.alpha = 0; this.sprite.addTo(game.scene.mg); var angle = this.sprite.position.angle(game.scene.playerShip.sprite.position); var distance = this.sprite.position.distance(game.scene.playerShip.sprite.position) - 256; var xPos = this.sprite.position.x + distance * Math.cos(angle); var yPos = this.sprite.position.y + distance * Math.sin(angle); game.Tween.add(this.sprite, { alpha: 1 }, 500, { easing: 'Linear.None' }).start(); this.tween1 = game.Tween.add(this.sprite, { x: xPos, y: yPos }, 2000, { easing: 'Quadratic.In' }).onComplete(function() { game.scene.stageSetup.shake(game.scene.gm, 10, 250); this.rot *= -1; }.bind(this)).start(); this.tween2 = game.Tween.add(this.sprite, { x: x, y: y }, 2500, { easing: 'Quadratic.Out' }).onComplete(function() { this.tween1.start(); }.bind(this)).stop(); this.tween1.chain(this.tween2); }, update: function() { this.sprite.rotation += this.rot * game.delta; }, remove: function() { game.Tween.stopTweensForObject(this.sprite); game.scene.spinvaders.erase(this); this.sprite.remove(); game.scene.shot ++; game.scene.progressCheck(); } }); game.createClass('Laser', { init: function() { this.sprite = new game.Sprite('laser.png'); this.sprite.position.set(game.scene.playerShip.sprite.x, game.scene.playerShip.sprite.y); this.sprite.anchorCenter(); this.sprite.rotation = game.scene.playerShip.sprite.rotation; this.sprite.addTo(game.scene.bg); game.Timer.add(2000, this.remove.bind(this)); }, remove: function() { this.sprite.remove(); game.scene.removeObject(this); }, update: function() { this.sprite.position.x += game.scene.laserSpeed * Math.cos(this.sprite.rotation - (0.5 * Math.PI)) * game.delta; this.sprite.position.y += game.scene.laserSpeed * Math.sin(this.sprite.rotation - (0.5 * Math.PI)) * game.delta; // Reverse for loop for (var i = game.scene.spinvaders.length - 1; i >= 0; i--) { var enemy = game.scene.spinvaders[i]; if (game.scene.hitTest(this.sprite, enemy.sprite)) { enemy.remove(); this.remove(); } } } }); Quote Link to comment Share on other sites More sharing options...
enpu Posted April 9, 2018 Share Posted April 9, 2018 The hit test function uses local positions for the hit detection. So if your rect and circle has different origin (position 0,0 is not same place) then that is definitely the issue. To fix that, you should get world positions for both and then replace all the rect.x, rect.y, circle.x, circle.y values Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 9, 2018 Author Share Posted April 9, 2018 Hi @enpu Thanks for your reply, but to be honest I'm not really getting it From what I can tell - what I'm doing is no different that what I see on Panda Examples, yet its doesn't seem to work like yours. Might have to play with it some more and see what I can do. Quote Link to comment Share on other sites More sharing options...
enpu Posted April 9, 2018 Share Posted April 9, 2018 Well do you understand the difference between local and world position? I can see that you are adding your laser.png to game.scene.bg container and spinvader.png to game.scene.mg container? Is the world positions of those containers same? If not then that's your problem. Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 9, 2018 Author Share Posted April 9, 2018 @enpu - Ok sorry I understand - but yeah it's the same. Just tried changing both to the same container but it's still off. Quote Link to comment Share on other sites More sharing options...
enpu Posted April 9, 2018 Share Posted April 9, 2018 Hmm interesting, then that's not the issue. Could you test your images (laser and spinvader) with the example scene: https://www.panda2.io/examples#misc-hitTest Does it work as expected? Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 9, 2018 Author Share Posted April 9, 2018 Hi @enpu - So, I've played with the images and did what you suggested, and part of the problem is that I have transparent pixels around the image. I've been trying to use the setting in your new function to set the size of the rect and circle to make it different than the size of the image. Cutting out the transparent pixels makes it work ... however, I need the images with the transparent pixels and adjusting the size using the function properties doesn't seem to work right - the hitTest is very off. Thanks for your help! Quote Link to comment Share on other sites More sharing options...
enpu Posted April 9, 2018 Share Posted April 9, 2018 Oh well then that's the issue, the hitTest function assumed that you are using the whole image. It used the rectWidth and rectHeight values to determine the center position of the rectangle, but since you were using values that are lower than the actual image, the center position would be off. hitTest: function(rect, circle, rectWidth, rectHeight, circleRadius) { rectWidth = rectWidth || rect.width; rectHeight = rectHeight || rect.height; circleRadius = circleRadius || circle.width / 2; var rectCenterX = rect.x + Math.cos(rect.rotation) * (rect.width / 2 - rect.anchor.x) - Math.sin(rect.rotation) * (rect.height / 2 - rect.anchor.y); var rectCenterY = rect.y + Math.sin(rect.rotation) * (rect.width / 2 - rect.anchor.x) + Math.cos(rect.rotation) * (rect.height / 2 - rect.anchor.y); var circleCenterX = circle.x - circle.anchor.x + circleRadius; var circleCenterY = circle.y - circle.anchor.y + circleRadius; var circleX = Math.cos(-rect.rotation) * (circleCenterX - rectCenterX) - Math.sin(-rect.rotation) * (circleCenterY - rectCenterY) + rectCenterX; var circleY = Math.sin(-rect.rotation) * (circleCenterX - rectCenterX) + Math.cos(-rect.rotation) * (circleCenterY - rectCenterY) + rectCenterY; var close = new game.Vector(circleX, circleY); if (circleX < rectCenterX - rectWidth / 2) { close.x = rectCenterX - rectWidth / 2; } else if (circleX > rectCenterX + rectWidth / 2) { close.x = rectCenterX + rectWidth / 2; } if (circleY < rectCenterY - rectHeight / 2) { close.y = rectCenterY - rectHeight / 2; } else if (circleY > rectCenterY + rectHeight / 2) { close.y = rectCenterY + rectHeight / 2; } if (close.distance(circleX, circleY) < circleRadius) return true; }, Try this one Quote Link to comment Share on other sites More sharing options...
Ninjadoodle Posted April 9, 2018 Author Share Posted April 9, 2018 @enpu - Thanks heaps, that's seems a lot better When testing with the playground example code, it works well. When shooting the lasers there is still some visible pixels in-between, but I think that might just be the way I've coded it or some sort of update issue. 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.