用Java写个小游戏--黄金矿工代码实现

     阅读:71

项目结构

在这里插入图片描述

  • GameWin类,游戏的主类
  • Gold类,金块类
  • Line类,线类
  • Parent类,提取出的父类
  • Sky类,背景类
  • Stone类,石块类

前期准备

需要获取相关的图片,我的图片是获取至爱给网,里面有挺多的素材而且…免费
搭建一个IDEA项目(会Java的都会吧…eclipse也行,反正我用的IDEA)
两个背景图和天空
在这里插入图片描述

在这里插入图片描述在这里插入图片描述
不同大小的金块和石块
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

矿工和钩子
在这里插入图片描述

在这里插入图片描述

Stone类

关于石头的相关参数

public class Stone extends Parent{
    Stone(){
        this.x=(int)(Math.random()*700);
        this.y=(int)(Math.random()*550+300);
        this.w=53;
        this.h=53;
        this.flag=false;
        this.m=150;
        this.money=50;
        this.type=2;
        this.img= Toolkit.getDefaultToolkit().getImage("img/black3.png");
    }
}


Gold类(包含Gold类,GoldMini类,GoldPlus类)

这个类继承我们书写的Parent方法,类中定义金块的相关属性

public class Gold extends Parent {

    Gold(){
        this.x=(int)(Math.random()*500);//生成金块的纵坐标
        this.y=(int)(Math.random()*550+300);
        this.w=105;//金块的宽
        this.h=105;//金块的高
        this.flag=false;//是否背勾中了
        this.m=180;//金块的重量
        this.money=200;//金块的价钱
        this.type=1;
        this.img= Toolkit.getDefaultToolkit().getImage("img/gold1.gif");
    }
}
class GoldMini extends Gold{
    GoldMini(){
        this.w=72;//金块的宽
        this.h=72;//金块的高
        this.m=70;//金块的重量
        this.money=100;//金块的价钱
        this.img= Toolkit.getDefaultToolkit().getImage("img/gold2.gif");
    }
}
class Goldplus extends Gold{
    Goldplus(){
        this.w=175;//金块的宽
        this.x=(int)(Math.random()*550);
        this.h=175;//金块的高
        this.m=230;//金块的重量
        this.money=500;//金块的价钱
        this.img= Toolkit.getDefaultToolkit().getImage("img/gold11.gif");
    }
}

GameWin类

  • 类中变量
    • state 整个游戏的状态 0未开始 1 运行 2商店 3失败 4胜利
    • image 展示的图片
    • gameTime 倒计时初始时间
    • start 是否开始的判断条件
  • 类中方法
    • launch 窗口事件
    • nextLevel 下一关卡
    • paint 绘制方法(重写方法)
    • main 主方法

代码实现:



public class GameWin extends JFrame {
    static  int state;//整个游戏的状态 0未开始 1 运行 2商店 3失败 4胜利
    Sky sky=new Sky();//背景类
    Line line=new Line(this);//钩子的线类
    Image image;//图片
    public static long gameTime = 30;//倒计时初始时间
    public Thread start;//是否开始
    List<Parent> parentList = new ArrayList<>();//存放父类
    {
        boolean isPlace=true;//是否可以放置
        for (int i = 0; i < 7; i++) {

            //生成不同金块
            Double random=Math.random();
            //先存放金块
            Gold gold;
            if (random<0.3)//概率30%以下生成小金块
            {
                gold=new GoldMini();
            }
            else if (random<0.7)//概率70%以下30%以上生成普通金块
            {
                gold=new Gold();
            }
            else//其他以下生成大金块
            {
                gold=new Goldplus();
            }
            //判断是否重叠
            for (Parent parent:parentList){
                if (gold.getRec().intersects(parent.getRec())){
                    isPlace = false;
                }
            }
            //添加未重叠元素
            if (isPlace)
            {
                parentList.add(gold);
            }
            else
            {
                isPlace=true;i--;
            }

        }
        //利用for循环来存放石块
        for (int i= 0; i < 3; i++) {
            Stone stone=new Stone();
            for (Parent parent:parentList){
                if (stone.getRec().intersects (parent.getRec()))
                {
                    isPlace=false;
                }
            }
            if (isPlace)
            {
                parentList.add(stone);//存储多个石块
            }
            else
            {
                isPlace=true;
                i--;
            }
        }

    }

    void launch() {              //定义窗口事件,无参构造方法
        this.setVisible(true);    //窗口可见
        this.setSize(768, 1000);  //窗口大小
        this.setResizable(false);
        this.setLocationRelativeTo(null);  //窗口位置
        this.setTitle("黄金矿工");   //窗口名称
        setDefaultCloseOperation(EXIT_ON_CLOSE);  //关闭窗口操作
        //在launch中添加鼠标事件
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                switch (state){
                    case 0:
                        if (e.getButton()==3){
                            if (start == null){
                                start = new Thread(()->{
                                    try {
                                        while (true){
                                            gameTime -= 1;
                                            Thread.sleep(1000);
                                        }
                                    }catch (Exception ex){
                                        ex.printStackTrace();
                                    }
                                });
                                start.start();
                            }
                            state=1;
                        }
                        break;
                    case 1:

                        if (e.getButton() == 1 && line.state == 0)       //1左键 2滑轮 3右键
                        {
                            line.state = 1;
                        }
                        //设置右键事件
                        if (e.getButton() == 3 && line.state == 3 ) {
                            if (Sky.yaoBasic > 0){
                                Sky.yaoBasic--;
                                Sky.yaoState = true;
                            }
                        };
                    case 2:
                        if (e.getButton()==1)//是否选择购买药水
                        {
                            System.out.println("购买");
                            state=1;
                            sky.shop=true;//调整状态
                        }
                        if (e.getButton()==3)//不购买,进入下一个关
                        {
                            System.out.println("不购买");
                            state=1;
                            System.currentTimeMillis();
                        }
                        break;
                    case 3:
                        //设置重开
                        if (e.getButton()==1){
                            state=0;
                            sky.reGame();
                            line.reGame();
                        }
                        break;
                    case 4:
                        //当点击左键时可以重新开始
                        if (e.getButton()==1){
                            state=0;
                            sky.reGame();
                            line.reGame();
                        }
                        break;
                    default:
                }

            }
        });
        //用死循环来实现窗口的重新绘制
        while (true) {
            repaint();
            //调用下一关
            nextLevel();
            //降低刷新率,在循环里面设置
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void nextLevel()  {
        if (GameWin.gameTime <= 0){
            System.out.println(sky.total);
            System.out.println(sky.goal);
            if(sky.total>=sky.goal) {
                if (sky.level == 5) {
                    state = 4;
                    System.out.println("通关");
                } else {
                    sky.level++;
                    GameWin.state=2;
                    System.out.println("商店:"+state);
                }

            }else{
                //失败,状态调为失败,展示失败页面
                GameWin.state = 3;
            }
            dispose();
            System.out.println(state);
            //刷新窗体
            GameWin.gameTime = 60;
            GameWin gameWin1=new GameWin();
            gameWin1.launch();
        }

    }

    @Override
    public void paint(Graphics g) {
        image=this.createImage(768,1000);
        //为了放置金块和石块的闪动,先绘制一个窗口
        Graphics grap=image.getGraphics();
        sky.paint(grap);
        if (state==1){
            line.paint(grap);

            //绘制金块
            for (Parent gold : parentList) {
                gold.parin(grap);
            }
        }
        g.drawImage(image,0,0,null);
    }

    public static void main(String[] args) throws InterruptedException {
        GameWin gameWin = new GameWin();
        gameWin.launch();

    }
}


Line类

  • 类中变量
    • x 起点的横轴
    • y 起点的纵轴
    • endx 终点的横轴
    • endy 终点的纵轴
    • length 初始绳子长度
    • n 线的角度百分比
    • maxLength 绳子的最长值
    • minLength 绳子的最短值
    • fangxiang 绳子的方向
    • state 绳子的状态 0 最初摇摆状态 1 绳子向下延伸 2 绳子往回拉取 3 绳子抓取到物体
    • gouzi 钩子的图片
  • 类中方法
    • logic 检测钩子是否碰撞物体
    • lines 绘制钩子与绳子
    • paint 主要是绳子状态的完成
    • reGame 重置元素
public class Line {
    int x=380,y=180;//起点坐标
    int endx=500,endy=500;//终点坐标
    //线段长度
    double length=50;
    double n=0;
    double maxLength=750;
    double minLength=50;
    //方向
    int fangxiang=1;
    //状态
    int state=0;
    //爪
    Image gouzi=Toolkit.getDefaultToolkit().getImage("img/gouzi.png");

    GameWin gameWin;
    Line(GameWin gameWin){
        this.gameWin=gameWin;
    }
    //
    void logic(){
        for (Parent obj:this.gameWin.parentList) {
            if (endx > obj.x && endx < obj.x + obj.w
                    && endy > obj.y && endx < obj.x + obj.h
            ) {
                state = 3;//碰撞检测
                obj.flag=true;
            }
        }
    }
    //绘制
    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-1, y-1, endx, endy);
        g.drawLine(x+1, y+1, endx, endy);
        g.drawLine(x, y, endx, endy);
        g.drawImage(gouzi,endx-36,endy-2,null);//让钩子在中间
    }

    public void paint(Graphics g) {

       logic();
        if (state==0) {
            if (n < 0.1) {
                fangxiang = 1;
            } else if (n > 0.9) {
                fangxiang = -1;
            }
            n = n + 0.005 * fangxiang;
            lines(g);
        }else  if (state==1){
            if (length<maxLength) {
                length = length + 10;
                lines(g);
            }else{ state=2;}
        }else if (state==2) {
            if (length>minLength) {
                length = length - 10;
                lines(g);
            }else{ state=0;}
        }
        else if (state==3) {
            int m=1;
            if (length>minLength) {
                length = length - 10;
                lines(g);
                for (Parent object : this.gameWin.parentList) {
                    if (object.flag){
                        m=object.m;
                        object.x=endx-object.getW()/2;//把金块放钩子中间
                        object.y=endy;
                        if (length<=minLength){
                            object.x=-150;
                            object.y=-150;
                            object.flag=false;
                            Sky.yaoState=false;
                            Sky.total+=object.money;
                            state=0;
                        }
                        if (Sky.yaoState){
                            if (object.type==1){
                                m=1;
                            }
                            if (object.type==2){
                                object.x=-150;
                                object.y=-150;
                                object.flag=false;
                                Sky.yaoState=false;
                                state=2;
                            }
                        }
                    }

                }
                try {
                    Thread.sleep(m);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }

    }
    //重置元素
    void reGame(){
        n=0;//线的角度百分比
        length=50;//线的长度
    }
}

Parent类

定义一下多次用到的变量


public class Parent {
    //坐标
    int x,y;
    //宽高
    int w,h;
    //图片
    Image img;
    //标记
    boolean flag;
    //重量
    int m;
    //钱
    int money;
    //类型 1是金块,2是石头
    int type;
    //绘制方法
    void  parin(Graphics g){
        g.drawImage(img,x,y,null);
    }

    public int getW() {
        return w;
    }
    //获取矩形
    public Rectangle getRec(){
        return new Rectangle(x,y,w,h);
    }


Sky类

  • 类中变量
    • level 关卡数
    • goal 目标金额
    • total 总金额
    • yaoBasic 初始药水值
    • yaoState 药水状态 使用或未使用
    • price 药水价格
    • shop 是否购买药水
    • 加一堆的图片
  • 类中方法
    • paint 绘制不同状态的窗口样式
    • draw 提取公共的代码
    • reGame 重置元素
public class Sky {
    //定义
    static int level=1;
    //目标金额
    int goal=level*200+100;
    //总金额
    static  int total=0;
    static  int  yaoBasic=3;//初始药水值
    //药水状态
    static  boolean yaoState=false;
    int price=(int) Math.random()*100+10;
    //是否购买药水
    boolean shop=false;
    //开始和结束
    Image yao= Toolkit.getDefaultToolkit().getImage("img/yao.png");
    Image bg= Toolkit.getDefaultToolkit().getImage("img/sky.jpg");
    Image bg1= Toolkit.getDefaultToolkit().getImage("img/bg1.jpg");//抓矿背景
    Image bg2= Toolkit.getDefaultToolkit().getImage("img/bg2.jpg");//商店背景
    Image miner= Toolkit.getDefaultToolkit().getImage("img/miner.png");
    public void paint(Graphics g) {
        g.drawImage(bg,0,0,null);
        g.drawImage(bg1,0,200,null);
        switch (GameWin.state){
            case 0:
                g.drawImage(bg2,0,200,null);
                draw(g,50,"准备开始,点击右键",150,400,Color.BLACK);
                break;
            case 1:
                g.drawImage(miner,310,50,null);
                draw(g,30,"目标得分"+goal,30,110,Color.black);
                draw(g,30,"总金额:"+total,30,150,Color.BLACK);
                //药水绘制
                g.drawImage(yao,480,90,null);
                draw(g,30,"x"+yaoBasic,550,150,Color.BLACK);
                //计算时间

                draw(g,30,"剩余时间:"+GameWin.gameTime,520,90,Color.BLACK);//rapaint
                break;
            case 2:
                g.drawImage(bg2,0,200,null);
                draw(g,60,"楠楠的商店",220,280,Color.black);
                System.out.println("...........");
                g.drawImage(yao,340,500,null);

                //药水价格
                draw(g,30,"价格"+price,337,650,Color.black);
//                //是否购买
//                draw(g,30,"是否购买",300,450,Color.black);
                if (shop&&total>=price)
                {
                    total-=price;
                    yaoBasic++;
                    shop=false;
                    System.currentTimeMillis();
                }
                break;
            case 3:
                g.drawImage(bg2,0,200,null);
                draw(g,50,"你失败啦!",250,350,Color.RED);//rapaint
                draw(g,50,"总金额!"+total,200,450,Color.BLACK);
                break;
            case 4:
                g.drawImage(bg2,0,200,null);
                draw(g,50,"您通关啦!",250,350,Color.RED);//rapaint
                draw(g,50,"总金额!"+total,200,450,Color.BLACK);
                break;
            default:
        }

    }
    public static  void  draw(Graphics g,int size,String str,int x,int y,Color color){
        g.setColor(color);
        g.setFont(new Font("楷体",Font.BOLD,size));
        g.drawString(str,x,y);
    }
    //重置元素
    void reGame(){
        //定义关卡数
         int level=1;
        //目标金额
        int goal=level*200+100;
        //总金额
          int total=0;
          int  yaoBasic=3;//初始药水值
        //药水状态
          boolean yaoState=false;
    }
}

运行效果

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

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

不是纯自己想的,是看尚学堂的!!但是我没有链接无法发转载,里面根据自己的理解我改了一些代码
原视频地址:https://www.bilibili.com/video/BV1zL411G7cd?p=1
在这里插入图片描述