我正在尝试旋转小行星(多边形)以使它们看起来很漂亮。我通过多个数学方程式做到这一点。首先,我给个体小行星一个旋转速度:
rotVel = ((Math.random()-0.5)*Math.PI/16);
然后我创建了多边形形状
this.shape = new Polygon();
然后生成积分,
for (j = 0; j < s; j++) {
theta = 2 * Math.PI / s * j;
r = MIN_ROCK_SIZE + (int) (Math.random() * (MAX_ROCK_SIZE - MIN_ROCK_SIZE));
x = (int) -Math.round(r * Math.sin(theta)) + asteroidData[0];
y = (int) Math.round(r * Math.cos(theta)) + asteroidData[1];
shape.addPoint(x, y);
}
最后,在循环中调用一个方法,在该方法中,它尝试将多边形及其点向下移动以及旋转它们。 (我只是粘贴旋转部件,因为另一个正在工作)
for (int i = 0; i < shape.npoints; i++) {
// Subtract asteroid's x and y position
double x = shape.xpoints[i] - asteroidData[0];
double y = shape.ypoints[i] - asteroidData[1];
double temp_x = ((x * Math.cos(rotVel)) - (y * Math.sin(rotVel)));
double temp_y = ((x * Math.sin(rotVel)) + (y * Math.cos(rotVel)));
shape.xpoints[i] = (int) Math.round(temp_x + asteroidData[0]);
shape.ypoints[i] = (int) Math.round(temp_y + asteroidData[1]);
}
现在,问题在于当它打印到屏幕上时,小行星似乎会变形“翘曲”。或者更确切地说,某些多边形点上的x和y位置浮动&#39;当然。
我注意到当我制作'rotVel&#39;是一个整数问题解决但小行星将以马赫速度旋转。所以我得出结论,问题必须在四舍五入,但无论我做什么,我都无法找到一种方法让它工作,因为Polygon对象需要一个整数数组。
有谁知道如何解决这个问题?
答案 0 :(得分:0)
你的问题肯定是由四舍五入到int
引起的!第一个改进是使所有形状坐标都为double
类型。这将解决您的大部分不必要的影响&#39;。
但即使使用double
,您也可能遇到令人讨厌的舍入错误,以防您进行大量非常小的坐标更新。解决方案很简单:只需避免小行星点的迭代更新。每次,您根据以前的坐标更新坐标,舍入误差将变得更糟。
相反,将旋转角度的字段添加到形状并增加它而不是点本身。在绘制形状之前,通过将旋转应用于点来计算最终位置。请注意,这永远不会改变点数。
您也可以将此概念扩展到其他转换(例如翻译)。你得到的是每种形状/物体的某种局部坐标系。形状的点在局部坐标系中定义。通过移动和旋转此系统,您可以将整个对象重新定位在空间的任何位置。
public class Shape {
// rotation and position of the local coordinate system
private double rot, x, y;
// points of the shape in local coordinate system
private double[] xp, yp;
private int npoints;
// points of the shape in world coordinates
private int[][] wxp, wyp;
private boolean valid;
public void setRotation(double r) { this.rot = r; valid = false; }
public void setPosition(double x, double y) { this.x = x; this.y = y; valid = false; }
public void addPoint(double x, double y) {
// TODO: add point to xp, yp
valid = false;
}
public void draw(...) {
if (!valid) {
computeWorldCoordinates(wxp, wyp);
valid = true;
}
// TODO: draw shape at world coordaintes wxp and wyp
}
protected void computeWorldCoordinates(int[] xcoord, int[] ycoord) {
for (int i = 0; i < npoints; i++) {
double temp_x = xp[i] * Math.cos(rot) - yp[i] * Math.sin(rot);
double temp_y = xp[i] * Math.sin(rot) + yp[i] * Math.cos(rot);
xcoord[i] = (int) Math.round(x + temp_x);
ycoord[i] = (int) Math.round(y + temp_y);
}
}
}