《黄金矿工》Java小游戏4399原汁原味版

前言

这个小游戏是参考的b站上尚学堂的视频,自己创新并且写的风格更偏向于本人。
是本人Java基础期末的项目作业,由于只花了一天,很多功能没有完善。

游戏介绍

《黄金矿工》是一款经典的塔防游戏,游戏中有多个关卡,通过收集金币、石头、物品,消灭敌人,最终过关。

项目简介

在这里插入图片描述
用户系统
在这里插入图片描述
表结构
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码,带注释

童年的味道

游戏主界面类

package com.GoldMiner.ui;

import com.GoldMiner.util.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

import static com.GoldMiner.util.Img.*;//导入所有图片静态常量

public class GameMain extends JFrame {
    private final ReentrantLock lock = new ReentrantLock();//锁
    public int delay = 20; //延迟多少毫秒重新绘制
    Line line = new Line(this);
    public static int count = 0;//总积分
    //存放物体的集合,包括金块、石头、物品
    public List<Item> items = new ArrayList<>();
    int level = DataBase.level; //当前关卡
    int goal = DataBase.goal; //目标分数
    long startTime;
    long endTime;
    long tim; //剩余时间
    DataBase db; //数据库

    public GameMain(){

    }

    //构造方法
    public GameMain(DataBase db) {
        startTime = System.currentTimeMillis();
        this.db = db;
        long startTime = System.currentTimeMillis();//开始时间
        try {
            //初始化窗口
            initUI();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //初始化金块、石头
        initItem();

        //鼠标点击事件
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                //鼠标左键是1,右键是3,滚轮是2
                if (e.getButton() == 1){
                    line.setState(1); //设置线条状态为1,抓取中
                }
            }
        });

        //键盘监听事件
        this.addKeyListener(new KeyListener() {
            @Override
            public void keyTyped(KeyEvent e) {
            }
            @Override
            public void keyPressed(KeyEvent e) {
            }
            @Override
            public void keyReleased(KeyEvent e) {
                //按下键盘上的方向键
                if (e.getKeyCode() == KeyEvent.VK_DOWN) {
                    line.setState(1); //设置线条状态为1,抓取中
                } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    exitGame();
                }
            }
        });
        //线程循环判断是否过关
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    lock.lock(); //获取锁
                    System.out.println("count:" + count + "  tim:" + tim);
                    if (tim < 0){
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                JOptionPane.showMessageDialog(null, "时间到!请重新开始游戏或者退出游戏");
                                //重新开始游戏
                                DataBase.level = 1;
                                DataBase.goal = 10;
                                //startTime = System.currentTimeMillis();
                                count = 0;
                                items.clear();
                                dispose();
                                new GameMain(db);
                            }
                        });

                        break;
                    }
                    if (count >= DataBase.goal){
                        // 过关,但不在当前线程中直接操作GUI
                        SwingUtilities.invokeLater(new Runnable() {
                            @Override
                            public void run() {
                                JOptionPane.showMessageDialog(null, "恭喜过关!");
                            }
                        });
                        DataBase.level++;//升级关卡
                        DataBase.goal = DataBase.level * 10; //升级目标分数
                        count = 0;
                        System.out.println("level up:" + DataBase.level);
                        new GameMain(db);//重新开始游戏
                        dispose();
                    }
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock(); //释放锁
                    }
                }
            }
        }).start();
    }

    private void initItem() {
        Gold gold;//存放当前金块
        //是否可以放置
        boolean isPlaced = true;
        //初始化金块
        for (int i = 0; i < 12; i++) {
            double x = Math.random();
            //随机生成不同大小金块
            if (x < 0.4){
                gold = new GoldMini();
            }else if (x < 0.8){
                gold = new Gold();
            }else {
                gold = new GoldPlus();
            }
            for (Item item : items){
                if (gold.getRect().intersects(item.getRect())){
                    //如果金块和其他物体重叠,则重新生成金块
                    isPlaced = false;
                }
            }
            if (isPlaced){
                //如果可以放置,则添加到集合中
                items.add(gold);
                isPlaced = true;
            } else {
                isPlaced = true;
                i--;
            }
        }
        //初始化石头
        for (int i = 0; i < 8; i++) {
            Stone stone = new Stone();//存放当前石块
            for (Item item : items){
                if (stone.getRect().intersects(item.getRect())){
                    //如果石头和其他物体重叠,则重新生成
                    isPlaced = false;
                }
            }
            if (isPlaced){
                //如果可以放置,则添加到集合中
                items.add(stone);
            } else {
                isPlaced = true;
                i--;
            }
        }
    }



    //初始化UI
    public void initUI() throws Exception {
        this.setTitle("GoldMiner");
        this.setIconImage(logo);
        this.setSize(800, 600);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
        this.setLocationRelativeTo(null);
        this.setLayout(new BorderLayout());
        //设置窗口不可改变大小
        this.setResizable(false);

        JMenuBar menuBar = new JMenuBar();
        JMenu menuJMenu = new JMenu("功能");
        JMenu aboutMenu = new JMenu("关于");
        menuBar.add(menuJMenu);
        menuBar.add(aboutMenu);
        JMenuItem reLoginItem = new JMenuItem("重新登录");
        JMenuItem restartItem = new JMenuItem("重新开始游戏");
        JMenuItem exitGameItem = new JMenuItem("退出并保存进度");
        JMenuItem aboutItem = new JMenuItem("关于作者");
        JMenuItem aboutGameItem = new JMenuItem("关于游戏");
        JMenuItem helpItem = new JMenuItem("游戏帮助");
        menuJMenu.add(reLoginItem);
        menuJMenu.add(restartItem);
        menuJMenu.addSeparator();
        menuJMenu.add(exitGameItem);
        aboutMenu.add(aboutItem);
        aboutMenu.add(aboutGameItem);
        aboutMenu.addSeparator();
        aboutMenu.add(helpItem);

        //重新登录
        reLoginItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
                try {
                    new Login();
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
            }
        });
        //重新开始游戏
        restartItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DataBase.level = 1;
                DataBase.goal = 10;
                startTime = System.currentTimeMillis();
                count = 0;
                items.clear();
                new GameMain(db);
                dispose();
            }
        });
        //退出游戏
        exitGameItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                exitGame();
            }
        });
        //关于作者
        aboutItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "作者:上玄\nQQ:1421148240\n参考视频:尚学堂Java黄金矿工");
            }
        });
        //关于游戏
        aboutGameItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "《黄金矿工》是一款经典的塔防游戏,游戏中有多个关卡,通过收集金币、石头、物品,消灭敌人,最终过关。");
            }
        });
        //游戏帮助
        helpItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(null, "1. 点击鼠标左键,开始抓取\n2. 按下方向键,开始抓取物品\n3. 按下ESC键,退出游戏");
            }
        });

        /*// 背景图片
        ImageIcon bg = new ImageIcon("src/com/GoldMiner/image/bkg.png");
        ImageIcon man = new ImageIcon("src/com/GoldMiner/image/man.png");*/

        // 创建自定义面板来放置组件
        JPanel mainPanel = new JPanel(null) {
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                //绘制背景图片
                g.drawImage(bg.getImage(), 0, 0, getWidth(), getHeight(), this);
                g.drawImage(man.getImage(), 335, 10,145,95, this);
                //绘制金块和石头
                for (Item item : items) {
                    item.paint(g);
                }

                //绘制线条
                line.paint(g);
                //绘制积分
                paintText(g,"总积分: " + count,30,30);
                //绘制关卡
                paintText(g,"当前关卡: " + level,30,60);
                //绘制目标分数
                paintText(g,"目标分数: " + goal,30,90);
                //绘制时间
                endTime = System.currentTimeMillis();
                tim = 30-(endTime-startTime)/1000;
                paintText(g,"时间:"+(tim>0?tim:0),520,30);

            }
        };
        mainPanel.setBounds(0, 0, 710, 800);
        //mainPanel.add(menuBar);
        this.setJMenuBar(menuBar);
        this.add(mainPanel);


        ActionListener taskPerformer = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                //调用repaint()方法重新绘制组件
                //System.out.println("repaint");
                repaint();
                //重新调用paintComponent()方法
                //mainPanel.paintComponents(mainPanel.getGraphics());
                //line.update(mainPanel.getGraphics());
            }
        };
        //启动定时器重新绘制
        new Timer(delay,taskPerformer).start();

    }

    //绘制文字
    private static void paintText(Graphics g,String text,int x,int y) {
        g.setColor(Color.BLACK);
        g.setFont(new Font("幼圆", Font.BOLD, 25));
        g.drawString(text,x,y);
    }
    //退出游戏并保存进度
    public void exitGame() {
        int record = db.getMax_record();
        if (DataBase.level > record){
            db.setMaxRecord(DataBase.level);//更新最高关卡
        }
        System.exit(0);
    }


}

线类

package com.GoldMiner.util;

import com.GoldMiner.ui.GameMain;
import java.awt.*;
import static com.GoldMiner.util.Img.hook;

/**
 * 矿工的线
 */
public class Line {
    private int x = 390;//起点x坐标
    private int y = 85;//起点y坐标
    private int endX = 600;//终点x坐标
    private int endY = 30;//终点y坐标
    private double length = 80;//线的长度
    private int direction = 1;//线的方向,1为正方向,-1为负方向
    private double n = 0;
    private int state;//线的状态,0为摇摆,1为抓取,2为没有抓到物体收回,3为金块碰撞完成
    GameMain gameMain;

    public Line(GameMain gameMain) {
        //空参构造函数
        this.gameMain = gameMain;
    }

    public void paint(Graphics g) {
        logic();//金块碰撞逻辑
        //通过状态画线
        switch (state) {
            case 0: //摇摆
                if (n < 0.1) {
                    direction = 1; //未超过180度,正方向
                } else if (n > 0.9) {
                    direction = -1; //超过180度,反方向
                }
                n += 0.005 * direction;//角度转弧度
                lines(g);//画线
                break;
            case 1: //抓取
                if (length < 550) {
                    length += 10; //线长增加
                    lines(g);
                } else {
                    state = 2; //抓取完成,收回线
                }
                break;
            case 2: //收回
                if (length > 80) {
                    length -= 10; //线长减少
                    lines(g);
                } else {
                    state = 0; //收回线,摇摆
                }
                break;
            case 3: //金块碰撞完成
                int m = 1; //暂停时间
                if (length > 80) {
                    length -= 10; //线长减少
                    //画线
                    lines(g);
                    for (Item item : this.gameMain.items) {
                        //是否为被抓取的金块
                        if (item.isIsCollected()) {
                            m = item.getM(); //暂停时间
                            //将金块位置设置为跟着线移动
                            item.setX(endX - item.getWidth() / 2);
                            item.setY(endY);
                            if (length <= 100) {
                                //将金块移出屏幕外
                                item.setX(-150);
                                item.setY(-150);
                                item.setIsCollected(false);//移动完毕修改回来
                                //增加积分
                                GameMain.count += item.getCount();
                                state = 0; //收回线,摇摆
                            }
                        }

                    }
                }
                try {
                    Thread.sleep(m);
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                }
                break;
            default: //摇摆
                if (n < 0.1) {
                    direction = 1; //未超过180度,正方向
                } else if (n > 0.9) {
                    direction = -1; //超过180度,反方向
                }
                n += 0.005 * direction;//角度转弧度
                lines(g);
                break;

        }
    }

    /**
     * 计算线的坐标并绘制
     */
    private void lines(Graphics g) {
        //公式计算终点坐标
        endX = (int) (x + length * Math.cos(n * Math.PI));
        endY = (int) (y + length * Math.sin(n * Math.PI));
        g.setColor(Color.black);
        g.drawLine(x, y, endX, endY);
        //加粗
        g.drawLine(x-1, y, endX-1, endY);
        g.drawLine(x+1, y, endX+1, endY);
        g.drawImage(hook,endX-25,endY-2,null);
    }

    /**
     * 金块碰撞的逻辑
     */
    public void logic() {
        //逻辑处理
        for (Item item : this.gameMain.items){
            if (endX > item.getX() && endX < item.getX() + item.getWidth() && endY > item.getY() && endY < item.getY() + item.getHeight()) {
                //物体碰撞
                setState(3);//抓取状态返回3
                //System.out.println(endX + " " + endY + " " + item.getX() + " " + item.getY() + " " + item.getWidth() + " " + item.getHeight());
                item.setIsCollected(true);
                break;
            }
        }
    }

    public void update(Graphics g){
        //更新线的坐标
        paint(g);
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getEndX() {
        return endX;
    }

    public void setEndX(int endX) {
        this.endX = endX;
    }

    public int getEndY() {
        return endY;
    }

    public void setEndY(int endY) {
        this.endY = endY;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public int getDirection() {
        return direction;
    }

    public void setDirection(int direction) {
        this.direction = direction;
    }

    public double getN() {
        return n;
    }

    public void setN(double n) {
        this.n = n;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public String toString() {
        return "Line{x = " + x + ", y = " + y + ", endX = " + endX + ", endY = " + endY + ", length = " + length + ", direction = " + direction + ", n = " + n + ", state = " + state + "}";
    }
}

物体类

package com.GoldMiner.util;

import java.awt.*;

/**
 * 抓取的物体类
 */
public class Item {
    //物体的坐标
    private int x;
    private int y;
    //物体的大小
    private int width;
    private int height;
    private Image img;//抓取的物体图片
    private boolean isCollected = false; //是否已经被抓取
    private int m; //物体的质量
    private int count; //物体的积分

    public Item() {
    }

    //绘制物体
    public void paint(Graphics g) {
        g.drawImage(img, x, y, width, height, null);
    }

    //检测物体矩形重合
    public Rectangle getRect() {
        return new Rectangle(x, y, width, height);
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public Image getImg() {
        return img;
    }

    public void setImg(Image img) {
        this.img = img;
    }

    public String toString() {
        return "Item{x = " + x + ", y = " + y + ", width = " + width + ", height = " + height + ", img = " + img + "}";
    }

    public boolean isIsCollected() {
        return isCollected;
    }

    public void setIsCollected(boolean isCollected) {
        this.isCollected = isCollected;
    }

    public int getM() {
        return m;
    }

    public void setM(int m) {
        this.m = m;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

更多代码访问Gitee下载源代码,以上为主要功能代码,需要配套课设PPT的可以联系我
全部源码开源下载

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值