【问题标题】:AffineTransform mouse aiming rotation stutter on 90 degreesAffineTransform 鼠标瞄准旋转 90 度口吃
【发布时间】:2011-05-05 22:50:25
【问题描述】:

编辑: 哦!!!!! 有用!!! 似乎在某一时刻它已被修复但是打开了错误的 HTML 文件,因此运行了错误的代码。我觉得很愚蠢,这应该是显而易见的。

但是谢谢!!!

能在这些东西上获得一些帮助真是太棒了。每当我在其他任何地方寻求帮助,甚至问我的老师时,我通常都会忽略或得到无用的建议。 (编辑结束)

我正在为我的最终项目在 java 类中制作游戏。我刚刚让鼠标瞄准使用 AffineTransform 工作,但是当玩家对象旋转到 90 度(或它的倍数)时,它会发生这种奇怪的口吃。 这是我特别关心的代码。

    g2.drawImage(img, x_pos,y_pos,this);
    AffineTransform oldTransform = g2.getTransform();

g2.setTransform(AffineTransform.getRotateInstance(radAngle,x_pos +   (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));

有人可以帮我弄清楚如何解决这个问题吗?我的项目明天到期,所以我很准时。 这是我使用的图像

这是代码。

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.lang.Math.*;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import javax.imageio.ImageIO;
import java.io.*;
import java.net.URL;

public class Game extends Applet implements Runnable, KeyListener, MouseMotionListener
{

    int x_pos = 250;
    int y_pos = 250;
    float x_speed = 0;
    float y_speed = 0;
    int radius = 20;
    int appletsize_x = 800;
    int appletsize_y = 600;

    int x = 0;
    int y = 0;
    int up = 0;
    int down= 0;
    int left = 0;
    int right= 0;

    int mouse_x;
    int mouse_y;
    int tracking_angle;

    private BufferedImage dbImage;
    private Graphics dbg;
    private  Image curser;
    BufferedImage img = null;
    BufferedImage round = null;

    AffineTransform at = new AffineTransform();
    double radAngle;
    public void init()
    {
            try {
               URL url = new URL(getCodeBase(), "Player.png");
               img = ImageIO.read(url);
            } catch (IOException e) {System.out.println("Cant find player image");
        }
                        try {
                           URL url = new URL(getCodeBase(), "round.png");
                           round = ImageIO.read(url);}
             catch (IOException e) {}

        setBackground (Color.blue);
        setFocusable(true);
        addKeyListener( this );
        curser = getImage(getDocumentBase(), "mouse.png");
        addMouseMotionListener(this);
        try
                {
                    Toolkit tk = Toolkit.getDefaultToolkit();
                    Cursor c = tk.createCustomCursor( curser,new Point( 5, 5 ), "Inodrop" );
                    setCursor( c );
                }
                catch( IndexOutOfBoundsException x )
                {}
    }

    public class Shot {

        int x_loc = -50;
        int y_loc = -50;
        public Shot(){
            if(x_loc < 0){
                x_loc = x_pos;}
            if(y_loc < 0){
                y_loc = y_pos;}

                paint(dbg);}
        public void paint(Graphics g){
            System.out.println("hi");

             Graphics2D g2d = (Graphics2D)g;

            Graphics g2D = round.getGraphics();
            g2d.drawImage(round, x_loc,y_loc,null);}}

    public void start ()
    {

        Thread th = new Thread (this);

        th.start ();

    }

    public void stop()
    {

    }

    public void destroy()
    {

    }
    public void mouseMoved(MouseEvent e){
        //get position of mouse
        mouse_x = e.getX();
        mouse_y = e.getY();
        double x_dist = mouse_x - x_pos;
        double y_dist = mouse_y - y_pos;


        if (x_dist == 0) {
          radAngle = 90;
        } else if ((x_dist == 0) && (y_dist == 0)) {
          radAngle = 0;
        } else {
          radAngle = Math.atan(y_dist / x_dist);
        }


        tracking_angle = (int)(Math.sin(radAngle) * 100);
        //System.out.println(Math.toRadians(tracking_angle));
        }
    public void mouseDragged(MouseEvent e){}


    public void keyReleased(KeyEvent r)
    {
        //Left
        if (r.getKeyCode()  == 39 ){
            x = 0;
            left = 0;
            Shot shoot = new Shot();
            }
        //Right
        if (r.getKeyCode() == 37){
            x = 0;
            right = 0;
            }
        //Down
        if (r.getKeyCode() == 38 ) {
            //y_speed = 0;
            down = 0;}
        //Up
        if (r.getKeyCode() == 40 ) {
            //y_speed = 0;
            up = 0;}
            //move();
}
    public void keyTyped(KeyEvent t){}
    public void keyPressed(KeyEvent r){


        //Left
        if (r.getKeyCode()  == 39 ){
            left = 1;}
        //Right
        if (r.getKeyCode() == 37){
            right = 1;}
        //Down
        if (r.getKeyCode() == 38 ) {
            down = 1;}
        //Up
        if (r.getKeyCode() == 40 ) {
            up = 1;}
            //move();
}


    public void run ()
    {

        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);


        while (true)
        {
            if (left  == 1 && x_speed < 11){
                x = 0;
                x_speed += 1;
                }
            //Right
            if (right == 1 && x_speed > -11){
                x = 0;
                 x_speed -= 1;
                }
            //Down
            if (down == 1  && y_speed > -11) {
                y_speed -= 1;}
            //Up
            if (up == 1  && y_speed < 11) {
            y_speed += 1;}
        if( x == 0 && x_speed > 0){
            x_speed -=.2;}
        if( x == 0 && x_speed < 0){
            x_speed +=.2;}
        if( y == 0 && y_speed > 0){
            y_speed -=.2;}
        if( y == 0 && y_speed < 0){
            y_speed +=.2;}



            if (x_pos > appletsize_x - radius && x_speed > 0)
            {

                x_pos = radius;
            }

            else if (x_pos < radius && x_speed < 0)
            {

                x_pos = appletsize_x + radius ;
            }
            //System.out.println(y_pos);
            if (y_pos > appletsize_y - radius && y_speed > 0){
                y_speed = 0;}
            else if ( y_pos < radius && y_speed < 0  ){
                    y_speed = 0;}

            x_pos += (int)x_speed;
            y_pos += (int)y_speed;



            repaint();

            try
            {


                Thread.sleep (15);


            }
            catch (InterruptedException ex)
            {

            }


            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
        }
    }


    public void update (Graphics g)
    {

        if (dbImage == null)
        {
            dbImage = new BufferedImage(this.getSize().width, this.getSize().height, BufferedImage.TYPE_INT_RGB);
            dbg = dbImage.getGraphics ();
        }


        dbg.setColor (getBackground ());
        dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);


        dbg.setColor (getForeground());
        paint (dbg);

        g.drawImage (dbImage, 0, 0, this);


    }

    public void paint (Graphics g)
    {
        //g = img.getGraphics();
        Graphics2D g2 = (Graphics2D)g;


        g2.drawImage(img, x_pos,y_pos,this);
        AffineTransform oldTransform = g2.getTransform();

        g2.setTransform(AffineTransform.getRotateInstance(radAngle,x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));



        System.out.println(img.getWidth());




    }
}

【问题讨论】:

  • 你能把你用的两个图片贴出来,我可以试试看有什么问题。
  • 请不要吞下异常。
  • +0.95 是一个几乎完整的示例。请参阅RotatableImage,这样人们就不必追踪图像和吞下的异常。 :-)
  • “我的项目明天到期,所以我很准时”我们都去过那里哈哈。

标签: java rotation bufferedimage affinetransform


【解决方案1】:
    double x_dist = mouse_x - x_pos;
    double y_dist = mouse_y - y_pos;
    double radAngle = Math.atan(y_dist / x_dist);
    tracking_angle = (int) (Math.sin(radAngle) * 100);

我认为错误出在这部分的某个地方。如果x_dist 为 0,您肯定会在此处除以 0。最好这样做:

if (x_dist == 0) {
    radAngle = 90;
} else {
    radAngle = Math.atan(y_dist / x_dist);
}

编辑:此外,我认为您应该完全丢弃 tracking_angle 行,然后再执行此操作:

g2.setTransform(AffineTransform.getRotateInstance(rad_angle,
  x_pos + (img.getWidth() / 2),y_pos+(img.getHeight() / 2)));

您还应该更改您在 cmets 中发布的新代码:

double radAngle;
if (x_dist == 0) {
  radAngle = 90;
} else if (y_dist == 0) {
  radAngle = 90;
} else {
  radAngle = Math.atan(y_dist / x_dist);
}

您正在为x_dist == 0 y_dist == 0 解决此问题(这不是边缘情况),但不适用于两者都是 0 的情况,您根本无法计算角度我认为你应该选择 0。所以改用这个:

double radAngle;
if (x_dist == 0) {
  radAngle = 90;
} else if ((x_dist == 0) && (y_dist == 0)) {
  radAngle = 0;
} else {
  radAngle = Math.atan(y_dist / x_dist);
}

另外,正如垃圾神指出的那样,您忽略了异常,例如:

    try {
        URL url = new URL(getCodeBase(), "Player.png");
        img = ImageIO.read(url);
    } catch (IOException e) {
    }

在这种情况下,您不应该只继续,而是 f.e.显示有用的错误消息并退出程序,无论如何做点什么而不是仅仅捕获异常并继续,就好像什么都没发生一样。

【讨论】:

  • +1 表示毅力。我注意到tracking_angle 的符号突然在接近 问题的角度发生变化,这让我对100 产生了怀疑。
  • 它不起作用,我认为它与此有关(来自 java api)“由于 90 度以弧度表示为 PI/2,并且由于 PI 是超越的(并且因此是无理数)数字,不可能将 90 度的倍数精确地表示为以弧度测量的精确双精度值。”这是我使用的代码,双 radAngle;如果 (x_dist == 0) { radAngle = 90; }else if(y_dist == 0){ radAngle = 90;} else { radAngle = Math.atan(y_dist / x_dist); } 替换了双 radAngle = Math.atan(y_dist / x_dist);行。
  • 请用新代码更新您的问题;在评论中很难阅读。
  • 嗯,tracking_angle = (int) (Math.sin(radAngle) * 100); 也很奇怪。 radAngle 是弧度,所以我认为你应该扔掉tracking_angle 并直接使用radAngle 而不是Math.toRadians(tracking_angle)。我将使用代码进行编辑以使其更清晰。
  • 在我尝试了上面推荐的东西之后,我实际上想到了这一点,但并没有什么不同。做了同样的口吃事情。在转换为度数而不是返回弧度时,我会失去一些精度是有道理的,但显然它没有任何区别。
【解决方案2】:

我没有测试过这个,但是试试:

double radAngle = Math.atan2(y_dist, x_dist);

【讨论】:

  • 没有变化。为什么java不能像...那样旋转度数......它应该T_T
  • +1,很好,atan2 应该正是我们需要的。 en.wikipedia.org/wiki/Atan2#Definition 很好地解释了 atan2。仍然会检查 (0,0),但会处理 atan(y/x) 失败的其他情况。
猜你喜欢
  • 2021-04-13
  • 2015-06-23
  • 2018-03-21
  • 1970-01-01
  • 2021-05-24
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 2015-06-22
相关资源
最近更新 更多