我最近看到了一个与Java中如何旋转图像有关的问题(此处为外部链接),我直接从那个答案中复制/粘贴了代码。实践证明,它似乎只能旋转正方形图像(即具有相同大小、宽度和高度的图像)。当我尝试将其用于非正方形图像时,它似乎会切掉那部分使其成为矩形的部分,如果这样说的话。就像这样
。
我该如何解决/解决这个问题?
编辑:我正在使用的代码。此外,由于这将是一个“游戏”,因此我不会有滚动条,并且也不会一直处于全屏状态。
![](https://istack.dev59.com/SiMDT.webp)
public class Player extends Entity { //Entity has basic values such as (float) x & y values, along with some getters and setters
double theta;
Reticle reticle; //draws a reticle where the cursor was(basically just replaces java.awt.Cursor due to something not neccessary for me to get into)
Sprite currentImage; //basically just a BufferedImage that you can apply aspect ratios to
//constructor
@Override
public void tick() {
//(this line) gets the Reticle from the main-method class and set it to this reticle object
reticleX = reticle.getX(); //basically gets the mouse coordinates
reticleY = reticle.getY();
x += dX; //delta or change in X
y += dY //delta or change in Y
checkCollision(); //bounds checking
//getCentralizedX()/Y() gets the center of the currentImage
theta = getAngle(getCentralizedX(), getCentralizedY(), reticleX, reticleY);
currentImage = Images.rotateSprite(currentImage, theta);
}
@Override
public void render(Graphics g) {
currentImage.render(g, x, y);
g.drawLine((int) getCentralizedX(), (int) getCentralizedY(), (int) reticleX, (int) reticleY);
}
public double getAngle(float startX, float startY, float goalX, float goalY) {
double angle = Math.atan2(goalY - startY, goalX - startX);
//if(angle < 0) { //removed this as this was the thing messing up the rotation
//angle += 360;
//}
}
如果士兵的角度在90 < angle < 270之间,那么它是(基本上)正确的,但如果它的角度在90 > angle > 270,则会有一些问题。这里有一些图片。问题不在于瞄准线(蓝色线)的角度不正确。
删除了所有图片,因为在getAngle()
中移除了if(angle < 0)
可以解决旋转错误的问题。现在唯一的问题是它不能原地旋转。
编辑2:我用相同的方法制作的SSCCE,在某些情况下会出现问题。
public class RotateEx extends Canvas implements Runnable {
Player player;
public RotateEx(BufferedImage image) {
player = new Player(image, 50, 50);
setPreferredSize(new Dimension(600, 600));
}
public void setDegrees(int degrees) {
player.theta = Math.toRadians(degrees);
}
public BufferedImage rotateImage(BufferedImage original, double theta) {
double cos = Math.abs(Math.cos(theta));
double sin = Math.abs(Math.sin(theta));
double width = original.getWidth();
double height = original.getHeight();
int w = (int) (width * cos + height * sin);
int h = (int) (width * sin + height * cos);
BufferedImage out = new BufferedImage(w, h, original.getType());
Graphics2D g2 = out.createGraphics();
double x = w / 2; //the middle of the two new values
double y = h / 2;
AffineTransform at = AffineTransform.getRotateInstance(theta, x, y);
x = (w - width) / 2;
y = (h - height) / 2;
at.translate(x, y);
g2.drawRenderedImage(original, at);
g2.dispose();
return out;
}
public void tick() {
player.tick();
}
public void render() {
BufferStrategy bs = this.getBufferStrategy();
if(bs == null) {
createBufferStrategy(4);
return;
}
Graphics g = bs.getDrawGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
player.render(g);
g.dispose();
bs.show();
}
public static void main(String args[]) throws IOException, InterruptedException {
String loc = "FILELOCATION"; //of course this would be a valid image file
BufferedImage image = ImageIO.read(new File(loc));
final RotateEx ex = new RotateEx(image);
final JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 360, 0);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
int value = slider.getValue();
ex.setDegrees(value);
}
});
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(ex);
f.add(slider, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
new Thread(ex).start();
}
@Override
public void run() {
long lastTime = System.nanoTime();
final double numTicks = 60.0;
double n = 1000000000 / numTicks;
double delta = 0;
int frames = 0;
int ticks = 0;
long timer = System.currentTimeMillis();
while (true) {
long currentTime = System.nanoTime();
delta += (currentTime - lastTime) / n;
lastTime = currentTime;
render();
tick();
frames++;
if (delta >= 1) {
ticks++;
delta--;
}
}
}
class Player {
public float x, y;
int width, height;
public double theta; //how much to rotate, in radians
BufferedImage currentImage; //this image would change, according to the animation and what frame its on
public Player(BufferedImage image, float x, float y) {
this.x = x;
this.y = y;
width = image.getWidth();
height = image.getHeight();
currentImage = image;
}
public void tick() {
currentImage = rotateImage(currentImage, theta);
}
public void render(Graphics g) {
g.drawImage(currentImage, (int) x, (int) y, null);
}
}
}
RotatedIcon
不是一个有效的类。我在谷歌上搜索了一下,甚至找不到Oracle关于它的文档。它不是一个单独的库,对吧? - Gannon PrudhommeRotatedIcon
。但是今天早上我试图实现它,结果它完美地运作了。我无法感谢你们的帮助。 - Gannon Prudhomme