21xrx.com
2025-03-23 13:44:49 Sunday
文章检索 我的文章 写文章
如何用 Java 制作简单的游戏?
2023-06-15 16:40:19 深夜i     --     --
Java 游戏制作 打砖块

Java 是一种高级编程语言,因为其可移植性和面向对象的特性而备受欢迎。Java 也是制作电脑游戏的重要工具之一。虽然 Java 不如 Unity 或 Unreal Engine 那么强大,但也可以用来制作一些简单的游戏。本文将介绍一些基本的 Java 游戏制作知识,并提供一个简单的游戏代码案例。

代码案例:打砖块游戏

打砖块游戏是一款经典游戏,也是入门 Java 游戏制作的好选择。这个游戏的规则很简单:玩家需要控制一个挡板,使小球反弹撞碎所有砖块。玩家需要尽可能少的时间完成游戏。

思路:玩家控制挡板移动,球与砖块的碰撞,球与挡板的碰撞,球出边界的条件与动作。我们需要画出游戏界面、定义挡板、球、砖块、音效等。

下面是“打砖块”游戏的代码:

import javax.swing.JFrame;
public class BrickGame {
  public static void main(String[] args) {
    JFrame frame = new JFrame("Brick Game");
    frame.setSize(800,600);
    frame.setResizable(false);
    frame.setLocationRelativeTo(null);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
}

这是游戏的入口,在 main 函数中创建一个 JFrame 并设置相关属性,如窗口大小、标题等。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class GamePanel extends JPanel implements KeyListener{
  private boolean play = false;
  private int score = 0;
  private int totalBricks = 21;
  private Timer timer;
  private int delay = 8;
  private int playerX = 310;
  private int ballPosX = 120;
  private int ballPosY = 350;
  private int ballXDir = -1;
  private int ballYDir = -2;
  private MapGenerator map;
  public GamePanel() {
    map = new MapGenerator(3, 7);
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
    timer = new Timer(delay, this);
    timer.start();
  }
  public void paint(Graphics g) {
    // 绘制背景
    g.setColor(Color.black);
    g.fillRect(1, 1, 692, 592);
    // 绘制砖块
    map.draw((Graphics2D)g);
    // 绘制边界
    g.setColor(Color.yellow);
    g.fillRect(0, 0, 3, 592);
    g.fillRect(0, 0, 692, 3);
    g.fillRect(691, 0, 3, 592);
    // 绘制玩家得分
    g.setColor(Color.white);
    g.setFont(new Font("serif",Font.BOLD, 25));
    g.drawString(""+score, 590, 30);
    // 绘制挡板
    g.setColor(Color.green);
    g.fillRect(playerX, 550, 100, 8);
    // 绘制小球
    g.setColor(Color.yellow);
    g.fillOval(ballPosX, ballPosY, 20, 20);
    // 判断玩家胜利条件
    if (totalBricks <= 0) {
      play = false;
      ballXDir = 0;
      ballYDir = 0;
      g.setColor(Color.RED);
      g.setFont(new Font("serif",Font.BOLD, 30));
      g.drawString("You Win", 260, 300);
      g.setFont(new Font("serif",Font.BOLD, 20));
      g.drawString("Press Enter to Restart", 230, 350);
    }
    // 判断小球出界条件
    if (ballPosY > 570) {
      play = false;
      ballXDir = 0;
      ballYDir = 0;
      g.setColor(Color.RED);
      g.setFont(new Font("serif",Font.BOLD, 30));
      g.drawString("Game Over, Scores: "+score, 190, 300);
      g.setFont(new Font("serif",Font.BOLD, 20));
      g.drawString("Press Enter to Restart", 230, 350);
    }
    g.dispose();
  }
  public void actionPerformed(ActionEvent e) {
    timer.start();
    if (play) {
      // 碰撞检测
      if (new Rectangle(ballPosX, ballPosY, 20, 20).intersects(new Rectangle(playerX, 550, 100, 8)))
        ballYDir = -ballYDir;
      
      A: for (int i = 0; i < map.map.length; i++) {
        for (int j = 0; j< map.map[0].length; j++) {
          if (map.map[i][j] > 0) {
            int brickX = j * map.brickWidth + 80;
            int brickY = i * map.brickHeight + 50;
            int brickWidth = map.brickWidth;
            int brickHeight = map.brickHeight;
            Rectangle rect = new Rectangle(brickX, brickY, brickWidth, brickHeight);
            Rectangle ballRect = new Rectangle(ballPosX, ballPosY, 20,20);
            
            // 砖块碰撞检测
            if (ballRect.intersects(rect)) {
              map.setBrickValue(0, i, j);
              totalBricks--;
              score += 5;
              if (ballPosX + 19 <= rect.x || ballPosX + 1 >= rect.x + rect.width)
                ballXDir = -ballXDir;
               else
                ballYDir = -ballYDir;
              
              break A;
            }
          }
        }
      }
      ballPosX += ballXDir;
      ballPosY += ballYDir;
      // 左侧边缘的碰撞检测
      if (ballPosX < 0)
        ballXDir = -ballXDir;
      
      // 上侧边缘的碰撞检测
      if (ballPosY < 0)
        ballYDir = -ballYDir;
      
      // 右侧边缘的碰撞检测
      if (ballPosX > 670)
        ballXDir = -ballXDir;
      
      repaint();
    }
  }
  public void keyTyped(KeyEvent e) {}
  public void keyReleased(KeyEvent e) {}
  public void keyPressed(KeyEvent e) {
    // 向左移动
    if (e.getKeyCode() == KeyEvent.VK_LEFT) {
      if (playerX <= 10)
        playerX = 10;
       else {
        moveLeft();
      }
    }
    // 向右移动
    if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
      if (playerX >= 600)
        playerX = 600;
       else {
        moveRight();
      }
    }
    // 按下 Enter 重置游戏
    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
      if (!play) {
        play = true;
        ballPosX = 120;
        ballPosY = 350;
        ballXDir = -1;
        ballYDir = -2;
        playerX = 310;
        score = 0;
        totalBricks = 21;
        map = new MapGenerator(3, 7);
        repaint();
      }
    }
  }
  public void moveLeft()
    play = true;
    playerX -= 20;
  
  public void moveRight() {
    play = true;
    playerX += 20;
  }
}

这是游戏的核心代码。GamePanel 类继承了 JPanel,并实现了 KeyListener 接口。在构造函数中,我们初始化了一些游戏需要的变量,如挡板位置、小球初始位置和方向、砖块数等。在 paint 方法中,我们绘制了游戏界面、砖块、挡板、小球以及玩家得分信息。在 actionPerformed 方法中,我们对游戏运行时的操作进行了处理,如碰撞检测、移动等。在 keyPressed 方法中,我们对玩家按键操作进行监听,以响应玩家的移动和重置游戏操作。

  
  

评论区