水正二十 2023-07-22 11:25 采纳率: 0%
浏览 17

做了一个黄金矿工小游戏,但是画的线偶尔会不显示,如何解决?

跟着网上做了一个黄金矿工小游戏,但是画的线偶尔会不显示咋办
其他的都可以正常显示,就那个摇摆的线在进游戏、进下一关、重置游戏的时候有时不显示

主运行类

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);
    }
}
  • 写回答

2条回答 默认 最新

  • 爱编程的小芒果 2023-07-22 11:44
    关注

    我以前也做过这种游戏,代码很多,就是第一次运行的时候,线一条显示,一条不显示,断断续续,后来我多刷新几次,好一点了,但每次重画线的时候会严重卡一下,可能会卡掉线条

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 7月22日

悬赏问题

  • ¥15 Java与Hbase相关问题
  • ¥20 bash代码推送不上去 git fetch origin master #失败了
  • ¥15 LOL外服加入了反作弊系统,现在游戏录像rofl文件离线都无法打开
  • ¥15 在centos7安装conda
  • ¥15 c#调用yolo3 dll文件获取的数据对不上
  • ¥20 WPF 如何实现多语言,label 和cs(live Charts)中是否都能翻译
  • ¥15 STM32F103上电短路问题
  • ¥15 打开软件提示错误:failed to get wglChoosePixelFormatARB
  • ¥15 (标签-python|关键词-char)
  • ¥15 python+selenium,在新增时弹出了一个输入框