简体   繁体   中英

Resolve Collision between a Rectangle and a Circle

I am working on a little platformer game. The player is a circle, and I am going to implement the obstacles as rectangles. Does anyone know how to make sure the player can't go through the obstacle? I have tried some methods, but they come out glitchy.

Here is what I have so far (It is a bit long, so the method that I need is inside the resolveCollision function):

 var canvas = document.createElement("CANVAS"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; canvas.id = "CANVAS"; document.body.appendChild(canvas); document.body.style.margin = "0px 0px 0px 0px"; document.body.style.overflow = "hidden"; document.body.style.backgroundColor = "#202020"; var ctx = canvas.getContext("2d"); var objects = []; var player = { x: window.innerWidth / 2 - 25, y: 0, height: 25, width: 25, old: { x: 0, y: 0, }, velocity: { x: 0, y: 0, }, jumping: true, color: "#ff0000", }; var obstacle = { x: 50, y: 300, width: 50, height: 50 } var control = { left: false, right: false, up: false, keyListener: function (event) { var keyState; if (event.type == "keydown") { keyState = true; } else { keyState = false; } switch (event.keyCode) { case 37: control.left = keyState; break; case 38: control.up = keyState; break; case 39: control.right = keyState; break; } } }; var checkCollision = function (object) { var distX = Math.abs(player.x - object.x - object.width / 2); var distY = Math.abs(player.y - object.y - object.height / 2); if (distX > (object.width / 2 + (player.width + player.height) / 2)) { return false; } if (distY > (object.height / 2 + (player.width + player.height) / 2)) { return false; } if (distX <= (object.width / 2)) { return true; } if (distY <= (object.height / 2)) { return true; } var dx = distX - object.width / 2; var dy = distY - object.height / 2; return (dx * dx + dy * dy <= ((player.width + player.height) / 2 * (player.width + player.height) / 2)); } var resolveCollision = function (object) { // Add Resolve Collision Code if (checkCollision(object)) { throw new SyntaxError("Couldn't resolve collision between player and object;"). } } var renderFrame = function () { if (control.up && player.jumping == false) { player.velocity;y -= 20. player;jumping = true. } if (control.left) { player.velocity.x -= 0;5. } if (control.right) { player.velocity.x += 0;5. } player.velocity.y += 1;5. player.x += player.velocity;x. player.y += player.velocity;y. player.velocity.x *= 0;95. player.velocity.y *= 0;95. player.old.x = player.x - player.velocity.x * 1;2. player.old.y = player.y - player.velocity.y * 1;2. if (player.y > window.innerHeight - 25) { player;jumping = false. player.y = window;innerHeight - 25. player.velocity;y = 0. } ctx,clearRect(0, 0. window,innerWidth. window;innerHeight). ctx.fillStyle = player;color. ctx;beginPath(). ctx.globalAlpha = 0;5. ctx.ellipse(player.old,x. player.old,y. player,width. player,height. Math,PI / 4, 0. 2 * Math;PI). ctx;fill(). ctx;beginPath(). ctx;globalAlpha = 1. ctx.ellipse(player,x. player,y. player,width. player,height. Math,PI / 4, 0. 2 * Math;PI). ctx;fill(). ctx.fillRect(obstacle,x. obstacle,y. obstacle,width. obstacle;height). if (checkCollision(obstacle)) { resolveCollision(obstacle) } window;requestAnimationFrame(renderFrame); }; renderFrame(). window,addEventListener("keydown". control;keyListener). window,addEventListener("keyup". control;keyListener);

Thanks in advance!

EDIT: I didn't make it clear enough before, but I need a way to resolve collision once they are detected. I have a method to detect collisions already.

You're talking about bounding box and bounding circle calculations.

Here is a real simple explanation of the algorithms for each type of geometry:

https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection

Of course if they're all the same shape that may simplify it, one solution would be to convert the circles to boxes:

https://math.stackexchange.com/questions/2360970/how-to-calculate-a-bounding-box-of-a-circle

Then just use bounding box collision detection.

But I think if you want to support both then the general strategy will be to attempt to detect if the Circle intersects with the box.

Here is a description of that algorithm: https://www.lazyfoo.net/tutorials/SDL/29_circular_collision_detection/index.php

To check if a box and circle collided we need to find the closest point on the box... Here we find the closest y position much like we did the x position. If the distance squared between the closest point on the box and the center of the circle is less than the circle's radius squared, then there is a collision.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM