为什么这个线程不起作用?

时间:2017-02-23 17:58:57

标签: java multithreading

我是一名Java程序员。我正在尝试构建一个可以直接在控制台中播放的Space Invaders游戏。后来,我想通过JFrame添加一个图形界面;但是,在这个时候,我限制自己创建一个非功能性的JFrame窗口。我将类保存在几个文件中 - Constants.java,Entity.java,Player.java和Board.java,SpaceInvaders.java - 我已按指定顺序编译这些文件。我的问题是,当我尝试运行main方法时,没有显示任何内容。没有窗口弹出。控制台中不显示任何输出。我怀疑问题出在类Board,也许是在方法gameInit()或方法run()中的线程构造中。我在课程教科书中找不到有关线程的任何信息 - 我从网站http://zetcode.com/tutorials/javagamestutorial/spaceinvaders/获得了线程代码,我将在项目的最终版本中引用它。

如果你能给我任何指示,请告诉我。对于我对stackoverflow.com的格式不熟悉,我深表歉意。

我在下面附上了我的代码副本。

Constants.java

import java.io.*;

public interface Constants {
    public static final int MOTION_WIDTH = 20;
    public static final int MOTION_LENGTH = 20;
    public static final int DELAY = 17;
}

Entity.java

import java.io.*;

public class Entity {
    private int xPosition;
    private int yPosition;

    public void setXPosition(int newXPosition) {
        this.xPosition = newXPosition;
    }

    public int getXPosition() {
        return xPosition;
    }

    public void setYPosition(int newYPosition) {
        this.yPosition = newYPosition;
    }

    public int getYPosition() {
        return yPosition;
    }
}

Player.java

import java.io.*;

import java.awt.event.KeyEvent;

public class Player extends Entity implements Constants{
    private final int START_X_POSITION = 0;
    private final int START_Y_POSITION = 0;
    int x = 0; 

    public Player() {
        setXPosition(START_X_POSITION);
        setYPosition(START_Y_POSITION);
    }

    public void move() {
        setXPosition((getXPosition()) + x);

        if ((getXPosition()) <= 0) {
            setXPosition(0);
        }
        if ((getXPosition()) >= MOTION_WIDTH) {
            setXPosition(MOTION_WIDTH);
        }
    }
        public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            x = 1;
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            x = -1;
        }
        }

    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            x = 0;
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            x = 0;
        }
    }
}

Board.java

import java.io.*;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;

public class Board extends JPanel implements Runnable, Constants {
    Player player;
    boolean gameRunning = true;
    Thread animator;

    char[][] motion = new char[MOTION_WIDTH][MOTION_LENGTH];


    public Board() {
        addKeyListener(new KeyListener());
        setFocusable(true);     
        gameInit();
        setDoubleBuffered(true);
    }

//Ensure that I cite this
    public void addNotify() {
        super.addNotify();
        gameInit();
    }

    public void gameInit() {

        player = new Player();

        for (int i = 0; i < MOTION_WIDTH; i++) {
            for (int j = 0; j < MOTION_LENGTH; j++) {
                    motion[i][j] = '0';
            }
        }

        motion[0][0] = '^';


            if (animator == null) {
                    animator = new Thread(this);
                    animator.start();
            }
    }
    private class KeyListener extends KeyAdapter {
        public void keyPressed(KeyEvent e) {
            player.keyPressed(e);
        }
        public void keyReleased(KeyEvent e) {
            player.keyReleased(e);
        }
    }

    public void paint() {

        for (int i = 0; i < MOTION_WIDTH; i++) {
            for (int j = 0; j < MOTION_LENGTH; j++) {
                    motion[i][j] = '0';
            }
        }       

        motion[player.getXPosition()][player.getYPosition()] = '^';

        for (int i = 0; i < MOTION_WIDTH; i++) {
            for (int j = 0; j < MOTION_LENGTH; j++) {
                System.out.print(motion[i][j]);
            }
            System.out.println();
        }
    }

    public void animationCycle() {
        player.move();
        paint();
    }
//Ensure that I cite this
    public void run() {
        long beforeTime, timeDiff, sleep;

        beforeTime = System.currentTimeMillis();

        while (gameRunning) {
            paint();
            animationCycle();

            timeDiff = System.currentTimeMillis() - beforeTime;
            sleep = DELAY - timeDiff;

            if (sleep < 0) 
                sleep = 2;
            try {
                Thread.sleep(sleep);
            } catch (InterruptedException e) {
                System.out.println("interrupted");
            }
            beforeTime = System.currentTimeMillis();
        }
    }
}

SpaceInvaders.java

import java.io.*;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyAdapter;

public class SpaceInvaders extends JFrame implements Constants {
    public void SpaceInvaders() {
        add(new Board());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(500, 500);
        setVisible(true);
        requestFocusInWindow();
    }

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

2 个答案:

答案 0 :(得分:0)

在类SpaceInvaders中,您提供的构造函数实际上不是构造函数。请删除返回类型void。所以应该阅读

public SpaceInvaders() {
    add(new Board());
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(500, 500);
    setVisible(true);
    requestFocusInWindow();
}

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

以下是Java文档中构造函数的信息:

  

一个类包含被调用以从类蓝图创建对象的构造函数。构造函数声明看起来像方法声明 - 除了它们使用类的名称并且没有返回类型。   (https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html

应用修改后,JFrame会显示出来,并且控制台上还会打印很多0和a ^。

答案 1 :(得分:0)

我没有看到代码中的线程开始。我认为你必须按照下面的例子启动线程

class Board implements Runnable{  
public void run(){  
System.out.println("thread is running...");  
}  

public static void main(String args[]){  
Board b1=new Board();  
Thread t1 =new Thread(b1);  
t1.start();  
 }  
} 

而且构造也不应该有返回类型

public void SpaceInvaders() {
}

更改为

public SpaceInvaders() {
}