我试图从1.7.0更新libgdx - > 1.7.2 之后,我的代码开始在Timer / Timer.task中出现一些错误
这是我不知道如何解决的第一个代码 请帮忙..
void loadScreen(String screen) {
clearScreen();
nextScreen = screen;
Timer.schedule(SHOW_SCREEN, Math.min(Gdx.graphics.getDeltaTime(), 0.02f));
}
// SHOW_SCREEN
Task SHOW_SCREEN = new Task() {
@Override
public void run() {
screen = nextScreen;
if (screen.equals("main")) { // MAIN
// load screen
map = new JsonReader().parse(Gdx.files.internal("main.hmp"));
mapWidth = map.getInt("map_width", 0);
// layers
Lib.addGroup("bg", map, stage.getRoot(), 0);
// menu buttons array
Array<Act> buttons = new Array<Act>();
// btnStart
buttons.add(Lib.addLayer("btnStart", map, stage.getRoot(), 0).first());
// sign button
btnSign = Lib.addLayer("btnSign", map, stage.getRoot(), 0).first();
buttons.add(btnSign);
setSigned(isSigned);
// btnLeaders
buttons.add(Lib.addLayer("btnLeaders", map, stage.getRoot(), 0).first());
// btnOptions
buttons.add(Lib.addLayer("btnOptions", map, stage.getRoot(), 0).first());
// groupOptions
groupOptions = Lib.addGroup("groupOptions", map, stage.getRoot(), 0);
groupOptions.setVisible(false);
btnSound = groupOptions.findActor("btnSound");
btnSound.tex = new TextureRegion(assetManager.get(
pref.getBoolean("soundMute", false) ? "btnSoundOn.png" : "btnSoundOff.png", Texture.class));
// map config
mapHeight = map.getInt("map_height", 0);
screenColor = map.getString("map_color", null);
// stage keyboard focus
Act a = new Act("");
stage.addActor(a);
a.addListener(controlListener);
stage.setKeyboardFocus(a);
// set stage moving XY limit
stageLimit();
}
};
这是错误日志:
Exception in thread "Timer" com.badlogic.gdx.utils.GdxRuntimeException: Task failed: com.badlogic.gdx.utils.Timer
at com.badlogic.gdx.utils.Timer$TimerThread.run(Timer.java:245)
at java.lang.Thread.run(Thread.java:745)
引起:java.lang.NullPointerException
at com.badlogic.gdx.utils.Timer.update(Timer.java:125)
at com.badlogic.gdx.utils.Timer$TimerThread.run(Timer.java:243)
... 1 more
这是libgdx版本1.7.0的time.java:
package com.badlogic.gdx.utils;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.LifecycleListener;
/** Executes tasks in the future on the main loop thread.
* @author Nathan Sweet */
public class Timer {
static final Array<Timer> instances = new Array(1);
static TimerThread thread;
static private final int CANCELLED = -1;
static private final int FOREVER = -2;
/** Timer instance for general application wide usage. Static methods on {@link Timer} make convenient use of this instance. */
static Timer instance = new Timer();
static public Timer instance () {
if (instance == null) {
instance = new Timer();
}
return instance;
}
private final Array<Task> tasks = new Array(false, 8);
public Timer () {
start();
}
/** Schedules a task to occur once as soon as possible, but not sooner than the start of the next frame. */
public Task postTask (Task task) {
return scheduleTask(task, 0, 0, 0);
}
/** Schedules a task to occur once after the specified delay. */
public Task scheduleTask (Task task, float delaySeconds) {
return scheduleTask(task, delaySeconds, 0, 0);
}
/** Schedules a task to occur once after the specified delay and then repeatedly at the specified interval until cancelled. */
public Task scheduleTask (Task task, float delaySeconds, float intervalSeconds) {
return scheduleTask(task, delaySeconds, intervalSeconds, FOREVER);
}
/** Schedules a task to occur once after the specified delay and then a number of additional times at the specified interval. */
public Task scheduleTask (Task task, float delaySeconds, float intervalSeconds, int repeatCount) {
if (task.repeatCount != CANCELLED) throw new IllegalArgumentException("The same task may not be scheduled twice.");
task.executeTimeMillis = System.nanoTime() / 1000000 + (long)(delaySeconds * 1000);
task.intervalMillis = (long)(intervalSeconds * 1000);
task.repeatCount = repeatCount;
synchronized (tasks) {
tasks.add(task);
}
wake();
return task;
}
/** Stops the timer, tasks will not be executed and time that passes will not be applied to the task delays. */
public void stop () {
synchronized (instances) {
instances.removeValue(this, true);
}
}
/** Starts the timer if it was stopped. */
public void start () {
synchronized (instances) {
if (instances.contains(this, true)) return;
instances.add(this);
if (thread == null) thread = new TimerThread();
wake();
}
}
/** Cancels all tasks. */
public void clear () {
synchronized (tasks) {
for (int i = 0, n = tasks.size; i < n; i++)
tasks.get(i).cancel();
tasks.clear();
}
}
long update (long timeMillis, long waitMillis) {
synchronized (tasks) {
for (int i = 0, n = tasks.size; i < n; i++) {
Task task = tasks.get(i);
if (task.executeTimeMillis > timeMillis) {
waitMillis = Math.min(waitMillis, task.executeTimeMillis - timeMillis);
continue;
}
if (task.repeatCount != CANCELLED) {
if (task.repeatCount == 0) {
// Set cancelled before run so it may be rescheduled in run.
task.repeatCount = CANCELLED;
}
Gdx.app.postRunnable(task);
}
if (task.repeatCount == CANCELLED) {
tasks.removeIndex(i);
i--;
n--;
} else {
task.executeTimeMillis = timeMillis + task.intervalMillis;
waitMillis = Math.min(waitMillis, task.intervalMillis);
if (task.repeatCount > 0) task.repeatCount--;
}
}
}
return waitMillis;
}
/** Adds the specified delay to all tasks. */
public void delay (long delayMillis) {
synchronized (tasks) {
for (int i = 0, n = tasks.size; i < n; i++) {
Task task = tasks.get(i);
task.executeTimeMillis += delayMillis;
}
}
}
static void wake () {
synchronized (instances) {
instances.notifyAll();
}
}
/** Schedules a task on {@link #instance}.
* @see #postTask(Task) */
static public Task post (Task task) {
return instance().postTask(task);
}
/** Schedules a task on {@link #instance}.
* @see #scheduleTask(Task, float) */
static public Task schedule (Task task, float delaySeconds) {
return instance().scheduleTask(task, delaySeconds);
}
/** Schedules a task on {@link #instance}.
* @see #scheduleTask(Task, float, float) */
static public Task schedule (Task task, float delaySeconds, float intervalSeconds) {
return instance().scheduleTask(task, delaySeconds, intervalSeconds);
}
/** Schedules a task on {@link #instance}.
* @see #scheduleTask(Task, float, float, int) */
static public Task schedule (Task task, float delaySeconds, float intervalSeconds, int repeatCount) {
return instance().scheduleTask(task, delaySeconds, intervalSeconds, repeatCount);
}
/** Runnable with a cancel method.
* @see Timer
* @author Nathan Sweet */
static abstract public class Task implements Runnable {
long executeTimeMillis;
long intervalMillis;
int repeatCount = CANCELLED;
/** If this is the last time the task will be ran or the task is first cancelled, it may be scheduled again in this method. */
abstract public void run ();
/** Cancels the task. It will not be executed until it is scheduled again. This method can be called at any time. */
public void cancel () {
executeTimeMillis = 0;
repeatCount = CANCELLED;
}
/** Returns true if this task is scheduled to be executed in the future by a timer. */
public boolean isScheduled () {
return repeatCount != CANCELLED;
}
/** Returns the time when this task will be executed in milliseconds */
public long getExecuteTimeMillis () {
return executeTimeMillis;
}
}
/** Manages the single timer thread. Stops thread on libgdx application pause and dispose, starts thread on resume.
* @author Nathan Sweet */
static class TimerThread implements Runnable, LifecycleListener {
Application app;
private long pauseMillis;
public TimerThread () {
Gdx.app.addLifecycleListener(this);
resume();
}
public void run () {
while (true) {
synchronized (instances) {
if (app != Gdx.app) return;
long timeMillis = System.nanoTime() / 1000000;
long waitMillis = 5000;
for (int i = 0, n = instances.size; i < n; i++) {
try {
waitMillis = instances.get(i).update(timeMillis, waitMillis);
} catch (Throwable ex) {
throw new GdxRuntimeException("Task failed: " + instances.get(i).getClass().getName(), ex);
}
}
if (app != Gdx.app) return;
try {
if (waitMillis > 0) instances.wait(waitMillis);
} catch (InterruptedException ignored) {
}
}
}
}
public void resume () {
long delayMillis = System.nanoTime() / 1000000 - pauseMillis;
synchronized (instances) {
for (int i = 0, n = instances.size; i < n; i++) {
instances.get(i).delay(delayMillis);
}
}
app = Gdx.app;
Thread t = new Thread(this, "Timer");
t.setDaemon(true);
t.start();
thread = this;
}
public void pause () {
pauseMillis = System.nanoTime() / 1000000;
synchronized (instances) {
app = null;
wake();
}
thread = null;
}
public void dispose () {
pause();
Gdx.app.removeLifecycleListener(this);
instances.clear();
instance = null;
}
}
}
这是针对最新版本的1.7.2 timer.java libgdx:
package com.badlogic.gdx.utils;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.LifecycleListener;
/** Executes tasks in the future on the main loop thread.
* @author Nathan Sweet */
public class Timer {
static final Array<Timer> instances = new Array(1);
static TimerThread thread;
static private final int CANCELLED = -1;
static private final int FOREVER = -2;
/** Timer instance for general application wide usage. Static methods on {@link Timer} make convenient use of this instance. */
static Timer instance = new Timer();
static public Timer instance () {
if (instance == null) {
instance = new Timer();
}
return instance;
}
private final Array<Task> tasks = new Array(false, 8);
public Timer () {
start();
}
/** Schedules a task to occur once as soon as possible, but not sooner than the start of the next frame. */
public Task postTask (Task task) {
return scheduleTask(task, 0, 0, 0);
}
/** Schedules a task to occur once after the specified delay. */
public Task scheduleTask (Task task, float delaySeconds) {
return scheduleTask(task, delaySeconds, 0, 0);
}
/** Schedules a task to occur once after the specified delay and then repeatedly at the specified interval until cancelled. */
public Task scheduleTask (Task task, float delaySeconds, float intervalSeconds) {
return scheduleTask(task, delaySeconds, intervalSeconds, FOREVER);
}
/** Schedules a task to occur once after the specified delay and then a number of additional times at the specified interval. */
public Task scheduleTask (Task task, float delaySeconds, float intervalSeconds, int repeatCount) {
if (task.repeatCount != CANCELLED) throw new IllegalArgumentException("The same task may not be scheduled twice.");
task.executeTimeMillis = System.nanoTime() / 1000000 + (long)(delaySeconds * 1000);
task.intervalMillis = (long)(intervalSeconds * 1000);
task.repeatCount = repeatCount;
synchronized (tasks) {
tasks.add(task);
}
wake();
return task;
}
/** Stops the timer, tasks will not be executed and time that passes will not be applied to the task delays. */
public void stop () {
synchronized (instances) {
instances.removeValue(this, true);
}
}
/** Starts the timer if it was stopped. */
public void start () {
synchronized (instances) {
if (instances.contains(this, true)) return;
instances.add(this);
if (thread == null) thread = new TimerThread();
wake();
}
}
/** Cancels all tasks. */
public void clear () {
synchronized (tasks) {
for (int i = 0, n = tasks.size; i < n; i++)
tasks.get(i).cancel();
tasks.clear();
}
}
long update (long timeMillis, long waitMillis) {
synchronized (tasks) {
for (int i = 0, n = tasks.size; i < n; i++) {
Task task = tasks.get(i);
if (task.executeTimeMillis > timeMillis) {
waitMillis = Math.min(waitMillis, task.executeTimeMillis - timeMillis);
continue;
}
if (task.repeatCount != CANCELLED) {
if (task.repeatCount == 0) {
// Set cancelled before run so it may be rescheduled in run.
task.repeatCount = CANCELLED;
}
Gdx.app.postRunnable(task);
}
if (task.repeatCount == CANCELLED) {
tasks.removeIndex(i);
i--;
n--;
} else {
task.executeTimeMillis = timeMillis + task.intervalMillis;
waitMillis = Math.min(waitMillis, task.intervalMillis);
if (task.repeatCount > 0) task.repeatCount--;
}
}
}
return waitMillis;
}
/** Adds the specified delay to all tasks. */
public void delay (long delayMillis) {
synchronized (tasks) {
for (int i = 0, n = tasks.size; i < n; i++) {
Task task = tasks.get(i);
task.executeTimeMillis += delayMillis;
}
}
}
static void wake () {
synchronized (instances) {
instances.notifyAll();
}
}
/** Schedules a task on {@link #instance}.
* @see #postTask(Task) */
static public Task post (Task task) {
return instance().postTask(task);
}
/** Schedules a task on {@link #instance}.
* @see #scheduleTask(Task, float) */
static public Task schedule (Task task, float delaySeconds) {
return instance().scheduleTask(task, delaySeconds);
}
/** Schedules a task on {@link #instance}.
* @see #scheduleTask(Task, float, float) */
static public Task schedule (Task task, float delaySeconds, float intervalSeconds) {
return instance().scheduleTask(task, delaySeconds, intervalSeconds);
}
/** Schedules a task on {@link #instance}.
* @see #scheduleTask(Task, float, float, int) */
static public Task schedule (Task task, float delaySeconds, float intervalSeconds, int repeatCount) {
return instance().scheduleTask(task, delaySeconds, intervalSeconds, repeatCount);
}
/** Runnable with a cancel method.
* @see Timer
* @author Nathan Sweet */
static abstract public class Task implements Runnable {
long executeTimeMillis;
long intervalMillis;
int repeatCount = CANCELLED;
/** If this is the last time the task will be ran or the task is first cancelled, it may be scheduled again in this method. */
abstract public void run ();
/** Cancels the task. It will not be executed until it is scheduled again. This method can be called at any time. */
public void cancel () {
executeTimeMillis = 0;
repeatCount = CANCELLED;
}
/** Returns true if this task is scheduled to be executed in the future by a timer. */
public boolean isScheduled () {
return repeatCount != CANCELLED;
}
/** Returns the time when this task will be executed in milliseconds */
public long getExecuteTimeMillis () {
return executeTimeMillis;
}
}
/** Manages the single timer thread. Stops thread on libgdx application pause and dispose, starts thread on resume.
* @author Nathan Sweet */
static class TimerThread implements Runnable, LifecycleListener {
Application app;
private long pauseMillis;
public TimerThread () {
Gdx.app.addLifecycleListener(this);
resume();
}
public void run () {
while (true) {
synchronized (instances) {
if (app != Gdx.app) return;
long timeMillis = System.nanoTime() / 1000000;
long waitMillis = 5000;
for (int i = 0, n = instances.size; i < n; i++) {
try {
waitMillis = instances.get(i).update(timeMillis, waitMillis);
} catch (Throwable ex) {
throw new GdxRuntimeException("Task failed: " + instances.get(i).getClass().getName(), ex);
}
}
if (app != Gdx.app) return;
try {
if (waitMillis > 0) instances.wait(waitMillis);
} catch (InterruptedException ignored) {
}
}
}
}
public void resume () {
long delayMillis = System.nanoTime() / 1000000 - pauseMillis;
synchronized (instances) {
for (int i = 0, n = instances.size; i < n; i++) {
instances.get(i).delay(delayMillis);
}
}
app = Gdx.app;
Thread t = new Thread(this, "Timer");
t.setDaemon(true);
t.start();
thread = this;
}
public void pause () {
pauseMillis = System.nanoTime() / 1000000;
synchronized (instances) {
app = null;
wake();
}
thread = null;
}
public void dispose () {
pause();
Gdx.app.removeLifecycleListener(this);
instances.clear();
instance = null;
}
}
}