AffineTransformOp.filter在非0,90,180,270度旋转时的奇怪行为

时间:2017-03-02 20:01:15

标签: java graphics affinetransform

所以我正在编写一个游戏,我试图让一个敌人在玩家四处移动时看一个玩家。我尝试使用以下代码旋转图像:

public static BufferedImage rotateImage(BufferedImage image, double radians) {
    //Rotate the given image by the angle
    AffineTransform at = AffineTransform.getRotateInstance(radians,image.getWidth()/2,image.getHeight()/2);
    AffineTransformOp atOp = new AffineTransformOp(at,AffineTransformOp.TYPE_BILINEAR);
    return atOp.filter(image,null);
}

图片在此处更新:

public void rotateEnemyImage() {
    double radians = Math.asin(xVel/Math.sqrt((yVel*yVel+xVel*xVel)));
    if (Math.abs(currentRotation - radians) > MINIMUMROTATION) {
        enemyImage = cemeteryfuntimes.Code.Shared.Utilities.rotateImage(enemyImage, radians - currentRotation);
        currentRotation = radians;
    }
}

(我知道计算弧度的公式并不完全正确我仍然在研究它,但是当敌人没有被正确绘制时很难修补)

我使用此代码绘制图像:

public void draw(Graphics2D g) {
    g.drawImage(enemyImage, Math.round(xSide+xPos), Math.round(ySide+yPos), null);
}

(xSide和ySide只是游戏边界的常量)

此代码适用于更改玩家正在查看的方向:

public void rotatePlayerImage(int direction) {
    //Rotate the image of the player
    int rotationAngle = shootDirection[direction];
    playerImage =        cemeteryfuntimes.Code.Shared.Utilities.rotateImage(playerImage,Math.toRadians(rotationAngle - currentRotation));
    currentRotation = rotationAngle;
}

(shootDirection是一个带有0,90,180和270的静态int数组)

但玩家只是在水平和垂直方向看。当我尝试传递的角度不是0,90,180或270度时,似乎不会围绕其中心旋转图像。图像被切断,似乎在某个任意轴上移动,然后程序停止运转。

Image of enemy after a few rotations

Original image of enemy

我不确定为什么这个轮换工作在90度倍数而不是其他任何东西。我已经尝试将玩家旋转更改为略微偏离0,90,180和270度,然后我从它看到相同的混乱行为。

1 个答案:

答案 0 :(得分:0)

您的代码中存在两个主要问题:

对于转换操作,您正在转换原始图像,因此会破坏'它

转换操作不准确,并且每步都会增加不准确性(或数据丢失)。实际上,AffineTransformOp.TYPE_BILINEAR意味着您正在进行双线性插值以计算'新形象,这是某种估计'。这就是为什么图像变得更加模糊'每次迭代。

而不是做"增量"与

中相同的图像
enemyImage = cemeteryfuntimes.Code.Shared.Utilities.rotateImage(
        enemyImage, 
        radians - currentRotation);

您应该保持原始图像不可变,不要对其进行任何更改,并且对于每个步骤,直接从原始图像计算所需的变换:

enemyImage = cemeteryfuntimes.Code.Shared.Utilities.rotateImage(
        sourceEnemyImage,
        currentRotation);

图像被截断

我不完全确定为什么会发生这种情况(虽然查看AffineTransformOp源代码我高度怀疑它,因为仿射变换会转换一些角落没有负坐标,并且由于某种原因{{1 }}方法选择只采取积极的部分),但你可以看到其他SO questions的解决方案(这可能会解决你的问题,但我还没有找到解释)。

截断问题的另一个解决方案是让你的敌人'在正方形图像的正中间,其长度与“敌人”相等(或者更大)。最大对角线。

为什么适用于直角?

如果我对负坐标的猜测是正确的,则它不适用于直角。此外,他们似乎有special treatment