首页 > 解决方案 > 创建新关卡

问题描述

作为一名 Java 初学者,我正在研究 Space Invaders 的一个项目。希望增加更多关卡。

private void LevelInit() {
    aliens = new ArrayList<>();
    int currentLevel = 1;

        if (currentLevel == 1) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 4; j++) {

                    var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
                    aliens.add(alien);
                    //System.out.println(currentLevel);


                }

            }
        }
        else if (currentLevel == 2) {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {

                    var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
                    aliens.add(alien);

                   // System.out.println(currentLevel);


                }
            }
        }
        else if (currentLevel == 3) {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 6; j++) {

                    var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
                    aliens.add(alien);
                    //System.out.println(currentLevel);
                }

            }
        }
        




    player = new Player();
    bullet = new Bullet();


}

该函数是初始化游戏并被构造函数调用的代码背后的逻辑。添加关卡的简单方法是添加更多外星人。这是昨天更新后的样子,正在添加级别,但数组列表被粘在一起。就像 12 - 16 - 24 个外星人一起打印一样,一些宇宙飞船受到 1 次撞击,一些 2 次和一些 3 次撞击,当它们全部被摧毁时,系统会发出消息说你一起通过了第 1 级、第 2 级和第 3 级,这让我很困惑,为什么它们被绑定在一起像那样,没有被通过。我想不通。还,

    private void update() {

    if (deaths == 12) {

            inGame = false;
            timer.stop();
            message = "Next Level!";

    }
    // player
    player.act();

    // shot
    if (bullet.isVisible()) {

        int shotX = bullet.getX();
        int shotY = bullet.getY();

        for (Alien alien : aliens) {

            int alienX = alien.getX();
            int alienY = alien.getY();

            if (alien.isVisible() && bullet.isVisible()) {
                if (shotX >= (alienX)
                        && shotX <= (alienX + Constants.ALIEN_WIDTH)
                        && shotY >= (alienY)
                        && shotY <= (alienY + Constants.ALIEN_HEIGHT)) {

                    var ii = new ImageIcon(explImg);
                    alien.setImage(ii.getImage());
                    alien.setDying(true);
                    deaths++;
                    bullet.die();
                }
            }
        }

        int y = bullet.getY();
        y -= 4;

        if (y < 0) {
            bullet.die();
        } else {
            bullet.setY(y);
        }
    }

    // aliens

    for (Alien alien : aliens) {

        int x = alien.getX();

        if (x >= Constants.BOARD_WIDTH - Constants.BORDER_RIGHT && direction != -1) {

            direction = -1;

            for(Alien a2 : aliens) {
                a2.setY(a2.getY() + Constants.GO_DOWN);
            }
        }

        if (x <= Constants.BORDER_LEFT && direction != 1) {

            direction = 1;


            for(Alien a : aliens) {

                a.setY(a.getY() + Constants.GO_DOWN);
            }
        }
    }



    for(Alien alien : aliens) {


        if (alien.isVisible()) {

            int y = alien.getY();

            if (y > Constants.GROUND - Constants.ALIEN_HEIGHT) {
                inGame = false;
                message = "Invasion!";
            }

            alien.act(direction);
        }
    }

    // bombs
    var generator = new Random();

    for (Alien alien : aliens) {

        int shot = generator.nextInt(15);
        Alien.Bomb bomb = alien.getBomb();

        if (shot == Constants.CHANCE && alien.isVisible() && bomb.isDestroyed()) {

            bomb.setDestroyed(false);
            bomb.setX(alien.getX());
            bomb.setY(alien.getY());
        }

        int bombX = bomb.getX();
        int bombY = bomb.getY();
        int playerX = player.getX();
        int playerY = player.getY();

        if (player.isVisible() && !bomb.isDestroyed()) {

            if (bombX >= (playerX)
                    && bombX <= (playerX + Constants.PLAYER_WIDTH)
                    && bombY >= (playerY)
                    && bombY <= (playerY + Constants.PLAYER_HEIGHT)) {

                var ii = new ImageIcon(explImg);
                player.setImage(ii.getImage());
                player.setDying(true);
                bomb.setDestroyed(true);
            }
        }

        if (!bomb.isDestroyed()) {

            bomb.setY(bomb.getY() + 1);

            if (bomb.getY() >= Constants.GROUND - Constants.BOMB_HEIGHT) {

                bomb.setDestroyed(true);
            }
        }
    }
}

此功能是在发生任何事情时更新游戏。该代码是由一堆 YouTube 视频和 GitHub 制作的,所以如果你看到任何复制,请原谅。我需要通过简单地添加更多外星人来创建新关卡,尝试使用 for 循环,但这会导致外星人移动得更快,或者子弹不会摧毁外星人,它只是击中。

板级:

public class Board extends JPanel {

private Dimension d;
private List<Alien> aliens;
private Player player;
private Bullet bullet;
private int level;
private int direction = -1;
private int deaths = 0;

private boolean inGame = true;
private String explImg = "src/images/explosion.png";
private String message = "Game Over";

private Timer timer;


public Board() {


    initBoard();
    gameInit();
    LevelInit();


}

private void initBoard() {

    addKeyListener(new TAdapter());
    setFocusable(true);
    d = new Dimension(Constants.BOARD_WIDTH, Constants.BOARD_HEIGHT);
    setBackground(Color.black);

    timer = new Timer(Constants.DELAY, new GameCycle());
    timer.start();

    gameInit();

}


private void gameInit() {

    aliens = new ArrayList<>();


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

            var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j,
                    Constants.ALIEN_INIT_Y + 18 * i);
            aliens.add(alien);

        }
    }


    player = new Player();
    bullet = new Bullet();

}
private void LevelInit() {


    inGame = true;
    timer.start();
    int level = 1;
    if (aliens.isEmpty()) {
        level++;
        int AlienCount;if(level == 2) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 6; j++) {
                    var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
                    aliens.add(alien);

                }
            }
        } else if (level == 3) {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 6; j++) {
                    var alien = new Alien(Constants.ALIEN_INIT_X + 18 * j, Constants.ALIEN_INIT_Y + 18 * i);
                    aliens.add(alien);
                    
                }
            }
        }
    }
    player = new Player();
    bullet = new Bullet();
}





private void drawAliens(Graphics g) {

    for (Alien alien : aliens) {

        if (alien.isVisible()) {

            g.drawImage(alien.getImage(), alien.getX(), alien.getY(), this);
        }

        if (alien.isDying()) {

            alien.die();
        }
    }
}

private void drawPlayer(Graphics g) {

    if (player.isVisible()) {

        g.drawImage(player.getImage(), player.getX(), player.getY(), this);
    }

    if (player.isDying()) {

        player.die();
        inGame = false;
    }
}

private void drawShot(Graphics g) {

    if (bullet.isVisible()) {

        g.drawImage(bullet.getImage(), bullet.getX(), bullet.getY(), this);
    }
}

private void drawBombing(Graphics g) {

    for (Alien a : aliens) {

        Alien.Bomb b = a.getBomb();

        if (!b.isDestroyed()) {

            g.drawImage(b.getImage(), b.getX(), b.getY(), this);
        }
    }
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);

    doDrawing(g);
}

private void doDrawing(Graphics g) {

    g.setColor(Color.black);
    g.fillRect(0, 0, d.width, d.height);
    g.setColor(Color.green);

    if (inGame) {

        g.drawLine(0, Constants.GROUND,
                Constants.BOARD_WIDTH, Constants.GROUND);

        drawAliens(g);
        drawPlayer(g);
        drawShot(g);
        drawBombing(g);

    } else {

        if (timer.isRunning()) {
            timer.stop();
        }

        gameOver(g);
    }

    Toolkit.getDefaultToolkit().sync();
}

private void gameOver(Graphics g) {

    g.setColor(Color.black);
    g.fillRect(0, 0, Constants.BOARD_WIDTH, Constants.BOARD_HEIGHT);

    g.setColor(new Color(0, 32, 48));
    g.fillRect(50, Constants.BOARD_WIDTH / 2 - 30, Constants.BOARD_WIDTH - 100, 50);
    g.setColor(Color.white);
    g.drawRect(50, Constants.BOARD_WIDTH / 2 - 30, Constants.BOARD_WIDTH - 100, 50);

    var small = new Font("Helvetica", Font.BOLD, 14);
    var fontMetrics = this.getFontMetrics(small);

    g.setColor(Color.white);
    g.setFont(small);
    g.drawString(message, (Constants.BOARD_WIDTH - fontMetrics.stringWidth(message)) / 2,
            Constants.BOARD_WIDTH / 2);
}

private void update() {

    if (deaths == aliens.size()) {

            inGame = false;
            timer.stop();
            message = "Next Level!";


    }
    // player
    player.act();

    // shot
    if (bullet.isVisible()) {

        int shotX = bullet.getX();
        int shotY = bullet.getY();

        for (Alien alien : aliens) {

            int alienX = alien.getX();
            int alienY = alien.getY();

            if (alien.isVisible() && bullet.isVisible()) {
                if (shotX >= (alienX)
                        && shotX <= (alienX + Constants.ALIEN_WIDTH)
                        && shotY >= (alienY)
                        && shotY <= (alienY + Constants.ALIEN_HEIGHT)) {

                    var ii = new ImageIcon(explImg);
                    alien.setImage(ii.getImage());
                    alien.setDying(true);
                    deaths++;
                    bullet.die();
                }
            }
        }

        int y = bullet.getY();
        y -= 4;

        if (y < 0) {
            bullet.die();
        } else {
            bullet.setY(y);
        }
    }

    // aliens

    for (Alien alien : aliens) {

        int x = alien.getX();

        if (x >= Constants.BOARD_WIDTH - Constants.BORDER_RIGHT && direction != -1) {

            direction = -1;

            Iterator<Alien> i1 = aliens.iterator();

            while (i1.hasNext()) {

                Alien a2 = i1.next();
                a2.setY(a2.getY() + Constants.GO_DOWN);
            }
        }

        if (x <= Constants.BORDER_LEFT && direction != 1) {

            direction = 1;

            Iterator<Alien> i2 = aliens.iterator();

            while (i2.hasNext()) {

                Alien a = i2.next();
                a.setY(a.getY() + Constants.GO_DOWN);
            }
        }
    }

    Iterator<Alien> it = aliens.iterator();

    while (it.hasNext()) {

        Alien alien = it.next();

        if (alien.isVisible()) {

            int y = alien.getY();

            if (y > Constants.GROUND - Constants.ALIEN_HEIGHT) {
                inGame = false;
                message = "Invasion!";
            }

            alien.act(direction);
        }
    }

    // bombs
    var generator = new Random();

    for (Alien alien : aliens) {

        int shot = generator.nextInt(15);
        Alien.Bomb bomb = alien.getBomb();

        if (shot == Constants.CHANCE && alien.isVisible() && bomb.isDestroyed()) {

            bomb.setDestroyed(false);
            bomb.setX(alien.getX());
            bomb.setY(alien.getY());
        }

        int bombX = bomb.getX();
        int bombY = bomb.getY();
        int playerX = player.getX();
        int playerY = player.getY();

        if (player.isVisible() && !bomb.isDestroyed()) {

            if (bombX >= (playerX)
                    && bombX <= (playerX + Constants.PLAYER_WIDTH)
                    && bombY >= (playerY)
                    && bombY <= (playerY + Constants.PLAYER_HEIGHT)) {

                var ii = new ImageIcon(explImg);
                player.setImage(ii.getImage());
                player.setDying(true);
                bomb.setDestroyed(true);
            }
        }

        if (!bomb.isDestroyed()) {

            bomb.setY(bomb.getY() + 1);

            if (bomb.getY() >= Constants.GROUND - Constants.BOMB_HEIGHT) {

                bomb.setDestroyed(true);
            }
        }
    }
}

private void doGameCycle() {

    update();
    repaint();
}

private class GameCycle implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {

        doGameCycle();
    }
}

private class TAdapter extends KeyAdapter {

    @Override
    public void keyReleased(KeyEvent e) {

        player.keyReleased(e);
    }

    @Override
    public void keyPressed(KeyEvent e) {

        player.keyPressed(e);

        int x = player.getX();
        int y = player.getY();

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_SPACE) {

            if (inGame) {

                if (!bullet.isVisible()) {

                    bullet = new Bullet(x, y);
                }
            }
        }
    }
}

}

标签: javagame-development

解决方案


正如@JoachimSauer 提到的,您的代码需要重构。这是您的问题的一种可能的解决方案。


加法

您将需要两个额外的变量和一个额外的方法。

  • 变量

    1: int currentLevel - keeps track of the current level
    2: boolean isLevelOver - keeps track if the current level is still active or not
    
  • 方法

    private void levelInit(int currentlevel)
    {
        aliens = new ArrayList<>();
        int alienCount = //calculate alien count depending upon the current level
    
        //Add aliens to aliens ArrayList
    
        player = new Player();
        bullet = new Bullet();
    }
    

alienCount您必须提供如何根据. currentLevel您之前用于添加外星人的嵌套循环aliens也将发生变化。您必须使循环依赖currentLevel.


变化

你的一些方法需要一些改变。

public Board() 
{
    initBoard();
}

private void initBoard()
{
    addKeyListener(new TAdapter());
    setFocusable(true);
    d = new Dimension(Constants.BOARD_WIDTH, Constants.BOARD_HEIGHT);
    setBackground(Color.black);

    levelInit(currentLevel);

    timer = new Timer(Constants.DELAY, new GameCycle());
    timer.start();
}

private void update() 
{
    if (deaths == aliens.size()) 
    {
        isLevelOver = true;
        currentLevel++;
        message = "Next Level!";
        return;
    }

    ...
}

private void doGameCycle() 
{
    if (isLevelOver)
    {
        levelInit(currentLevel);
        isLevelOver = false;
    }
    
    update();
    repaint();
}

笔记

  • 这是实现你想要的可能的方法之一。可能还有其他方法,可能更好,但这就是我想出的。
  • 我试图在您的代码中找到尽可能多的添加和更新。但是,我不知道它的结构,你知道。所以可能需要更多的添加或更改。
  • 我注意到您正在调用gameInit()initBoard()然后又在Board()构造函数中调用。我认为这可能是不必要的,请考虑一下。
  • timer.stop()在设置后拨打了一个电话isGame = false这再次可能是不必要的,因为您已经在里面这样做了doDrawing(...)也请检查一下。
  • 您可能应该对屏幕上可以显示的外星人数量或最大外星人设置一个限制,levelCount()因为如果您继续在每个新关卡中添加更多外星人,它们可能会填满整个屏幕。

我提供了许多提示,可以帮助您解决问题。如果您仍然面临任何问题或有人发现答案有任何问题,请发表评论。


推荐阅读