2

ひどいタイトルでごめんなさい。Javaアプレットの目的は、次のとおりです。ボールが画面上で跳ね返っています。このボールのサイズと速度は、スクロールバーを介して変更できます。ユーザーは、画面上でマウスを押してドラッグし、長方形を描くことができます。ボールはこれらの長方形からも跳ね返ります。これらの長方形の境界はベクトルに格納されます。長方形をクリックすると、その長方形(およびそのポイントにある他のすべての長方形)がベクトル(および画面)から削除されます。

私が抱えている問題は2つあります。1つは、長方形をクリックして削除しても削除されないことですが、後で解決できます。

2:ボールが想定どおりに長方形から跳ね返らない。ボールと同じ行または列に長方形を描くと、ボールが動かなくなったように、小さな長方形の内側で跳ね返ります。

ボールがアプレットまたはいずれかの長方形の境界に当たっているかどうかを検出するための私のコードは次のとおりです。

  public void move()
  {
    //if it will hit the right or left boundary, flip the x direction and set it
    if (loc.x+size >= boundx || loc.x <= 0)
    { dx *= -1; }
    //if it will hit the top or bottom boundray, flip the y direction and set it
    if (loc.y+size >= boundy || loc.y <= 0)
    { dy *= -1; }


    for (int i = 0; i < r.size(); i++)
    {

      temp = new Rectangle(r.elementAt(i));
      int rx = temp.x;
      int ry = temp.y;
      int rh = temp.height;
      int rw = temp.width;
      //If the ball hits either side of the rectangle, change the x direction
      if((loc.x > rx && loc.x > ry && loc.x < (ry + rh))||(loc.x < (rx + rw) && loc.x > rx && loc.x <(ry + rh)))
        {dx *= -1;}
      //If the ball hits either the top or bottom, change the y direction
      if((loc.y > ry && loc.y > rx && loc.y < (rx + rw))||(loc.y < (ry + rh) && loc.y > ry && loc.y <(rx + rw)))
        {dy *= -1;}
    }
    //Increment or decrement the location of the ball based on the X and Y directions.
    loc.x += dx;
    loc.y += dy;
  }

コード全体を表示したい場合は、ここにあります:http: //ideone.com/R1hpBx

すべての素晴らしい助けを事前に感謝します。

4

1 に答える 1

8

私はついに私が好きなエッジ検出システムを見つけました...

運命の回転するボール

基本的に、魔法はここで起こります...

// Detect if we collided with any one (collision is the rectangle, bounds is us)
if (collision.intersects(bounds)) {
    // Determine the intersect of the collision...
    insect = collision.intersection(bounds);

    // Flags...
    boolean vertical = false;
    boolean horizontal = false;
    boolean isLeft = false;
    boolean isTop = false;

    // Left side...
    if (insect.x == collision.x) {
        horizontal = true;
        isLeft = true;
    // Right side
    } else if (insect.x + insect.width == collision.x + collision.width) {
        horizontal = true;
    }
    // Top
    if (insect.y == collision.y) {
        vertical = true;
        isTop = true;
    // Bottom
    } else if (insect.y + insect.height == collision.y + collision.height) {
        vertical = true;
    }

    // Technically, we can really only collide with a single edge...more or less
    if (horizontal && vertical) {
        // Basically, we try and give precedence to the longer edge...
        if (insect.width > insect.height) {
            horizontal = false;
        } else {
            vertical = false;
        }
    }

    // We collided with a horizontal side...
    if (horizontal) {
        dx *= -1;
        // Move the ball to the approriate edge so we don't get caught...
        if (isLeft) {
            bounds.x = collision.x - bounds.width;
        } else {
            bounds.x = collision.x + collision.width;
        }
    // We collided with a vertical side...
    } else if (vertical) {
        dy *= -1;
        // Move the ball to the approriate edge so we don't get caught...
        if (isTop) {
            bounds.y = collision.y - bounds.height;
        } else {
            bounds.y = collision.y + collision.height;
        }
    }

}

今、私には障害物が1つしかないのですが、一連の障害物を処理するのに多くの労力がかかるとは思えません...;)

public class TestBouncingBall {

    private Rectangle insect;

    public static void main(String[] args) {
        new TestBouncingBall();
    }

    public TestBouncingBall() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new BallPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class BallPane extends JLayeredPane {

        private Ball ball;
        private Timer timer;
        private Rectangle world;

        public BallPane() {

//            world = new Rectangle(random(400), random(400), random(100), random(100));
            world = new Rectangle(100, 100, 200, 200);

            ball = new Ball();
            ball.setSize(ball.getPreferredSize());
            ball.setLocation(10, 10);

            add(ball);

            timer = new Timer(16, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    ball.move(getBounds(), world);
                    invalidate();
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();

        }

        protected int random(int max) {

            return (int) Math.round(Math.random() * max);

        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setColor(Color.GRAY);
            g2d.fill(world);
            if (insect != null) {
                g2d.setColor(Color.RED);
                g2d.fill(insect);
            }
            g2d.dispose();
        }
    }

    public class Ball extends JPanel {

        public int maxSpeed = 10;
        private BufferedImage beachBall;
        private int dx = 10 - (int)Math.round(Math.random() * (maxSpeed * 2)) + 1;
        private int dy = 10 - (int)Math.round(Math.random() * (maxSpeed * 2)) + 1;
        private int spin = 20;
        private int rotation = 0;

        public Ball() {
            try {
                beachBall = ImageIO.read(getClass().getResource("/ball.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            setOpaque(false);
        }

        @Override
        public Dimension getPreferredSize() {
            Dimension size = beachBall == null ? new Dimension(48, 48) : new Dimension(beachBall.getWidth(), beachBall.getHeight());
            size.width += 4;
            size.height += 4;
            return size;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (beachBall != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
                g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
                g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
                g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
                g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);

                int x = (getWidth() - beachBall.getWidth()) / 2;
                int y = (getHeight() - beachBall.getHeight()) / 2;
                AffineTransform transform = g2d.getTransform();
                AffineTransform at = new AffineTransform();
                at.translate(getX(), getY());
                at.rotate(Math.toRadians(rotation), getWidth() / 2, getHeight() / 2);
                g2d.setTransform(at);
                g2d.drawImage(beachBall, x, y, this);
                g2d.setTransform(transform);
                g2d.dispose();
            }
        }

        public void move(Rectangle world, Rectangle collision) {
            Rectangle bounds = getBounds();
            bounds.x += dx;
            bounds.y += dy;

            if (bounds.x < 0) {
                bounds.x = 0;
                dx *= -1;
            }
            if (bounds.y < 0) {
                bounds.y = 0;
                dy *= -1;
            }
            if (bounds.x + bounds.width > world.width) {
                bounds.x = world.width - bounds.width;
                dx *= -1;
            }
            if (bounds.y + bounds.height > world.height) {
                bounds.y = world.height - bounds.height;
                dy *= -1;
            }

            if (collision.intersects(bounds)) {
                insect = collision.intersection(bounds);

                boolean vertical = false;
                boolean horizontal = false;
                boolean isLeft = false;
                boolean isTop = false;

                if (insect.x == collision.x) {
                    horizontal = true;
                    isLeft = true;
                } else if (insect.x + insect.width == collision.x + collision.width) {
                    horizontal = true;
                }
                if (insect.y == collision.y) {
                    vertical = true;
                    isTop = true;
                } else if (insect.y + insect.height == collision.y + collision.height) {
                    vertical = true;
                }

                if (horizontal && vertical) {
                    if (insect.width > insect.height) {
                        horizontal = false;
                    } else {
                        vertical = false;
                    }
                }

                System.out.println("v = " + vertical + "; h = " + horizontal);

                if (horizontal) {
                    dx *= -1;
                    if (isLeft) {
                        bounds.x = collision.x - bounds.width;
                    } else {
                        bounds.x = collision.x + collision.width;
                    }
                } else if (vertical) {
                    dy *= -1;
                    if (isTop) {
                        bounds.y = collision.y - bounds.height;
                    } else {
                        bounds.y = collision.y + collision.height;
                    }
                }

            }

            rotation += spin;

            setBounds(bounds);
            repaint();

        }
    }
}
于 2012-11-07T04:12:50.230 に答える