Java javax.swing.Timer持续时间
我需要使用Java javax.swing.Timer持续时间,java,swing,animation,timer,Java,Swing,Animation,Timer,我需要使用javax.swing.Timer在X秒内执行N次计算(带有图形更新)。 做这件事最好的方法是什么 如果我为计时器设置了固定的延迟,我会超过X秒,因为每次执行所需的时间是延迟+计算 为了解决这个问题,我尝试动态设置计时器的延迟,但时间仍然不准确 作为最后一次机会,我尝试将dalay设置为1ms,并使用Thread.sleep(sleepTime)来控制持续时间,并完美地工作,而不会影响动画效果 我的问题是: 这是一个好的解决方案吗?我可以在javax.swing.Timer中使用Thr
javax.swing.Timer
在X秒内执行N次计算(带有图形更新)。
做这件事最好的方法是什么
如果我为计时器设置了固定的延迟,我会超过X秒,因为每次执行所需的时间是延迟+计算
为了解决这个问题,我尝试动态设置计时器的延迟
,但时间仍然不准确
作为最后一次机会,我尝试将dalay
设置为1ms,并使用Thread.sleep(sleepTime)
来控制持续时间,并完美地工作,而不会影响动画效果
我的问题是:
这是一个好的解决方案吗?我可以在javax.swing.Timer
中使用Thread.sleep(sleepTime)
吗
编辑,这里有一些代码可以更好地理解。我想说的是,图形只需要看看动作是否正确,在最终版本中,我只需要更新游戏并生成一份比赛结果报告
带有“游戏循环”的主框架:
package engine.test;
导入引擎、实体、技能;
导入engine.math.Point;
导入engine.math.Vector;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.io.File;
导入java.io.FileNotFoundException;
导入java.util.ArrayList;
导入java.util.HashMap;
导入java.util.Map;
导入java.util.Scanner;
导入java.util.logging.Level;
导入java.util.logging.Logger;
导入javax.swing.JFrame;
导入javax.swing.JMenu;
导入javax.swing.JMenuBar;
导入javax.swing.JMenuItem;
导入javax.swing.Timer;
导入org.json.JSONArray;
导入org.json.JSONException;
导入org.json.JSONObject;
公共最终类EngineName扩展JFrame实现ActionListener
{
公共静态最终整数比例=6;
公共静态最终整数宽度=100*刻度;
公共静态最终内部高度=60*刻度;
public static final int DURATION=2;//动画持续时间(秒)
公共静态最终整数FPS=60;
公共静态最终整数跳过刻度=1000/FPS;
私有最终JSONObject数据;
私人决赛选手;
私人播放面板播放面板;
PublicEngineName(字符串标题)抛出JSONException、FileNotFoundException
{
超级(标题);
设置尺寸(宽度、高度);
setVisible(真);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createMenu();
数据=新的JSONObject(loadData());
players=buildPlayers(data.getJSONArray(“团队”).getJSONObject(0.getJSONArray(“玩家”));
playersPanel=新的playersPanel(玩家);
添加(播放器面板);
}
公共数组列表getPlayers()
{
返回球员;
}
/**
*返回运行匹配所需的数据。
*
*@返回表示匹配数据的json字符串
*@抛出FileNotFoundException
*/
私有字符串loadData()引发FileNotFoundException
{
扫描仪文件输入=新扫描仪(新文件(
“C:\\Users\\packard bell\\Documents\\JavaProjects\\Engine\\src\\resources\\data.json”
));
字符串jsonText=“”;
while(fileInput.hasNextLine()){
jsonText+=fileInput.nextLine();
}
返回jsonText;
}
/**
*创建并返回播放器实体。
*
*@param playersData
*@返回
*/
私有ArrayList构建播放器(JSONArray PlayerData)抛出JSONException
{
ArrayList players=新的ArrayList();
JSONObject playerData;
玩家;
对于(int i=0,l=playerData.length();ipackage engine.test;
import engine.entity.Skill;
import engine.math.Point;
import engine.math.Vector;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.Timer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public final class EngineFrame extends JFrame implements ActionListener
{
public static final int SCALE = 6;
public static final int WIDTH = 100 * SCALE;
public static final int HEIGHT = 60 * SCALE;
public static final int DURATION = 2; // animation duration in seconds
public static final int FPS = 60;
public static final int SKIP_TICKS = 1000 / FPS;
private final JSONObject data;
private final ArrayList<Player> players;
private PlayersPanel playersPanel;
public EngineFrame(String title) throws JSONException, FileNotFoundException
{
super(title);
setSize(WIDTH, HEIGHT);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createMenu();
data = new JSONObject(loadData());
players = buildPlayers(data.getJSONArray("teams").getJSONObject(0).getJSONArray("players"));
playersPanel = new PlayersPanel(players);
add(playersPanel);
}
public ArrayList<Player> getPlayers()
{
return players;
}
/**
* Returns the data required to run a match.
*
* @return a json string representing the match data
* @throws FileNotFoundException
*/
private String loadData() throws FileNotFoundException
{
Scanner fileInput = new Scanner(new File(
"C:\\Users\\packard bell\\Documents\\JavaProjects\\Engine\\src\\resources\\data.json"
));
String jsonText = "";
while (fileInput.hasNextLine()) {
jsonText += fileInput.nextLine();
}
return jsonText;
}
/**
* Creates and returns the player entities.
*
* @param playersData
* @return
*/
private ArrayList<Player> buildPlayers(JSONArray playersData) throws JSONException
{
ArrayList<Player> players = new ArrayList<Player>();
JSONObject playerData;
Player player;
for (int i = 0, l = playersData.length(); i < l; i++) {
playerData = playersData.getJSONObject(i);
player = new Player.Builder()
.setId(playerData.getInt("id"))
.setFirstName(playerData.getString("first_name"))
.setLastName(playerData.getString("last_name"))
.setMass(playerData.getInt("weight"))
.setSkills(buildSkills(playerData.getJSONObject("skills")))
.setInitialPosition(new Point(0, i * 10 + 20))
.setInitialVelocity(new Vector(0, 0))
.build();
players.add(player);
}
return players;
}
/**
*
*/
private Map<Skill, Double> buildSkills(JSONObject skillsData) throws JSONException
{
Map<Skill, Double> skills = new HashMap();
for (Skill skill : Skill.values()) {
skills.put(
skill,
skill.getMinValue() + (skill.getMaxValue() - skill.getMinValue()) * (skillsData.getDouble(skill.getName()) / 100)
);
}
return skills;
}
/**
*
*/
private void createMenu()
{
JMenu seekMenu = new JMenu("Seek behavior");
JMenuItem initSeek = new JMenuItem("Init seek");
initSeek.addActionListener(this);
JMenuItem runSeek = new JMenuItem("Run seek");
runSeek.addActionListener(this);
JMenuItem stopSeek = new JMenuItem("Stop seek");
stopSeek.addActionListener(this);
seekMenu.add(initSeek);
seekMenu.add(runSeek);
seekMenu.add(stopSeek);
JMenuBar bar = new JMenuBar();
bar.add(seekMenu);
setJMenuBar(bar);
}
public static void main(String[] args) throws JSONException, FileNotFoundException, InterruptedException
{
EngineFrame frame = new EngineFrame("Engine");
}
@Override
public void actionPerformed(ActionEvent e)
{
String menuString = e.getActionCommand();
if (menuString.equalsIgnoreCase("init seek")) {
Player player1 = getPlayers().get(0);
Player player2 = getPlayers().get(1);
player1.setPosition(new Point(0, 20));
player1.setVelocity(new Vector(0, 0));
player2.setPosition(new Point(0, 30));
player2.setVelocity(new Vector(0, 0));
repaint();
}
else if (menuString.equalsIgnoreCase("run seek")) {
Timer t = new Timer(1, new ActionListener() {
private final long start = System.currentTimeMillis();
private long nextGameUpdate = start;
private long sleepTime = 0;
private int loops = DURATION * 1000 / SKIP_TICKS;
@Override
public void actionPerformed(ActionEvent e) {
Player player1 = getPlayers().get(0);
Player player2 = getPlayers().get(1);
//System.out.println("Position: " + player1.getPosition());
//System.out.println("Velocity: " + player1.getVelocity());
System.out.println();
player1.getSteering().seek(new Point(50, 20));
player2.getSteering().seek(new Point(50, 30));
player1.update();
player2.update();
repaint();
nextGameUpdate += SKIP_TICKS;
sleepTime = nextGameUpdate - System.currentTimeMillis();
//System.out.println(nextGameUpdate);
//System.out.println(sleepTime);
loops--;
if (sleepTime >= 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException ex) {
Logger.getLogger(EngineFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
if (loops <= 0) {
((Timer)e.getSource()).stop();
long end = System.currentTimeMillis();
// should be 2000ms (equals to DURATION constant)
System.out.println("Duration: " + (end - start) + "ms");
}
}
});
t.setInitialDelay(0);
t.start();
}
}
// version without swing timer (it works if called in the main method)
private void runSeek() throws InterruptedException
{
Player player1 = getPlayers().get(0);
Player player2 = getPlayers().get(1);
player1.setPosition(new Point(0, 20));
player2.setPosition(new Point(0, 30));
// run
long start = System.currentTimeMillis();
long nextGameUpdate = start;
long sleepTime = 0;
int i = DURATION * 1000 / SKIP_TICKS;
System.out.println("Loop executions: " + i);
int steps = 0;
String stepsCode = "[";
String velocitiesCode = "[";
String positionsCode = "[";
while (i > 0) {
stepsCode += steps + ", ";
velocitiesCode += player1.getVelocity().len() + ", ";
positionsCode += player1.getPosition().toVector().len() + ", ";
System.out.println("Position: " + player1.getPosition());
System.out.println("Velocity: " + player1.getVelocity());
System.out.println();
player1.getSteering().seek(new Point(50, 20));
player2.getSteering().seek(new Point(50, 30));
player1.update();
player2.update();
repaint();
nextGameUpdate += SKIP_TICKS;
sleepTime = nextGameUpdate - System.currentTimeMillis();
steps += sleepTime;
//System.out.println(sleepTime);
if (sleepTime >= 0) {
Thread.sleep(sleepTime);
}
i--;
}
stepsCode = stepsCode.substring(0, stepsCode.length() - 2) + "]";
velocitiesCode = velocitiesCode.substring(0, velocitiesCode.length() - 2) + "]";
positionsCode = positionsCode.substring(0, positionsCode.length() - 2) + "]";
long end = System.currentTimeMillis();
System.out.println("Duration: " + (end - start) + "ms");
System.out.println("Steps:");
System.out.println(stepsCode);
System.out.println("Positions:");
System.out.println(positionsCode);
System.out.println("Velocities:");
System.out.println(velocitiesCode);
}
}
package engine.test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import javax.swing.JPanel;
public class PlayersPanel extends JPanel
{
private ArrayList<Player> players;
public PlayersPanel(ArrayList<Player> players)
{
this.players = players;
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (Player player : players) {
int x = (int) (player.getPosition().x() * EngineFrame.SCALE);
int y = (int) (player.getPosition().y() * EngineFrame.SCALE);
g2.setColor(Color.BLACK);
g2.fillArc(x, y, 18, 18, 0, 360);
g2.setColor(new Color(0x11539f));
g2.fillArc(x + 2, y + 2, 14, 14, 0, 360);
}
}
}