跟着网上做了一个黄金矿工小游戏,但是画的线偶尔会不显示咋办
其他的都可以正常显示,就那个摇摆的线在进游戏、进下一关、重置游戏的时候有时不显示
主运行类
package gold_miner;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
/**
* 内容实现
*
* @author Legion
* @date 2023/07/20
*/
public class GameWin extends JFrame {
/**
* 游戏状态 0 未开始 1 运行中 2 商店 3 失败 4 胜利
*/
static int state;
/**
* 存储金块、石块
*/
List<MyObject> golds = new ArrayList<>();
/**
* 背景图片对象
*/
Bg bg = new Bg();
/**
* 钩爪对象
*/
Line line = new Line(this);
{
//是否可以放置
boolean isPlace = true;
//生成金块
for (int i = 0; i < 7; i++) {
double random = Math.random();
//存放当前生成的金块
Gold gold;
//30概率放大金块,40概率普通金块,30概率小金块
if (random < 0.3) {
gold = new GoldPlus();
} else if (random < 0.7) {
gold = new Gold();
} else {
gold = new GoldMini();
}
for (MyObject obj : golds) {
//判断是否重合,重合则无法放置
if (gold.getRec().intersects(obj.getRec())) {
isPlace = false;
}
}
//如果可以放置,添加进集合,否则i--,重新生成
if (isPlace) {
golds.add(gold);
} else {
isPlace = true;
i--;
}
}
//石块
for (int i = 0; i < 5; i++) {
double random = Math.random();
Rock rock;
if (random < 0.3) {
rock = new RockPlus();
} else if (random < 0.7) {
rock = new Rock();
} else {
rock = new RockMini();
}
for (MyObject obj : golds) {
//判断是否重合,重合则无法放置
if (rock.getRec().intersects(obj.getRec())) {
isPlace = false;
}
}
//如果可以放置,添加进集合,否则i--,重新生成
if (isPlace) {
golds.add(rock);
} else {
isPlace = true;
i--;
}
}
}
/**
* 新画布
*/
Image offScreenImage;
/**
* 初始化窗口信息
*/
void launch() {
//窗口是否可见
this.setVisible(true);
//窗口大小
this.setSize(1148, 881);
//窗口位置 居中
this.setLocationRelativeTo(null);
this.setTitle("小薛矿工");
//点击窗口右上角的×也能关闭程序
setDefaultCloseOperation(EXIT_ON_CLOSE);
//鼠标事件改变红线状态
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
switch (state) {
//准备阶段
case 0:
//点击鼠标左键进入游戏状态,重置开始时间
if (e.getButton() == 1) {
state = 1;
bg.statTime = System.currentTimeMillis();
}
break;
//游戏阶段
case 1:
//1 左键 2 滑轮 3 右键
//左右摇摆时点击左键,线的状态进入出钩状态
if (e.getButton() == 1 && line.state == 0) {
line.state = 1;
}
//线的状态为抓住物体状态,结晶数量大于0,点击鼠标右键使用结晶
if (e.getButton() == 3 && line.state == 3 && Bg.kryptonGoldNum > 0) {
//结晶状态改为true
Bg.kryptonGoldFlag = true;
//数量减少
Bg.kryptonGoldNum--;
}
break;
//商店
case 2:
//左键购买,右键进入下一关
if (e.getButton() == 1) {
bg.shop = true;
}
if (e.getButton() == 3) {
state = 1;
bg.statTime = System.currentTimeMillis();
}
break;
//失败状态
case 3:
//成功状态
case 4:
//点击鼠标左键重置游戏,进入准备阶段状态,重新绘制背景和线
if (e.getButton() == 1) {
state = 0;
bg.reGame();
line.reGame();
}
break;
default:
}
}
});
//不断重新绘制,条件满足进入下一关
while (true) {
repaint();
nextLevel();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
/**
* 下一关
* 先判断游戏状态和时间,再判断总分数是否大于目标分数
* 如果完成了5关,则进入成功界面,否则进入商店
* 不满足目标分数即失败
* 判断完成后释放原窗体并重新生成窗体
*/
public void nextLevel() {
if (bg.gameTime() && state == 1) {
if (Bg.count >= bg.goal) {
if (Bg.level == 5) {
state = 4;
} else {
state = 2;
Bg.level++;
}
} else{
state = 3;
}
//释放原来的窗体
dispose();
//重新生成窗体
GameWin gameWin1 = new GameWin();
gameWin1.launch();
}
}
/**
* 调用绘制方法
* 使用双缓存,创建新画布并在新画布上绘制,完成后将新画布绘制到窗体
*
* @param g Graphics类型画笔
*/
@Override
public void paint(Graphics g) {
//创建新画布,再新画布上绘制
offScreenImage = this.createImage(1148, 881);
Graphics graphics = offScreenImage.getGraphics();
/*
往新画布绘制
绘制线在绘制物体前面时,抓取物体时原石在物体上面一层
绘制线在绘制物体后面时,抓取物体时原石在物体下面一层
*/
//背景绘制
bg.paintSelf(graphics);
//判断是否是游戏运行中状态
if (state == 1) {
//绘制物体
for (MyObject obj : golds) {
obj.paintSelf(graphics);
}
//绘制线
line.paintSelf(graphics);
}
//将新画布绘制到窗口
g.drawImage(offScreenImage,0,0,null);
}
/**
* 主函数
*/
public static void main(String[] args) {
GameWin gameWin = new GameWin();
gameWin.launch();
}
}
线类
package gold_miner;
import java.awt.*;
/**
* 摇摆爪子线
* @author Legion
*/
public class Line {
//起点坐标
int x = 555;
int y = 190;
//终点坐标
int endx = 500;
int endy = 500;
//线长
double length = 100;
double MIN_LENGTH = 100;
double MAX_LENGTH = 900;
//角度
double angle = 0;
//控制方向
int dir = 1;
//状态 0 摇摆 1 抓取 2 收回 3 抓取返回
int state;
//使得可接受主窗口中的元素
GameWin frame;
//钩爪图片
// File hookImg = new File("imgs/原石50.png");
Image hook = Toolkit.getDefaultToolkit().getImage("imgs/原石50.png");
int hookWidth = 25;
/*
{
try {
hookWidth = ImageIO.read(new FileInputStream(hookImg)).getWidth();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
*/
/**
* 有参构造
*/
public Line(GameWin frame) {
this.frame = frame;
}
/**
* 抓取判定
*/
void logic() {
for (MyObject obj : this.frame.golds) {
if (endx > obj.x && endx < obj.x + obj.width && endy > obj.y && endy < obj.y + obj.height) {
state = 3;
obj.flag = true;
}
}
}
/**
* 绘制方法
*/
void paintSelf(Graphics g) {
logic();
switch (state) {
case 0:
if (angle < 0.1) {
dir = 1;
} else if (angle > 0.9) {
dir = -1;
}
angle += 0.005*dir;
lines(g);
break;
case 1:
if (length < MAX_LENGTH) {
length += 5;
lines(g);
} else {
state = 2;
}
break;
case 2:
if (length > MIN_LENGTH) {
length -= 5;
lines(g);
} else {
state = 0;
}
break;
case 3:
int m = 1;
if (length > MIN_LENGTH) {
length -= 5;
lines(g);
for (MyObject obj : this.frame.golds) {
if (obj.flag){
m = obj.m;
obj.x = endx - obj.getWidth()/2;
obj.y = endy;
if (length <= MIN_LENGTH) {
obj.x = -150;
obj.y = -150;
obj.flag = false;
Bg.kryptonGoldFlag = false;
//加分
Bg.count += obj.count;
state = 0;
}
//使用结晶
if (Bg.kryptonGoldFlag) {
if (obj.type == 1) {
m = 1;
}
if (obj.type == 2) {
obj.x = -150;
obj.y = -150;
obj.flag = false;
Bg.kryptonGoldFlag = false;
state = 2;
}
}
}
}
}
try {
Thread.sleep(m);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
break;
default:
}
}
public void reGame () {
angle = 0;
length = 100;
}
/**
* 绘制线,线摇摆
*/
public void lines(Graphics g) {
endx = (int) (x + length * Math.cos(angle * Math.PI));
endy = (int) (y + length * Math.sin(angle * 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 - hookWidth - 5, endy - 6, null);
}
}