首页 > 解决方案 > 用java fillRect画一个像子弹计数器一样的电池

问题描述

我正在玩游戏,现在我被困在 gui 的一个愚蠢部分,我无法意识到正确的方法

这是我的子弹计数器的逻辑:

        g.setColor(Color.black);
        g.fillRect(600,20,120,40);
        g.setColor(Color.white);
        g.fillRect(605,25,110,30);


        for(int i=0;i < player.ammo;i++){
            g.setColor(Color.black);
            g.fillRect(610+(i*5),30,20,20);

        }
        bs.show();

这实际上工作正常,问题是子弹计数器增长为单个条,我希望它像这样在单个矩形中增长:▐▐▐▐▐▐▐▐ 就像相机电池电量指示器一样,​​我已经尝试了我能想到的一切。

Obs.:如果可能的话,我只想使用 image.getGraphics() 的方法(如果最后一句有意义的话,idk)

提前致谢

标签: javauser-interfacegraphics

解决方案


让我们从一个简单、孤立的例子开始......

进度条

你需要知道的是:

  • 每个条的宽度
  • 每个条之间的空间量
  • 构成整个进度条的条数(即,多少条代表 100%)

从那里,您可以根据当前进度渲染进度条,只需计算需要显示的条数,然后将每个条从最后一个偏移条宽和条间距

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;

public class Test {
    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                JPanel content = new JPanel(new BorderLayout());
                content.setBorder(new EmptyBorder(50, 50, 50, 50));
                frame.setContentPane(content);

                BulletProgress bulletProgress = new BulletProgress();
                Timer timer = new Timer(1000, new ActionListener() {

                    private double progress = 0;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        progress += 0.1;
                        bulletProgress.setProgress(progress);

                        if (progress >= 1.0) {
                            progress = 0;
                        }
                    }
                });
                timer.setInitialDelay(1000);
                timer.start();

                frame.add(bulletProgress);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class BulletProgress extends JPanel {

        private int bulletWidth = 10;
        private int bulletHeight = 20;
        private int bulletGap = 5;

        private double progress;

        public BulletProgress() {
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension((getBulletWidth() * 10) + (getBulletGap() * 9), bulletHeight);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            int barCount = (int)Math.round(10 * progress);
            int xPos = 0;

            int bulletWidth = getBulletWidth();
            int bulletHeight = getBulletHeight();
            int bulletGap = getBulletGap();
            for (int bar = 0; bar < barCount; bar++) {
                g2d.fillRect(xPos, 0, getBulletWidth(), getBulletHeight());
                xPos += bulletWidth + bulletGap;
            }
            g2d.dispose();
        }

        public int getBulletWidth() {
            return bulletWidth;
        }

        public int getBulletHeight() {
            return bulletHeight;
        }

        public int getBulletGap() {
            return bulletGap;
        }

        public double getProgress() {
            return progress;
        }

        public void setProgress(double progress) {
            this.progress = progress;
            repaint();
        }



    }
}

但是,由于您可能不需要完全成熟的组件,因此我会考虑使用某种“绘制”概念来进一步解耦(并重用)该概念,例如...

public class BarProgressPainter {
    private int bulletWidth = 10;
    private int bulletHeight = 20;
    private int bulletGap = 5;

    public void paint(Graphics2D graphics, double progress) {
        Graphics2D g2d = (Graphics2D) graphics.create();
        int barCount = (int)Math.round(10 * progress);
        int xPos = 0;

        int bulletWidth = getBulletWidth();
        int bulletHeight = getBulletHeight();
        int bulletGap = getBulletGap();
        for (int bar = 0; bar < barCount; bar++) {
            g2d.fillRect(xPos, 0, getBulletWidth(), getBulletHeight());
            xPos += bulletWidth + bulletGap;
        }
        g2d.dispose();
    }

    public int getBulletWidth() {
        return bulletWidth;
    }

    public int getBulletHeight() {
        return bulletHeight;
    }

    public int getBulletGap() {
        return bulletGap;
    }
}

对我来说,进步应该来自某种可以适当抽象的模型,允许渲染过程被解耦(我有一个可绘制的模型,我有模型,我捣碎;))

Obs.:如果可能的话,我只想使用 image.getGraphics() 的方法(如果最后一句有意义的话,idk)

这通常会使过程复杂化,但是,假设您愿意在重新绘制之前清除图像(或进度条使用的区域),使用上述方法应该很容易做到


推荐阅读