Java球对象不像它应该的那样从绘制的矩形反弹.
作者:互联网
抱歉这个糟糕的头衔. 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();
}
}
}
标签:rectangles,java,collision-detection,mouseevent,applet 来源: https://codeday.me/bug/20190917/1808805.html