<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # Java 太空侵略者 > 原文: [https://zetcode.com/tutorials/javagamestutorial/spaceinvaders/](https://zetcode.com/tutorials/javagamestutorial/spaceinvaders/) 在 Java 2D 游戲教程的這一部分中,我們將使用 Java 創建一個簡單的太空侵略者游戲克隆。 源代碼和圖像可在作者的 Github [Java-Space-Invaders](https://github.com/janbodnar/Java-Space-Invaders) 存儲庫中找到。 太空侵略者是由 Nishikado Tomohiro Nishikado 設計的街機游戲。 它于 1978 年首次發布。 在“太空侵略者”游戲中,玩家控制一門大炮。 他即將拯救地球免遭邪惡太空入侵者的入侵。 ## 用 Java 開發太空侵略者 在我們的 Java 克隆中,我們有 24 個入侵者。 這些外星人重重炮擊地面。 當玩家射擊導彈時,只有當導彈擊中外星人或棋盤頂部時,他才能射擊另一枚導彈。 玩家使用空格鍵射擊。 外星人隨機發射炸彈。 每個外星人只有在前一個擊中底部后才會發射炸彈。 `com/zetcode/SpaceInvaders.java` ```java package com.zetcode; import java.awt.EventQueue; import javax.swing.JFrame; public class SpaceInvaders extends JFrame { public SpaceInvaders() { initUI(); } private void initUI() { add(new Board()); setTitle("Space Invaders"); setSize(Commons.BOARD_WIDTH, Commons.BOARD_HEIGHT); setDefaultCloseOperation(EXIT_ON_CLOSE); setResizable(false); setLocationRelativeTo(null); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var ex = new SpaceInvaders(); ex.setVisible(true); }); } } ``` 這是主要的類。 它設置了應用。 `com/zetcode/Commons.java` ```java package com.zetcode; public interface Commons { int BOARD_WIDTH = 358; int BOARD_HEIGHT = 350; int BORDER_RIGHT = 30; int BORDER_LEFT = 5; int GROUND = 290; int BOMB_HEIGHT = 5; int ALIEN_HEIGHT = 12; int ALIEN_WIDTH = 12; int ALIEN_INIT_X = 150; int ALIEN_INIT_Y = 5; int GO_DOWN = 15; int NUMBER_OF_ALIENS_TO_DESTROY = 24; int CHANCE = 5; int DELAY = 17; int PLAYER_WIDTH = 15; int PLAYER_HEIGHT = 10; } ``` `Commons.java`文件具有一些公共常數。 他們是不言自明的。 `com/zetcode/sprite/Alien.java` ```java package com.zetcode.sprite; import javax.swing.ImageIcon; public class Alien extends Sprite { private Bomb bomb; public Alien(int x, int y) { initAlien(x, y); } private void initAlien(int x, int y) { this.x = x; this.y = y; bomb = new Bomb(x, y); var alienImg = "simg/alien.png"; var ii = new ImageIcon(alienImg); setImage(ii.getImage()); } public void act(int direction) { this.x += direction; } public Bomb getBomb() { return bomb; } public class Bomb extends Sprite { private boolean destroyed; public Bomb(int x, int y) { initBomb(x, y); } private void initBomb(int x, int y) { setDestroyed(true); this.x = x; this.y = y; var bombImg = "simg/bomb.png"; var ii = new ImageIcon(bombImg); setImage(ii.getImage()); } public void setDestroyed(boolean destroyed) { this.destroyed = destroyed; } public boolean isDestroyed() { return destroyed; } } } ``` 這是`Alien`子畫面。 每個外星人都有一個內部的`Bomb`類。 ```java public void act(int direction) { this.x += direction; } ``` 從`Board`類中調用`act()`方法。 用于在水平方向上定位外星人。 ```java public Bomb getBomb() { return bomb; } ``` 當外星人將要投下炸彈時,將調用`getBomb()`方法。 `com/zetcode/sprite/Player.java` ```java package com.zetcode.sprite; import com.zetcode.Commons; import javax.swing.ImageIcon; import java.awt.event.KeyEvent; public class Player extends Sprite { private int width; public Player() { initPlayer(); } private void initPlayer() { var playerImg = "simg/player.png"; var ii = new ImageIcon(playerImg); width = ii.getImage().getWidth(null); setImage(ii.getImage()); int START_X = 270; setX(START_X); int START_Y = 280; setY(START_Y); } public void act() { x += dx; if (x <= 2) { x = 2; } if (x >= Commons.BOARD_WIDTH - 2 * width) { x = Commons.BOARD_WIDTH - 2 * width; } } public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = -2; } if (key == KeyEvent.VK_RIGHT) { dx = 2; } } public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = 0; } if (key == KeyEvent.VK_RIGHT) { dx = 0; } } } ``` 這是`Player`子畫面。 我們用光標鍵控制大炮。 ```java int START_X = 270; setX(START_X); int START_Y = 280; setY(START_Y); ``` 這些是播放器精靈的初始坐標。 ```java public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = -2; } ... ``` 如果按左光標鍵,則`dx`變量將設置為 -2。 下次調用`act()`方法時,播放器向左移動。 ```java public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = 0; } if (key == KeyEvent.VK_RIGHT) { dx = 0; } } ``` 如果釋放左或右光標,則`dx`變量將設置為零。 播放器精靈停止移動。 `com/zetcode/sprite/Shot.java` ```java package com.zetcode.sprite; import javax.swing.ImageIcon; public class Shot extends Sprite { public Shot() { } public Shot(int x, int y) { initShot(x, y); } private void initShot(int x, int y) { var shotImg = "simg/shot.png"; var ii = new ImageIcon(shotImg); setImage(ii.getImage()); int H_SPACE = 6; setX(x + H_SPACE); int V_SPACE = 1; setY(y - V_SPACE); } } ``` 這是`Shot`子畫面。 用 `Space` 鍵觸發射擊。 `H_SPACE`和`V_SPACE`常數用于適當地定位導彈。 `com/zetcode/sprite/Sprite.java` ```java package com.zetcode.sprite; import java.awt.Image; public class Sprite { private boolean visible; private Image image; private boolean dying; int x; int y; int dx; public Sprite() { visible = true; } public void die() { visible = false; } public boolean isVisible() { return visible; } protected void setVisible(boolean visible) { this.visible = visible; } public void setImage(Image image) { this.image = image; } public Image getImage() { return image; } public void setX(int x) { this.x = x; } public void setY(int y) { this.y = y; } public int getY() { return y; } public int getX() { return x; } public void setDying(boolean dying) { this.dying = dying; } public boolean isDying() { return this.dying; } } ``` 這是基本的`Sprite`類。 其他精靈也繼承自它。 它具有一些常用功能。 `com/zetcode/Board.java` ```java package com.zetcode; import com.zetcode.sprite.Alien; import com.zetcode.sprite.Player; import com.zetcode.sprite.Shot; import javax.swing.ImageIcon; import javax.swing.JPanel; import javax.swing.Timer; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; public class Board extends JPanel { private Dimension d; private List<Alien> aliens; private Player player; private Shot shot; private int direction = -1; private int deaths = 0; private boolean inGame = true; private String explImg = "simg/explosion.png"; private String message = "Game Over"; private Timer timer; public Board() { initBoard(); gameInit(); } private void initBoard() { addKeyListener(new TAdapter()); setFocusable(true); d = new Dimension(Commons.BOARD_WIDTH, Commons.BOARD_HEIGHT); setBackground(Color.black); timer = new Timer(Commons.DELAY, new GameCycle()); timer.start(); gameInit(); } private void gameInit() { aliens = new ArrayList<>(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 6; j++) { var alien = new Alien(Commons.ALIEN_INIT_X + 18 * j, Commons.ALIEN_INIT_Y + 18 * i); aliens.add(alien); } } player = new Player(); shot = new Shot(); } 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 (shot.isVisible()) { g.drawImage(shot.getImage(), shot.getX(), shot.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, Commons.GROUND, Commons.BOARD_WIDTH, Commons.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, Commons.BOARD_WIDTH, Commons.BOARD_HEIGHT); g.setColor(new Color(0, 32, 48)); g.fillRect(50, Commons.BOARD_WIDTH / 2 - 30, Commons.BOARD_WIDTH - 100, 50); g.setColor(Color.white); g.drawRect(50, Commons.BOARD_WIDTH / 2 - 30, Commons.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, (Commons.BOARD_WIDTH - fontMetrics.stringWidth(message)) / 2, Commons.BOARD_WIDTH / 2); } private void update() { if (deaths == Commons.NUMBER_OF_ALIENS_TO_DESTROY) { inGame = false; timer.stop(); message = "Game won!"; } // player player.act(); // shot if (shot.isVisible()) { int shotX = shot.getX(); int shotY = shot.getY(); for (Alien alien : aliens) { int alienX = alien.getX(); int alienY = alien.getY(); if (alien.isVisible() && shot.isVisible()) { if (shotX >= (alienX) && shotX <= (alienX + Commons.ALIEN_WIDTH) && shotY >= (alienY) && shotY <= (alienY + Commons.ALIEN_HEIGHT)) { var ii = new ImageIcon(explImg); alien.setImage(ii.getImage()); alien.setDying(true); deaths++; shot.die(); } } } int y = shot.getY(); y -= 4; if (y < 0) { shot.die(); } else { shot.setY(y); } } // aliens for (Alien alien : aliens) { int x = alien.getX(); if (x >= Commons.BOARD_WIDTH - Commons.BORDER_RIGHT && direction != -1) { direction = -1; Iterator<Alien> i1 = aliens.iterator(); while (i1.hasNext()) { Alien a2 = i1.next(); a2.setY(a2.getY() + Commons.GO_DOWN); } } if (x <= Commons.BORDER_LEFT && direction != 1) { direction = 1; Iterator<Alien> i2 = aliens.iterator(); while (i2.hasNext()) { Alien a = i2.next(); a.setY(a.getY() + Commons.GO_DOWN); } } } Iterator<Alien> it = aliens.iterator(); while (it.hasNext()) { Alien alien = it.next(); if (alien.isVisible()) { int y = alien.getY(); if (y > Commons.GROUND - Commons.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 == Commons.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 + Commons.PLAYER_WIDTH) && bombY >= (playerY) && bombY <= (playerY + Commons.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() >= Commons.GROUND - Commons.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 (!shot.isVisible()) { shot = new Shot(x, y); } } } } } } ``` 游戲的主要邏輯位于`Board`類中。 ```java private void gameInit() { aliens = new ArrayList<>(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 6; j++) { var alien = new Alien(Commons.ALIEN_INIT_X + 18 * j, Commons.ALIEN_INIT_Y + 18 * i); aliens.add(alien); } } player = new Player(); shot = new Shot(); } ``` 在`gameInit()`方法中,我們創建了 24 個外星人。 外星人圖像大小為`12x12px`。 我們在外星人中間放了 6px 的空間。 我們還創建了播放器和射擊對象。 ```java 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); } } } ``` `drawBombing()`方法繪制由外星人發射的炸彈。 ```java if (inGame) { g.drawLine(0, Commons.GROUND, Commons.BOARD_WIDTH, Commons.GROUND); drawAliens(g); drawPlayer(g); drawShot(g); drawBombing(g); } ... ``` 在`doDrawing()`方法中,我們繪制地面,外星人,玩家,射擊和炸彈。 ```java private void update() { if (deaths == Commons.NUMBER_OF_ALIENS_TO_DESTROY) { inGame = false; timer.stop(); message = "Game won!"; } ... ``` 在`update()`方法內,我們檢查損壞的行數。 如果我們消滅所有外星人,我們將贏得比賽。 ```java if (alien.isVisible() && shot.isVisible()) { if (shotX >= (alienX) && shotX <= (alienX + Commons.ALIEN_WIDTH) && shotY >= (alienY) && shotY <= (alienY + Commons.ALIEN_HEIGHT)) { var ii = new ImageIcon(explImg); alien.setImage(ii.getImage()); alien.setDying(true); deaths++; shot.die(); } } ``` 如果玩家觸發的射擊與外星人發生碰撞,則該外星人的船只將被摧毀。 更確切地說,將設置垂死標記。 我們用它來顯示爆炸。 死亡變量增加,射擊精靈被破壞。 ```java if (x >= Commons.BOARD_WIDTH - Commons.BORDER_RIGHT && direction != -1) { direction = -1; Iterator<Alien> i1 = aliens.iterator(); while (i1.hasNext()) { Alien a2 = i1.next(); a2.setY(a2.getY() + Commons.GO_DOWN); } } ``` 如果外星人到達`Board`的右端,他們將向下移動并將其方向更改為左側。 ```java Iterator<Alien> it = aliens.iterator(); while (it.hasNext()) { Alien alien = it.next(); if (alien.isVisible()) { int y = alien.getY(); if (y > Commons.GROUND - Commons.ALIEN_HEIGHT) { inGame = false; message = "Invasion!"; } alien.act(direction); } } ``` 此代碼可移動外星人。 如果他們到達最低點,入侵就開始了。 ```java int shot = generator.nextInt(15); Alien.Bomb bomb = alien.getBomb(); if (shot == Commons.CHANCE && alien.isVisible() && bomb.isDestroyed()) { bomb.setDestroyed(false); bomb.setX(alien.getX()); bomb.setY(alien.getY()); } ``` 這是確定外星人是否會投下炸彈的代碼。 不得破壞外星人; 即他必須是可見的。 必須設置炸彈的銷毀標志。 換句話說,這是外星人的第一枚炸彈掉落,或者是先前投下的炸彈已經落地。 如果滿足這兩個條件,轟炸就留給了機會。 ```java if (!bomb.isDestroyed()) { bomb.setY(bomb.getY() + 1); if (bomb.getY() >= Commons.GROUND - Commons.BOMB_HEIGHT) { bomb.setDestroyed(true); } } ``` 如果炸彈沒有被銷毀,它將離地面 1px。 如果到達底部,則設置銷毀標志。 外星人現在準備投下另一枚炸彈。 ```java public void keyReleased(KeyEvent e) { player.keyReleased(e); } ``` 此特定`KeyEvent`的實際處理被委派給播放器精靈。 ![Space Invaders](https://img.kancloud.cn/2b/3d/2b3d5f734021a3d0f47dcaac6e81c1e1_358x350.jpg) 圖:太空侵略者 在 Java 游戲教程的這一部分中,我們創建了太空侵略者。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看