【COCOS2DX-游戏开发之三七】圆与旋转矩形的碰撞检测(下篇)
来源:互联网 发布:mac硬盘资料被隐藏 编辑:程序博客网 时间:2024/04/27 14:19
Circle and Rotated Rectangle Collision Detection
Circle and Rotated Rectangle
I’m going to explain how to implement collision detection for circle and rotated rectangle. Collision detection is determining if object A is hitting object B. A circle has center x y position with a radius. A rectangle contains left top x y position, width, height, and the angle to be rotated with. We assume a rectangle rotates around its center point.
I will use applet, pictures, and code to show this. I read this article as a reference to understanding collision detection between a circle and a rectangle not rotated.
Sample Applet
Here is a sample Applet to demonstrate collision detection. If collision is detected, the shapes turn blue. The green outlined shapes represent the state used to calculate. The orange line connects the center of unrotated circle to the closest point on rectangle. You can type in an angle and press the button to rotate. Click and/or drag anywhere to move the circle.
Implementing collision detection with a circle and rectangle with angle
The idea is simple. To perform the calculation, We need to have both shapes at the position when rectangle has 0 degree. It gets a little complicated if we rotate the rectangle with an angle. It’s easier to keep the rectangle straight with 0 degree to locate other points with simple addition. Top left is (x, y), top right is (x + width, y), and bottom left is (x, y + height).
Instead of rotating rectangle, rotate the circle back with the angle we were going to rotate rectangle. Put the circle’s center point to where it would be when rectangle’s angle is 0. Single point is easy to rotate. Looking at the rough picture, Blue shapes represent when rectangle is rotated and actually what we will see. Black shapes are used for calculation. We adjust the shapes with 0 degree or in other words, leaving the rectangle with 0 degree and rotating the circle back with rectangle’s angle instead.
The formula I used is below. Variable cx/cy stand for circle’s center point, originX/originY are the point we rotate the circle around, and x’/y’ are the rotated point.
x’ = cos(theta) * (cx – originX) – sin(theta) * (cy – originY) + originX
y’ = sin(theta) * (cx – originX) + cos(theta) * (cy – originY) + originY
Find the closest point from the unrotated circle and the rectangle. All we need to do is if-else comparisons for x and y separately.
For x, we use rectangle’s left x (rx) and right x (rx + width) to compare with circle’s center x (cx). If cx is on the left of rx, then rx is the closest x. Otherwise if cx is on the right of rx + width, then closest x is at rx + width. Finally, if none of 2 cases match, closest x point is cx itself. In the picture below, the red line is where the x will lie on.
The same rule applies for y. If circle’s center y (cy) is above top y (ry), ry is the closest y point. If cy is below the bottom y (ry + height) point, ry + height is the closest y point. If these cases don’t match, the closest y point is cy itself.
Lastly, we need to compute the distance from the unrotated circle’s center to the closest point we found earlier. I used the Pythagorean theorem to find that distance (a^2 + b^2 = c^2). Then you compare it with the circle’s radius. If distance is smaller than radius, the 2 shapes are colliding.
Sample Code
// Rotate circle's center point backdouble unrotatedCircleX = Math.cos(rect.angle) * (circle.x - rect.centerX) - Math.sin(rect.angle) * (circle.y - rect.centerY) + rect.centerX;double unrotatedCircleY = Math.sin(rect.angle) * (circle.x - rect.centerX) + Math.cos(rect.angle) * (circle.y - rect.centerY) + rect.centerY; // Closest point in the rectangle to the center of circle rotated backwards(unrotated)double closestX, closestY; // Find the unrotated closest x point from center of unrotated circleif (unrotatedCircleX < rect.x) closestX = rect.x;else if (unrotatedCircleX > rect.x + rect.width) closestX = rect.x + rect.width;else closestX = unrotatedCircleX ; // Find the unrotated closest y point from center of unrotated circleif (unrotatedCircleY < rect.y) closestY = rect.y;else if (unrotatedCircleY > rect.y + rect.height) closestY = rect.y + rect.height;else closestY = unrotatedCircleY; // Determine collisionboolean collision = false; double distance = findDistance(unrotatedCircleX , unrotatedCircleY, closestX, closestY);if (distance < circle.radius) collision = true; // Collisionelse collision = false;
/** * Pythagorean theorem * @param fromX * @param fromY * @param toX * @param toY */public double findDistance(double fromX, double fromY, double toX, double toY){ double a = Math.abs(fromX - toX); double b = Math.abs(fromY - toY); return Math.sqrt((a * a) + (b * b));}
原文链接:http://www.migapro.com/circle-and-rotated-rectangle-collision-detection/
- 【COCOS2DX-游戏开发之三七】圆与旋转矩形的碰撞检测(下篇)
- 【COCOS2DX-游戏开发之三六】圆与未旋转矩形的碰撞检测(上篇)
- 圆与旋转矩形的碰撞检测(下篇)
- 圆与旋转矩形的碰撞检测
- 圆与未旋转矩形的碰撞检测(上篇)
- 圆与矩形碰撞检测
- 矩形与圆碰撞检测
- 弹幕射击游戏中旋转矩形碰撞检测的算法描述
- cocos旋转矩形碰撞检测
- 游戏开发之碰撞检测
- Android游戏开发之检测游戏碰撞的原理实现
- 圆与矩形简单碰撞检测
- 圆,矩形碰撞检测
- 2D游戏中圆形与矩形碰撞检测
- 2D游戏碰撞检测--矩形与圆形
- 2D游戏中圆形与矩形碰撞检测
- 求旋转矩形的四个顶点坐标,用来做旋转矩形的碰撞检测
- android+unity3D游戏开发之简单的碰撞检测
- hdu 1176 免费馅饼 (dp 数塔类型)
- 《血液制品管理条例》
- 『ANDROID』Android中px dpi dip density densityDpi 的相关说明
- 八大排序算法
- PreparedStatement和Statement区别
- 【COCOS2DX-游戏开发之三七】圆与旋转矩形的碰撞检测(下篇)
- jmeter 插件使用
- Combination, subset
- GPU/APU加速库、算法及应用
- WINCE6 同时支持简繁体
- 如何正确入门Windows系统下驱动开发领域?
- C指针右左法则
- GIT分支管理是一门艺术
- cygwin完全安装步骤方法(组图)