有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

用户界面使用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();

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

注意事项:如果可能的话,我想只使用图像的方法。getGraphics()

提前谢谢


共 (2) 个答案

  1. # 1 楼答案

    这是一个独立的倒计时版本。大部分是锅炉板。它使用计时器来减少子弹数量

    详细信息在BulletCounter类中

    • 它保持初始值,以便重置
    • 从右到左倒计时
    • 提供一种方法,用于查看是否有剩余的项目符号
    • 提供减量方法
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    
    import javax.swing.JComponent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class BulletCounterDemo extends JPanel {
        
        public static void main(String[] args) {
            SwingUtilities
                    .invokeLater(() -> new BulletCounterDemo().start());
        }
        
        public void start() {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(this);
            f.pack();
            f.setLocationRelativeTo(null);
            BulletCounter bc = new BulletCounter(10);
            add(bc);
            f.setVisible(true);
            
            Timer timer = new Timer(1000, (ae) -> {
                bc.decrement();
                if (bc.expired())
                    bc.reset();
            });
            timer.start();
        }
        
        public Dimension getPreferredSize() {
            return new Dimension(200, 40);
        }
    }
    
    class BulletCounter extends JComponent {
        private static int BULLET_WIDTH = 5;
        private static int BULLET_HEIGHT = 30;
        private int nBullets = 0;
        private int fixed = 0;
        
        public BulletCounter(int nBullets) {
            this.nBullets = nBullets;
            this.fixed = nBullets;
        }
        
        public void decrement() {
            if (nBullets >= 0) {
                nBullets ;
            }
            repaint();
        }
        
        public void reset() {
            nBullets = fixed;
            repaint();
        }
        
        public boolean expired() {
            return nBullets < 0;
        }
        
        public Dimension getPreferredSize() {
            return new Dimension(nBullets * 2 * BULLET_WIDTH,
                    BULLET_HEIGHT);
        }
        
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g = g.create();
            g.setColor(Color.BLACK);
            int x = 0;
            for (int i = 0; i <= nBullets; i++) {
                g.fillRect(x, 1, BULLET_WIDTH, BULLET_HEIGHT);
                x = (i * 2) * BULLET_WIDTH;
            }
            if(nBullets <= 0) {
                g.setColor(getBackground());
                g.fillRect(0,0,getWidth(), getHeight());
            }
            
            
            g.dispose();
        }
        
    }
    

    当然,这是一个酒吧骨骼版本。您可以根据需要添加其他方法。例如:

    • 设置背景色
    • 设置bullets的尺寸和颜色
  2. # 2 楼答案

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

    Bar Progress

    您需要知道的是:

    • 每个条的宽度
    • 每个条之间的空间量
    • 构成整个进度条的条数(即,多少条代表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();
            }
    
    
    
        }
    }
    

    既然你可能不需要一个完全成熟的组件,我会考虑使用某种“着色”的概念来进一步解耦(并重新使用)这个概念,例如……p>

    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;
        }
    }
    

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

    Obs.: If possible i would like to do it only using the methods of image.getGraphics()(idk if that last sentence make sense)

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