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

AffineTransformOp.filter strange behavior when rotating by non 0,90,180,270 degrees

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

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 度,然后我从中看到了同样混乱的行为。

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

对于转换操作,您正在转换原始图像,因此 'destroying' 它。

转换操作不准确,每一步都会增加不准确性(或数据丢失)。实际上,AffineTransformOp.TYPE_BILINEAR 意味着您正在对 'calculate' 新图像进行双线性插值,这是某种 'estimation'。这就是每次迭代图像变得更多 'blurry' 的原因。

而不是对

中的同一图像进行 "increments"
enemyImage = cemeteryfuntimes.Code.Shared.Utilities.rotateImage(
        enemyImage, 
        radians - currentRotation);

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

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

图像被截断

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

截断问题的另一种解决方案是让 'enemy' 位于正方形图像的正中间,该正方形图像的长度等于(或大于)'enemy' 最大对角线。

为什么适用于直角?

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