My java game runs in slow motion on different computers - java

I am developing a game, and just wanted to test it on a different computer to check if the resolutions are ok and all that stuff but noticed one big problem, the game runs in slow motion for some reason... Not laggy, but slow motion..
My game loop is a temporary:
while(gameisRunnin){
doStuff();
Thread.sleep(1000/60);
But after the test, I've tried to check how much time does it take to do the doStuff(); code and I tested it like this:
while(gameisRunnin){
long startT = System.currentTimeMillis();
doStuff();
long stopT = System.currentTimeMillis();
System.out.println(stopT-startT);
Thread.sleep(1000/60);
The result it gives me is 0, on both computers, (On the one I am developing the game which runs in the perfect speed, and on the pc that it runs in slow motion..
Also I tested it with nano time, it gives me like 50000-80000 on both computes too (pretty much same result.
Seriously what's up? Could a superman save me?
UPDATE:
Ok so when I run the game on the other computer NOT on full screen, it's runs fine, but when it is on full screen, it's slowmotion
Update:
Looks like I am the superhero here, I've set the displaymode the refresh rate to unknown, I guess that was the whole problem...

You've to use something what is usually called "delta time". Basically it means, that you measure how long it takes to do one iteration of the game loop and then use this number for all the movements.
This is because of the different count of FPS on different computers. Instead of moving objects for just constant amount of pixels, you're defining speed and calculating the actual size of movement dynamically.
Short example:
public void gameLoop() {
long initialTime = System.nanoTime();
game.redraw();
game.update(System.nanoTime() - initialTime);
}
// inside the class Game
public void update(long deltaTime) {
someObject.moveToRight(deltaTime * speed);
}

The answer is that the refresh rate of the game wasn't supported by the monitor, changing the refresh-rate from 60 to DisplayMode.REFRESH_RATE_UNKNOWN fixes the slowmotion problem.

Read this article: click here
Also, as a side note, use System.nanoTime() because System.getTimeMillis() isn't as accurate.

Related

delay between two inputs java

I'm creating a little game as a project for my studies using Java with Libgdx.
The game is really simple: 2D, side view, controled with the arrowpad and everything is seen like in a grid divided in units (player is 1 unit tall, environment tides are 1 unit tall, ...).
The problem is that the movement of the character is quick (and it has to be) so it's really hard to move only 1 unit to the left or to the right.
I was wondering if it's possible to create a delay between two inputs from the keyboard because the movement part is in an "update" method so everytime I press a key it creates like 5 or 10 inputs.
I tried to handle it with java timers (like 0.2 or 0.3 sec) that happened everytime I press a key and unable the programm to listen to the keyboard until the timer is done. But I find it really dirty so i'm asking for your help to lead me on a more decent way to do this. Thanks.
You can easily implement a cooldown kind of thing, by comparing the last time of use by the current time.
double coolDownInMillis = 1200;
double lastTime = 0;
public void move() {
double now = System.currentTimeMillis();
if(lastTime - now > coolDownInMillis && pressingTheRightKey()){
//do what you want
lastTime = System.currentTimeMillis();
}
}
Or something like this.

Utilising the Android Camera Flash + Timing

I'm kinda new to the dev scene, I'm in the middle of an Android project.
I am trying to utilise the mobile phone camera flash. I'm trying to make it flash on and off in a repetitive motion. Below is a clip from my .java file.
public void clickGo(View view) {
Bundle newtempo = getIntent().getExtras();
int tempo = newtempo.getInt("tempoData");
int scaledTempo = 60000/tempo;
while (true) {
long futureTime1a = System.currentTimeMillis() + (100);
long futureTime1b = System.currentTimeMillis() + (scaledTempo - 100);
while (System.currentTimeMillis() < futureTime1a) {
setFlashlightOn();
}
while (System.currentTimeMillis() < futureTime1b) {
setFlashlightOff();
}
}
Let me explain what's going on...
So I've gained data from another activity then scaled it to a milleseconds value.
I've put the rest of the algorithm in a while(true) loop, just until I can get it working properly. I set two times, one with 100 milliseconds, and one with the scaled millesecond value MINUS the 100 milliseconds.
I then apply these two timings to turn the flash on then off.
In theory, this should work. I have data inputted from another activity which scales the number into milliseconds as shown. The concept does work, as lower numbers and higher numbers make the flash beat slower and quicker on my phone. However, the precision is my issue. When I play a click beat to the same time of the app, it's easy to tell that some flashes come in slower, or last longer.etc. I was wondering what this could possibly be? I've stripped down most of the code to a completely bare script (as I thought it could be a processing issue). It could also be the way I've implemented the time feature - if anyone else has a more efficient way, I would love to hear it!
As I said at the beginning, I'm relatively new to the dev scene, so I would appreciate it if you could answer with this in mind :)
Thank you very much!
The internal clock for computers is somewhat unreliable in quick successions like what you want. I would recommend using a timer to achieve what you want.

Is using "SwingUtilities.invokeLater()" inside a Java game loop a bad practice?

So, I'm creating a isometric game in JAVA; to put it simply, it has a map made of tiles, and when the user drag the mouse on the screen, the map moves. To give you guys an idea, it currently looks like this:
Before the actual prototype version, I built a small java application that had no "Game Loop" per se; the only thing updating the tile-map position was the event listeners for the mouse dragging, and it called the repaint() method after the movement update. It worked fine, and I could select Tiles and move the map without a problem.
Since then, I rebuild the prototype thinking in developing something more like a real game engine, with a Game States Manager and a real Game Loop; the Game Loop code looks like this:
init();
long start;
long elapsed;
long wait;
while(running){
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - elapsed / 1000000;
if(wait < 0)wait = 5;
try{
Thread.sleep(wait);
} catch(Exception e) {
e.printStackTrace();
}
}
A GameStateManager is acessed with the update() and draw() methods, so I can draw the map just fine, like the older prototype. The problem happened when I dragged the mouse on the screen so the map could move; the animation became VERY croppy, in the extent that I could actually see the black background between the tiles moving before the final position of all tiles.
At first I thought the problem was in a concurrency between the Game Loop thread and the event listeners of the main class, because the mouseDragged event could be called while the JPanel was trying to draw what the map was like a moment ago; then I tested this on my game loop code:
SwingUtilities.invokeLater(new Runnable(){
public void run(){
draw();
drawToScreen();
}
});
//draw();
//drawToScreen();
And now the prototype is working just fine.
So, my question is, is this performance heavy, or just a bad practice in Java? Also, was my "concurrency" assumption right? This is my first time dealing with threads in Java, so I don't really know if I dealed with the problem the right way.
obs: This is the entire class I made in which the game loop is in:
http://pastebin.com/RMRHYc5X
obs2: If someone is interested, the game loop logic I worked in was based on a youtube java tutorial made by pj644 named "2D Game Programming in Java".
obs3: Sorry if the question became too big, this is my first time posting a question on this site!
Swing isn't really a great technology for writing games, it updates slowly and is quite limited in a number of ways.
Having said that yes calling invokeLater or using a SwingWorker would be the correct way to update the screen when your game thread has done its work.
Before you go too much further though I really suggest looking at a 2d or 3d java graphics and game framework. You will be able to get much better results that way and a lot of the work in terms of setting up the game loop, updates, managing frame rates, etc will be done for you.

Using Delta Time to Improve Movement

I looked up many threads on how to use delta time and I can't figure it out.
I want my guy to move at a constant speed every time I run the game.
So I have:
timer = new Timer(9, this);
timer.start();
then the paint method.
I tried doing start time at the beginning of the paint method and then a current time at the end of it. How would I make it affect the timer's speed or how far the player moves. I've tried multiplying the time delta by the increment to the x. nHeroX = dx*deltaTIme;
I feel like it's very simple I just need someone to tell me straight what to do please.
Traditionally, game programming relies on a continuous loop.
Anyway, all I have realized.
In this loop, you should separate model update and graphic update.
In your snipset, you seem to try mixing the two things.
In this loop :
- In a first time, you let the model to update.For example : guy's move from x to x1.
- In a second time, you must refresh the graphics to allow the guy to have a new position in the screen.
The speed of your guy depends on the guy model (ex: constant in your guy class).
But the speed of another type of guy could be different.
The general speed of your game relies on the FPS set in your main loop.
You can see an example on this post :
Java Main Game Loop
Good luck
Get the system time from the System object.
Get it again during your animation. Delta time is nothing more than subtraction.
Get rid of the JavaScript tag. The languages are completely different.

Android smooth game loop

I have problems with smooth scrolling in OpenGL (testing on SGS2 and ACE)
I created simple applications - only fixed speed horizontal scrolling of images, or only one image (player) moving by accelerator,
but it's movement is not smooth :-(
I tried many various of code but no satisfaction...
first I tried work with GLSurfaceView.RENDERMODE_CONTINUOUSLY and I put all code to onDrawFrame:
public void onDrawFrame(GL10 gl)
{
updateGame(gl, 0.017f);
drawGame(gl);
}
this is the simplest and absolute smooth!! - but it's dependent on hardware speed (= useless)
public void onDrawFrame(GL10 gl)
{
frameTime = SystemClock.elapsedRealtime();
elapsedTime = (frameTime - lastTime) / 1000;
updateGame(gl, elapsedTime);
drawGame(gl);
lastTime = frameTime;
}
this is the best of all but it's not as smooth as the previous, sometimes flick
second I tried GLSurfaceView.RENDERMODE_WHEN_DIRTY, in onDrawFrame i have only drawing objects and this code in separate Thread:
while (true)
{
updateGame(renderer, 0.017f);
mGLSurfaceView.requestRender();
next_game_tick += SKIP_TICKS;
sleep_time = next_game_tick - System.currentTimeMillis();
if (sleep_time >= 0)
{
try
{
Thread.sleep(sleep_time);
}
catch (Exception e) {}
}
else
{
Log.d("running behind: ", String.valueOf(sleep_time));
}
}
this is not smooth and it's not problem with "running behind"
My objective is smooth image movement like in first code example above.
Possible error is somewhere else then I looking. Please, Can somebody help me with this?
Is better use RENDERMODE_WHEN_DIRTY or RENDERMODE_CONTINUOUSLY?
Thank you.
I was fighting with the exact same issue for several days. The loop looks smooth without any Android time reference, but as soon it includes any type of “time sync” , external factors out of the android development control introduce serious discontinuities to the final result.
Basically, these factors are:
eglSwapInterval is not implemented in Android, so is difficult to know the moment when the hardware expose the final draw in the screen (hardware screen sync)
Thread.sleep is not precise. The Thread may sleep more or less than requested.
SystemClock.uptimeMillis()System.nanoTime(), System.currentTimeMillis() and other timing related measurement are not accurate (its precise).
The issue is independent of the drawing technology (drawing, openGL 1.0/1.1 and 2.0) and the game loop method (fixed time step, interpolation, variable time step).
Like you, I was trying Thread.sleep, crazy interpolations, timers, etc. Doesn’t matter what you will do, we don’t have control over this factors.
According with many Q&A on this site, the basic rules to produce smooth continuous animations are:
Reduce at the minimum the GC by removing all dynamic memory request.
Render frames as fast the hardware can process them (40 to 60fps is ok in most android devices).
Use fixed time steps with interpolation or variable time steps.
Optimize the update physics and draw routines to be execute in relative constant time without high peaks variance.
For sure, you made a lot of previous work before post this question by optimizing your updateGame() and drawGame() (without appreciable GC and relative constant execution time) in order to get a smooth animation in your main loop as you mention: “simple and absolute smooth”.
Your particular case with variable stepTime and no special requirements to be in perfect sync with realTime events (like music), the solution is simple: “smooth the step Time variable”.
The solution works with other game loop schemes (fixed time step with variable rendering) and is easy to port the concept (smooth the amount of displacement produced by the updateGame and the real time clock across several frames.)
// avoid GC in your threads. declare nonprimitive variables out of onDraw
float smoothedDeltaRealTime_ms=17.5f; // initial value, Optionally you can save the new computed value (will change with each hardware) in Preferences to optimize the first drawing frames
float movAverageDeltaTime_ms=smoothedDeltaRealTime_ms; // mov Average start with default value
long lastRealTimeMeasurement_ms; // temporal storage for last time measurement
// smooth constant elements to play with
static final float movAveragePeriod=40; // #frames involved in average calc (suggested values 5-100)
static final float smoothFactor=0.1f; // adjusting ratio (suggested values 0.01-0.5)
// sample with opengl. Works with canvas drawing: public void OnDraw(Canvas c)
public void onDrawFrame(GL10 gl){
updateGame(gl, smoothedDeltaRealTime_ms); // divide 1000 if your UpdateGame routine is waiting seconds instead mili-seconds.
drawGame(gl);
// Moving average calc
long currTimePick_ms=SystemClock.uptimeMillis();
float realTimeElapsed_ms;
if (lastRealTimeMeasurement_ms>0){
realTimeElapsed_ms=(currTimePick_ms - lastRealTimeMeasurement_ms);
} else {
realTimeElapsed_ms=smoothedDeltaRealTime_ms; // just the first time
}
movAverageDeltaTime_ms=(realTimeElapsed_ms + movAverageDeltaTime_ms*(movAveragePeriod-1))/movAveragePeriod;
// Calc a better aproximation for smooth stepTime
smoothedDeltaRealTime_ms=smoothedDeltaRealTime_ms +(movAverageDeltaTime_ms - smoothedDeltaRealTime_ms)* smoothFactor;
lastRealTimeMeasurement_ms=currTimePick_ms;
}
// Optional: check if the smoothedDeltaRealTIme_ms is too different from original and save it in Permanent preferences for further use.
For a fixed time step scheme, an intermetiate updateGame can be implemented to improve the results:
float totalVirtualRealTime_ms=0;
float speedAdjustments_ms=0; // to introduce a virtual Time for the animation (reduce or increase animation speed)
float totalAnimationTime_ms=0;
float fixedStepAnimation_ms=20; // 20ms for a 50FPS descriptive animation
int currVirtualAnimationFrame=0; // useful if the updateGameFixedStep routine ask for a frame number
private void updateGame(){
totalVirtualRealTime_ms+=smoothedDeltaRealTime_ms + speedAdjustments_ms;
while (totalVirtualRealTime_ms> totalAnimationTime_ms){
totalAnimationTime_ms+=fixedStepAnimation_ms;
currVirtualAnimationFrame++;
// original updateGame with fixed step
updateGameFixedStep(currVirtualAnimationFrame);
}
float interpolationRatio=(totalAnimationTime_ms-totalVirtualRealTime_ms)/fixedStepAnimation_ms;
Interpolation(interpolationRatio);
}
Tested with canvas and openGlES10 drawing with the following devices: SG SII (57 FPS), SG Note(57 FPS) , SG tab(60 FPS), unbranded Android 2.3 (43 FPS) slow emulator running on Windows XP(8 FPS). The test platform draws around 45 objects + 1 huge background (texture from 70MP source image) moving along a path specified in real physics parameters (km/h and G’s), without spikes or flick between several devices (well, 8 FPS on the emulator doesn’t look good, but its flow at constant speed as expected)
Check The graphs for how android report the time. Some times Android report a large delta time and just the next loop it's small than average, meaning an offset on the reading of realTime value.
with more detail:
How to limit framerate when using Android's GLSurfaceView.RENDERMODE_CONTINUOUSLY?
System.currentTimeMillis vs System.nanoTime
Does the method System.currentTimeMillis() really return the current time?

Categories