我正在尝试制作纸牌游戏。现在显示它我使用Allegro API,它具有以下功能:
al_draw_rotated_bitmap(OBJECT_TO_ROTATE,CENTER_X,CENTER_Y,X
,Y,DEGREES_TO_ROTATE_IN_RADIANS);
因此,我可以轻松地使我的粉丝效果。问题在于知道哪个卡在鼠标下面。为此,我想到做多边形碰撞测试。我只是不确定如何旋转卡上的4个点来构成多边形。我基本上需要和Allegro做同样的操作。
例如,卡的4个点是:card.x
card.y
card.x + card.width
card.y + card.height
我需要一个像:
这样的功能POINT rotate_point(float cx,float cy,float angle,POINT p)
{
}
由于
答案 0 :(得分:288)
哦,这很简单..首先减去枢轴点(cx,cy),然后旋转它,然后再添加点。
未经测试的:
POINT rotate_point(float cx,float cy,float angle,POINT p)
{
float s = sin(angle);
float c = cos(angle);
// translate point back to origin:
p.x -= cx;
p.y -= cy;
// rotate point
float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;
// translate point back:
p.x = xnew + cx;
p.y = ynew + cy;
return p;
}
答案 1 :(得分:64)
如果您将点(px, py)
围绕点(ox, oy)
旋转角度θ,您将获得:
p'x = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox
p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy
这是一种在2D中旋转点的简单方法。
答案 2 :(得分:43)
屏幕上的坐标系是左撇子,即 x 坐标从左到右增加, y 坐标从上到下增加。原点O(0,0)位于屏幕的左上角。
具有坐标(x,y)的点的原点周围的顺时针旋转由以下等式给出:
其中(x',y')是旋转后的点的坐标和角度θ,旋转角度(需要以弧度表示,即乘以:PI / 180)。
要围绕与原点O(0,0)不同的点进行旋转,请说出A(a,b)点(轴心点)。首先,我们通过减去枢轴点的坐标(x - a,y - b)将要旋转的点(即(x,y))转换回原点。 然后我们执行旋转并获得新坐标(x',y'),最后我们通过将枢轴点的坐标添加到新坐标(x'+ a,y'+ b)来将点转换回来。 / p>
遵循以上描述:
使用你的函数原型:(x,y) - > (p.x,p.y); (a,b) - > (cx,cy); theta - >角:
POINT rotate_point(float cx, float cy, float angle, POINT p){
return POINT(cos(angle) * (p.x - cx) - sin(angle) * (p.y - cy) + cx,
sin(angle) * (p.x - cx) + cos(angle) * (p.y - cy) + cy);
}
答案 3 :(得分:21)
float s = sin(angle); // angle is in radians
float c = cos(angle); // angle is in radians
顺时针旋转:
float xnew = p.x * c + p.y * s;
float ynew = -p.x * s + p.y * c;
逆时针旋转:
float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;
答案 4 :(得分:1)
这是Nils Pipenbrinck的回答,但使用c#小提琴实现。
https://dotnetfiddle.net/btmjlG
using System;
public class Program
{
public static void Main()
{
var angle = 180 * Math.PI/180;
Console.WriteLine(rotate_point(0,0,angle,new Point{X=10, Y=10}).Print());
}
static Point rotate_point(double cx, double cy, double angle, Point p)
{
double s = Math.Sin(angle);
double c = Math.Cos(angle);
// translate point back to origin:
p.X -= cx;
p.Y -= cy;
// rotate point
double Xnew = p.X * c - p.Y * s;
double Ynew = p.X * s + p.Y * c;
// translate point back:
p.X = Xnew + cx;
p.Y = Ynew + cy;
return p;
}
class Point
{
public double X;
public double Y;
public string Print(){
return $"{X},{Y}";
}
}
}
Ps:显然我无法发表评论,所以我有义务将其发布为答案...
答案 5 :(得分:0)
我在使用MS OCR Read API时遇到了麻烦,该API返回的旋转角度范围为(-180,180]。因此,我必须执行一个额外的步骤,将负角度转换为正角度。我希望有人为负点旋转而苦苦挣扎或正角度可以使用以下内容。
def rotate(origin, point, angle):
"""
Rotate a point counter-clockwise by a given angle around a given origin.
"""
# Convert negative angles to positive
angle = normalise_angle(angle)
# Convert to radians
angle = math.radians(angle)
# Convert to radians
ox, oy = origin
px, py = point
# Move point 'p' to origin (0,0)
_px = px - ox
_py = py - oy
# Rotate the point 'p'
qx = (math.cos(angle) * _px) - (math.sin(angle) * _py)
qy = (math.sin(angle) * _px) + (math.cos(angle) * _py)
# Move point 'p' back to origin (ox, oy)
qx = ox + qx
qy = oy + qy
return [qx, qy]
def normalise_angle(angle):
""" If angle is negative then convert it to positive. """
if (angle != 0) & (abs(angle) == (angle * -1)):
angle = 360 + angle
return angle