关于ZAKER 融媒体解决方案 合作 加入

Java 球对象不像它应该的那样从绘制的矩形 .

CocoaChina 09-18

抱歉这个糟糕的头衔 . Java applet 的目的是这样的:一个球在屏幕上弹跳 . 这个球的大小和速度可以通过滚动条改变 . 用户可以在屏幕上按下并拖动鼠标以绘制矩形 . 球也将从这些矩形反弹 . 这些矩形的边界存储在矢量中 . 单击矩形时 , 将从矢量 ( 和屏幕 ) 中删除它 ( 以及该点处的所有其他矩形 ) .

我遇到的问题有两个:一 , 当我点击一个矩形去除它时 , 它不会被删除 , 但这可以在以后解决 .

二:球不会像它应该的那样从矩形反弹 . 当我在与球相同的行或列中绘制一个矩形时 , 球会在一个小矩形内部反弹 , 就像它被卡住一样 .

这是我的代码 , 用于检测球是否正在击中小程序或任何矩形的边界:

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

在此先感谢所有精彩的帮助 .

最佳答案

我终于找到了一个我喜欢的边缘检测系统……

基本上 , 魔术发生在这里……

// 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; } }}

现在 , 我只有一个障碍 , 但我怀疑它需要花费很多精力才能让它与一系列障碍一起工作…… ; )

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 ( ) ; } }}

以上内容由"CocoaChina"上传发布 查看原文
相关标签 we

觉得文章不错,微信扫描分享好友

扫码分享