libgdx Timer countdown implmentation - java

I want to create efficienty timer in LibGDX framework, that will count the time left for my character. The doSmth() method should be called as many times as some flag is set to true. I know that the third parametr of Timer is that, how many times should it trigger. For now one Im calling the method recursive, but I dont think it is the efficient way.
public void updateTimer(){
new Timer().scheduleTask(new Timer.Task() {
#Override
public void run() {
doSmth();
updateTimer();
}
},1);
}

It would be more accurate to use a repeat count. Your method will introduce a bit of error each time the task is run, because the task is run on the GL thread, so it will occur just slightly after one second, but you are repeating it one second after that. So with each repeat you are slightly further behind.
private Timer.Task myTimerTask = new Timer.Task() {
#Override
public void run() {
doSmth();
}
};
public void startTimer(){
Timer.schedule(myTimerTask, 1f, 1f);
}
And when you need to stop it:
myTimerTask.cancel();

The com.badlogic.gdx.utils.Timer executes tasks in the future on the main loop thread,even if your game is in a pause screen, a menu or in another state, you can simply control time in the render method by adding delta time.
private float timeSeconds = 0f;
private float period = 1f;
public void render() {
//Execute handleEvent each 1 second
timeSeconds +=Gdx.graphics.getRawDeltaTime();
if(timeSeconds > period){
timeSeconds-=period;
handleEvent();
}
[...]
}
public void handleEvent() {
[...]
}
To keep organized i personally have an array on my main game class that holds all my timed events and process everything on the render cycle. In your case you can put some control variables as you wish.
my implementation example:
// MainGame.java
private ObjectMap<TimedEventEnum, TimedEvent> hshTimedEvent;
public void render(){
executeTimedEvents();
}
private void executeTimedEvents() {
for (ObjectMap.Entry<TimedEventEnum, TimedEvent> entry : hshTimedEvent) {
TimedEvent event = entry.value;
event.process();
}
}
public void killEvent(TimedEventEnum event) {
hshTimedEvent.remove(event);
}
// TimedEventEnum.java
public enum TimedEventEnum {
COUNT_MONEY,
CHECK_FOR_ACHIEVS,
ANOTHER_EVENT_EXAMPLE
}
//CountMoneyTimedEvent.java
public class CountMoneyTimedEvent extends Timer implements TimedEvent {
public CountMoneyTimedEvent() {
super();
init(this, 4f, false);
}
#Override
public void execute() {
//execute logic here
}
#Override
public void reset() {
this.timesFired = 0L;
}
}
//Timer.java
public abstract class Timer {
private Float deltaCount;
private Float timeToEvent;
private Boolean isRepeatable;
protected Long timesFired;
private TimedEvent event;
Timer() {
}
public void init(TimedEvent event, Float eventTime, Boolean isRepeatable) {
this.deltaCount = 0f;
this.timeToEvent = eventTime;
this.isRepeatable = isRepeatable;
this.timesFired = 0L;
this.event = event;
}
public void process() {
if (isEventTime()) {
event.execute();
}
}
private Boolean isEventTime() {
if (event != null && (isRepeatable || timesFired == 0)) {
deltaCount += Gdx.graphics.getRawDeltaTime();
if (deltaCount > timeToEvent) {
deltaCount -= timeToEvent;
timesFired++;
return true;
}
}
return false;
}
protected void executeNextEvent() {
deltaCount = timeToEvent;
}
}
// TimedEvent.java
public interface TimedEvent {
void execute();
void reset();
void process();
}

Related

Two overloaded methods, same actions, causing duplicate code

I have two methods that take either a Circle or a Scene and make the background flash red - green - blue by changing the fill value every N ms.
The two methods:
private void makeRGB(Circle c) {
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(c.getFill() == Color.RED) {
c.setFill(Color.GREEN);
} else if (c.getFill() == Color.GREEN) {
c.setFill(Color.BLUE);
} else {
c.setFill(Color.RED);
}
}
},0, RGB_CHANGE_PERIOD);
}
private void makeRGB(Scene s) {
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(s.getFill() == Color.RED) {
s.setFill(Color.GREEN);
} else if (s.getFill() == Color.GREEN) {
s.setFill(Color.BLUE);
} else {
s.setFill(Color.RED);
}
}
},0, RGB_CHANGE_PERIOD);
}
Obviously these are very similar, however as Circle and Scene aren't in the same inheritance tree I can't use the approach of calling a superclass of them both containing the .setFill() / .getFill() methods.
How would I go about removing code duplication here?
In general, you remove duplicate code by factoring the common code into a function/method/class and parameterizing the parts that vary. In this case, what varies is the way you retrieve the current fill, and the way you set the new fill. The java.util.function package provides the appropriate types for parametrizing these, so you can do:
private void makeRGB(Circle c) {
makeRGB(c::getFill, c:setFill);
}
private void makeRGB(Scene s) {
makeRGB(s::getFill, s:setFill);
}
private void makeRGB(Supplier<Paint> currentFill, Consumer<Paint> updater) {
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if(currentFill.get() == Color.RED) {
updater.accept(Color.GREEN);
} else if (currentFill.get() == Color.GREEN) {
updater.accept(Color.BLUE);
} else {
updater.accept(Color.RED);
}
}
},0, RGB_CHANGE_PERIOD);
}
Note, though, that you should not change the UI from a background thread. You should really do
private void makeRGB(Supplier<Paint> currentFill, Consumer<Paint> updater) {
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
Platform.runLater(() -> {
if(currentFill.get() == Color.RED) {
updater.accept(Color.GREEN);
} else if (currentFill.get() == Color.GREEN) {
updater.accept(Color.BLUE);
} else {
updater.accept(Color.RED);
}
}
}
},0, RGB_CHANGE_PERIOD);
}
or, (better), use a Timeline to do things on a periodic basis.
As noted in the comments, you can also provide a Map that maps each color to the color that comes after it. Combining all this gives:
private final Map<Paint, Paint> fills = new HashMap<>();
// ...
fills.put(Color.RED, Color.GREEN);
fills.put(Color.GREEN, Color.BLUE);
fills.put(Color.BLUE, Color.RED);
// ...
private void makeRGB(Circle c) {
makeRGB(c::getFill, c:setFill);
}
private void makeRGB(Scene s) {
makeRGB(s::getFill, s:setFill);
}
private void makeRGB(Supplier<Paint> currentFill, Consumer<Paint> updater) {
Timeline timeline = new Timeline(Duration.millis(RGB_CHANGE_PERIOD),
e-> updater.accept(fills.get(currentFill.get())));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
}

Android/Java: Is there a way to store a method?

So I have a loop class that is basically as follows:
public class Loop extends Thread {
private boolean running;
public Loop() {
running = false;
}
public void run() {
while(running) {
//Do stuff
}
}
public void setRunning(boolean b) {
running = b;
}
}
What I'd like to know is whether or not it is possible to store methods. For example the class could look like this instead.
public class Loop extends Thread {
private boolean running;
private Method method;
public Loop() {
running = false;
}
public void run() {
while(running) {
if(method != null)
method.callMethod();
}
}
public void setRunning(boolean b) {
running = b;
}
public void setMethod(Method m) {
method = m;
}
}
Is anything like this possible?
I assume you want this functionality in Java 6, so you can use interface and anonymous class.
Interface code:
public interface Listener {
void callMethod();
}
Your Thread:
public class Loop extends Thread {
private boolean running;
private Listener listener;
public Loop() {
running = false;
}
public void run() {
while(running) {
if(listener != null)
listener.callMethod();
}
}
public void setRunning(boolean b) {
running = b;
}
public void setListener(Listener listener) {
this.listener = listener;
}
}
Set Listener:
Loop loop = new Loop();
loop.setListener(new Listener() {
#Override
public void callMethod() {
// Do stuff
}
});
This will work for your usecase. If you want to save methods and pass methods as data, you have to either use Java 8 (not supported on all Android API levels) or Kotlin.

Changing Rendering Screen on separate thread after an HTTP request

My goal is to change the screen of a user when the game can't reach the backend anymore. My code executes as expected except the screen never changes. Here's the initial call:
timer.testTimeToServer(api, game);
Here's the timer object's class. I put (my url) in place of the actual IP address of my backend:
public class CustomTimer {
private static final float timeToDrop = 2000;
private float time = 0;
private StopWatch watch = new StopWatch();
public void testTimeToServer(ApiCall api,final proofOfConcept game){
watch.start();
api.httpGetWithCallback("(my url)/api/v1/character", new CallBack(){
#Override
public void callback(String resp){
System.out.println("Server Responded");
time = watch.getTime();
watch.stop();
watch.reset();
if(time > timeToDrop){
game.setScreen(new GameOverScreen(game, false));
System.out.println("Should have switched screen")
}
}
});
}
}
Here's the httpGetWithCallback method in the api object:
public void httpGetWithCallback (final String URL, final CallBack callback){
Thread th = new Thread(new Runnable(){
#Override
public void run() {
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
Net.HttpRequest httpRequest = new Net.HttpRequest(Net.HttpMethods.GET);
httpRequest.setUrl(URL);
httpRequest.setHeader("Content-Type", "application/json");
httpRequest.setTimeOut(timeoutTimeInMilli);
Gdx.net.sendHttpRequest(httpRequest, new Net.HttpResponseListener() {
#Override
public void handleHttpResponse(Net.HttpResponse httpResponse) {
String successValue = httpResponse.getResultAsString();
if (successValue.contains("\"total_count\": 0"))//wrong credentials
{
callback.callback("EMPTY");
} else//there was a match yo! should probably have a unique conststraint on username. too hard eff it
{
callback.callback(successValue);
}
}
#Override
public void failed(Throwable t) {
callback.callback("FAILED");
}
#Override
public void cancelled() {
callback.callback("CANCELLED");
}
});
}
}
);
}
});
th.start();
threads.add(th);
}
I'm stumped because the code prints out "Should have switched screens" so it's acting like expected except for the fact that the game is frozen up and the screen switch never actually happens.
The Lazy Way:
on your main game class:
public static ProofOfConcept game;
and your method
public void testTimeToServer(ApiCall api){
watch.start();
api.httpGetWithCallback("(my url)/api/v1/character", new CallBack(){
#Override
public void callback(String resp){
System.out.println("Server Responded");
time = watch.getTime();
watch.stop();
watch.reset();
if(time > timeToDrop){
Main.game.setScreen(new GameOverScreen(false));
System.out.println("Should have switched screen")
}
}
});
}
}
The Right Way
You can create a callback inside your ProofOfConcept class that every frame on the render method checks the result and change the screen.

Libgdx - Use void as an agrument in a function

i'm trying to make a void with a Void as an argument in libgdx,
how do i make it work?
this is what i have:
public class ReleaseDetector{
boolean Touched = false;
//
// --- Simple void for touch release detection, when looped. ---
// --- and the argument void, or how i imagine it..
//
public void ReleaseListener(void MyArgumentVoid)//<---The argument void
{
if (Gdx.input.isTouched()){
Touched = true;
}
if (!Gdx.input.isTouched() && Touched){
MyArgumentVoid();<----------// Call for a void from the Argument.
Touched = false;
}
}
}
Usage in MyGdxGame class, or how i imagine it:
public class MyGdxGame extends ApplicationAdapter {
int Counter = 0;
ReleaseDetector RD = new ReleaseDetector();
public void AddCounter(){// just a simple void.
Counter++;
}
#Override
public void render() { // Render Loop void.
RD.ReleaseListener(AddCounter);// how i imagine it's usage.
}
}
now, how am i making it real? i hope there is a simple way..
It seems that you need a callback method which takes no argument and returns void.
public class ReleaseDetector {
boolean touched = false;
public void releaseListener(MyGdxGame game) { // Argument
if (Gdx.input.isTouched()) {
touched = true;
}
if (!Gdx.input.isTouched() && touched){
game.addCounter(); // Callback
touched = false;
}
}
}
public class MyGdxGame extends ApplicationAdapter {
int counter = 0;
ReleaseDetector detector = new ReleaseDetector();
public void addCounter() {
counter++;
}
#Override
public void render() { // Render Loop.
detector.releaseListener(this);
}
}
Hope this helps.

How can I make Java add to a private int mouseClicks every second?

public class Blank extends WindowController
{
private int mouseClicks;
public void onMousePress(Location point)
{
mouseClicks++;
}
}
My goal is for if mouseClicks to increment once every second, while while only having to click once to start it.
Here is the best solution I can get.
public class Blank extends WindowController
{
private final AtomicInteger mouseClicks = new AtomicInteger();
private boolean hasStarted = false;
public void onMousePress(Location point)
{
if(!hasStarted){
hasStarted = true;
Thread t = new Thread(){
public void run(){
while(true){
mouseClicks.incrementAndGet(); //adds one to integer
Thread.sleep(1000); //surround with try and catch
}
}
};
t.start();
}
}
}
Look into using Thread.sleep(1000); to pause execution for one second.
http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
You could test the time passed since the last click.
long lLastClickTime = Long.MIN_VALUE;
public void onMousePress(Location point) {
final long lCurrentTime = System.currentTimeMillis();
if(lCurrentTime - lClickLastTime >= 1000) {
mouseClicks++;
lLastClickTime = lCurrentTime;
}
}

Categories