<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # Breakout 游戲 > 原文: [https://zetcode.com/tutorials/javagamestutorial/breakout/](https://zetcode.com/tutorials/javagamestutorial/breakout/) 在 Java 2D 游戲教程的這一部分中,我們創建一個簡單的 Breakout 游戲克隆。 源代碼和圖像可以在作者的 Github [Java-Breakout-Game](https://github.com/janbodnar/Java-Breakout-Game) 存儲庫中找到。 Breakout 是一款最初由 Atari Inc. 開發的街機游戲。該游戲創建于 1976 年。 在此游戲中,玩家移動屏幕上的槳葉并彈起一個或多個球。 目的是銷毀窗口頂部的磚塊。 ## 開發 在我們的游戲中,我們只有一個槳,一個球和 30 塊磚。 我在 Inkscape 中為球,槳和磚塊創建了圖像。 我們使用計時器來創建游戲周期。 我們不使用角度,只是改變方向。 頂部,底部,左側和右側。 pybreakout 游戲啟發了我。 它是由 Nathan Dawson 在 PyGame 庫中開發的。 游戲包含七個文件:`Commons.java`,`Sprite.java`,`Ball.java`,`Paddle.java`,`Brick.java`,`Board.java`和`Breakout.java`。 `com/zetcode/Commons.java` ```java package com.zetcode; public interface Commons { int WIDTH = 300; int HEIGHT = 400; int BOTTOM_EDGE = 390; int N_OF_BRICKS = 30; int INIT_PADDLE_X = 200; int INIT_PADDLE_Y = 360; int INIT_BALL_X = 230; int INIT_BALL_Y = 355; int PERIOD = 10; } ``` `Commons.java`文件具有一些公共常數。 `WIDTH`和`HEIGHT`常數存儲電路板的大小。 當球通過`BOTTOM_EDGE`時,比賽結束。 `N_OF_BRICKS`是游戲中的積木數量。 `INIT_PADDLE_X`和`INIT_PADDLE_Y`是槳狀對象的初始坐標。 `INIT_BALL_X`和`INIT_BALL_Y`是球對象的初始坐標。 `DELAY`是執行任務之前的初始延遲(以毫秒為單位),`PERIOD`是形成游戲周期的連續任務執行之間的時間(以毫秒為單位)。 `com/zetcode/Sprite.java` ```java package com.zetcode; import java.awt.Image; import java.awt.Rectangle; public class Sprite { int x; int y; int imageWidth; int imageHeight; Image image; protected void setX(int x) { this.x = x; } int getX() { return x; } protected void setY(int y) { this.y = y; } int getY() { return y; } int getImageWidth() { return imageWidth; } int getImageHeight() { return imageHeight; } Image getImage() { return image; } Rectangle getRect() { return new Rectangle(x, y, image.getWidth(null), image.getHeight(null)); } void getImageDimensions() { imageWidth = image.getWidth(null); imageHeight = image.getHeight(null); } } ``` `Sprite`類是`Board`中所有對象的基類。 我們將`Ball`,`Brick`和`Paddle`對象中的所有方法和變量都放在此處,例如`getImage()`或`getX()`方法。 `com/zetcode/Brick.java` ```java package com.zetcode; import javax.swing.ImageIcon; public class Brick extends Sprite { private boolean destroyed; public Brick(int x, int y) { initBrick(x, y); } private void initBrick(int x, int y) { this.x = x; this.y = y; destroyed = false; loadImage(); getImageDimensions(); } private void loadImage() { var ii = new ImageIcon("src/resources/brick.png"); image = ii.getImage(); } boolean isDestroyed() { return destroyed; } void setDestroyed(boolean val) { destroyed = val; } } ``` 這是`Brick`類。 ```java private boolean destroyed; ``` 在`destroyed`變量中,我們保留磚的狀態。 `com/zetcode/Ball.java` ```java package com.zetcode; import javax.swing.ImageIcon; public class Ball extends Sprite { private int xdir; private int ydir; public Ball() { initBall(); } private void initBall() { xdir = 1; ydir = -1; loadImage(); getImageDimensions(); resetState(); } private void loadImage() { var ii = new ImageIcon("src/resources/ball.png"); image = ii.getImage(); } void move() { x += xdir; y += ydir; if (x == 0) { setXDir(1); } if (x == Commons.WIDTH - imageWidth) { System.out.println(imageWidth); setXDir(-1); } if (y == 0) { setYDir(1); } } private void resetState() { x = Commons.INIT_BALL_X; y = Commons.INIT_BALL_Y; } void setXDir(int x) { xdir = x; } void setYDir(int y) { ydir = y; } int getYDir() { return ydir; } } ``` 這是`Ball`類。 ```java void move() { x += xdir; y += ydir; if (x == 0) { setXDir(1); } if (x == Commons.WIDTH - imageWidth) { System.out.println(imageWidth); setXDir(-1); } if (y == 0) { setYDir(1); } } ``` `move()`方法將球移到`Board`上。 如果球撞到邊界,方向將相應更改。 ```java void setXDir(int x) { xdir = x; } void setYDir(int y) { ydir = y; } ``` 當球擊中槳或磚時,將調用這兩種方法。 `com/zetcode/Paddle.java` ```java package com.zetcode; import java.awt.event.KeyEvent; import javax.swing.ImageIcon; public class Paddle extends Sprite { private int dx; public Paddle() { initPaddle(); } private void initPaddle() { loadImage(); getImageDimensions(); resetState(); } private void loadImage() { var ii = new ImageIcon("src/resources/paddle.png"); image = ii.getImage(); } void move() { x += dx; if (x <= 0) { x = 0; } if (x >= Commons.WIDTH - imageWidth) { x = Commons.WIDTH - imageWidth; } } void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = -1; } if (key == KeyEvent.VK_RIGHT) { dx = 1; } } void keyReleased(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = 0; } if (key == KeyEvent.VK_RIGHT) { dx = 0; } } private void resetState() { x = Commons.INIT_PADDLE_X; y = Commons.INIT_PADDLE_Y; } } ``` 這是`Paddle`類。 它封裝了 Breakout 游戲中的槳對象。 操縱桿通過左右箭頭鍵控制。 通過按箭頭鍵,我們設置方向變量。 通過釋放箭頭鍵,將`dx`變量設置為零。 這樣,槳停止移動。 ```java void move() { x += dx; if (x <= 0) { x = 0; } if (x >= Commons.WIDTH - imageWidth) { x = Commons.WIDTH - imageWidth; } } ``` 槳葉僅在水平方向上移動,因此我們僅更新 x 坐標。 如果條件確保槳不通過窗口邊緣。 `com/zetcode/Board.java` ```java package com.zetcode; import javax.swing.JPanel; import javax.swing.Timer; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; public class Board extends JPanel { private Timer timer; private String message = "Game Over"; private Ball ball; private Paddle paddle; private Brick[] bricks; private boolean inGame = true; public Board() { initBoard(); } private void initBoard() { addKeyListener(new TAdapter()); setFocusable(true); setPreferredSize(new Dimension(Commons.WIDTH, Commons.HEIGHT)); gameInit(); } private void gameInit() { bricks = new Brick[Commons.N_OF_BRICKS]; ball = new Ball(); paddle = new Paddle(); int k = 0; for (int i = 0; i < 5; i++) { for (int j = 0; j < 6; j++) { bricks[k] = new Brick(j * 40 + 30, i * 10 + 50); k++; } } timer = new Timer(Commons.PERIOD, new GameCycle()); timer.start(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); var g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); if (inGame) { drawObjects(g2d); } else { gameFinished(g2d); } Toolkit.getDefaultToolkit().sync(); } private void drawObjects(Graphics2D g2d) { g2d.drawImage(ball.getImage(), ball.getX(), ball.getY(), ball.getImageWidth(), ball.getImageHeight(), this); g2d.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(), paddle.getImageWidth(), paddle.getImageHeight(), this); for (int i = 0; i < Commons.N_OF_BRICKS; i++) { if (!bricks[i].isDestroyed()) { g2d.drawImage(bricks[i].getImage(), bricks[i].getX(), bricks[i].getY(), bricks[i].getImageWidth(), bricks[i].getImageHeight(), this); } } } private void gameFinished(Graphics2D g2d) { var font = new Font("Verdana", Font.BOLD, 18); FontMetrics fontMetrics = this.getFontMetrics(font); g2d.setColor(Color.BLACK); g2d.setFont(font); g2d.drawString(message, (Commons.WIDTH - fontMetrics.stringWidth(message)) / 2, Commons.WIDTH / 2); } private class TAdapter extends KeyAdapter { @Override public void keyReleased(KeyEvent e) { paddle.keyReleased(e); } @Override public void keyPressed(KeyEvent e) { paddle.keyPressed(e); } } private class GameCycle implements ActionListener { @Override public void actionPerformed(ActionEvent e) { doGameCycle(); } } private void doGameCycle() { ball.move(); paddle.move(); checkCollision(); repaint(); } private void stopGame() { inGame = false; timer.stop(); } private void checkCollision() { if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) { stopGame(); } for (int i = 0, j = 0; i < Commons.N_OF_BRICKS; i++) { if (bricks[i].isDestroyed()) { j++; } if (j == Commons.N_OF_BRICKS) { message = "Victory"; stopGame(); } } if ((ball.getRect()).intersects(paddle.getRect())) { int paddleLPos = (int) paddle.getRect().getMinX(); int ballLPos = (int) ball.getRect().getMinX(); int first = paddleLPos + 8; int second = paddleLPos + 16; int third = paddleLPos + 24; int fourth = paddleLPos + 32; if (ballLPos < first) { ball.setXDir(-1); ball.setYDir(-1); } if (ballLPos >= first && ballLPos < second) { ball.setXDir(-1); ball.setYDir(-1 * ball.getYDir()); } if (ballLPos >= second && ballLPos < third) { ball.setXDir(0); ball.setYDir(-1); } if (ballLPos >= third && ballLPos < fourth) { ball.setXDir(1); ball.setYDir(-1 * ball.getYDir()); } if (ballLPos > fourth) { ball.setXDir(1); ball.setYDir(-1); } } for (int i = 0; i < Commons.N_OF_BRICKS; i++) { if ((ball.getRect()).intersects(bricks[i].getRect())) { int ballLeft = (int) ball.getRect().getMinX(); int ballHeight = (int) ball.getRect().getHeight(); int ballWidth = (int) ball.getRect().getWidth(); int ballTop = (int) ball.getRect().getMinY(); var pointRight = new Point(ballLeft + ballWidth + 1, ballTop); var pointLeft = new Point(ballLeft - 1, ballTop); var pointTop = new Point(ballLeft, ballTop - 1); var pointBottom = new Point(ballLeft, ballTop + ballHeight + 1); if (!bricks[i].isDestroyed()) { if (bricks[i].getRect().contains(pointRight)) { ball.setXDir(-1); } else if (bricks[i].getRect().contains(pointLeft)) { ball.setXDir(1); } if (bricks[i].getRect().contains(pointTop)) { ball.setYDir(1); } else if (bricks[i].getRect().contains(pointBottom)) { ball.setYDir(-1); } bricks[i].setDestroyed(true); } } } } } ``` 這是`Board`類。 這里我們把游戲邏輯。 ```java private void gameInit() { bricks = new Brick[Commons.N_OF_BRICKS]; ball = new Ball(); paddle = new Paddle(); int k = 0; for (int i = 0; i < 5; i++) { for (int j = 0; j < 6; j++) { bricks[k] = new Brick(j * 40 + 30, i * 10 + 50); k++; } } timer = new Timer(Commons.PERIOD, new GameCycle()); timer.start(); } ``` 在`gameInit()`方法中,我們創建一個球,一個球拍和三十塊積木。 然后,我們創建并啟動一個計時器。 ```java if (inGame) { drawObjects(g2d); } else { gameFinished(g2d); } ``` 根據`inGame`變量,我們可以使用`drawObjects()`方法繪制所有對象,也可以使用`gameFinished()`方法完成游戲。 ```java private void drawObjects(Graphics2D g2d) { g2d.drawImage(ball.getImage(), ball.getX(), ball.getY(), ball.getImageWidth(), ball.getImageHeight(), this); g2d.drawImage(paddle.getImage(), paddle.getX(), paddle.getY(), paddle.getImageWidth(), paddle.getImageHeight(), this); for (int i = 0; i < Commons.N_OF_BRICKS; i++) { if (!bricks[i].isDestroyed()) { g2d.drawImage(bricks[i].getImage(), bricks[i].getX(), bricks[i].getY(), bricks[i].getImageWidth(), bricks[i].getImageHeight(), this); } } } ``` `drawObjects()`方法繪制游戲的所有對象。 使用`drawImage()`方法繪制精靈。 ```java private void gameFinished(Graphics2D g2d) { var font = new Font("Verdana", Font.BOLD, 18); FontMetrics fontMetrics = this.getFontMetrics(font); g2d.setColor(Color.BLACK); g2d.setFont(font); g2d.drawString(message, (Commons.WIDTH - fontMetrics.stringWidth(message)) / 2, Commons.WIDTH / 2); } ``` `gameFinished()`方法將`"Game Over"`或`"Victory"`繪制到窗口的中間。 ```java private class GameCycle implements ActionListener { @Override public void actionPerformed(ActionEvent e) { doGameCycle(); } } ``` 計時器會定期調用`actionPerformed()`方法,該方法又調用`doGameCycle()`方法,從而創建游戲周期。 ```java private void doGameCycle() { ball.move(); paddle.move(); checkCollision(); repaint(); } ``` `doGameCycle()`移動球和球拍。 我們檢查是否可能發生碰撞并重新粉刷屏幕。 ```java private void checkCollision() { if (ball.getRect().getMaxY() > Commons.BOTTOM_EDGE) { stopGame(); } ... ``` 如果球觸底,我們將停止比賽。 ```java for (int i = 0, j = 0; i < Commons.N_OF_BRICKS; i++) { if (bricks[i].isDestroyed()) { j++; } if (j == Commons.N_OF_BRICKS) { message = "Victory"; stopGame(); } } ``` 我們檢查了多少磚被破壞了。 如果我們摧毀了所有`N_OF_BRICKS bricks`,我們將贏得這場比賽。 ```java if (ballLPos < first) { ball.setXDir(-1); ball.setYDir(-1); } ``` 如果球碰到了槳的第一部分,我們會將球的方向更改為西北。 ```java if (bricks[i].getRect().contains(pointTop)) { ball.setYDir(1); }... ``` 如果球撞擊磚的底部,我們將改變球的 y 方向; 它下降了。 `com/zetcode/Breakout.java` ```java package com.zetcode; import javax.swing.JFrame; import java.awt.EventQueue; public class Breakout extends JFrame { public Breakout() { initUI(); } private void initUI() { add(new Board()); setTitle("Breakout"); setDefaultCloseOperation(EXIT_ON_CLOSE); setLocationRelativeTo(null); setResizable(false); pack(); } public static void main(String[] args) { EventQueue.invokeLater(() -> { var game = new Breakout(); game.setVisible(true); }); } } ``` 這是具有主要輸入方法的`Breakout`類。 ![The Breakout game](https://img.kancloud.cn/54/05/5405f9aa45d304575006b67ce10938f3_300x400.jpg) 圖:打磚塊游戲 這是打磚塊游戲。
                  <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>

                              哎呀哎呀视频在线观看