I have a Sprite, which is a ball, and it is falling properly, acording with my FixedStepPhysicsWorld options. But I would like a vector follow this ball as it is falling.
So I decided to override the onManagedUpdate sprite's method.
After lots of tests, I just got 1 vector drawn, then I realized that the pSecondsElapsed, were not being incremented.
Here is my code:
#Override
public void onPopulateScene(Scene pScene,
OnPopulateSceneCallback pOnPopulateSceneCallback) throws Exception {
sPlayer= new Sprite(200,0, playerTextureRegion, this.mEngine.getVertexBufferObjectManager()){
#Override
protected void onManagedUpdate(float pSecondsElapsed) {
super.onManagedUpdate(pSecondsElapsed);
Log.d("<<<<<<<<<<<,>>>>>>>>>"+pSecondsElapsed+","");
}
The output is the following:
11-07 21:14:32.242: D/<<<<<<<<<<<,>>>>>>>>0.02 (23720): [MainActivity.java:359:onManagedUpdate()]
11-07 21:14:32.257: D/<<<<<<<<<<<,>>>>>>>>0.02 (23720): [MainActivity.java:359:onManagedUpdate()]
11-07 21:14:32.281: D/<<<<<<<<<<<,>>>>>>>>0.02 (23720): [MainActivity.java:359:onManagedUpdate()]
My Engine is like:
#Override
public Engine onCreateEngine(final EngineOptions pEngineOptions) {
return new FixedStepEngine(pEngineOptions, 50);
}
QUESTION:
1 - Why pSecondsElapsed is not changing?
2 - I want to draw vectors for each position of this ball. Should I detach and atach a new Line each time this method(onManagedUpdate) is called?
The API tried to make that clear by calling it "Seconds Elapsed" which means "seconds passed" since the last time the update was called. It's not a cumulative number, but instead the number of milliseconds since the function was last called.
If you want to maintain a cumulative count, you will need to add pSecondsElapsed to a counter variable on each call of that function.
The reason pSecondsElapsed is not changing is due to two conditions being true.
1) You are using a FixedStepOption with the frame rate set to 50.
2) The android you tested it on had the capability to run at 50 frames per second.
This results in it running 50 FPS which results in .02 of a second elapsed per frame. (1 second divided by 50 frames). You can test this by changing the 50 to 25 and expect to get .04 (1 second divided by 25 frames).
Where it becomes important is if the hardware cannot support the frame rate you specify. In this case, it is likely it varies due to needing to do more work in certain situations of your app. (For example if you create an explosion the FPS may drop due to the extra sprites).
To properly support hardware that cannot keep up with the framerate you specify, you can use the pSecondsElapsed to account for the variance. (for example by multiplying the distance times the variance in elapsed time vs specified time).
Related
I have just started using the OpenGL ES 2 for android for my little game and have encountered a problem on redrawing the screen on each frame.
I have setup a loop on my Renderer's onDrawFrame, just a simple [ updateGameLogic() -> drawGame() ] or Thread.sleep() loop based on the time lapsed from last drawGame call.
Currently the updateGameLogic() method simply translate the camera to the +ve X direction (the game is 2d).
In the drawGame() call, I first clear my screen with GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT). Then I have 3 glBindTexture and glDrawElements calls for drawing 3 categories of objects with different texture atlas.
Here comes the problem, in between each frame drawn on screen, there is a blink of the previous frame appearing which is undesired and makes the game look dizzy. Precisely, say the game is just about to draw frame 3 from frame 2, right before frame 2 vanish and frame 3 appearing, there is a split moment where frame 1 is displayed.
I thought this may be due to the way the GLSurfaceView is buffered by the system so I experimented with calling multiple glClear before drawing but everything stays the same. Would be grateful if someone can provide some explanation / solution to the problem, and what I have done wrong, thanks. (basically paragraph 2 to 4 is all my code so I have not posted it, unless requested)
From the clarification in the comment, it sounds like you have something like this in your code:
public void onDrawFrame(GL10 gl) {
long currentTime = SystemClock.elapsedRealtime();
long deltaTime = currentTime - mLastFrameTime;
if (deltaTime < 33) {
Thread.sleep(33 - deltaTime);
return;
}
mLastFrameTime = currentTime;
updateGameLogic(deltaTime);
drawGame();
}
This will indeed cause problems. When onDrawFrame() is called, you have to render a frame. You can't just return without drawing anything. The caller will assume that you rendered a frame in any case, and it will end up being presented on the screen. If you decide not to render anything, whatever happened to be in the surface you were supposed to draw to will be presented. There's no telling what this will be, but it's quite likely that it's an old frame from 2-3 frames earlier.
If you want to artificially throttle the frame rate, e.g. to save power, unfortunately there's no very good way to do this in Android. Using sleeps in onDrawFrame() is kind of dirty (and inherently unreliable, IMHO), but it might be necessary in this case. The key is that either before or after you sleep, you still need to render a frame. As a first attempt, I would try tweaking the above to something like this:
public void onDrawFrame(GL10 gl) {
long currentTime = SystemClock.elapsedRealtime();
long deltaTime = currentTime - mLastFrameTime;
if (deltaTime < 33) {
Thread.sleep(33 - deltaTime);
currentTime = SystemClock.elapsedRealtime();
deltaTime = currentTime - mLastFrameTime;
}
mLastFrameTime = currentTime;
updateGameLogic(deltaTime);
drawGame();
}
Note that while there is still an artificial delay, there is no early return in the code anymore.
There are probably more robust variations of this idea for throttling the redraws to 30 fps. Some searching on SO or the rest of the internet should reveal previous discussions.
I am developing a game using andEngine in android, I've developed animated sprites background, platforms and scores. for loading level, I've made a
.lvl
extension file in which I've defined platforms, player and obstacles at fixed positions. I want to know is there anything provided by andEngine so that I can dynamically load obstacles, platforms, coins and other objects rather than loading any file, my aim is to keep my game-world going as long as my player is alive.
I think I am clear.
Thanks!!!
I would like to point you to investigate "TimerHandler" as your dynamic time handler (Defining how often to attach another object/entity.
With a time handler in place, you can assign nearly any int/double/float value of an object/entity with MathUtils.random(min, max).
Example:
TimerHandler objectTimerHandler = new TimerHandler(1f, true, new ITimerCallback() {
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
int timerSeconds = 0;
timerSeconds++;
final Sprite object1 = new Sprite(0, 0, resourcesManager.object1_region, vbom);
if (timerSeconds == MathUtils.random(1, 4))
{
attachChild(object1);
object1.setX(MathUtils.random(0, 480));
}
});
registerUpdateHandler(objectTimerHandler);
So, the TimeHandler "objectHandler" is called every 1 seconds defined by the 1f variable.
An integer counter "timerSeconds" is setup as a base.
The Sprite object/entity is initialized.
Now the "magic": the if boolean is in place to set a sense of true randomness. So here's the math... Every second passed, add a "timerSecond". Then, IF "timerSecond" is EQUAL to a random number between 1-4, then attach the sprite "object1" and set it's X position, also on a random range 0-480.
In reality, this means for every 1 second passed, there is a 1/4 chance that this sprite will be created/attached. (this can be altered to any desired chance range by changing that random range max value. EG: MathUtils.random(1, 100) <-- this would state a 1 in 100 chance to spawn the sprite each second.)
The 2nd to last line closes the Timehandler code, and the last line registers the Timehandler to the class/scene/entity/engine (ect..).
I'm making an android game and am currently not getting the performance I'd like. I have a game loop in its own thread which updates an object's position. The rendering thread will traverse these objects and draw them. The current behavior is what seems like choppy/uneven movement. What I cannot explain is that before I put the update logic in its own thread, I had it in the onDrawFrame method, right before the gl calls. In that case, the animation was perfectly smooth, it only becomes choppy/uneven specifically when I try to throttle my update loop via Thread.sleep. Even when I allow the update thread to go berserk (no sleep), the animation is smooth, only when Thread.sleep is involved does it affect the quality of the animation.
I've created a skeleton project to see if I could recreate the issue, below are the update loop and the onDrawFrame method in the renderer:
Update Loop
#Override
public void run()
{
while(gameOn)
{
long currentRun = SystemClock.uptimeMillis();
if(lastRun == 0)
{
lastRun = currentRun - 16;
}
long delta = currentRun - lastRun;
lastRun = currentRun;
posY += moveY*delta/20.0;
GlobalObjects.ypos = posY;
long rightNow = SystemClock.uptimeMillis();
if(rightNow - currentRun < 16)
{
try {
Thread.sleep(16 - (rightNow - currentRun));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
And here is my onDrawFrame method:
#Override
public void onDrawFrame(GL10 gl) {
gl.glClearColor(1f, 1f, 0, 0);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
gl.glTranslatef(transX, GlobalObjects.ypos, transZ);
//gl.glRotatef(45, 0, 0, 1);
//gl.glColor4f(0, 1, 0, 0);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, uvBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, drawOrder.length,
GL10.GL_UNSIGNED_SHORT, indiceBuffer);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
I've looked through replica island's source and he's doing his update logic in a separate thread, as well as throttling it with Thread.sleep, but his game looks very smooth. Does anyone have any ideas or has anyone experienced what I'm describing?
---EDIT: 1/25/13---
I've had some time to think and have smoothed out this game engine considerably. How I managed this might be blasphemous or insulting to actual game programmers, so please feel free to correct any of these ideas.
The basic idea is to keep a pattern of update, draw... update, draw... while keeping the time delta relatively the same (often out of your control).
My first course of action was to synchronize my renderer in such a way that it only drew after being notified it was allowed to do so. This looks something like this:
public void onDrawFrame(GL10 gl10) {
synchronized(drawLock)
{
while(!GlobalGameObjects.getInstance().isUpdateHappened())
{
try
{
Log.d("test1", "draw locking");
drawLock.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
When I finish my update logic, I call drawLock.notify(), releasing the rendering thread to draw what I just updated. The purpose of this is to help establish the pattern of update, draw... update, draw... etc.
Once I implemented that, it was considerably smoother, although I was still experiencing occasional jumps in movement. After some testing, I saw that I had multiple updates occurring between calls of ondrawFrame. This was causing one frame to show the result of two (or more) updates, a larger jump than normal.
What I did to resolve this was to cap the time delta to some value, say 18ms, between two onDrawFrame calls and store the extra time in a remainder. This remainder would be distributed to subsequent time deltas over the next few updates if they could handle it. This idea prevents all sudden long jumps, essentially smoothing a time spike out over multiple frames. Doing this gave me great results.
The downside to this approach is that for a little time, the position of objects will not be accurate with time, and will actually speed up to make up for that difference. But it's smoother and change in speed is not very noticeable.
Finally, I decided to rewrite my engine with the two above ideas in mind, rather than patching up the engine I had originally made. I made some optimizations for the thread synchronization that perhaps someone could comment on.
My current threads interact like this:
-Update thread updates the current buffer (double buffer system in order to update and draw simultaneously) and will then give this buffer to the renderer if the previous frame has been drawn.
-If the previous frame has not yet draw, or is drawing, the update thread will wait until the render thread notifies it that it has drawn.
-Render thread waits until notified by update thread that an update has occurred.
-When the render thread draws, it sets a "last drawn variable" indicating which of the two buffers it last drew and also notifies the update thread if it was waiting on the previous buffer to be drawn.
That may be a little convoluted, but what that's doing is allowing for the advantages of multithreading, in that it can perform the update for frame n while frame n-1 is drawing while also preventing multiple update iterations per frame if the renderer is taking a long time. To further explain, this multiple-update scenario is handled by the update thread locking if it detects that the lastDrawn buffer is equal to the one which was just updated. If they are equal, this indicates to the update thread that the frame before has not yet been drawn.
So far I'm getting good results. Let me know if anyone has any comments, would be happy to hear your thoughts on anything I'm doing, right or wrong.
Thanks
(The answer from Blackhex raised some interesting points, but I can't cram all this into a comment.)
Having two threads operating asynchronously is bound to lead to issues like this. Look at it this way: the event that drives animation is the hardware "vsync" signal, i.e. the point at which the Android surface compositor provides a new screen full of data to the display hardware. You want to have a new frame of data whenever vsync arrives. If you don't have new data, the game looks choppy. If you generated 3 frames of data in that period, two will be ignored, and you're just wasting battery life.
(Running a CPU full out may also cause the device to heat up, which can lead to thermal throttling, which slows everything in the system down... and can make your animation choppy.)
The easiest way to stay in sync with the display is to perform all of your state updates in onDrawFrame(). If it sometimes takes longer than one frame to perform your state updates and render the frame, then you're going to look bad, and need to modify your approach. Simply shifting all game state updates to a second core isn't going to help as much as you might like -- if core #1 is the renderer thread, and core #2 is the game state update thread, then core #1 is going to sit idle while core #2 updates the state, after which core #1 will resume to do the actual rendering while core #2 sits idle, and it's going to take just as long. To actually increase the amount of computation you can do per frame, you'd need to have two (or more) cores working simultaneously, which raises some interesting synchronization issues depending on how you define your division of labor (see http://developer.android.com/training/articles/smp.html if you want to go down that road).
Attempting to use Thread.sleep() to manage the frame rate generally ends badly. You can't know how long the period between vsync is, or how long until the next one arrives. It's different for every device, and on some devices it may be variable. You essentially end up with two clocks -- vsync and sleep -- beating against each other, and the result is choppy animation. On top of that, Thread.sleep() doesn't make any specific guarantees about accuracy or minimum sleep duration.
I haven't really gone through the Replica Island sources, but in GameRenderer.onDrawFrame() you can see the interaction between their game state thread (which creates a list of objects to draw) and the GL renderer thread (which just draws the list). In their model, the game state only updates as needed, and if nothing has changed it just re-draws the previous draw list. This model works well for an event-driven game, i.e. where the contents on screen update when something happens (you hit a key, a timer fires, etc). When an event occurs, they can do a minimal state update and adjust the draw list as appropriate.
Viewed another way, the render thread and the game state work in parallel because they're not rigidly tied together. The game state just runs around updating things as needed, and the render thread locks it down every vsync and draws whatever it finds. So long as neither side keeps anything locked up for too long, they don't visibly interfere. The only interesting shared state is the draw list, guarded with a mutex, so their multi-core issues are minimized.
For Android Breakout ( http://code.google.com/p/android-breakout/ ), the game has a ball bouncing around, in continuous motion. There we want to update our state as frequently as the display allows us to, so we drive the state change off of vsync, using a time delta from the previous frame to determine how far things have advanced. The per-frame computation is small, and the rendering is pretty trivial for a modern GL device, so it all fits easily in 1/60th of a second. If the display updated much faster (240Hz) we might occasionally drop frames (again, unlikely to be noticed) and we'd be burning 4x as much CPU on frame updates (which is unfortunate).
If for some reason one of these games missed a vsync, the player may or may not notice. The state advances by elapsed time, not a pre-set notion of a fixed-duration "frame", so e.g. the ball will either move 1 unit on each of two consecutive frames, or 2 units on one frame. Depending on the frame rate and the responsiveness of the display, this may not be visible. (This is a key design issue, and one that can mess with your head if you envisioned your game state in terms of "ticks".)
Both of these are valid approaches. The key is to draw the current state whenever onDrawFrame is called, and to update state as infrequently as possible.
Note for anyone else who happens to read this: don't use System.currentTimeMillis(). The example in the question used SystemClock.uptimeMillis(), which is based on the monotonic clock rather than wall-clock time. That, or System.nanoTime(), are better choices. (I'm on a minor crusade against currentTimeMillis, which on a mobile device could suddenly jump forward or backward.)
Update: I wrote an even longer answer to a similar question.
Update 2: I wrote an even longer longer answer about the general problem (see Appendix A).
One part of the problem may be caused by fact that Thread.sleep() is not accurate. Try to investigate what is the actual time of the sleep.
The most important thing that should make your animations smooth is that you should compute some interpolation factor, call it alpha, that linearly interpolates your animations in consecutive rendering thread calls between two consecutive animation update thread calls. In other words, if your update interval is high comparing to your framerate, not interpolating your animation update steps is like you'd be rendering at update interval framerate.
EDIT: As an example, this is how PlayN does it:
#Override
public void run() {
// The thread can be stopped between runs.
if (!running.get())
return;
int now = time();
float delta = now - lastTime;
if (delta > MAX_DELTA)
delta = MAX_DELTA;
lastTime = now;
if (updateRate == 0) {
platform.update(delta);
accum = 0;
} else {
accum += delta;
while (accum >= updateRate) {
platform.update(updateRate);
accum -= updateRate;
}
}
platform.graphics().paint(platform.game, (updateRate == 0) ? 0 : accum / updateRate);
if (LOG_FPS) {
totalTime += delta / 1000;
framesPainted++;
if (totalTime > 1) {
log().info("FPS: " + framesPainted / totalTime);
totalTime = framesPainted = 0;
}
}
}
I'll try to explain what I mean.
I'm developing a 2d game. When I run the code below on the small screen it works more quickly than the same code on the big screen. I think it depends on an iteration of the game loop takes more time on the big screen than on the small. How can I implement time unit or something else to it doesn't depend on the iteration of the game loop?
private void createDebris(){
if(dx<=0) return;
if(stepDebris==2){
Debris debris = new Debris(gameActivity, dx-=1280*coefX/77, 800*coefY-50*coefY, coefX, coefY);
synchronized (necessaryObjects) {
necessaryObjects.add(debris);
}
stepDebris=-1;
Log.e("COUNT", (count++)+"");
}
stepDebris++;
}
P.S. Debris is visual object which is drawn on canvas. I'll appreciate your answers. Thanks.
If, stepDebris is the unit by which you move objects on the screen - then incrementing it per draw call is wrong, because it ties the rate of movement to the framerate.
What you want is something like this
stepDebris += elapsedMilliseconds * speedFactor
where elapsedMilliseconds is the time elapsed since the game started (in mS). Once you find the correct speedFactor for stepDebris - it will move at the same speed on different machines/resolutions irrespective of framerate.
Hope this helps!
You can make an 'iteration' take x milliseconds by measuring the time it takes to do the actual iteration (= y), and afterwards sleeping (x-y) millisecs.
See also step 3 of this tutorial
Android provies the Handler API, which implements timed event loops, to control the timing of computation. This article is pretty good.
You will save battery life by implementing a frame rate controller with this interface rather redrawing as fast as you can.
Frame rate: I'm referring to the rate at which display changes. i.e. Ondraw() is called and the canvas is redrawn.
Is there a default rate for all android devices ? As this rate depends on the processing power of the device , How to find out the frame rate of a device , before starting to program for that mobile device ?
This may be a follow-up to this question, where I suggested that having a redraw loop that just kept drawing over and over again might be a bit excessive. There may be an api to find out the capabilities of the devices display, but if there is I'm not aware of it. When you're writing your own event loop / thread function you can control the framerate by how often you call your 'draw' method. Typically, I think for most purposes, you would be ok with a refresh rate of 30 or so. If you're writing a fast action game, that needs rapid animation then you may want to run as fast as you can, the more fps, the smoother it will be.
A typical event loop (thread run function) might look something like this:
// define the target fps
private static final int UPDATE_RATE = 30; // Frames per second (fps)
public void run() {
while(running) { // volatile flag, set somewhere else to shutdown
long beginTimeMillis, timeTakenMillis, timeLeftMillis;
// get the time before updates/draw
beginTimeMillis = System.currentTimeMillis();
// do the thread processing / draw
performUpdates(); // move things if required
draw(); // draw them on the screen
// get the time after processing and calculate the difference
timeTakenMillis = System.currentTimeMillis() - beginTimeMillis;
// check how long there is until we reach the desired refresh rate
timeLeftMillis = (1000L / UPDATE_RATE) - timeTakenMillis;
// set some kind of minimum to prevent spinning
if (timeLeftMillis < 5) {
timeLeftMillis = 5; // Set a minimum
}
// sleep until the end of the current frame
try {
TimeUnit.MILLISECONDS.sleep(timeLeftMillis);
} catch (InterruptedException ie) {
}
}
}
You can use the dumpsys tool provided by Android. To obtain information about the display of the device execute the command:
adb shell dumpsys display
The information about the frame rate of the device is provided in the attribute "mPhys".
You will find something like:
mPhys=PhysicalDisplayInfo{1080x1920, 60.000004 fps, densitiy 3.0,
480.0x480.0 dpi, secure true}
The frame rate of the device is in the second field, in my case is 60.000004 fps
You can't rely on a certain framerate. Android is a using multitasking operating system. If there are some threads running in the background that do some heavy lifting, you might not be able to reach the framerate you want. Even if you're the only active process, the framerate depends on your GPU and CPU, and the clock of each. Maybe the user has a hacked ROM that changes the clock to a custom value.
Some phones might be locked to a certain framerate. The HTC EVO was locked to 30fps for the longest time, until custom ROMs came out that removed that limitation. Newer EVO ROMs also removed that limitation.
I don't know what you're trying to do, but your best bet is to measure the time after each frame and use that delta for your animations. If you're trying to display the FPS, then use a smoothed average.
There is a simple tricky way to find device FPS during runtime.
Just call the following method:
long oneSecondLater=0;
int FPS=0;
int counter=0;
ValueAnimator v_animator;
private void logFPS()
{
oneSecondLater = System.currentTimeMillis()+1000;
v_animator = ValueAnimator.ofFloat(0.0f, 1.0f);
v_animator.setRepeatCount(ValueAnimator.INFINITE);
v_animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
FPS++;
if(System.currentTimeMillis() > oneSecondLater)
{
counter++;
if(counter>1)//ignore the first onAnimationUpdate call (it is not correct)
Log.i("checkFPS","FPS:" + FPS);
FPS=0;
oneSecondLater = System.currentTimeMillis()+1000;
}
}
});
v_animator.start();
}
I log FPS every second, The output of my Logcat was as follows
It works because for ValueAnimator, onAnimationUpdate() method will call according to device FPS;
This might be an old question, but for future reference, I found this library named Takt
https://github.com/wasabeef/Takt.
Takt is Android library for measuring the FPS using Choreographer.