Can't set delay in libgdx - java

I want to remove an index from an array after some time, I want it to fall, then delete it.
private final int gravity = 4;
private long lifeTime=0;
private long delay = 20000L;
public void objGravity() {
while (array.get(array.size - 1).y > 0)
array.get(array.size - 1).y -= gravity;
lifeTime = System.currentTimeMillis();
lifeTime += Gdx.graphics.getDeltaTime();
if (lifeTime > delay) {
array.removeIndex(array.size - 1);
lifeTime = 0;
}
}
The object gets removed from array immediately as if there's no delay whatsoever, so it doesn't appear to be falling down on the screen.
Update
I removed time and so on. I added a counter to count how many objects need to be removed and then I do a loop that removes array.size-1 as long as counter>0.
Not sure if it's the best approach, seems like a hack but I don't want to do threads on old mobile phones. If you have a better idea please share

Don't fire threads inside the render method, it's not safe, can cause thread leaks, a lot of other problems and will be harder to maintain your code, to handle time use a variable adding delta time every time render is called, when this variable is superior a 1.0f means that one second has passed, your code would be something like this:
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.

Related

How to manage time in non-linear idle game?

I'm new at Java and I'm trying to develop a non-linear idle game for Android.
I'm a bit stuck on how to manage the "time" in my game.
In linear idle game, I would have used System.currentTimeMillis() to update my model during game (application opened), and at game restart (as model is linear, simple formula to update model based on elapse time is sufficient).
But in non-linear idle game, my model must be time discrete, and a loop must be done at game restart. Then, at game restart, my models can't use System.currentTimeMillis().
My idea was to use a specific timer to calculate model when game is opened. But with my current knowledge, I don't know how to access a given timer from all my classes.
For example, in a class representing a Ship there is a method to travel. For this example, model is linear:
public class Ship {
double travelStartTime, travelEndTime;
double positionX, positionY;
double maxSpeed = 10;
public Ship(double buildPostionX, double buildPositionY) {
positionX = buildPositionY;
positionY = buildPostionX;
maxSpeed = 10;
travelStartTime = 0;
travelEndTime = 0;
}
public void startTravel(double destX, double destY){
travelStartTime = System.currentTimeMillis();
travelEndTime = System.currentTimeMillis() + travelTime(destX, destY);
}
public double travelTime(double destinationX, double destinationY) {
double currentX = this.getPositionX();
double currentY = this.getPositionY();
//calculate distance in km
double distance = Math.pow(Math.pow(currentX-destinationX, 2) + Math.pow(currentY-destinationY, 2), 0.5);
double time = distance/maxSpeed; //time in seconds
return time;
}
My questions are:
1. I would like to replace System.currentTimeMillis() by my own timer (started each time application starts), but how can I do that ? Knowing that any class of my model need to access the same timer ? Or is there any other to manage this issue ?
2. At the end of the travel, I would like to send a new "event", for example to display a new pop-up (or alertDialog) or to start a metho. How can I do that ?
Hope I was clear enough in my explanations.
Thank you in advance for any answer.
You could add a currentTime field on your main game class and pass it down to entity instances on each update. You can also use a static long field, but this is discouraged. Example:
class MyGame {
private long currentTime = 0;
private Ship myShip = /* TODO */;
// Called every x ms by an ExecutorService
public void update() {
// Update currentTime however you want
// e.g. currentTime += 1000
myShip.update(currentTime);
}
}
class Ship {
private int x;
private int y;
public void update(long currentTime) {
// TODO e.g. perform lerp with previous position
}
}
This is known as the Update Method pattern.

Mp3 player with timer in java [fast forward]

I'm making fast forward button in my Mp3 player. I wrote already code for this, but have problem how to implement timer to jump 5% forward? I mean when I press button timer should jump 5% forward of total long song. This is my fastForward method.
public void FastForward(){
try {
//songTotalLength = fis.available();
fis.skip((long) ((songTotalLength * 0.05)));
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the button method:
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
bar+=5;
}
And this one is for timer:
private void setTime(float t) {
int mili = (int) (t / 1000);
int sec = (mili / 1000) % 60;
int min = (mili / 1000) / 60;
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
end.set(Calendar.MINUTE, 0 + min);
end.set(Calendar.SECOND, 0 + sec);
timer = new javax.swing.Timer(1000, new TimerListener());
percent = (float)100/(min*60+sec);
}
You're already redundantly tracking progress in two variables fis and bar. For the sake of good design, use one of those to determine elapsed time rather than using yet another variable for the same purpose.
but have problem how to implement timer to jump 5% forward?
You seem to have mistaken the purpose of a Timer. According to the Timer class documentation, it:
Fires one or more ActionEvents at specified intervals.
So the timer is not meant to keep track of how much time has elapsed. It will simply invoke the actionPerformed(ActionEvent) method of your TimerListener once per second (every 1000 milliseconds) as you have it configured.
For a more complete answer, please post the code for your TimerListener class.
Notes
It seems that your setTime(float) method is meant to be called repeatedly, so this method should not be initializing the timer variable. Rather initialize the timer once and leave it alone to do its job.
I'm assuming you intended the supplied float parameter t to represent microseconds.
The float data type has only 7 digits of precision. This could be fine since you're interested only in minutes and seconds, otherwise float is only good for up to about four months of seconds before losing accuracy.
It seems like you wanted your button click handler to do this (increment bar sooner):
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
bar+=5; // increment bar before checking complete, and before setting progress
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
}

Updating and rendering for a 2D game in Java

So, I am working on making a 2D game in Java, and I really don't have too much experience with Java. I currently use a very simple loop using a swing timer running every 10ms or so that looks something like:
public void actionPerformed(ActionEvent e) {
update();
repaint();
}
However, I need something more practical for obvious reasons. These reasons include the fact that more lag means less FPS AND slower movement/other updating.
I found the following code in a tutorial for a 3D Java game here. It would begin running when the program starts, and I understand enough to know it would work. However, I do not fully understand it: (tick() is the updater, render() renders the screen)
long currenttime;
long previoustime = System.nanoTime();
long passedtime;
int frames = 0;
double unprocessedseconds = 0;
double secondspertick = 1 / 60.0;
int tickcount = 0;
boolean ticked = false;
while (gameIsRunning) {
currenttime = System.nanoTime();
passedtime = currenttime - previoustime;
previoustime = currenttime;
unprocessedseconds += passedtime / 1000000000.0;
while (unprocessedseconds > secondspertick) {
tick();
unprocessedseconds -= secondspertick;
ticked = true;
tickcount++;
System.out.println(tickcount);
if (tickcount % 60 == 0) {
System.out.println(frames + " FPS");
previoustime += 1000;
frames = 0;
}
}
if (ticked) {
render();
frames++;
}
render();
frames++;
}
This code was not explained in the tutorial I found it in. Could someone please break this down and explain it?
I have also looked here for ideas, and the final piece of code on that page with a render thread and an update thread makes a lot of sense to me.
Which method should I use? One of the above, or something totally different? Also, you can probably tell that this is my first question here on stackoverflow.
Thanks in advance,
Josh
tick() is probably updating the game object's physical properties (position, velocity, etc.) tick() is called multiple times each update because some simulations can't handle too large a timestep without becoming unstable.
There's a popular article online which explains why this is the case, and why using a fixed timestep is the proper procedure. Check it out.
Each update the game is advanced in 1/60th second (so 60 frames a second) increments. This is repeated until there's less than 1/60th a second remaining in the aggregate. Aggregate is just a fancy word for sum.
Then a snapshot of the game's current state is rendered to the screen.
I won't get too deep into it, but really this code should be inerpolating each object's position by the remaining time in the aggregate during render().
long currenttime;
long previoustime = System.nanoTime();
long passedtime;
int frames = 0;
//this is an aggregate, games usually step in fixed units of time.
//this is usually because physics simulations can't handle too large of time steps.
double unprocessedseconds = 0;
double secondspertick = 1 / 60.0;
int tickcount = 0;
boolean ticked = false;
while (gameIsRunning) {
//get elapsed nano seconds from the epoch (january 1st, 1970)
currenttime = System.nanoTime();
//take difference of current time in nanos and previous time in nanos
passedtime = currenttime - previoustime;
previoustime = currenttime;
//divide to get the elapsed time in seconds.
unprocessedseconds += passedtime / 1000000000.0;
while (unprocessedseconds > secondspertick) {
tick();
unprocessedseconds -= secondspertick;
ticked = true;
tickcount++;
System.out.println(tickcount);
if (tickcount % 60 == 0) {
System.out.println(frames + " FPS");
previoustime += 1000;
frames = 0;
}
}
if (ticked) {
render();
frames++;
}
render();
frames++;
}
Good luck Josh.
Edit:
I have no experience with games using one thread for updates, and one for rendering. I can't give advice on those for that reason. If you have little or no experience with multithreading I'd avoid it as only complex games are likely to require this approach, and multithreading will add a multitude of issues you probably don't want to deal with.
Multithreaded game engines will consume more memory between rendering and updating than a single threaded game, or will wind up being depend on one another anyway. This is because the two threads can't manipulate the same data simultaneously. Therefor the only way for the two threads to operate is with synchronization on those data structures, or by the update thread suppling the render thread with immutable data to render.
Writing a multithreaded game engine would be a good introduction to threading. It could teach you quite a lot. Depends on what you want to get out of this.
If you are making a 2D game I feel even more confident that you will not need one thread for updating and one for rendering.
If you really want to pursue this, here's the approach I'd take.
You don't need more than a while loop to control rendering.
The way I do my engines is just as explained before, I multi-thread. Basically, if you split the job of processing and drawing the game into two segments it becomes quicker at the expense of more resources in use. I do a little something like this:
public class Engine implements Runnable {
//Sets classes
Engine tick = new Engine(true);
Engine render = new Engine(false);
Thread tickThread = new Thread(tick);
Thread renderThread = new Thread(render);
boolean job;
boolean isRunning = false;
long sleepTime = 5L;
public Engine(boolean job) {
//Sets what the thread does
this.job = job;
}
public static void startEngine() {
//Starts Engine
isRunning = true;
tickThread.start();
renderThread.start();
}
public void tick() {
//Process things
}
public void render() {
//Draw things
}
public void run() {
//Do engine base things
while(isRunning) {
if(job) {
tick();
} else {
render();
}
Thread.sleep(sleepTime);
}
}
}
This is by no means advanced. This is just an example of what a simple multi-thread game engine would be like. Honestly, I used this exact code when I was starting off making games. This could be used but some adjustments should be made depending on what you use it for. What I mean is that lets say you have an object that's moving and its being rendered at the same time. If the objects position is 50 and increasing and the render method is drawing it then the object could go to 51 then 52 before being rendered again. Normally, the processing is faster than the drawing. Another example: Lets say you have an ArrayList and are constantly removing and adding objects to it. Sometimes you can remove an object just as the render method is about to draw it and cause a null pointer exception because it's trying to draw something that doesn't exist. (I used "if(object.get(i) != null)" and worked around it that way)
I hope this helped at least a little (two years later, lol) and helped you get a basis of what multi-threading is like (if you didn't already).

read array in certain time range

How can I read an array in java in a certain time? Lets say in 1000 milliseconds.
for example:
float e[]=new float [512];
float step = 1000.0 / e.length; // I guess we need something like that?
for(int i=0; i<e.length; i++){
}
You'd need a Timer. Take a look at its methods... There's a number of them, but they can be divided into two categories: those that schedule at a fixed delay (the schedule(... methods) and those that schedule at a fixed rate (the scheduleAtFixedRate(... methods).
A fixed delay is what you want if you require "smoothness". That means, the time in between executions of the task is mostly constant. This would be the sort of thing you'd require for an animation in a game, where it's okay if one execution might lag behind a bit as long as the average delay is around your target time.
A fixed rate is what you want if you require the task's executions to amount to a total time. In other words, the average time over all executions must be constant. If some executions are delayed, multiple ones can then be run afterwards to "catch up". This is different from fixed delay where a task won't be run sooner just because one might have "missed" its cue.
I'd reckon fixed rate is what you're after. So you'd need to create a new Timer first. Then you'd need to call method scheduleAtFixedRate(TimerTask task, long delay, long period). That second argument can be 0 if you wish the timer to start immediately. The third argument should be the time in between task runs. In your case, if you want the total time to be 1000 milliseconds, it'd be 1000/array size. Not array size/1000 as you did.
That leaves us with the first argument: a TimerTask. Notice that this is an abstract class, which requires only the run() method to be implemented. So you'll need to make a subclass and implement that method. Since you're operating over an array, you'll need to supply that array to your implementation, via a constructor. You could then keep an index of which element was last processed and increment that each time run() is called. Basically, you're replacing the for loop by a run() method with a counter. Obviously, you should no longer do anything if the counter has reached the last element. In that case, you can set some (boolean) flag in your TimerTask implementation that indicates the last element was processed.
After creating your TimerTask and scheduling it on a Timer, you'll need to wait for the TimerTask's flag to be set, indicating it has done its work. Then you can call cancel() on the Timer to stop it. Otherwise it's gonna keep calling useless run() methods on the task.
Do keep the following in mind: if the work done in the run() method typically takes longer than the interval between two executions, which in your case would be around 2 milliseconds, this isn't gonna work very well. It only makes sense to do this if the for loop would normally take less than 1 second to complete. Preferably much less.
EDIT: oh, also won't work well if the array size gets too close to the time limit. If you want 1000 milliseconds and you have 2000 array elements, you'll end up passing in 0 for the period argument due to rounding. In that case you might as well run the for loop.
EDIT 2: ah why not...
import java.util.Random;
import java.util.Timer;
public class LoopTest {
private final static long desiredTime = 1000;
public static void main(String[] args) {
final float[] input = new float[512];
final Random rand = new Random();
for(int i = 0; i < input.length; ++i) {
input[i] = rand.nextFloat();
}
final Timer timer = new Timer();
final LoopTask task = new LoopTask(input);
double interval = ((double)desiredTime/((double)input.length));
long period = (long)Math.ceil(interval);
final long t1 = System.currentTimeMillis();
timer.scheduleAtFixedRate(task, 0, period);
while(!task.isDone()) {
try {
Thread.sleep(50);
} catch(final InterruptedException i) {
//Meh
}
}
final long t2 = System.currentTimeMillis();
timer.cancel();
System.out.println("Ended up taking " + (t2 - t1) + " ms");
}
}
import java.util.TimerTask;
public class LoopTask extends TimerTask {
private final float[] input;
private int index = 0;
private boolean done = false;
public LoopTask(final float[] input) {
this.input = input;
}
#Override
public void run() {
if(index == input.length) {
done = true;
} else {
//TODO: actual processing goes here
System.out.println("Element " + index + ": " + input[index]);
++index;
}
}
public boolean isDone() {
return done;
}
}
Change your step to be time per number (or total time divided by number of steps)
float step = 1000.0 / e.length;
Inside your for() loop:
try{
Thread.sleep(step);
}catch(InterruptedException e){
e.printStackTrace();
}

Attempting to create a stable game engine loop

I'm writing a fairly simple 2D multiplayer-over-network game. Right now, I find it nearly impossible for myself to create a stable loop. By stable I mean such kind of loop inside which certain calculations are done and which is repeated over strict periods of time (let's say, every 25 ms, that's what I'm fighting for right now). I haven't faced many severe hindrances this far except for this one.
In this game, several threads are running, both in server and client applications, assigned to various tasks. Let's take for example engine thread in my server application. In this thread, I try to create game loop using Thread.sleep, trying to take in account time taken by game calculations. Here's my loop, placed within run() method. Tick() function is payload of the loop. It simply contains ordered calls to other methods doing constant game updating.
long engFPS = 40;
long frameDur = 1000 / engFPS;
long lastFrameTime;
long nextFrame;
<...>
while(true)
{
lastFrameTime = System.currentTimeMillis();
nextFrame = lastFrameTime + frameDur;
Tick();
if(nextFrame - System.currentTimeMillis() > 0)
{
try
{
Thread.sleep(nextFrame - System.currentTimeMillis());
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
The major problem is that Thread.sleep just loves to betray your expectations about how much it will sleep. It can easily put thread to rest for much longer or much shorter time, especially on some machines with Windows XP (I've tested it myself, WinXP gives really nasty results compared to Win7 and other OS). I've poked around internets quite a lot, and result was disappointing. It seems to be fault of the thread scheduler of the OS we're running on, and its so-called granularity. As far as I understood, this scheduler constantly, over certain amount of time, checks demands of every thread in system, in particular, puts/awakes them from sleep. When re-checking time is low, like 1ms, things may seem smooth. Although, it is said that WinXP has granularity as high as 10 or 15 ms. I've also read that not only Java programmers, but those using other languages face this problem as well.
Knowing this, it seems almost impossible to make a stable, sturdy, reliable game engine. Nevertheless, they're everywhere.
I'm highly wondering by which means this problem can be fought or circumvented. Could someone more experienced give me a hint on this?
Don't rely on the OS or any timer mechanism to wake your thread or invoke some callback at a precise point in time or after a precise delay. It's just not going to happen.
The way to deal with this is instead of setting a sleep/callback/poll interval and then assuming that the interval is kept with a high degree of precision, keep track of the amount of time that has elapsed since the previous iteration and use that to determine what the current state should be. Pass this amount through to anything that updates state based upon the current "frame" (really you should design your engine in a way that the internal components don't know or care about anything as concrete as a frame; so that instead there is just state that moves fluidly through time, and when a new frame needs to be sent for rendering a snapshot of this state is used).
So for example, you might do:
long maxWorkingTimePerFrame = 1000 / FRAMES_PER_SECOND; //this is optional
lastStartTime = System.currentTimeMillis();
while(true)
{
long elapsedTime = System.currentTimeMillis() - lastStartTime;
lastStartTime = System.currentTimeMillis();
Tick(elapsedTime);
//enforcing a maximum framerate here is optional...you don't need to sleep the thread
long processingTimeForCurrentFrame = System.currentTimeMillis() - lastStartTime;
if(processingTimeForCurrentFrame < maxWorkingTimePerFrame)
{
try
{
Thread.sleep(maxWorkingTimePerFrame - processingTimeForCurrentFrame);
}
catch(Exception e)
{
System.err.println("TSEngine :: run :: " + e);
}
}
}
Also note that you can get greater timer granularity by using System.nanoTime() in place of System.currentTimeMillis().
You may getter better results with
LockSupport.parkNanos(long nanos)
altho it complicates the code a bit compared to sleep()
maybe this helps you.
its from david brackeen's bock developing games in java
and calculates average granularity to fake a more fluent framerate:
link
public class TimeSmoothie {
/**
How often to recalc the frame rate
*/
protected static final long FRAME_RATE_RECALC_PERIOD = 500;
/**
Don't allow the elapsed time between frames to be more than 100 ms
*/
protected static final long MAX_ELAPSED_TIME = 100;
/**
Take the average of the last few samples during the last 100ms
*/
protected static final long AVERAGE_PERIOD = 100;
protected static final int NUM_SAMPLES_BITS = 6; // 64 samples
protected static final int NUM_SAMPLES = 1 << NUM_SAMPLES_BITS;
protected static final int NUM_SAMPLES_MASK = NUM_SAMPLES - 1;
protected long[] samples;
protected int numSamples = 0;
protected int firstIndex = 0;
// for calculating frame rate
protected int numFrames = 0;
protected long startTime;
protected float frameRate;
public TimeSmoothie() {
samples = new long[NUM_SAMPLES];
}
/**
Adds the specified time sample and returns the average
of all the recorded time samples.
*/
public long getTime(long elapsedTime) {
addSample(elapsedTime);
return getAverage();
}
/**
Adds a time sample.
*/
public void addSample(long elapsedTime) {
numFrames++;
// cap the time
elapsedTime = Math.min(elapsedTime, MAX_ELAPSED_TIME);
// add the sample to the list
samples[(firstIndex + numSamples) & NUM_SAMPLES_MASK] =
elapsedTime;
if (numSamples == samples.length) {
firstIndex = (firstIndex + 1) & NUM_SAMPLES_MASK;
}
else {
numSamples++;
}
}
/**
Gets the average of the recorded time samples.
*/
public long getAverage() {
long sum = 0;
for (int i=numSamples-1; i>=0; i--) {
sum+=samples[(firstIndex + i) & NUM_SAMPLES_MASK];
// if the average period is already reached, go ahead and return
// the average.
if (sum >= AVERAGE_PERIOD) {
Math.round((double)sum / (numSamples-i));
}
}
return Math.round((double)sum / numSamples);
}
/**
Gets the frame rate (number of calls to getTime() or
addSample() in real time). The frame rate is recalculated
every 500ms.
*/
public float getFrameRate() {
long currTime = System.currentTimeMillis();
// calculate the frame rate every 500 milliseconds
if (currTime > startTime + FRAME_RATE_RECALC_PERIOD) {
frameRate = (float)numFrames * 1000 /
(currTime - startTime);
startTime = currTime;
numFrames = 0;
}
return frameRate;
}
}

Categories