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();
这实际上工作正常,问题是子弹计数器增长为单个条,我希望它像这样在单个矩形中增长:▐▐▐▐▐▐▐▐ 就像相机电池电量指示器一样,我已经尝试了我能想到的一切。
Obs.:如果可能的话,我只想使用 image.getGraphics() 的方法(如果最后一句有意义的话,idk)
提前致谢
解决方案
让我们从一个简单、孤立的例子开始......
你需要知道的是:
- 每个条的宽度
- 每个条之间的空间量
- 构成整个进度条的条数(即,多少条代表 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)
这通常会使过程复杂化,但是,假设您愿意在重新绘制之前清除图像(或进度条使用的区域),使用上述方法应该很容易做到
推荐阅读
- c# - 如何以编程方式退出正在运行的单元测试(使用 Visual Studio c# 和单元测试框架)
- c# - 像 PDF 签名一样使用 iTextSharp 签署 PDF 表单
- elasticsearch - Logstash 每日索引下个月的日期格式错误
- gitlab - GitLab CI:YAML 未运行
- neo4j - 为什么 Neo4j 检查点时间会随着图形大小的增加而增加?
- javascript - 宿主函数返回后的事件中可用的 JavaScript 局部范围变量。为什么?
- java - 一些Ashot策略有“模拟器”字样,它们之间有什么区别?
- javascript - 使用样式系统(和样式组件)在悬停时减轻当前按钮颜色
- javascript - 使用事件传递安慰信息
- flutter - 我如何知道用户是否取消订阅?