设置动画球的边界

时间:2016-06-11 19:48:43

标签: java animation

我有一个简单的类,它创建一个框架,其中有一些球从侧面反弹。由于某种原因,球从框架的北侧,西侧和东侧反射得很好,但是稍微越过南侧,然后从它弹回。我在设置边界时考虑了球的大小,这在x轴上工作正常,但在y轴上工作正常。

import javax.swing.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.*;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;

public class BallBounceFrame
{

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

JFrame frame;   
static int WIDTH = 500;
static int HEIGHT = 500;

public BallBounceFrame()
{   
    frame = new JFrame("Ball Bounce Frame");
    frame.setSize(WIDTH, HEIGHT);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLocationRelativeTo(null);
    frame.setResizable(false);
    BallCanvas c = new BallCanvas(5);
    frame.add(c, BorderLayout.CENTER);
    frame.setVisible(true); 
    c.animate();
}

class BallCanvas extends JPanel
{

    private static final long serialVersionUID = 1L;

    ArrayList<Ball> balls = new ArrayList<Ball>();

    public BallCanvas(int ballNum)
    {
        for(int i = 0; i < ballNum; i++)
        {
            balls.add(new Ball(20));
        }
    }

    public void paint(Graphics g)
    {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(Color.RED);
        for(Ball b : balls)
        {
            b.move();
            g2.fill(b);
        }
    }

    public void animate()
    {
        while(true)
        {
            try
            {
                frame.repaint();
                Thread.sleep(10);
            }
            catch(Exception e)
            {
                System.out.println(e);
            }
        }
    }
}

class Ball extends Ellipse2D.Float
{
    private int xVel, yVel;
    private int size;
    private int WIDTH = BallBounceFrame.WIDTH;
    private int HEIGHT = BallBounceFrame.HEIGHT;

    public Ball(int size)
    {
        super((int) (Math.random() * (BallBounceFrame.WIDTH - 20) + 1), (int) (Math.random() * (BallBounceFrame.HEIGHT - 20) + 1), size, size);
        this.size = size;
        this.xVel = (int) (Math.random() * 5 + 1);
        this.yVel = (int) (Math.random() * 5 + 1);          
    }

    public void move()
    {
        if(super.x < 0 || super.x > WIDTH - size) xVel *= -1;
        if(super.y < 0 || super.y > HEIGHT - size ) yVel *= -1;
        super.x += xVel;
        super.y += yVel;
    }
}
}

2 个答案:

答案 0 :(得分:0)

我认为,原因是xVel / yVel加入了移动。

当你靠近边境时,你会检查你是否已越过边界。如果没有,则添加速度。

如果到边框的距离为10且您的速度为15,则您将在边界框架上移动5。在下一步中,您将反转速度并反弹。在这种情况下,此举可能会分开。移动10,反向速度,移动5。

答案 1 :(得分:0)

问题是WIDTH和HEIGHT来自JFrame。特别是窗口标题标题会降低面板的高度。人们可以将面板边界/大小传递给球的移动。

@Override
public void paint(Graphics g)
{
    ...
        b.move(getSize());
    ...
}

public void move(Dimension panelSize)
{
    if (x < 0 || x > panelSize.getWidth() - size) xVel *= -1;
    if (y < 0 || y > panelSize.getHeight - size) yVel *= -1;
    x += xVel;
    y += yVel;
}

要将球保持在你可能考虑的范围内:

public void move(Dimension panelSize)
{
    x += xVel;
    y += yVel;
    if (x < 0) {
        x *= -1;
        xVel *= -1;
    } else if (x > panelSize.getWidth() - size) {
        x -= 2 * (x - panelSize.getWidth() - size);
        xVel *= -1;
    }
    if (y < 0) {
        y *= -1;
        yVel *= -1;
    } else if (y > panelSize.getHeight() - size) {
        y -= 2 * (y - panelSize.getHeight() - size);
        yVel *= -1;
    }
}

根据

    \ |         (xVel == 5)
     \|
     /|\
    / | \
   /  |  \

(在pack()末尾通常还有一个马蹄莲BallBounceFrame来进行布局计算。)