java - Java 中弹跳球的动画?

标签 java

我正在用 Java 为弹跳球制作 JApplet。

这就是我到目前为止所拥有的。我可以让球向右移动,但我不能让它再次向左移动。我仍然对为什么使用计时器而不是像无限循环之类的东西感到困惑。

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

public class animation extends Applet implements ActionListener {

    Timer clock;
    boolean sleepy;
    int x = 100;
    int y = 100;
    // Initializes this applet
    public void init()
    {
        clock = new Timer(100,this);
        // fires every second
        clock.start();
    }

    // Called automatically after a repaint request
    public void paint(Graphics g) {
       // super.paint(g);
        g.setColor(Color.blue);
        g.fillOval(x, y, 100, 100);
        //Redraws the circles
        if(x < 240){
            x = x+10;
            System.out.println(x);
        }
        if(x > 240){
            x = x - 10;
            System.out.println(x);
        }
    }

    // Called automatically when the timer fires
    public void actionPerformed (ActionEvent e) {
        repaint();
    }
}

现在这个逻辑已经消失了,我真的想不出如何让球返回,并继续返回直到再次 x = 0。

有没有办法实现计时器,让球向右移动 5 秒,然后向左移动 5 秒?

最佳答案

好吧,我建议您应用 vector 数学来更新球的位置和速度。这使得代码更清晰、更容易理解。

您还应该进行适当的边界检查。您可以对其进行调整以调整更新的速度和时间。

这是一个相当样板的示例,它允许轻松扩展。

应用程序.java

在可绘制面板上显示一个弹跳球。

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class App implements Runnable, ActionListener {
    private final static String APP_TITLE = "Bouncing Ball";

    private JFrame frame;
    private DrawablePanel drawPanel;

    private Timer clock;
    private int fps = 60;
    private int timeout = 1000 / fps;

    public App() {
        frame = new JFrame();
        drawPanel = new DrawablePanel(240, 240);

        frame.setTitle(APP_TITLE);
        frame.setContentPane(drawPanel);

        Ball ball = new Ball(50, Color.BLUE, 1.0, Math.PI);

        drawPanel.addDrawable(ball);
    }

    @Override
    public void run() {
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        clock = new Timer(timeout, this);
        clock.start();
    }

    public void actionPerformed(ActionEvent e) {
        drawPanel.updateAll();
        drawPanel.repaint();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new App());
    }
}

DrawablePanel.java

绘制图形列表并在需要时更新它们。

import java.awt.Dimension;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JPanel;

public class DrawablePanel extends JPanel {
    private static final long serialVersionUID = 3746382634873472355L;
    private List<Drawable> objects;

    public DrawablePanel(int width, int height) {
        this.setPreferredSize(new Dimension(width, height));

        objects = new ArrayList<Drawable>();
    }

    public boolean addDrawable(Drawable drawable) {
        drawable.setParent(this);
        return objects.add(drawable);
    }

    public boolean removeDrawable(Drawable drawable) {
        drawable.setParent(null);
        return objects.remove(drawable);
    }

    public void updateAll() {
        for (Drawable object : objects) {
            object.update();
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        for (Drawable object : objects) {
            object.draw(g);
        }
    }
}

球.java

代表一个可绘制的球,当被告知更新时它将移动。它还知道如何绘制自己。

import java.awt.Color;
import java.awt.Graphics;

public class Ball extends DrawableShape {
    private Color color;

    public Ball(int size, Color color, double speedX, double speedY) {
        this(size, color, 0, 0, speedX, speedY);
    }

    public Ball(int size, Color color, int x, int y, double dX, double dY) {
        super(new Vector2D(size, size), new Vector2D(x, y), new Vector2D(dX, dY));

        this.color = color;
    }

    @Override
    public void draw(Graphics g) {
        if (g.getColor() != color) {
            g.setColor(color);
        }

        g.fillOval(position.getX(), position.getY(), size.getX(), size.getY()); 
    }
}

DrawableShape.java

用于描述和处理可绘制形状的更新和定位的抽象类。

import java.awt.Container;

public abstract class DrawableShape implements Drawable {
    private Container parent;
    protected Vector2D size;
    protected Vector2D position;
    protected Vector2D speed;

    @Override
    public Container getParent() {
        return parent;
    }

    @Override
    public void setParent(Container parent) {
        this.parent = parent;
    }

    public DrawableShape(Vector2D size, Vector2D position, Vector2D speed) {
        this.size = size;
        this.position = position;
        this.speed = speed;
        this.parent = null;
    }

    public void update() {
        position = position.add(speed);

        double directionX = inBoundsX() ? 1 : -1;
        double directionY = inBoundsY() ? 1 : -1;

        speed = speed.scale(directionX, directionY);
    }

    private boolean inBoundsX() {
        return (position.getX() > 0)
            && (position.getX() + size.getX() < parent.getWidth());
    }

    private boolean inBoundsY() {
        return (position.getY() > 0)
            && (position.getY() + size.getY() < parent.getHeight());
    }
}

Drawable.java

表示放置在绘图面板上的可绘制图形。

import java.awt.Container;
import java.awt.Graphics;

public interface Drawable {
    Container getParent();
    void setParent(Container parent);

    void update();
    void draw(Graphics g);
}

Vector2D.java

这是我从 Google 搜索中检索到的一个简单的二维 vector 类。

/** 
 *  ========================================================
 *  Vector2D.java: Source code for two-dimensional vectors
 * 
 *  Written by: Mark Austin                   November, 2005
 *  ========================================================
 */

import java.lang.Math;

public class Vector2D {
    protected double dX;
    protected double dY;

    public int getX() {
        return (int) dX;
    }

    public int getY() {
        return (int) dY;
    }

    // Constructor methods ....
    public Vector2D() {
        dX = dY = 0.0;
    }

    public Vector2D(double dX, double dY) {
        this.dX = dX;
        this.dY = dY;
    }

    // Convert vector to a string ...
    public String toString() {
        return "Vector2D(" + dX + ", " + dY + ")";
    }

    // Compute magnitude of vector ....
    public double length() {
        return Math.sqrt(dX * dX + dY * dY);
    }

    // Sum of two vectors ....
    public Vector2D add(Vector2D v1) {
        Vector2D v2 = new Vector2D(this.dX + v1.dX, this.dY + v1.dY);
        return v2;
    }

    // Subtract vector v1 from v .....
    public Vector2D sub(Vector2D v1) {
        Vector2D v2 = new Vector2D(this.dX - v1.dX, this.dY - v1.dY);
        return v2;
    }

    // Scale vector by a constant ...
    public Vector2D scale(double scaleFactorX, double scaleFactorY) {
        Vector2D v2 = new Vector2D(this.dX * scaleFactorX, this.dY * scaleFactorY);
        return v2;
    }

    public Vector2D scale(double scaleFactor) {
        return scale(scaleFactor, scaleFactor);
    }

    // Normalize a vectors length....
    public Vector2D normalize() {
        Vector2D v2 = new Vector2D();

        double length = Math.sqrt(this.dX * this.dX + this.dY * this.dY);
        if (length != 0) {
            v2.dX = this.dX / length;
            v2.dY = this.dY / length;
        }

        return v2;
    }

    // Dot product of two vectors .....
    public double dotProduct(Vector2D v1) {
        return this.dX * v1.dX + this.dY * v1.dY;
    }

    // Exercise methods in Vector2D class
    public static void main(String args[]) {
        Vector2D vA = new Vector2D(1.0, 2.0);
        Vector2D vB = new Vector2D(2.0, 2.0);

        System.out.println("Vector vA =" + vA.toString());
        System.out.println("Vector vB =" + vB.toString());

        System.out.println("Vector vA-vB =" + vA.sub(vB).toString());
        System.out.println("Vector vB-vA =" + vB.sub(vA).toString());

        System.out.println("vA.normalize() =" + vA.normalize().toString());
        System.out.println("vB.normalize() =" + vB.normalize().toString());

        System.out.println("Dot product vA.vB =" + vA.dotProduct(vB));
        System.out.println("Dot product vB.vA =" + vB.dotProduct(vA));
    }
}

关于java - Java 中弹跳球的动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41224060/

相关文章:

java - 如何使用 float 操作按钮(fab)创建新 Activity ?

java - 在 ListView 中将 TextView 向右移动

java - 使用 IP 地址作为我的 Web 应用程序的 URL 时无法检索数据

java - Java 8 默认接口(interface)方法上的 Spring Integration @ServiceActivator

java - @WebFilter 排除 url 模式

java - Ctrl+方向键,多字变量名和eclipse pydev

java - 尝试读取文件后 rrString 为空

java - 在 Activity 之间导航时如何保留数据而不加载数据

java - 音频文件无法在 Android 中播放

java - 从 Java 获取 LDAP (OpenDS) 中的附加响应代码