【问题标题】:Java Animation with thread带线程的 Java 动画
【发布时间】:2016-03-14 19:33:10
【问题描述】:

我正在为学校做作业。我必须在随机位置创建 30 个随机颜色的游戏对象。我必须使用 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)

与我使用的循环相比,这到底有什么作用?

【问题讨论】:

  • Im doing an assignment for school. - 那么你应该使用正确的变量名。变量名不应以大写字符开头。
  • 您没有在更新循环中更新您的游戏对象。你只是创建了一个新的游戏对象,然后循环遍历你的游戏对象并移动这个新的游戏对象,但它永远不会显示,然后被销毁。只需通过它们更新循环中的每个游戏对象,您就应该接近实现目标了。
  • then you should be using proper variable names 我同意这一点。当人们告诉我他们的学校老师不关心命名约定时,我有点恼火。
  • 对不起,我知道,但它们是给我们的变量名称,我打算更改它们。感谢您的帮助
  • 不,不要在 paint 方法中调用 paintComponent,是的,为您的动画扩展 JPanel,而不是 JFrame,请不要尝试编辑我的答案。

标签: java multithreading swing animation


【解决方案1】:

您需要在 JPanel 的 paintComponent 方法中进行绘制(我相信您已经阅读过......所以我建议您这样做。您

  • 用 GameObjects 填充您的 GameObjectsArray,不要在任何绘画方法中这样做,而是在 GUI 构造中这样做
  • 创建一个 JPanel 并覆盖它的paintComponent 方法,就像Swing painting tutorials 告诉你的那样
  • 在您的覆盖中调用 super 的 paintComponent 方法(同样,教程会告诉您这样做)
  • 在paintComponent 方法中遍历您的GameObjectsArray(但将其重命名为gameObjectsArray,因为它是一个变量而不是一个类)
  • 在同一个 for 循环中调用每个 GameObject 的绘制方法。

编辑:查看你的这段代码:

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

你正在做的是创建一个全新的 GameObject 对象,MoveSquare,并试图在 for 循环中移动 ,同时你没有接触到 gameObjectsArray 中的任何 GameObjects .你看到你的错误了吗?


编辑 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 move 方法中的 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();
    }
}

编辑下一步 :)
您正在创建 两个 Thread 对象并同时启动它们——不要那样做。只有一个会做。

【讨论】:

  • 我希望我能给你更多的支持。你的辅导工作做得和我在问答网站上看到的一样好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
相关资源
最近更新 更多