带有线程的Java动画

时间:2016-03-14 19:33:11

标签: java multithreading swing animation

我正在为学校做作业。我必须在随机位置创建30个随机colured GameObjects。我必须使用2个类,一个GameObject类,其中包含GameObject数据,x和y坐标和颜色,以及移动和绘制方法......以及主MovingSquaresApplication它将GameObjects放入一个数组并调用paint()move()方法...当前程序编译,运行,绘制60个方块(paint()repaint())但不动画。我看了很多不同的帖子,但仍然无法做到正确。任何帮助都会很棒。这是代码.....

*编辑了新代码

import java.awt.*;
import javax.swing.*;

public class MovingSquaresApplication extends JFrame implements Runnable {


//member data
private static final Dimension WindowSize = new Dimension(600,600);
private static final int NUMGAMEOBJECTS = 30;
private GameObject[] gameObjectsArray = new GameObject[NUMGAMEOBJECTS];
private int i,j;

//constructor
public MovingSquaresApplication(){


            this.setTitle("MovingSquaresApplication");
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


            //Display the window, centered on the screen
            Dimension screensize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
            int x = screensize.width/2 - WindowSize.width/2;
            int y = screensize.height/2 - WindowSize.height/2;
            setBounds(x, y, WindowSize.width, WindowSize.height);
            setVisible(true);           


            for (i=0; i<gameObjectsArray.length; i++){        //fills array with GameObjects
                GameObject NewSquare = new GameObject();
                gameObjectsArray[i] = NewSquare;
            }

            Thread t = new Thread(this);        //creates and stars a thread
            t.start();              
}

//threads entry point
public void run(){


while (true){
    try {
        Thread.sleep(20);

            for (j=0; j<gameObjectsArray.length; j++){
                gameObjectsArray[j].move();
                repaint();
            }


        } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}
}

//applications paint method
public void paint (Graphics g){

    super.paintComponents(g);
    for (i=0; i<gameObjectsArray.length; i++){
        gameObjectsArray[i].paint(g);
    }

    }

//applications entry point
public static void main(String[] args){
    MovingSquaresApplication w = new MovingSquaresApplication();

}

}

GameObject

import java.awt.*;

public class GameObject {

//member data
private int x,y,xvel=2,yvel=2;
private Color c;

public GameObject(){

    x = (int) (Math.random( )*600);
    y = (int) (Math.random( )*600);

    int R = (int) (Math.random( )*256);
    int G = (int)(Math.random( )*256);
    int B= (int)(Math.random( )*256);

    c = new Color (R, G, B);
}

//public interface
public void move(){
    x += xvel;
    y += yvel;

    if(x<10)
    {
        xvel = 2;
    }

    else if(y<30)
    {
        yvel = 2;
    }

    else if(x>=560)
    {
        xvel = -2;
    }

    else if(y>=560)
    {
        yvel = -2;
    }
}


public void paint(Graphics g){
    g.setColor(c);
    g.fillRect(x, y, 30, 30);
}


}

感谢所有帮助,非常感谢

感谢您的帮助,我没有创建一个扩展JPanel的类,我只是把

super.paintComponent(g);

在绘画方法中,不确定这是不是很好的做法,但它有效....也在旁边我还没见过这个

for (GameObject gameObject : gameObjectArray)

与我使用的循环相比,这究竟做了什么?

1 个答案:

答案 0 :(得分:4)

你需要在JPanel的paintComponent方法中绘画(因为我确定你已经读过了......所以我建议你这样做。你

  • 使用GameObjects填充GameObjectsArray,并且不是在任何绘制方法中,而是在GUI构造中
  • 创建一个JPanel并覆盖其paintComponent方法,就像Swing painting tutorials告诉你的那样
  • 在覆盖中调用super的paintComponent方法(再次按照教程告诉你的方法)
  • 在paintComponent方法中迭代你的GameObjectsArray(但重命名为gameObjectsArray,因为它的变量不是类)
  • 在同一个循环中调用每个GameObject的绘制方法。

编辑:查看你的代码:

GameObject MoveSquare = new GameObject();
for (y = 0; y < GameObjectsArray.length; y++) {
    MoveSquare.move();
}

您正在做的是创建一个全新的GameObject对象MoveSquare,并尝试在for循环中移动 it ,同时您不会触及任何GameObjects在gameObjectsArray中保存。你在这看到你的错误吗?

编辑2
此外,您还使用y变量作为数组索引,您使用相同的变量来计算GUI的y轴边界 - 不要这样做。使用完全独立的变量。

编辑4
在这里:

public void paint(Graphics g) {
    for (y = 0; y < GameObjectsArray.length; y++) {
        GameObject NewSquare = new GameObject();
        if (GameObjectsArray[y] == null) {
            GameObjectsArray[y] = NewSquare;
            NewSquare.paint(g);
        }
    }
}

您每次调用paint都会创建新的GameObject变量,忽略数组中已经存在的任何变量(??)。绘画方法应仅用于绘画和绘画。再次,使用新的GameObject项填充GameObject数组,并在类构造函数中填充,而不是在绘制方法中。

你在这里做了很多猜测,并在墙上抛出代码,看看哪些棍子对于创建程序来说不是一个好的启发式方法。而是在将代码提交到IDE之前计划上的每个步骤。

编辑5
您需要修复GameObject移动方法中的if条件。但是一旦你运行了代码,你就会明白我的意思,因为你会看到所有游戏对象在页面上运行。

编辑6

我不打算向您展示所有代码,但是,您还要创建一个扩展JPanel的类,覆盖其paintComponent方法,并且该方法非常简单,看起来像这样:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);  // do housekeeping painting

    // note that I've renamed the array to gameObjectArray
    for (GameObject gameObject : gameObjectArray) {
        gameObject.paint(g);  // this is all you need to call
    }
}

同样,run方法类似于:

@Override
public void run() {
    while (true) {
        try {
            Thread.sleep(SLEEP_TIME); // constant for the sleep time
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // again note that the array has been renamed
        for (GameObject gameObject : gameObjectArray) {
            gameObject.move();  // this is all that needs to be called here
        }
        repaint();
    }
}

编辑下一步 :) 您正在创建两个线程对象并启动它们 - 不要这样做。只有一个会做。