Java Swing 经典小游戏之 ———— 黄金矿工

(一)效果预览 (项目简介)

1.游戏预览

在这里插入图片描述

2.玩法简介

1)开局一条红绳, 左键让他变长
2)5个金块(分成 )3个石块
3)3种速度 空爪 > 抓回金块 > 抓回石块
4)4个得分

获得得分
大金块30
中金块20
小金块10
石块0

5) 没有输赢,尽情赚钱 (当然你也可以自己加上得分目标)

(二)项目配置

1.Vscode

  1. 官网链接 自行下载即可
  2. 插件的话,搜索Java根据需要下载,建议
    在这里插入图片描述

2.JDK 18.0.2.1

  1. 官网链接 自行下载安装
  2. 配置环境变量,将以下bat文件复制到对应安装目录,管理员身份运行即可
@echo off


rem author: lxfhahaha(http://blog.csdn.net/lxfhahaha)
rem time:2017年10月5日02:16:56
rem msg:请将该文件放在jdk安装目录下,然后以管理员身份运行,即可自动配置java环境



title java环境配置
echo 一键配置java环境!
echo Tips:请在jdk安装目录下以管理员身份运行~~
set java_h=%~dp0
if "%java_h:~-1%" == "\"  set  java_h=%java_h:~0,-1%
echo 您当前路径为---%java_h%
echo 是否进行环境变量设置?[Y/n]


:shuru
set /p input=
if "%input%"=="Y" goto zhixing
if "%input%"=="y" goto zhixing
if "%input%"=="N" goto guanbi
if "%input%"=="n" goto guanbi
echo 输入错误,请重新输入![Y/n]
goto shuru

:zhixing
echo -----
echo JAVA_HOME:
setx "JAVA_HOME" "%java_h%
echo -----
echo CLASSPATH:
setx "CLASSPATH" ".;%%JAVA_HOME%%\lib\dt.jar;%%JAVA_HOME%%\lib\tools.jar;"
echo -----
echo Path:
set p_=%Path%
set t_="java环境变量配置.data"
echo %p_% >%t_%
findstr /c:"%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;" %t_% >nul 2>&1
if %errorlevel% equ 0 (
  echo path无需配置!
  ) else (
 setx "Path" "%%JAVA_HOME%%\bin;%%JAVA_HOME%%\jre\bin;%Path%"

)
del %t_%
echo -----
pause
exit



:guanbi
echo byebye~~
pause
exit

在这里插入图片描述

(三)项目结构

使用Vscode创建Java项目
项目结构如下
在这里插入图片描述

(1)Images 储存项目的资源文件(图片)

需要的可以在我的资源中下载

(2)GameWin 游戏的主窗口类

(4)Bg 游戏的资源类,加载资源图片

(6)Material Gold和Rock的父类,设置其公共属性

(5)Gold(继承Material)黄金类 生成金块

(7)Rock(继承Material)石头类 生成石块

(8)Line 线类 红线 + 抓取判定

(四)代码实现

各部分功能详见代码注释
GameWin.java

import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.util.List;
import java.util.ArrayList;
import java.awt.*;
import java.awt.event.MouseEvent;

public class GameWin extends JFrame{ // 继承 JFrame Swing 自带框架
	/*
		窗口长,宽
	*/
    int width = 537; 
    int height = 700;
    /*
    	实例化 红线
    */
    Line line = new Line(this);
    /*
    	得分
    */
    int score = 0;
    /*
    	被抓走的尽快数
    */
    int picked_cnt = 0;
	
	/*
		实例化资源类
	*/
    Bg bg = new Bg();
    /*
    	石块 + 金块 列表
    */
    List<Material> materials = new ArrayList<>();
    /*
    	双缓冲
    */
    Image offScreenImage;

    void MakeGold() { // 创造金块
    	/*
    		不断随机化坐标直到不存在物体重叠现象
    	*/
        while(true) {
            Gold gd = new Gold();
            boolean putin = true;
            for(Material material: this.materials) {
            	/*
            		在没有被抓走的金块中做碰撞检测
            	*/
                if (material.rect.intersects(gd.rect) && !material.used){
                    putin = false;
                    break;
                }
            }
            if (putin) {
                materials.add(gd);
                break;
            }
        }
    }
    void MakeRock() {
    	/*
    		同 MakeGold() 生成石块
    	*/
        while(true) {
            Rock gd = new Rock();
            boolean putin = true;
            for(Material material: this.materials) {
                if (material.rect.intersects(gd.rect)  && !material.used ){
                    putin = false;
                    break;
                }
            }
            if (putin) {
                materials.add(gd);
                break;
            }
        }
    }

    {
    	/*
    		初始化
    	*/
        for(int i = 0;i < 5;i ++) {
            MakeGold();
        }
        for(int i = 0;i < 3;i ++) {
            MakeRock();
        }
    }

    void launch() {
    	/*
    		窗口属性设置
    	*/
        this.setVisible(true);
        this.setSize(width,height);
        this.setLocationRelativeTo(null);
        this.setTitle("黄金矿工");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
		
		/*
			鼠标事件检测
		*/
        addMouseListener(new MouseInputAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                // TODO Auto-generated method stub
                super.mouseClicked(e);
                if (e.getButton() == 1) { // 鼠标左键
                    if (line.state != 3) line.state = 1; // 设置线类伸长状态
                }
            }
        });

        while (true) {
            repaint(); // 刷新窗口

            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    @Override
    public void paint(Graphics g) {
        // TODO Auto-generated method stub
        // 双缓冲
        offScreenImage = this.createImage(width,height);
        Graphics gImage = offScreenImage.getGraphics();
		// 在缓冲区绘制场景
        bg.paintSelf(gImage);
        for(Material materail: materials) {
            materail.paintSelf(gImage);
        }
        line.paintSelf(gImage);
        // 注意顺序不能换,后画的在上面
        gImage.setFont(new Font("黑体",Font.BOLD,25));
        gImage.setColor(Color.red);
        gImage.drawString("得分: " + score, 10, 70);

		// 加载到屏幕上
        g.drawImage(offScreenImage,0,0,null);
    }
    
    // 程序主函数
    public static void main(String[] args) throws Exception {
        GameWin gameWin = new GameWin();
        gameWin.launch();
    }
}

Bg.java

import java.awt.*;

public class Bg {
	/*
		静态资源 只加载一次
	*/
    public static Image bg_ground = Toolkit.getDefaultToolkit().getImage("src/Images/bg_ground.jpg");
    public static Image bg_sky = Toolkit.getDefaultToolkit().getImage("src/Images/bg_sky.jpg");
    public static Image peo = Toolkit.getDefaultToolkit().getImage("src/Images/peo.png");
    public static Image Rock = Toolkit.getDefaultToolkit().getImage("src/Images/rock.png");
    public static Image hook = Toolkit.getDefaultToolkit().getImage("src/Images/hook.png");
    public static Image Gold[] = {
        Toolkit.getDefaultToolkit().getImage("src/Images/gold0.gif"),
        Toolkit.getDefaultToolkit().getImage("src/Images/gold1.gif"),
        Toolkit.getDefaultToolkit().getImage("src/Images/gold2.gif")
    };

    void paintSelf(Graphics g) {
        g.drawImage(bg_ground, 0,124,537,576,null);
        g.drawImage(bg_sky, 0,0,537,124,null);
        g.drawImage(peo,237,62,60,62,null);
    }
}

Material.java

import java.awt.*;

public class Material {
    Image img; // 图片
    /**
     * 坐标 (rect.x,rect.y)
     * 宽高 (rect.width,rect.height)
     * 支持碰撞检测 (矩形对矩形,点对矩形)
     */
    Rectangle rect;
    boolean picked; // 是否正在被抓去
    boolean used = false; // 是否被抓去
    int score; // 抓取后的得分
    int speed; // 抓取后钩爪的回收速度

    void paintSelf(Graphics g) {
        g.drawImage(img, rect.x, rect.y, rect.width,rect.height,null);
    }
}

Gold.java

import java.awt.*;

public class Gold extends Material{
    public static int[][] GoldSize = {
        {36,36},
        {52,52},
        {76,76}
    }; 
    public static int[] Score = {
        10,20,30
    };
    Gold() {
        double random = Math.random();
        /*
        	按照比例生成大/中/小三种金块
        */
        int tp;
        if (random < 0.3) tp = 0;
        else if(random < 0.7) tp = 1;
        else tp = 2;
        this.img = Bg.Gold[tp];
        this.score = Score[tp];
        this.picked = false;
        this.speed = 5;
        this.rect = new Rectangle((int)(Math.random() * (489 - 0)) + 0,(int)(Math.random() * (385 - 0)) + 210,Gold.GoldSize[tp][0],Gold.GoldSize[tp][1]);
    }
}

Rock.java

// 基本上同 Gold
import java.awt.*;

public class Rock extends Material{
    Rock() {
        this.img = Bg.Rock;
        this.score = 0;
        this.picked = false;
        this.speed = 2;
        this.rect = new Rectangle((int)(Math.random() * (489 - 0)) + 0,(int)(Math.random() * (385 - 0)) + 210,52,52);
    }
}

Line.java 重点
首先引用大佬的PPT ———— 计算机中的方向角
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

import java.awt.*;

public class Line {
    int startx = 267,starty = 104; // 起点
    int endx,endy; // 终点
    double length = 100;
    double ndegree = 0;

    // 方向
    int dir = 1;
    // 状态 0 摇摆 1 抓取 2 收回 3 抓取返回
    int state;
    int speed;
	
	/* 
		为了可以获取并设置物体的位置
	*/
    GameWin frame;

    Line(GameWin frame) {
        this.frame = frame;
    }

    void logic() { // 判断近金块被抓取
        for(Material material: this.frame.materials) {
            if (material.rect.contains(endx,endy)) {
                state = 3;
                material.picked = true;
                speed = material.speed;
            }
        }
    }

    void paintSelf(Graphics g) {
        logic();
        switch (state) {
            case 0:
            	// 设置红线左右摇摆
                if (ndegree < 0.1) dir = 1;
                else if (ndegree > 0.9) dir = -1;
                ndegree += 0.005 * dir;
                break;
            case 1:
                if (length < 600){
                    length += 10;
                }
                else {
                    state = 2;
                }
                break;
            case 2:
                if (length > 100) {
                    length -= 10;
                } else {
                    state = 0;
                }
                break;
            case 3:
            	// 模拟红线收回
                if (length > 100) {
                    length -= speed;
                    for(Material material: this.frame.materials) {
                        if (material.picked)
                        	/*
                        		直接用API
                        	*/
                            material.rect.setLocation(endx - material.rect.width / 2, endy - material.rect.height / 2);
                    }
                } else {
                    state = 0;
                    for(Material material: this.frame.materials) {
                        if (material.picked){
                        	/*
                        		被抓取物体跟随
                        	*/
                            material.rect.setLocation(-150,-150);
                            material.picked = false;
                            this.frame.picked_cnt ++;
                            this.frame.score += material.score;
                            material.used = true;
                        }
                    }
                    if ((Math.random() >= 0.6 && this.frame.materials.size() - this.frame.picked_cnt < 8) || this.frame.materials.size() - this.frame.picked_cnt <= 3) {
                        int num = (int)(Math.random() * (8 - (this.frame.materials.size() - this.frame.picked_cnt) - 1)) + 1;
                        for(int i = 1;i <= num;i ++) {
                            if (Math.random() <= 0.7) 
                                this.frame.MakeGold();
                            else
                                this.frame.MakeRock();
                        }
                    }
                }
                break;
        }
        endx = (int)(startx + length * Math.cos(ndegree * Math.PI));
        endy = (int)(starty + length * Math.sin(ndegree * Math.PI));
        g.setColor(Color.red);
        g.drawLine(startx, starty, endx, endy);
        // 挂钩
        g.drawImage(Bg.hook, endx - 13,endy - 13,30,30,null);
    }
}

运行即可,大功告成
项目源码可到 我的资源 领取
萌新第二个Java程序~~(继Helloworld.java后)~~ 如果有不正确的或可以优化的地方欢迎赐教
撰写不易,做人,一定要善良; 点赞,好人,有好福。

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值