用JAVA实现吃豆人小游戏

游戏运行效果

在这里插入图片描述
在这里插入图片描述

Model.java

package pacman;

import javax.swing.*;
import javax.swing.Timer;
import javax.swing.JPanel;

import java.awt.*;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class Model extends JPanel implements ActionListener {

    private Dimension d;    //窗口的宽度
    private final Font smallFont = new Font("Arial",Font.BOLD,14);  //游戏内文字字体及字号
    private boolean inGame = false;     //判断游戏是否开始
    private boolean dying = false;      //判断Pacman是否存活

    private final int BLOCK_SIZE = 24;  //豆 横排个数: 24
    private final int N_BLOCK = 15;     //豆 竖排个数: 15
    private final int SCREEN_SIZE = N_BLOCK * N_BLOCK;  //共计:24 * 15 = 360 (个)
    private final int MAX_GHOSTS = 12;      //游戏内敌人的数量
    private final int PACMAN_SPEED = 6;     //Pacman移动的速度

    private int N_GHOSTS = 6;       //敌人数量
    private int lives,score;        //生命值,关卡得分
    private int [] dx, dy;
    private int [] ghost_x, ghost_y, ghost_dx, ghost_dy, ghostSpeed;

    private Image heart, ghost;
    private Image up, down, left, right;

    private int pacman_x, pacman_y, pacmand_x, pacmand_y;
    private int req_dx, req_dy;

    private final int validSpeeds[] = {1,2,3,4,6,8};
    private final int maxSpeed = 6;
    private int currentSpeed = 3;
    private short [] screenDate;
    private Timer timer;

    /**
     *  0 = blue蓝色           4 = right border右边款
     *  1 = left border左边框       8 = bottom border底边框
     *  2 = top border顶边框        16 = white dots白点豆
     */
    private final short levelData[] = {
            19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 22,
            17, 16, 16, 16, 16, 24, 16, 16, 16, 16, 16, 16, 16, 16, 20,
            25, 24, 24, 24, 28, 0, 17, 16, 16, 16, 16, 16, 16, 16, 20,
            0,  0,  0,  0,  0,  0, 17, 16, 16, 16, 16, 16, 16, 16, 20,
            19, 18, 18, 18, 18, 18, 16, 16, 16, 16, 24, 24, 24, 24, 20,
            17, 16, 16, 16, 16, 16, 16, 16, 16, 20, 0,  0,  0,   0, 21,
            17, 16, 16, 16, 16, 16, 16, 16, 16, 20, 0,  0,  0,   0, 21,
            17, 16, 16, 16, 24, 16, 16, 16, 16, 20, 0,  0,  0,   0, 21,
            17, 16, 16, 20, 0, 17, 16, 16, 16, 16, 18, 18, 18, 18, 20,
            17, 24, 24, 28, 0, 25, 24, 24, 16, 16, 16, 16, 16, 16, 20,
            21, 0,  0,  0,  0,  0,  0,   0, 17, 16, 16, 16, 16, 16, 20,
            17, 18, 18, 22, 0, 19, 18, 18, 16, 16, 16, 16, 16, 16, 20,
            17, 16, 16, 20, 0, 17, 16, 16, 16, 16, 16, 16, 16, 16, 20,
            17, 16, 16, 20, 0, 17, 16, 16, 16, 16, 16, 16, 16, 16, 20,
            25, 24, 24, 24, 26, 24, 24, 24, 24, 24, 24, 24, 24, 24, 28
    };

    public Model() {
        loadImages();
        initVariables();
        addKeyListener(new TAdapter());
        setFocusable(true);
        initGame();
    }

    /*导入图片—吃豆人的每一个动作图*/
    private void loadImages() {
        down = new ImageIcon("images/down.gif").getImage();
        up = new ImageIcon("images/up.gif").getImage();
        left = new ImageIcon("images/left.gif").getImage();
        right = new ImageIcon("images/right.gif").getImage();
        ghost = new ImageIcon("images/ghost.gif").getImage();
        heart = new ImageIcon("images/heart.png").getImage();
    }

    /*游戏标题文字*/
    public void showIntroScreen(Graphics2D graphics2D) {
        String start = "Press SPACE to start";      //游戏开始文字
        graphics2D.setColor(Color.yellow);          //文字颜色
        graphics2D.drawString(start,(SCREEN_SIZE) / 4, 150);      //文字在窗体的位置
    }

    /*分数模块*/
    public void drawScore(Graphics2D graphics2D) {
        graphics2D.setFont(smallFont);      //分数字体 : 小号字体
        graphics2D.setColor(new Color(5,151,79));       //分数文字颜色 :重构颜色RGB格式
        String s = "Score: " + score;
        graphics2D.drawString(s,SCREEN_SIZE / 2 + 96,SCREEN_SIZE + 16);

        for (int i = 0; i < lives; i++) {
            graphics2D.drawImage(heart,i * 28 + 8, SCREEN_SIZE + 1,this);
        }

    }

    private void initVariables() {
        screenDate = new short[N_BLOCK * N_BLOCK];
        d = new Dimension(400,400);
        ghost_x = new int[MAX_GHOSTS];
        ghost_dx = new int[MAX_GHOSTS];
        ghost_y = new int[MAX_GHOSTS];
        ghost_dy = new int[MAX_GHOSTS];
        dx = new int[4];
        dy = new int[4];

        timer = new Timer(60,this);     //每40ms 绘制一次图形及游戏运行速度(可以作为游戏难度调整功能)
        timer.start();
    }

    /*游戏初始化*/
    private void initGame() {
        lives = 3;      //初始化生命值数量
        score = 0;      //初始化分数为0
        initLevel();
        N_GHOSTS = 6;       //初始化敌人数量
        currentSpeed = 3;       //初始化移动速度
    }

    /*游戏关卡范围*/
    private void initLevel() {
        int i;
        for (i = 0; i < N_BLOCK * N_BLOCK; i++) {
            screenDate[i] = levelData[i];
        }
        //continueLevel();
    }

    //游戏图形化初始
    private void playGame(Graphics2D graphics2D) {
        if (dying) {
            death();
        } else {
            movePacman();
            drawPacman(graphics2D);
            moveGhost(graphics2D);
            checkMaze();
        }
    }

    public void movePacman() {
        int pos;
        short ch;

        if (pacman_x % BLOCK_SIZE == 0 && pacman_y % BLOCK_SIZE == 0) {
            pos = pacman_x / BLOCK_SIZE + N_BLOCK * (int) (pacman_y / BLOCK_SIZE);
                    ch = screenDate[pos];
            if ((ch & 16 ) != 0) {      //判断pacman吃到豆子(16)
                screenDate[pos] = (short) (ch & 15);
                score++;
            }
            if (req_dx != 0 || req_dy != 0 ) {
                if (!((req_dx == -1 && req_dy == 0 && (ch & 1) != 0)
                || (req_dy == 1 && req_dy == 0 && (ch & 4) != 0)
                        || (req_dx == 0 && req_dy == -1 && (ch & 2) != 0)
                        || (req_dx == 0 && req_dy == 1 && (ch & 8) != 0))) {
                    pacmand_y = req_dy;
                    pacmand_x = req_dx;
                }
            }

            if (( pacmand_x == -1 && pacmand_y == 0 && (ch & 1) != 0)
            || (pacmand_x == 1 && pacmand_y == 0 && (ch & 4) != 0)
                    || (pacmand_x == 0 && pacmand_y == -1 && (ch & 2) != 0)
                    || (pacmand_x == 0 && pacmand_y == 1 && (ch & 8) != 0)) {
                pacmand_x = 0;
                pacmand_y = 0;
            }
        }

        pacman_x = pacman_x + PACMAN_SPEED * pacmand_x;
        pacman_y = pacman_y + PACMAN_SPEED * pacmand_y;

    }

    /*绘制Pacman移动模型*/
    public void drawPacman(Graphics2D graphics2D) {
        if (req_dx == -1) {
            graphics2D.drawImage(left,pacman_x + 1, pacman_y + 1,this);
        }else if (req_dx == 1) {
            graphics2D.drawImage(right,pacman_x + 1, pacman_y + 1,this);
        }else if (req_dy == -1) {
            graphics2D.drawImage(up,pacman_x + 1, pacman_y + 1,this);
        }else {
            graphics2D.drawImage(down,pacman_x + 1,pacman_y + 1,this);
        }
    }

    /*Ghost移动模型算法*/
    public void moveGhost(Graphics2D graphics2D) {
        int pos;
        int count;
        for (int i = 0; i < N_GHOSTS; i++) {
            if (ghost_x[i] % BLOCK_SIZE == 0 && ghost_y[i] % BLOCK_SIZE == 0) {
                pos = ghost_x[i] / BLOCK_SIZE + N_BLOCK * (int) (ghost_y[i] / BLOCK_SIZE);

                count = 0;
                if ((screenDate[pos] & 1 ) == 0 && ghost_dx[i] != 1 ) {
                    dx[count] = -1;
                    dy[count] = 0;
                    count++;
                }
                if ((screenDate[pos] & 2 ) == 0 && ghost_dy[i] != 1 ) {
                    dx[count] = 0;
                    dy[count] = -1;
                    count++;
                }
                if ((screenDate[pos] & 4 ) == 0 && ghost_dx[i] != -1 ) {
                    dx[count] = 1;
                    dy[count] = 0;
                    count++;
                }
                if ((screenDate[pos] & 8 ) == 0 && ghost_dy[i] != -1 ) {
                    dx[count] = 0;
                    dy[count] = 1;
                    count++;
                }

                if (count == 0) {
                    if ((screenDate[pos] & 15) == 15) {
                        ghost_dy[i] = 0;
                        ghost_dx[i] = 0;
                    }else {
                        ghost_dy[i] = -ghost_dy[i];
                        ghost_dx[i] = -ghost_dx[i];
                    }
                } else {
                    count = (int) (Math.random() * count);

                    if (count > 3) {
                        count = 3;
                    }

                    ghost_dx[i] = dx[count];
                    ghost_dy[i] = dy[count];
                }
            }
            ghost_x[i] = ghost_x[i] + (ghost_dx[i] * ghostSpeed[i]);
            ghost_y[i] = ghost_y[i] + (ghost_dy[i] * ghostSpeed[i]);
            drawGhost(graphics2D,ghost_x[i] + 1,ghost_y[i] + 1);

            if (pacman_x > (ghost_x[i] - 12) && pacman_x < (ghost_x[i] + 12)
                && pacman_y > (ghost_y[i] - 12) && pacman_y < (ghost_y[i] + 12)
                    && inGame) {
                dying = true;
            }
        }
    }

    /*绘制Ghost移动模型*/
    public void drawGhost(Graphics2D graphics2D,int x, int y) {
        graphics2D.drawImage(ghost,x,y,this);
    }

    public  void checkMaze() {
        int i = 0;
        boolean finished = true;

        while (i < N_BLOCK * N_BLOCK && finished ) {
            if ((screenDate[i] & 48 ) != 0 ) {
                finished = false;
            }
        } i++;

        if (finished) {
            score += 50;

            if (N_GHOSTS < MAX_GHOSTS) {
                N_GHOSTS++;
            }
            if (currentSpeed < maxSpeed) {
                currentSpeed++;
            }
        }   initLevel();

    }

    /*死亡机制判定*/
    private void death() {
        lives--;        //生命值自减一
        if (lives == 0) {       //判断当生命值等于0的时候,使游戏结束
            inGame = false;
        }
        continueLevel();
    }

    /*角色随机移动速度算法*/
    private void continueLevel() {
        int dx = 1;
        int random;

        for (int i = 0; i < N_GHOSTS; i++) {
            ghost_y[i] = 4 * BLOCK_SIZE;
            ghost_x[i] = 4 * BLOCK_SIZE;
            ghost_dy[i] = 0;
            ghost_dx[i] = dx;
            dx = -dx;
            random = (int) (Math.random() * (currentSpeed +1));

            if (random > currentSpeed) {
                random = currentSpeed;
            }
            ghostSpeed[i] = validSpeeds[random];
        }

        pacman_x = 7 * BLOCK_SIZE;
        pacman_y = 11 * BLOCK_SIZE;
        pacmand_x = 0;
        pacmand_y = 0;
        req_dx = 0;
        req_dy = 0;
        dying = false;
    }

    public void drawMaze(Graphics2D graphics2D) {
        short i = 0;
        int x,y;

        for (y = 0; y < SCREEN_SIZE; y += BLOCK_SIZE) {
            for (x = 0; x < SCREEN_SIZE; x += BLOCK_SIZE) {

                graphics2D.setColor(new Color(0,72,251));
                graphics2D.setStroke(new BasicStroke(5));

                if ((screenDate[i] == 0)) {
                    graphics2D.fillRect(x,y, BLOCK_SIZE,BLOCK_SIZE);
                }
                if ((screenDate[i] & 1) != 0) {
                    graphics2D.drawLine(x,y,x,y + BLOCK_SIZE - 1);
                }
                if ((screenDate[i] & 2) != 0) {
                    graphics2D.drawLine(x,y,x + BLOCK_SIZE - 1,y);
                }
                if ((screenDate[i] & 4) != 0) {
                    graphics2D.drawLine(x + BLOCK_SIZE - 1,y,x + BLOCK_SIZE - 1,y + BLOCK_SIZE - 1);
                }
                if ((screenDate[i] & 8) != 0) {
                    graphics2D.drawLine(x,y + BLOCK_SIZE - 1,x + BLOCK_SIZE - 1,y + BLOCK_SIZE - 1);
                }
                if ((screenDate[i] & 4) != 0) {
                    graphics2D.setColor(new Color(255,255,255));
                    graphics2D.fillOval(x + 10, y + 10, 6, 6);
                }

                i++;
                /*
                *   数值说明:
                *   0 = blue        4 = right border
                *   1 = left border     8 = bottom border
                *   2 = top border      16 = white dots
                * */
            }
        }
    }

    public void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);

        Graphics2D graphics2D = (Graphics2D) graphics;
        graphics2D.setColor(Color.black);
        graphics2D.fillRect(0,0, d.width,d.height);

        drawMaze(graphics2D);
        drawScore(graphics2D);

        if (inGame) {
            playGame(graphics2D);
        }else {
            showIntroScreen(graphics2D);
        }
        Toolkit.getDefaultToolkit().sync();
    }
    /*键盘控制部分*/
    class TAdapter extends KeyAdapter {
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();

            if (inGame) {       //首先判断是否游戏开始
                if (key == KeyEvent.VK_LEFT) {      //监听到键盘方向左键触发 向左移动一格子,Y轴不变
                    req_dx = -1;
                    req_dy = 0;
                } else if (key == KeyEvent.VK_RIGHT) {      //监听到键盘方向右键触发 向右移动一格子,Y轴不变
                    req_dx = 1;
                    req_dy = 0;
                } else if (key == KeyEvent.VK_UP) {      //监听到键盘方向上键触发 向上移动一格子,Z轴不变
                    req_dx = 0;
                    req_dy = -1;
                } else if (key == KeyEvent.VK_DOWN) {      //监听到键盘方向下键触发 向下移动一格子,Z轴不变
                    req_dx = 0;
                    req_dy = 1;
                } else if (key == KeyEvent.VK_ESCAPE && timer.isRunning()) {      //监听到键盘ESC时或者时间结束,退出游戏
                    inGame = false;
                } else {
                    if (key == KeyEvent.VK_SPACE) {      //监听到键盘SPACE时,开始游戏
                        inGame = true;
                        initGame();
                    }
                }
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) { repaint(); }
}


Pacman.java

package pacman;

import javax.swing.*;

public class Pacman extends JFrame {

    public Pacman() {
        add(new Model());
    }

    public static void main(String[] args) {
        Pacman pacman = new Pacman();
        pacman.setVisible(true);
        pacman.setTitle("Pacman Game");     //窗体标题
        pacman.setSize(380,420);        //窗体的大小
        pacman.setDefaultCloseOperation(EXIT_ON_CLOSE);
        pacman.setLocationRelativeTo(null);
    }
}

完整的游戏代码及资源文件

在这里插入图片描述
下载地址https://download.csdn.net/download/weixin_50679163/78951807

  • 4
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIGBOSSyifi

Thanks & Salute

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值