JAVA 黄金矿工小游戏项目

项目简介:黄金矿工游戏项目

项目采用技术:Java变量及数据类型,判断语句,循环结构,Java集合,简单窗口创建,图形图片绘制,鼠标事件,双缓存技术,流式布局

功能需求分析:

1. 游戏基本设计:
   - 设计游戏场景,包括金矿、岩石、矿石等元素以及它们的外观和分布。

2. 资源管理:
   - 设计金矿的生成、存储和收集机制,玩家通过挖掘获得金矿资源。
   - 创建资源管理系统,跟踪玩家的金矿数量和存储情况。

3. 游戏进度与挑战:
   - 设定不同的关卡目标和挑战任务,例如在规定时间内挖掘一定量的黄金或完成特定任务。

4. 道具与技能系统:
   - 提供各种道具和技能供玩家购买或解锁,比如生命药水等。
   - 实现道具和技能的购买和出售系统。

5. 用户界面与用户体验:
   - 设计直观易懂的用户界面

项目亮点:

1.简单易上手:游戏操作简单直观,玩家只需简单的点击操作

2.策略性挖掘体验:玩家需合理规划挖矿路线

3.重新游戏选项:使用流式布局,添加菜单栏,失败后可选择重新游戏或退出

团队成员负责内容
郭忆微创建金块,设置多种金块,解决物体堆叠,红线完善,力量与爆破关卡设置,添加鼠标事件,整合GameWin类,添加菜单栏
李夏冉绘制图片及窗口,红线绘制及状态,双缓存技术,抓取状态,药水设置,积分设置,游戏重置,计时效果,失败与成功状态
package sxt;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import static java.awt.Color.black;
import static sxt.Bg.waterNum;

public class GameWin extends JFrame {
    /*
    设置静态变量,表示整个游戏的状态
    0表示游戏未开始
    1表示游戏进行中
    2表示商店选购中
    3表示游戏失败
    4表示游戏胜利
     */
    static int state;
    /*
    创建集合存储金块,石块
     */
    List<Object> objectList = new ArrayList<>();
    /*
    载入图片
     */
    Bg bg = new Bg();
    Line line = new Line(this);

    {
        /*
        布尔类型变量,判断是否可以放置物块
         */
        boolean isPlace = true;
        /*
        三种金块按照一定概率添加
         */
        for (int i = 0; i < 15; i++) {
            /*
            生成随机数计算不同金块生成概率,数值在0-1之间
             */
            double random = Math.random();
            /*
            每次生成物块时,需要判断是否与已生成物块堆叠,如果没有堆叠,则添加在集合中
            成员变量gold用来存放已经生成的物块
             */
            Gold gold;
            if (random < 0.4) {
                gold = new GoldMini();
            } else if (random < 0.75) {
                gold = new Gold();
            } else {
                gold = new GoldPlus();
            }
            /*
            增强for循环判断生成的金块是否和集合中存在的物块重叠
             */
            for (Object obj : objectList) {
                if (gold.getRec().intersects(obj.getRec())) {
                    /*
                    不可放置,需要重新生成
                     */
                    isPlace = false;
                }
            }
                    /*
        循环结束后,如果可以放置,则添加到链表中
         */
            if (isPlace) {
                objectList.add(gold);
            } else {
                isPlace = true;
                i--;
            }
        }
        for (int i = 0; i < 5; i++) {
        /*
        同以上方法,循环判断石块是否和已经存在的物块堆叠
         */
            Rock rock = new Rock();
            for (Object obj : objectList) {
                if (rock.getRec().intersects(obj.getRec())) {
                    isPlace = false;
                }
            }
            if (isPlace) {
                objectList.add(rock);
            } else {
                isPlace = true;
                i--;
            }
        }
    }

    /*
    解决闪动问题,新定义一张画布,双缓存缓存图像数据
     */
    Image offScreenImage;

    /*
    创建方法来初始化窗口信息
     */
    void launch() {
        Image icon = Toolkit.getDefaultToolkit().getImage("C:\\Users\\86185\\Desktop\\imgs\\gold-miner-\\src\\peo.png");

        JMenuBar jMenuBar = new JMenuBar();
        JMenu fuctionJMenu = new JMenu("功能");
        fuctionJMenu.setFont(new Font("黑体", Font.BOLD, 18));
        JMenuItem replay = new JMenuItem("重新开始");
        JMenuItem close = new JMenuItem("关闭游戏");
        replay.setFont(new Font("黑体", Font.BOLD, 18));
        close.setFont(new Font("黑体", Font.BOLD, 18));
        close .addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        replay.addActionListener(new ReplayGame());
        jMenuBar.add(fuctionJMenu);
        fuctionJMenu.add(replay);
        fuctionJMenu.add(close);
        this.setJMenuBar(jMenuBar);
        add(drawingPanek,BorderLayout.CENTER);

        this.setIconImage(icon);
        this.setVisible(true);
        this.setSize(768, 1000);
        this.setLocationRelativeTo(null);
        this.setTitle("黄金矿工");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
/*
添加鼠标事件
 */
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                switch (state) {
                    case 0:
                                 /*
                                 点击鼠标右键,进入游戏
                                  */
                        if (e.getButton() == 3) {
                            state = 1;
                                     /*
                                     进入游戏的同时给开始时间赋值
                                     赋值为系统时间
                                      */
                            bg.startTime = System.currentTimeMillis();
                        }
                        break;
                    case 1:
                               /*
                               游戏进行中时
                               左右摇摆,点击左键
                               */
                        if (e.getButton() == 1 && line.state == 0) {
                            line.state = 1;
                        }                                       /*
                               抓取返回,点击右键
                              */
                        if ((e.getButton() == 3 && line.state == 3) && (waterNum > 0)) {
                            Bg.waterFlag = true;
                            waterNum--;
                        }
                        break;
                    case 3:

                    case 4:
                        if (e.getButton() == 1) {
                    /*
                    返回准备开始
                     */
                            state = 0;
                    /*
                    重置背景和线中的元素
                     */
                            bg.reGame();
                            line.reGame();


                        }
                        break;
                    default:
                }
            }

                         }
        );
/*
不停的创建repaint对象使线不停地摇摆
 */
        while (true) {
    /*
    刷新组件外观
     */
            repaint();
    /*
    刷新关卡
     */
            nextLevel();
    /*
    判断关卡
     */
            if (Bg.count >= bg.goal) {
                System.out.println("过关");
            }
            try {
                Thread.sleep(8);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /*
    刷新,进入下一关
     */
    public void nextLevel() {
/*
游戏运行中才会进入下一关
 */
        if (bg.gameTime() && state == 1) {
            if (Bg.count >= bg.goal) {
    /*
    关卡数加一
     */
                if (Bg.level == 5) {
                    state = 4;
                }
        /*
        如果满足条件并且还没有到成功的时候,就进入商店
         */
                else {
                    state = 2;
                    Bg.level++;
                }
            /*
            释放之前的窗体
            */
                dispose();

                GameWin gameWin1 = new GameWin();
                gameWin1.launch();
            } else {
                state = 3;
            }
        }
    }
    public JPanel drawingPanek = new JPanel() {
        public void paint(Graphics g) {
        /*
        背景在任何游戏状态下都需要绘制
         */
            offScreenImage = this.createImage(768, 1000);
            Graphics gImage = offScreenImage.getGraphics();
            bg.paintSelf(gImage);
        /*
        在游戏运行中的状态下
        绘制物体和线
         */
            if (state == 1) {
                for (Object obj : objectList) {
                    obj.paintSelf(gImage);

                }
                line.paintSelf(gImage);
            }
            g.drawImage(offScreenImage, 0, 0, null);
        }
    };

    public static void main(String[] args) {
        GameWin gameWin = new GameWin();
        gameWin.launch();
    }
}
package sxt;

import java.awt.*;


public class Rock extends Object{
    Rock(){
        this.x=(int)(Math.random()*700);
        this.y=(int)(Math.random()*550+300);
        this.height=71;
        this.width=71;
        this.flag=false;
        this.m=50;
        this.type =2;
        this.img= Toolkit.getDefaultToolkit().getImage("imgs/rock1.png");
    }
}
package sxt;


import java.awt.*;

import static java.awt.Color.black;

public class Bg {
    /*
    载入图片
     */
    Image bg = Toolkit.getDefaultToolkit().getImage("imgs/bg.jpg");
    Image bg1 = Toolkit.getDefaultToolkit().getImage("imgs/bg1.jpg");
    Image peo = Toolkit.getDefaultToolkit().getImage("imgs/peo.png");
    Image water = Toolkit.getDefaultToolkit().getImage("imgs/water.png");
    /*
    关卡数
     */
    static int level = 1;
    /*
    目标分数(达到后方可进入下一关)
     */
    int goal = level * 15;
    /*
    总分
     */
    static int count = 0;
    /*
    药水数量
     */
    static int waterNum = 5;
    /*
    药水状态,默认false,true表示正在使用
     */
    static boolean waterFlag = false;
    /*
    定义变量
    设置游戏开始时间和结束时间
     */
    long startTime;
    long endTime;
    /*
    药水数量
     */
    int price=(int)Math.random()*10;
    /*设置是否进入商店
    f 不购买
     */
    boolean shop=false;
    /*
    绘制组件外观
     */
    void paintSelf(Graphics g) {
        /*
        背景块在任何游戏状态下都需要绘制
         */
        g.drawImage(bg1, 0, 0, null);
        g.drawImage(bg, 0, 200, null);
        /*
        矿工,积分块,药水组件,关卡数,关卡目标积分都需要在游戏进行状态下绘制
         */
        switch (GameWin.state) {
            case 0:
                /*
                准备开始
                 */
                drawWord(g,Color.GREEN ,80,"准备开始",200,400) ;
                break;
            case 1:
                /*
                绘制矿工
                 */
                g.drawImage(peo, 310, 50, null);
                 /*
                 绘制积分块
                */
                drawWord(g, Color.BLACK, 30, "积分:" + count, 30, 150);
                 /*
                 添加药水组件
                 */
                g.drawImage(water, 450, 40, null);
                drawWord(g, Color.CYAN, 30, "*" + waterNum, 510, 80);
                 /*
                 绘制关卡数
                 */
                drawWord(g, Color.BLACK, 20, "第" + level + "关", 30, 60);
                 /*
                 绘制关卡目标积分
                 */
                drawWord(g, Color.BLACK, 30, "目标:" + goal, 30, 110);
                /*
                时间组件
                实时赋值
                 */
                endTime =System .currentTimeMillis() ;
              /*
                每一关限时20秒,超时即为失败
                定义局部变量,用来计算倒计时
                将时间单位从毫秒换算成秒
                并将其进行打印
                 */
                long tim=30-(endTime -startTime )/1000;
                drawWord(g, Color.BLACK, 30, "时间:" + (tim>0?tim:0), 520, 150);
                break;
            case 2:
                g.drawImage(water,300,400,null);
                drawWord(g,Color.black,30,"价格"+waterNum,300,500);
                drawWord(g,Color.black,30,"是否购买?"+waterNum,300,550);
                /*
                买药水
                 */
                if(shop){
                    count=count-price;
                    waterNum++;
                    /*释放商店状态
                     */
                    shop=false;
                    GameWin.state=1;
                    /*
                    同时重新计时
                     */
                    startTime=System.currentTimeMillis();


                }

                break;
            case 3:
                /*
                失败状态
                 */
                drawWord(g, Color.cyan, 80, "失败" , 250, 350);
                drawWord(g, Color.cyan, 80, "积分:" + count, 200, 450);
                break;
            case 4:
                drawWord(g, Color.RED, 80, "成功" , 250, 350);
                drawWord(g, Color.RED, 80, "积分:" + count, 200, 450);
                break;
            default :
        }
    }
    /*
    添加判断倒计时的方法
    返回值为true,表示倒计时完成
    false,正在倒计时
     */
    boolean gameTime(){
        long tim=30-(endTime -startTime )/1000;
        if(tim<0){
            return true;
        }
        else {
            return false ;
        }
    }
    /*重置元素
    */
     void reGame(){
         level = 1;
    /*
    目标分数(达到后方可进入下一关)
     */
         goal = level * 15;
    /*
    总分
     */
          count = 0;
    /*
    药水数量
     */
         waterNum = 3;
         waterFlag=false;

     }
    /*
    为简化代码,将打印字符串方法进行封装
     */
    public static void drawWord(Graphics g, Color color, int size, String str, int x, int y) {
        /*
        字体颜色
         */
        g.setColor(color);
        /*
        字体类型(加粗)
         */
        g.setFont(new Font("黑体", Font.BOLD, size));
        /*
        打印字符串
         */
        g.drawString(str, x, y);
    }
}
package sxt;

import com.sun.javafx.tk.Toolkit;

import java.awt.*;


public class Line<frame> {
    /*
    起点坐标
     */
    int x=380;
    int y=180;
    /*
    终点坐标
     */
    int endx=500;
    int endy=500;
    /*
    线长
     */
    double length=100;
    double n=0;
    /*
    添加方向
     */
    int dir=1;
    /*
    状态为0就左右摇摆
    状态为1就向下抓取
    状态为2就收回
    状态为3时抓取返回
     */
    int state;
    /*
    让红线类接收到主窗口中的元素
    线长最小值
     */
    double MinLength=100;
    /*
    线长最大值
     */
    double MaxLength=750;
    /*
    给红线添加钩爪图片
     */
    Image hook=java.awt.Toolkit .getDefaultToolkit() .getImage("imgs/hook.png");
    /*
    有参构造
     */
    GameWin frame;
    Line(GameWin frame){
        this.frame=frame;
    }
    /*
    检测物块是否被抓取
     */
    void logic(){
        for(Object obj:this.frame.objectList){
            if(endx>obj.x && endx<obj.x+obj.width
                    &&endy>obj.y && endy<obj.y+obj.height){
                state=3;
                obj.flag=true;
            }
        }
    }
    /*
    绘制方法
     */
    void lines(Graphics g){
        logic();
        endx=(int)(x+length*Math.cos(n*Math.PI));
        endy=(int)(y+length*Math.sin(n*Math.PI));
        g.setColor(Color.red);
        /*
        以下两部分是绘制红线部分的完善
        加粗红线,绘制三条平行线
         */
        g.drawLine(x-1,y,endx-1,endy);
        g.drawLine(x,y,endx,endy);
        g.drawLine(x+1,y,endx+1,endy);
        /*
        保证红线终点在钩爪的中心
         */
        g.drawImage(hook ,endx-36 ,endy-2 ,null) ;
    }
    void paintSelf(Graphics g) {
        switch (state) {
            case 0:
                if (n < 0.1) {
                    dir = 1;
                } else if (n > 0.9) {
                    dir = -1;
                }
                n = n + 0.005 * dir;
                lines(g);
                break;
            case 1:
                if (length < MaxLength) {
                    /*
                    通过调整线长来调整绳子返回速度
                     */
                    length = length + 5;
                    lines(g);
                } else {
                    state = 2;
                }
                break;
            case 2:
                if (length > MinLength) {
                    length = length - 5;
                    lines(g);
                } else {
                    state = 0;
                }
                break;
            /*
            此状态为红线碰到金块立即返回
             */
            case 3:
                /*
                金块石块都在3状态中,不能仅仅通过线长来调整
                需要为金块和石块添加质量属性
                 */
                int m = 1;
                if (length > MinLength) {
                    length = length - 5;
                    lines(g);
                    for (Object obj : this.frame.objectList) {
                        /*
                        判断金块能否移动再让它移动
                         */
                        if (obj.flag) {
                            /*
                            判断金块能否移动再让它移动
                             */
                            if (obj.flag) {
                                m = obj.m;
                                obj.x = endx - obj.getWidth() / 2;
                                obj.y = endy;
                                if (length <= MinLength) {
                                    /*
                                    移至屏幕外
                                     */
                                    obj.x = -150;
                                    obj.y = -150;
                                    obj.flag = false;
                                    Bg.count += obj.count;
                                    state = 0;
                                    /*
                                    释放药水
                                     */
                                    Bg.waterFlag = false;
                                }
                                /*
                                判断抓取时是否使用了药水
                                 */
                                if ((Bg.waterFlag == true) && (Bg.waterNum > 0)) {
                                    /*
                                    为判断抓取的是石块还是金块,需要再返回两个物块类做标记
                                    若抓取的是石块,点击鼠标右键石块消除
                                    若抓取的是金块,点击鼠标右键快速拉取
                                     */
                                    if (obj.type == 1) {
                                        /*
                                        降低质量,提高刷新频率,加快抓取速度
                                         */
                                        m = 1;
                                    }
                                    if (obj.type == 2) {
                                        /*
                                        直接移除石块
                                         */
                                        obj.x = 750;
                                        obj.y = 750;
                                        obj.flag = false;
                                        /*
                                        刷新药水状态
                                         */
                                        Bg.waterFlag = false;
                                        /*
                                        线立即返回
                                         */
                                        state = 2;
                                    }
                                } else if (Bg.waterNum <= 0) {
                                    Bg.waterNum = 0;
                                    Bg.waterFlag = false;
                                }
                            }
                            /*
                            会出现抓一个金块其他金块都消失的现象
                            为解决此问题,去给金块打一个标记flag
                             */
                        }

                    }
                    /*
                    添加延时来降低刷新速度,达到缓慢的效果
                     */
                    try {
                        Thread.sleep(m);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    break;




                }
            default:
        }
    }

     //重置线
    void reGame(){
        n=0;
        length=100;


    }
}
package sxt;

import java.awt.*;

public class Object {
    int x,y;
    int height;
    int width;
    Image img;
    /*
     标记是否能移动
     */
    boolean flag;
    /*
    质量属性
     */
    int m;
    /*
    积分
     */
    int count;
    /*
    类型为1是金块,类型为2是石块
    用来判断抓取的物块种类
     */
    int type;
    void paintSelf(Graphics g){
        g.drawImage(img,x,y,null);
    }
    public int getWidth(){
        return width;
    }
    /*
    为了防止物块堆叠,需要通过判断物块矩形是否重合来判断物块是否堆叠
    获取矩形
     */
    public Rectangle getRec(){
        return new Rectangle(x,y,width ,height);
    }
}
package sxt;

import java.awt.*;

public class Gold extends Object {
    Gold(){
        this.x=(int)(Math.random()*700);
        this.y=(int)(Math.random()*550+300);
        this.height=52;
        this.width=52;
        this.flag=false;
        this.m=30;
        this.count =4;
        this.type =1;
        this.img= Toolkit.getDefaultToolkit().getImage("imgs/gold1.gif");
    }
}
/*
构造多种金块
 */
class GoldMini extends Gold{
    GoldMini (){
        /*
        重置与原有金块类不同的参数
         */
        this.height =36;
        this.width =36;
        this.m=15;
        this.count =2;
        this.img =Toolkit.getDefaultToolkit().getImage("imgs/gold0.gif");
    }
}
class GoldPlus extends Gold{
    GoldPlus (){
        this.x=(int)(Math.random()*650);
        /*
        宽度比普通金块宽出很多,因此重置横坐标
         */
        this.height =105;
        this.width =105;
        this.m=60;
        this.count =8;
        this.img =Toolkit.getDefaultToolkit().getImage("imgs/gold2.gif");
    }
}
package sxt;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class ReplayGame implements ActionListener  {
    GameWin gameWin;
    @Override
    public void actionPerformed(ActionEvent e) {
        try{
            GameWin.state = 0;
                        /*
                        重置背景和线中的元素
                         */
            Bg.count =0;
            Bg.waterNum=5;
            Bg.waterFlag=false ;
            gameWin. bg.reGame();
            gameWin.line.reGame();
            gameWin.launch();
        }catch (NullPointerException e1){
            e1.printStackTrace();
        }
    }
}

项目Git地址:

https://gitee.com/guoyiwei_1_0/gold-miner-

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值