1

堆栈和Java的新人。

首先,这是我的代码,AsteroidsGame.java

   import java.applet.*;
   import java.awt.*;
   import java.awt.event.*;
   import javax.swing.*;
   import java.net.*;
   import java.util.*;


public class AsteroidsGame extends JApplet implements Runnable, KeyListener {

    Thread thread;

    Dimension dim;

    Image img;

    Graphics g;

    long endTime, startTime, framePeriod;

    Ship ship;

    boolean paused;

// True if the game is paused. Enter is the pause key

    Shot[] shots;

    int numShots;

    boolean shooting;
    Asteroid[] asteroids;

    int numAsteroids;

    double astRadius;

    double minAstVel;

    double maxAstVel;

    int astNumHits;

    int astNumSplit;

    int level;

    private AudioClip audioClip;




public void init() {

    resize(500, 500);

    shots = new Shot[41];

    numAsteroids = 0;

    level = 0;

    astRadius = 60;

    minAstVel = .5;

    maxAstVel = 5;

    astNumHits = 3;

    astNumSplit = 2;

    endTime = 0;

    startTime = 0;

    framePeriod = 25;

    addKeyListener(this);

    setFocusable(true);

    requestFocusInWindow();

    dim = getSize();

    img = createImage(dim.width, dim.height);

    g = img.getGraphics();

    thread = new Thread(this);

    thread.start();

    URL urlAudioClip = getClass().getResource("audio/minorcircuit.wav");

    audioClip = Applet.newAudioClip(urlAudioClip);

    audioClip.loop();

}



public void start() {

    audioClip.loop();

}

public void stop() {

    audioClip.stop();

}





public void setUpNextLevel() {

    level++;

    ship = new Ship(250, 250, 0, .35, .98, .1, 12);

    numShots = 0;

    paused = false;

    shooting = false;

    asteroids = new Asteroid[level * (int)Math.pow(astNumSplit, astNumHits - 1) + 1];

    numAsteroids = level;

    for(int i = 0; i < numAsteroids; i++) {

        asteroids[i] = new Asteroid(Math.random() * dim.width, Math.random() * dim.height, astRadius, minAstVel, maxAstVel, astNumHits, astNumSplit);

    }

}



public void paint(Graphics gfx) {

    g.setColor(Color.black);

    g.fillRect(0, 0, 500, 500);

    for(int i = 0; i < numShots; i++) {

        shots[i].draw(g);

    }

    for(int i = 0; i < numAsteroids; i++) {

        asteroids[i].draw(g);

    }

    ship.draw(g);

//draw the ship

    g.setColor(Color.cyan);

    g.drawString("Level " + level, 20, 20);

    gfx.drawImage(img, 0, 0, this);

}



public void update(Graphics gfx) {

    paint(gfx);

}



public void run() {

    for(;;) {

        startTime = System.currentTimeMillis();

//start next level when all asteroids are destroyed

        if(numAsteroids <= 0) {

            setUpNextLevel();

        }

        if(!paused) {

            ship.move(dim.width, dim.height);

//move the ship

            for(int i = 0; i < numShots; i++) {

                shots[i].move(dim.width, dim.height);

                if(shots[i].getLifeLeft() <= 0) {

                    deleteShot(i);

                    i--;

                }

            }

            updateAsteroids();

            if(shooting && ship.canShoot()) {

//add a shot on to the array

                shots[numShots] = ship.shoot();

                numShots++;

            }

        }

        repaint();

        try {

            endTime = System.currentTimeMillis();

            if(framePeriod - (endTime - startTime) > 0) {

                Thread.sleep(framePeriod - (endTime - startTime));

            }

        }

        catch(InterruptedException e) {

        }

    }

}



private void deleteShot(int index) {

//delete shot and move all shots after it up in the array

    numShots--;

    for(int i = index; i < numShots; i++) {

        shots[i] = shots[i + 1];

        shots[numShots] = null;

    }

}



private void deleteAsteroid(int index) {

//delete asteroid and shift ones after it up in the array

    numAsteroids--;

    for(int i = index; i < numAsteroids; i++) {

        asteroids[i] = asteroids[i + 1];

        asteroids[numAsteroids] = null;

    }

}



private void addAsteroid(Asteroid ast) {

//adds asteroid in at end of array

    asteroids[numAsteroids] = ast;

    numAsteroids++;

}



private void updateAsteroids() {

    for(int i = 0; i < numAsteroids; i++) {

// move each asteroid

        asteroids[i].move(dim.width, dim.height);

//check for collisions with the ship

        if(asteroids[i].shipCollision(ship)) {

            level--;

//restart this level

            numAsteroids = 1;

            return;

        }

//check for collisions with any of the shots

        for(int j = 0; j < numShots; j++) {

            if(asteroids[i].shotCollision(shots[j])) {

//if the shot hit an asteroid, delete the shot

                deleteShot(j);

//split the asteroid up if needed

                if(asteroids[i].getHitsLeft() > 1) {

                    for(int  k = 0; k < asteroids[i].getNumSplit(); k++) {

            addAsteroid(

                asteroids[i].createSplitAsteroid(

        minAstVel, maxAstVel));

                    }

                }

//delete the original asteroid

                deleteAsteroid(i);

                j=numShots;

                i--;

            }

        }

    }

}



public void keyPressed(KeyEvent e) {

    if(e.getKeyCode() == KeyEvent.VK_ENTER) {

        if(!ship.isActive() && !paused) {

            ship.setActive(true);

        }

        else {

        paused = !paused;

//enter is the pause button

            if(paused) {

//grays out the ship if paused

                ship.setActive(false);

            }

            else {

                ship.setActive(true);

            }

        }

    }

    else if(paused || !ship.isActive()) {

        return;

    }

    else if(e.getKeyCode() == KeyEvent.VK_SPACE) {

        ship.setAccelerating(true);

    }

    else if(e.getKeyCode() == KeyEvent.VK_LEFT) {

        ship.setTurningLeft(true);

    }

    else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {

        ship.setTurningRight(true);

    }

    else if(e.getKeyCode() == KeyEvent.VK_CONTROL) {

        shooting=true;

    }

    else if(e.getKeyCode() == KeyEvent.VK_M) {

        audioClip.stop();

    }

    else if(e.getKeyCode() == KeyEvent.VK_S) {

        audioClip.loop();

    }

}



public void keyReleased(KeyEvent e) {

    if(e.getKeyCode() == KeyEvent.VK_UP) {

        ship.setAccelerating(false);

    }

    else if(e.getKeyCode() == KeyEvent.VK_LEFT) {

        ship.setTurningLeft(false);

    }

    else if(e.getKeyCode() == KeyEvent.VK_RIGHT) {

        ship.setTurningRight(false);

    }

    else if(e.getKeyCode() == KeyEvent.VK_CONTROL) {

        shooting=false;

    }

}



public void keyTyped(KeyEvent e) {

}



}

这是小行星的“克隆”。你们中的一些人可能比我长一点,可能在街机中玩过它。无论如何,我为我的 Java 课程的一个期末项目写了这个,但永远无法完全工作。它启动得很好,你可以转身射击,但不能向前移动。不过我现在不担心搬家。小程序启动后发生的是音乐播放和“小行星”穿过屏幕。如果你向小行星射击或向任何方向射击 3 次,就会发生线程异常。

Exception in thread "Thread-3" java.lang.NullPointerException
at AsteroidsGame.updateAsteroids(AseroidsGame.java:161)
at AsteroidsGame.run(AsteroidsGame.java:115)
at java.lang.Thread.run(Thread.java:722)

在网上四处看看对我没有什么好处。我学到的大部分东西都是自学的,并不那么容易理解。我不完全确定在这里做什么来解决这个异常。在堆栈上的另一个线程中,提到使用 ArrayList,因为该数组以前没有用大小声明。修修补补;从来没有让它工作。

我需要想法/建议/批评。我想让它工作,这样我就可以说我完成了。

其他类,Asteroid.java

import java.awt.*;



public class Asteroid {



double x, y, xVelocity, yVelocity, radius;

int hitsLeft, numSplit;



public Asteroid(double x,double y,double radius,double minVelocity, double maxVelocity,int hitsLeft,int numSplit) {

    this.x = x;

    this.y = y;

    this.radius = radius;

    this.hitsLeft = hitsLeft;

    this.numSplit = numSplit;

    double vel = minVelocity + Math.random() * (maxVelocity - minVelocity);

    double dir = 2 * Math.PI * Math.random();

    xVelocity = vel * Math.cos(dir);

    yVelocity = vel * Math.sin(dir);

}



public void move(int scrnWidth, int scrnHeight) {

    x += xVelocity;

    y += yVelocity;

    if(x < 0 - radius) {

        x += scrnWidth + 2 * radius;

    }

    else if(x > scrnWidth + radius) {

        x -= scrnWidth + 2 * radius;

    }

    if(y < 0 - radius) {

        y += scrnHeight + 2 * radius;

    }

    else if(y > scrnHeight + radius) {

        y -= scrnHeight + 2 * radius;

    }

}



public void draw(Graphics g) {

    g.setColor(Color.gray);

    g.fillOval((int)(x - radius + .5), (int)(y - radius + .5), (int)(2 * radius), (int)(2 * radius));

}



public Asteroid createSplitAsteroid(double minVelocity,double maxVelocity) {

    return new Asteroid(x, y, radius / Math.sqrt(numSplit), minVelocity, maxVelocity, hitsLeft - 1, numSplit);

}



public boolean shipCollision(Ship ship) {

    if(Math.pow(radius + ship.getRadius(), 2) > Math.pow(ship.getX() - x, 2) + Math.pow(ship.getY() - y, 2) && ship.isActive()) {

        return true;

    }

    return false;

}



public boolean shotCollision(Shot shot) {

    if(Math.pow(radius, 2) > Math.pow(shot.getX() - x, 2) + Math.pow(shot.getY() - y, 2)) {

        return true;

    }

    return false;

}



public int getHitsLeft() {

    return hitsLeft;

}



public int getNumSplit() {

    return numSplit;

}

}

Ship.java

import java.awt.*;



public class Ship {



final double[] origXPts = {14,-10,-6,-10}, origYPts = {0,-8,0,8}, origFlameXPts = {-6,-23,-6}, origFlameYPts = {-3,0,3};

final int radius = 6;



double x, y, angle, xVelocity, yVelocity, acceleration, velocityDecay, rotationalSpeed;

//used for movement

boolean turningLeft, turningRight, accelerating, active;

int [] xPts, yPts, flameXPts, flameYPts;

//current location of ship

int shotDelay, shotDelayLeft;

//rate of fire



public Ship(double x, double y, double angle, double acceleration, double velocityDecay, double rotationalSpeed, int shotDelay) {

    this.x = x;

    this.y = y;

    this.angle = angle;

    this.acceleration = acceleration;

    this.velocityDecay = velocityDecay;

    this.rotationalSpeed = rotationalSpeed;

    xVelocity = 0;

    yVelocity = 0;

    turningLeft = false;

    turningRight = false;

    accelerating = false;

    active = false;

    xPts = new int[4];

    yPts = new int[4];

    flameXPts = new int[3];

    flameYPts = new int[3];

    this.shotDelay = shotDelay;

    shotDelayLeft = 0;

}



public void draw(Graphics g) {

    if(accelerating && active) {

        for(int i = 0; i < 3; i++) {

            flameXPts[i] = (int)(origFlameXPts[i] * Math.cos(angle) - origFlameYPts[i] * Math.sin(angle) + x + .5);

            flameYPts[i] = (int)(origFlameXPts[i] * Math.sin(angle) + origFlameYPts[i] * Math.cos(angle) + y + .5);

        }

        g.setColor(Color.red);

//color of flame

        g.fillPolygon(flameXPts, flameYPts, 3);



    }

    for(int i = 0; i < 4; i++) {

        xPts[i] = (int)(origXPts[i] * Math.cos(angle) - origYPts[i] * Math.sin(angle) + x + .5);

        yPts[i] = (int)(origXPts[i] * Math.sin(angle) + origYPts[i] * Math.cos(angle) + y + .5);

    }



    if(active) {

        g.setColor(Color.white);

    }

    else {

        g.setColor(Color.darkGray);

    }

    g.fillPolygon(xPts, yPts, 4);

}



public void move(int scrnWidth, int scrnHeight) {

    if(shotDelayLeft > 0) {

        shotDelayLeft--;

    }

    if(turningLeft) {

        angle -= rotationalSpeed;

    }

    if(turningRight) {

        angle += rotationalSpeed;

    }

    if(angle > (2 * Math.PI)) {

        angle -= (2 * Math.PI);

    }

    else if(angle < 0) {

        angle += (2 * Math.PI);

    }

    if(accelerating) {

        xVelocity += acceleration * Math.cos(angle);

        yVelocity += acceleration * Math.sin(angle);

    }

    x += xVelocity;

    y += yVelocity;

    xVelocity *= velocityDecay;

    yVelocity *= velocityDecay;

    if(x<0) {

        x += scrnWidth;

    }

    else if(x > scrnWidth) {

        x -= scrnWidth;

    }

    if(y < 0) {

        y += scrnHeight;

    }

    else if(y > scrnHeight) {

        y -= scrnHeight;

    }

}



public void setAccelerating(boolean accelerating) {

    this.accelerating = accelerating;

//start or stop accelerating the ship

}



public void setTurningLeft(boolean turningLeft) {

    this.turningLeft = turningLeft;

//start or stop turning the ship

}



public void setTurningRight(boolean turningRight) {

    this.turningRight = turningRight;

}



public double getX() {

    return x;

//returns the ship’s x location

}



public double getY() {

    return y;

//returns the ship's y location

}



public double getRadius() {

    return radius;

//returns radius of circle that approximates the ship

}



public void setActive(boolean active) {

    this.active = active;

//used when the game is paused or unpaused

}



public boolean isActive() {

    return active;

}



public boolean canShoot() {

    if(shotDelayLeft > 0) {

        return false;

    }

    else {

        return true;

    }

}



public Shot shoot() {

    shotDelayLeft=shotDelay;

//set delay till next shot can be fired

//a life of 40 makes the shot travel about the width of the

//screen before disappearing

    return new Shot(x, y, angle, xVelocity, yVelocity, 40);

}

}

Shot.java

import java.awt.*;



public class Shot {



final double shotSpeed = 12;

double x, y, xVelocity, yVelocity;

int lifeLeft;



public Shot(double x, double y, double angle, double shipXVel, double shipYVel, int lifeLeft) {

    this.x = x;

    this.y = y;

    xVelocity = shotSpeed * Math.cos(angle) + shipXVel;

    yVelocity = shotSpeed * Math.sin(angle) + shipYVel;

    this.lifeLeft = lifeLeft;

}



public void move(int scrnWidth, int scrnHeight) {

    lifeLeft--;

    x += xVelocity;

    y += yVelocity;

    if(x < 0) {

        x += scrnWidth;

    }

    else if(x > scrnWidth) {

        x -= scrnWidth;

    }

    if(y < 0) {

        y += scrnHeight;

    }

    else if(y > scrnHeight) {

        y -= scrnHeight;

    }

}



public void draw(Graphics g) {

    g.setColor(Color.yellow);

    g.fillOval((int)(x - .5), (int)(y - .5), 3, 3);

}



public double getX() {

    return x;

}



public double getY() {

    return y;

}



public int getLifeLeft() {

    return lifeLeft;

}

}

感谢您的关注。

---------------------编辑 2012 年 12 月 9 日----------- -

尝试使用 NetBeans IDE 7.2.1 进行调试。它不正确地描述了船的转向并给出了完全不同的错误:

Exception in thread "Thread-3" java.lang.NullPointerException
at AsteroidsGame.run(AsteroidsGame.java:122)
at java.lang.Thread.run(Thread.java:722)

它将注意力指向 run 方法中的 Shot[] 镜头数组。这是可以预料的,因为 Asteroid[] 和 Shot[] 的数组设置相同。

4

0 回答 0