Java Can';无法在main中启动线程,但文件编译成功
我正在努力读完《开始JavaSE6游戏编程》一书。我以前有一点Java方面的经验,但是我从未遇到过可运行的接口。书中的第三章展示了一个简单的小行星游戏,几乎包含了所有需要的代码。作者没有提供main()方法,我自己尝试的所有方法最终要么编译成功,要么什么也不做,要么出错 java文件的代码几乎有400行,可能只有init()、start()和run()方法是最重要的,但是我将粘贴所有这些方法Java Can';无法在main中启动线程,但文件编译成功,java,multithreading,applet,runnable,Java,Multithreading,Applet,Runnable,我正在努力读完《开始JavaSE6游戏编程》一书。我以前有一点Java方面的经验,但是我从未遇到过可运行的接口。书中的第三章展示了一个简单的小行星游戏,几乎包含了所有需要的代码。作者没有提供main()方法,我自己尝试的所有方法最终要么编译成功,要么什么也不做,要么出错 java文件的代码几乎有400行,可能只有init()、start()和run()方法是最重要的,但是我将粘贴所有这些方法 package asteroids; import java.applet.*; import jav
package asteroids;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.util.*;
public class Asteroids extends Applet implements Runnable, KeyListener {
//the main thread becomes the game loop
Thread gameloop;
//use this as a double buffer
BufferedImage backbuffer;
//the main drawing object for the back buffer
Graphics2D g2d;
//toggle for drawing bounding boxes
boolean showBounds = false;
//create the asteroid array
int ASTEROIDS = 20;
Asteroid[] ast = new Asteroid[ASTEROIDS];
//create the new bullet array
int BULLETS = 10;
Bullet[] bullet = new Bullet[BULLETS];
int currentBullet = 0;
//the player's ship
Ship ship = new Ship();
//create the identity transform(0,0)
AffineTransform identity = new AffineTransform();
//create a random number generator
Random rand = new Random();
//applet init event
public void init(){
//create the back buffer for smooth graphics
backbuffer = new BufferedImage(640,480, BufferedImage.TYPE_INT_RGB);
g2d = backbuffer.createGraphics();
//det up the ship
ship.setX(320);
ship.setY(240);
//set up the bullets
for(int n = 0 ; n < BULLETS ; n++)
{
bullet[n] = new Bullet();
}
//create the asteroid
for(int n = 0 ; n < ASTEROIDS ; n++)
{
ast[n] = new Asteroid();
ast[n].setRotationVelocity(rand.nextInt(3)+1);
ast[n].setX((double)rand.nextInt(600)+20);
ast[n].setY((double)rand.nextInt(440)+20);
ast[n].setMoveAngle(rand.nextInt(360));
double ang = ast[n].getMoveAngle() - 90;
ast[n].setVelX(calcAngleMoveX(ang));
ast[n].setVelY(calcAngleMoveY(ang));
}
//start the user input listener
addKeyListener(this);
}
//applet update event to redraw the screen
public void update(Graphics g){
//start off transform at identity
g2d.setTransform(identity);
//erase the background
g2d.setPaint(Color.BLACK);
g2d.fillRect(0, 0, getSize().width, getSize().height);
//print some status information
g2d.setColor(Color.WHITE);
g2d.drawString("Ship: " + Math.round(ship.getX()) + ", " + Math.round(ship.getY()), 5, 10);
g2d.drawString("Move angle: " + Math.round(ship.getMoveAngle())+90, 5, 25);
g2d.drawString("Face angle: " + Math.round(ship.getFaceAngle()), 5, 40);
//draw the game g raphics
drawShip();
drawBullets();
drawAsteroids();
//repaint the applet window
paint(g);
}
//drawShip called by applet update event
public void drawShip(){
g2d.setTransform(identity);
g2d.translate(ship.getX(), ship.getY());
g2d.rotate(Math.toRadians(ship.getFaceAngle()));
g2d.setColor(Color.ORANGE);
g2d.fill(ship.getShape());
}
//drawBullets called by applet update event
public void drawBullets(){
//iterate through the array of bullets
for(int n = 0 ; n < BULLETS ; n++)
{
//is this bullet currently in use?
if(bullet[n].isAlive()){
//draw the bullet
g2d.setTransform(identity);
g2d.translate(bullet[n].getX(), bullet[n].getY());
g2d.setColor(Color.MAGENTA);
g2d.draw(bullet[n].getShape());
}
}
}
//drawAsteroids called by applet update event
public void drawAsteroids(){
//iterate through the asteroids array
for(int n = 0 ; n < ASTEROIDS ; n++)
{
//is this asterois currently in use?
if(ast[n].isAlive()){
//draw the Asteroid
g2d.setTransform(identity);
g2d.translate(ast[n].getX(), ast[n].getY());
g2d.rotate(Math.toRadians(ast[n].getMoveAngle()));
g2d.setColor(Color.DARK_GRAY);
g2d.fill(ast[n].getShape());
}
}
}
//applet window repaint event - - draw the back buffer
public void paint(Graphics g){
//draw the back buffer onto the applet window
g.drawImage(backbuffer, 0, 0, this);
}
//thread start event - start the game loop running
public void start(){
//create the gameloop thread for real-time updates
gameloop = new Thread(this);
gameloop.start();
}
//thread run event (game loop)
public void run(){
//acquire the current thread
Thread t = Thread.currentThread();
//keep going as long as the thread is alive
while(t == gameloop){
try{
//update game loop
gameUpdate();
//target framerate is 50 fps
Thread.sleep(20);
}
catch(InterruptedException e){
e.printStackTrace();
}
repaint();
}
}
//thread stop event
public void stop(){
//kill the gameloop thread
gameloop = null;
}
//move and animate objects in the game
private void gameUpdate(){
updateShip();
updateBullets();
updateAsteroids();
checkCollisions();
}
//update the ship position based on velocity
public void updateShip(){
//update ship's X position
ship.incX(ship.getVelX());
//wrap around left/right
if(ship.getX() < -10)
ship.setX(getSize().width+10);
else if(ship.getX() > getSize().width + 10)
ship.setX(-10);
//update ship's Y position
ship.incY(ship.getVelY());
//wrap around top/bottom
if(ship.getY() < - 10)
ship.setY(getSize().height + 10);
else if(ship.getY() > getSize().height + 10)
ship.setY(-10);
}
//update the bullets based on velocity
public void updateBullets(){
//move each of the bullets
for(int n = 0 ; n < BULLETS ; n++)
{
//is the bullet alive?
if(bullet[n].isAlive()){
//update bullet's x position
bullet[n].incX(bullet[n].getVelX());
//bullet disappears at left/right edge
if(bullet[n].getX() < 0 ||
bullet[n].getX() > getSize().width)
{
bullet[n].setAlive(false);
}
//update bullet's y position
bullet[n].incY(bullet[n].getVelY());
//bullet disappears at top/bottom edge
if(bullet[n].getY() < 0 ||
bullet[n].getY() > getSize().height)
{
bullet[n].setAlive(false);
}
}
}
}
//update asteroids based on velocity
public void updateAsteroids(){
//move and rotate the asteroids
for(int n = 0 ; n < ASTEROIDS ; n++)
{
//is this asteroid being used?
if(ast[n].isAlive()){
//update this asteroid's X value
ast[n].incX(ast[n].getVelX());
//warp the asteroid at screen edges
if(ast[n].getX() < -20)
ast[n].setX(getSize().width + 20);
else if(ast[n].getX() > getSize().width + 20)
ast[n].setX(-20);
//update the asteroid’s Y value
ast[n].incY(ast[n].getVelY());
//warp the asteroid at screen edges
if (ast[n].getY() < -20)
ast[n].setY(getSize().height + 20);
else if (ast[n].getY() > getSize().height + 20)
ast[n].setY(-20);
//update the asteroid’s rotation
ast[n].incMoveAngle(ast[n].getRotationVelocity());
//keep the angle within 0-359 degrees
if (ast[n].getMoveAngle() < 0)
ast[n].setMoveAngle(360 - ast[n].getRotationVelocity());
else if (ast[n].getMoveAngle() > 360)
ast[n].setMoveAngle(ast[n].getRotationVelocity());
}
}
}
//Test asteroids for collisions with ship or bullets
public void checkCollisions(){
//iterate through the asteroids array
for(int m = 0 ; m < ASTEROIDS ; m++)
{
//is this asteroid being used
if(ast[m].isAlive())
{
//check for collisions with bullet
for(int n = 0 ; n < BULLETS; n++)
{
//is this bullet being used?
if(bullet[n].isAlive())
{
//perform collision test
if(ast[m].getBounds().contains(
bullet[n].getX(), bullet[n].getY()))
{
bullet[n].setAlive(false);
ast[m].setAlive(false);
continue;
}
}
}
}
//check for collision with ship
if(ast[m].getBounds().intersects(ship.getBounds())){
ast[m].setAlive(false);
ship.setX(320);
ship.setY(240);
ship.setFaceAngle(0);
ship.setVelX(0);
ship.setVelY(0);
continue;
}
}
}
//key listener events
public void keyReleased(KeyEvent k){}
public void keyTyped(KeyEvent k){}
public void keyPressed(KeyEvent k){
int keyCode = k.getKeyCode();
switch(keyCode){
case KeyEvent.VK_LEFT:
//left arrow rotates ship left 5 degrees
ship.incFaceAngle(-5);
if(ship.getFaceAngle() < 0)ship.setFaceAngle(360-5);
break;
case KeyEvent.VK_RIGHT:
//right arrow rotates ship right 5 degrees
ship.incFaceAngle(5);
if(ship.getFaceAngle() > 360)ship.setFaceAngle(5);
break;
case KeyEvent.VK_UP:
//up arrow adds thrust to ship (1/10 normal speed)
ship.setMoveAngle(ship.getFaceAngle() - 90);
ship.incVelX(calcAngleMoveX(ship.getMoveAngle()) * 0.1);
ship.incVelY(calcAngleMoveY(ship.getMoveAngle()) * 0.1);
//Ctrl, Enter, or Space can be used to fire weapon
case KeyEvent.VK_CONTROL:
case KeyEvent.VK_ENTER:
case KeyEvent.VK_SPACE:
//fire a bullet
currentBullet++;
if(currentBullet > BULLETS -1)currentBullet = 0;
bullet[currentBullet].setAlive(true);
//point bullet in same direction ship is facing
bullet[currentBullet].setX(ship.getX());
bullet[currentBullet].setY(ship.getY());
bullet[currentBullet].setMoveAngle(ship.getFaceAngle() - 90);
//fire bullet at angle of the ship
double angle = bullet[currentBullet].getMoveAngle();
double svx = ship.getVelX();
double svy = ship.getVelY();
bullet[currentBullet].setVelX(svx + calcAngleMoveX(angle) * 2);
bullet[currentBullet].setVelY(svy + calcAngleMoveY(angle) * 2);
break;
}
}
//calculate X movement value based on direction angle
public double calcAngleMoveX(double angle){
return (double)(Math.cos(angle * Math.PI / 180));
}
//calculate Y movement value based on direction able
public double calcAngleMoveY(double angle){
return (double)(Math.sin(angle * Math.PI / 180));
}
成功构建,什么都不会发生。我猜这应该是一个命令,而不是两个单独的命令?我也不确定是否应该对小行星对象或线程实例调用.run()或.init()方法
public static void main(String[] args) {
Thread t = new Thread(new Asteroids());
t.run();
}
再次强调,如果构建成功,什么也不会发生。另一个猜测是,因为我已经有了一个start()方法,它创建了一个新线程,所以我应该在一个新的Asteroids()对象上调用它,但是我得到了一个NullPointerException
我尝试过两种类似的方法,但我认为这篇文章足够长,没有展示它们。主要问题是:
- 有了这些方法,我应该怎么称呼它们?线程对象还是小行星对象李>
- 调用的唯一方法不应该是run()(因为我找到的关于线程和可运行接口的代码示例只使用run()方法)
- 如果没有,因为我在Asteroids类中有几个方法,在游戏实际运行之前是否应该按特定顺序调用它们?例如,.start(),.init(),.run()
我只是觉得我的知识和作者的期望之间有一个巨大的差距,而且,即使看代码,我能理解大多数东西代表什么,我自己也很难继续前进。有什么提示,具体的Oracle文档,我可以通过它来掌握这一点吗?我正在使用NetBeans进行编译。根据我从您的代码中读到的信息,发生了以下情况:
Asteroids a = new Asteroids(); // Instantiate an object for the game
a.init(); // Init the applet for the game, add key listeners.
a.start(); // Start the thread(its handled internally) with the game loop, which handles UI updates and game mechanics
第一次尝试失败,因为start()将成员属性gameloop设置为新线程。因此,当您手动调用run时,gameloop未设置,因此currentThread(t)不等于gameloop(null)
第二次尝试失败的原因相同,也因为小程序未初始化。它是一个小程序。启动小程序与启动普通java程序有点不同。让我们看看《费边》,你应该回答这个问题,而不是发表评论。其实没什么可说的了。1)为什么要编写小程序?如果是由于老师的特殊要求,请参考。2) 为什么是AWT而不是Swing?关于放弃使用AWT组件的许多好理由,请参见我的答案。谢谢您的评论@谢谢,我从来不知道小程序不需要一个主类。帮了很多忙!Andrew Thompson嗯,这本书的作者使用了Applet和AWT,我相信我自己还没有足够的能力来进行任何导入更改。谢谢你的建议,你,我会记住的。
Asteroids a = new Asteroids(); // Instantiate an object for the game
a.init(); // Init the applet for the game, add key listeners.
a.start(); // Start the thread(its handled internally) with the game loop, which handles UI updates and game mechanics