- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在创建一个迷宫游戏,并希望在游戏舞台上显示一个计时器。我尝试过使用 java.util,但它要求我摆脱我的 Swing 计时器。我怎样才能在游戏中添加一个令人耳目一新的计时器
此代码用于制作包含按钮 Pane 和游戏舞台的游戏框架。
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
* This class Holds the game pane that has the moving player. It also contains
* the GamePane
*
* @author 602052004
*
*/
public class GamePane extends JPanel implements ActionListener, KeyListener {// *change
// GamePane
// to
// GamePane
// This is were the game screen is made and the player is created.
static final long serialVersionUID = 1L;
JLabel player = new JLabel();
JLabel finish = new JLabel();
JFrame gameFrame;
int playerSpeed = 4;
int FPS = 40;
// This array holds my JLabels for the walls.I used it so that i can have a
// for loop with an index for the labels.
JLabel[] walls = new JLabel[3];
{
walls[0] = new JLabel();
walls[1] = new JLabel();
walls[2] = new JLabel();
}
private final Set<Integer> keys = new HashSet<>();
// The keys set holds the keys being pressed
public static void main(String[] args) {
// Open the GUI window
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Create a new object and
// run its go() method
new GamePane().go();
}
});
}
GamePane() {
// Run the parent class constructor
super();
// Allow the panel to get focus
setFocusable(true);
// Don't let keys change the focus
}
/**
* This method creates the gameFrame and sets its layout to a cardlayout.It
* then proceeds the set up the GameFrame.The gameFrame contains the button
* pane and the gameStage
*
* The walls are an array and are used to create an index which is then used
* for the collisions.I set up the walls location here
*/
protected void go() {
setLayout(new CardLayout());
// Setup the window
gameFrame = new JFrame();
// Add this panel to the window
gameFrame.setLayout(new CardLayout());
gameFrame.add(this, "main");
gameFrame.setContentPane(this);
// Set's the window properties
gameFrame.setTitle("main");
gameFrame.setSize(800, 600);
gameFrame.setResizable(false);
gameFrame.setLocationRelativeTo(null);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setVisible(true);
gameFrame.add(new ButtonPane(gameFrame), "buttons");
// Creates the new JPanel that will hold the game.
JPanel gamestage = new JPanel();
gamestage.setBackground(Color.darkGray);
gameFrame.add(gamestage, "game");
gamestage.setLayout(null);
// *Move the setup of the player and the timer under the walls
// Get a sample of collisions going so that i can do it over the weekend
// Setup the movable box
player.setBounds(25, 25, 20, 20);
player.setVisible(true);
player.setBackground(Color.red);
// Opaque makes the background visible
player.setOpaque(true);
// Setup the key listener
addKeyListener(this);
// Null layout allows moving objects!!!
gamestage.add(player);
// Set the timer
Timer tm = new Timer(1000 / FPS, this);
tm.start();
walls[0].setBounds(10, 15, 10, 480);// left height
walls[0].setVisible(true);
walls[0].setBackground(Color.white);
walls[0].setOpaque(true);
gamestage.add(walls[0]);
walls[1].setBounds(10, 10, 490, 10);// top width
walls[1].setVisible(true);
walls[1].setBackground(Color.white);
walls[1].setOpaque(true);
gamestage.add(walls[1]);
// wall3.setBounds(x, y, width, height);
walls[2].setBounds(10, 100, 100, 10);
walls[2].setVisible(true);
walls[2].setBackground(Color.white);
walls[2].setOpaque(true);
gamestage.add(walls[2]);
finish.setBounds(30, 455, 20, 20); // *make the game change to the main
// screen when finished
// Add a timer
finish.setVisible(true);
finish.setBackground(Color.LIGHT_GRAY);
finish.setOpaque(true);
gamestage.add(finish);
}
/**
* Check if two JLabel objects are touching
*
* @param a
* The first JLabel
* @param b
* The second JLabel
* @return true if the JLabels are touching
*/
public boolean areColliding(JLabel a, JLabel b) {
return a.getBounds().intersects(b.getBounds());
}
/**
* this method makes the player move. It takes the players speed and
* subtracts or adds the player speed to the current position of the player.
* It also figures out were the player is at currently aswell.
*
* @param arg0
*/
@Override
public void actionPerformed(ActionEvent arg0) {
// Move up if W is pressed
if (keys.contains(KeyEvent.VK_W)) {
player.setLocation(player.getX(), player.getY() - playerSpeed);
}
// Move right if D is pressed
if (keys.contains(KeyEvent.VK_D)) {
player.setLocation(player.getX() + playerSpeed, player.getY());
}
// Move down if S is pressed
if (keys.contains(KeyEvent.VK_S)) {
player.setLocation(player.getX(), player.getY() + playerSpeed);
}
// Move left if A is pressed
if (keys.contains(KeyEvent.VK_A)) {
player.setLocation(player.getX() - playerSpeed, player.getY());
}
for (int i = 0; i < walls.length; i++) {
// I created a for loop instead
// of a do loop because the for
// loop would have been a lot
// simpler to manage
if (areColliding(walls[i], player)) { // Reposition the target
int newX = (int) (25);
int newY = (int) (25);
player.setLocation(newX, newY);
}
}
if (areColliding(finish, player)) {
// Reposition the target
int newX = 25;
int newY = 25;
player.setLocation(newX, newY);
CardLayout layout = (CardLayout) gameFrame.getContentPane()
.getLayout();
layout.show(gameFrame.getContentPane(), "buttons");
}
}
@Override
public void keyPressed(KeyEvent e) {
// Add the key to the list
// of pressed keys
if (!keys.contains(e.getKeyCode())) {
keys.add(e.getKeyCode());
}
}
@Override
public void keyReleased(KeyEvent e) {
// Remove the key from the
// list of pressed keys
keys.remove((Integer) e.getKeyCode());
}
@Override
public void keyTyped(KeyEvent e) {
}
}
此代码在按下按钮时显示游戏 Pane
/**
* This pane contains the button and sets up the button pane
*/
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonPane extends JPanel {
private JButton startBTN;// Calls the JButton
JFrame game;
public ButtonPane(JFrame g) {
game = g;
setLayout(new GridBagLayout());
setBackground(Color.gray);// Sets the menu stages color blue
startBTN = new JButton("Game");// Creates a new button
add(startBTN);// Adds the button on the startStage
startBTN.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (game.getContentPane().getLayout() instanceof CardLayout) {
CardLayout layout = (CardLayout) getParent().getLayout();
layout.show(game.getContentPane(), "game");
}
}
});
}
}
最佳答案
好的,现在您已经有了一个 Timer
,它每秒运行 1000/FPS
次,很酷。您真正需要的只是计算两个时间点之间的差异,令人惊讶的是,这非常简单。
首先定义“开始时间”
private Instant startTime;
在您需要它之前,这将是null
。当您想启动计时器时,请使用 startTime = Instant.now();
当startTime != null
时,你想计算它与现在的差值...
Duration runningTime = Duration.between(startTime, Instant.now());
现在可以告诉您计时器已经运行了多长时间。
接下来,我们需要做出一些决定,例如计时器耗尽时该怎么做,但为此,我们实际上需要知道计时器应该运行多长时间...
private Duration timeOutDuration = Duration.ofSeconds(5);
这只是设置了 5 秒的超时,您可以使用您想要的任何范围。
这样我们就可以计算计时器的剩余时间......
Duration timeRemainig = timeOutDuration.minus(runningTime);
然后决定要做什么......
if (timeRemainig.isNegative() || timeRemainig.isZero()) {
// Time has run out...
// startTime = null; // stop the timer
} else {
// Update the UI
}
Java 8 中引入的日期/时间 API 非常强大且灵活(并且当您了解它时会很有趣)
解决方案可能开始看起来像......
private Duration timeOutDuration = Duration.ofSeconds(5);
private Instant startTime; // Set this when you're ready to start the timer
@Override
public void actionPerformed(ActionEvent arg0) {
if (startTime != null) {
Duration runningTime = Duration.between(startTime, Instant.now());
Duration timeRemainig = timeOutDuration.minus(runningTime);
if (timeRemainig.isNegative() || timeRemainig.isZero()) {
// Time has run out...
// startTime = null; // stop the timer
} else {
// Update the UI
}
}
格式化输出的Duration
通常看起来像......
long hours = timeRemainig.toHours();
long mins = timeRemainig.minusHours(hours).toMinutes();
// Or if you're lucky enough to be using Java 9+
//String formatted = String.format("%dhrs %02dmins", duration.toHours(), duration.toMinutesPart());
String formatted = String.format("%dhrs %02dmins", hours, mins);
或类似,取决于您想要的格式
Why use this approach instead of some "counter"
简单,( super )准确。 Timer
仅保证“至少”间隔,也就是说,它将延迟不少于应用的值,这意味着随着时间的推移可能会引入“拖拽”,从而导致计数器掉落的同步。当然,在短时间内,这可能不是什么大问题,但既然有一种( super 简单)更好的方法来做到这一点,为什么不利用它呢。
该解决方案也非常灵活,适用于广泛的类似问题。我将上述概念用作基于时间的动画的一部分,通常会产生更出色的整体结果。
关于java - 如何使用 swing 组件向 JLabel 添加刷新计时器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50824562/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!