I am a beginner and I want a complete example in LibGDX how to limit the framerate to 50 or 60. Also how to mangae interpolation between game state with simple example code
e.g. deWiTTERS Game Loop:
#Override
public void render()
{
float deltaTime = Gdx.graphics.getDeltaTime();
Update(deltaTime);
Render(deltaTime);
}
There is a Gdx.graphics.setVsync() method (generic = backend-independant), but it is not present in 0.9.1, only in the Nightlies.
"Relying on vsync for fixed time steps is a REALLY bad idea. It will break on almost all hardware out there.
See LwjglApplicationConfiguration, there's a flag in there that let s use toggle gpu/software vsynching. Play around with it." (Mario)
NOTE that none of these limit the framerate to a specific value... if you REALLY need to limit the framerate for some reason, you'll have to handle it yourself by returning from render calls if xxx ms haven't passed since the last render call.
As a complete game engine that LibGDX is, it handles things like this itself. You can configure this at the start of your game, at least with the latest nightlies.
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "Example";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
cfg.vSyncEnabled = true;
cfg.foregroundFPS = 60;
new LwjglApplication(new ExampleGame(), cfg);
}
Now your render loop will be limited to 60 calls per second. As to the actual implementation, you should use a Game and Screens. The Screen interface already has a render method which might look like this:
public void render(deltaTime )
{
...
updateAllEntities(deltaTime);
...
renderAllEntities(deltaTime);
...
}
There is only the render method being called by LibGDX, but you can split up your game logic update and the rendering yourself like in the example above.
Related
I am trying to calibrate an accelerometer, but I can't obtain the 6 sample values at 6 different acceleration readings required for the calibration. PreliminaryW is a double[6][3] array made to fill those sample values. It is 6 by 3 because each acceleration reading has an x, y, and a z component.
I am planning to sample them by pressing a button at the 6 different acceleration readings. This button makes "calibrate" true.
I ofcourse, first make "calibrating" true to start this thread.
For some unfathomable reason, preliminaryW[i] = currentAcc seems to be filling up from 0 to i with the same value instead of just i. I made sure that the currentAcc is different every time I press the "calibrate" button.
What is wrong with my code?
public synchronized void run() {
Log.d(TAG, "+ in Calibrator thread +");
int i = -1;
while (calibrating) {
if (calibrate) {
i = i + 1;
calibrate = false;
preliminaryW[i] = currentAcc;
if (i == 5) {
calibrating = false;
}
}
}
}
I'm not very familiar with the inner-workings of the accelerometer, and it's hard to decide why it's not working without seeing more of the code. For example, can you be sure that there's only one instance of the Thread, or are you creating multiple instances?
Why does this need to be in a Thread?
Looping like that is not good practice either, you should use wait/notify if you absolutely need a Thread. (more info at http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)
I've drafted a class that does approximately what you want, but doesn't use threading. You could create a Calibrator and then call performCalibration() with each new value:
class Calibrator{
int count = 0;
double[][] preliminaryW = new double[6][3];
public void performCalibration(double[] currentAcc){
preliminaryW[count] = currentAcc;
count++;
}
}
without the Thread and "busy loop", you might be able to omit those flags for 'calibrate' and 'calibrating' which would certainly help debugging as well.
Good Luck!
So, I have one problem, which I can't solve. My app used over 45% of cpu samsung SII. I think the main reason is postDelayed.
Here is part of my code:
Handler a=new Handler();
a.post(new Runnable(){
#Override
public void run() {
Calendar cal = Calendar.getInstance(Locale.US);
cal.setTime(curr);
Format formatter = new SimpleDateFormat("\r EE \n d");
int currentDOW = cal.get(Calendar.DAY_OF_WEEK);
cal.add(Calendar.DAY_OF_YEAR,(currentDOW*-1)+i+2);
den.setText(formatter.format(cal.getTime()));
}
a.postDelayed(this,400);
});
So, this is part of my code, it is work, but I think, it is the main reason of high CPU usage. Please help me! Thank you!
you could optimize the code a bit , but i suspect that you simply don't stop the updating when you don't need to , so more and more updates are being accumulated .
as an example , if you change the orientation , it will add more events of the previous activitiy (which was destroyed) and you end up with double the rate of updating .
I had this problem. My app was using around 60% CPU time until I added the following code to my run() method in my worker thread:
#Override
public void run()
{
while( _running )
{
// do usual stuff
// ...
// ** add the following to the end of your loop **
try
{
Thread.sleep( 5 );
}
catch( InterruptedException e )
{
_running = false;
/* at least we tried */
}
}
}
It now uses ~8% CPU with no noticeable difference.
Experiment with the value '5'. I've added an app setting to allow the user to balance better graphics (i.e. number lower than 5) with better battery usage (number higher than 5).
I created a custom view from scratch. Extended View and overrided onDraw().
When comes down in animating the view i generate a custom animation using offsets.
eg.
while(!isOnTop){
mOffset++;
//draw the component a a it higher using the offset
if(position == 0)
isOnTop==true;
invalidate();
}
The thinking is that my frames come from invalidate it self. The problem is that invalidation of this view can come just by scrolling a listview at the same screen.
This "shared invalidation()" causes lag to my animation.So is there a way out of that lag?
Do you have any other suggestion of performing animations in that shared enviroment?
Creating an animation using a seperate thread that calculates the offset also needs forced invalidation() calls to display the animation (correct me if i'm wrong).
Is the only solution to perform the animation in eg 10 invalidation requests with a larger step? It will ease the lag out but i think i can use a different approach on that.
"What is best" of course depends greatly on exactly what you are trying to do. You haven't said what you are trying to accomplish, so we can only guess at what may be best for you.
Here are some simple things:
If you want to animate bitmap frames, use AnimationDrawable: http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html
If you want to animate the movement of views within your hierarchy, use the view animation framework: http://developer.android.com/guide/topics/graphics/view-animation.html
The new more general animation framework can do a lot more stuff an is often easier to use: http://developer.android.com/guide/topics/graphics/animation.html. This is natively available in Android 3.0+ but can also be used in Android API level 7 with the support v7 library.
If you want to write a custom widget that is an integrated part of its view hierarchy and manually does its own animation drawing, you can use a Handler to time the updates (usually you'll want 60fps or 20ms between each invalidate()) and then in your onDraw() method draw your view's state based on SystemClock.uptimeMillis() as a delta from when the animation started.
Here's a simple repeated invalidate using Handler:
long mAnimStartTime;
Handler mHandler = new Handler();
Runnable mTick = new Runnable() {
public void run() {
invalidate();
mHandler.postDelayed(this, 20); // 20ms == 60fps
}
}
void startAnimation() {
mAnimStartTime = SystemClock.uptimeMillis();
mHandler.removeCallbacks(mTick);
mHandler.post(mTick);
}
void stopAnimation() {
mHandler.removeCallbacks(mTick);
}
Since this question has some interest I will reply.
The best way to to that is to have a separate canvas thread. A "separate" canvas can only be achieved with a SurfaceView. LunarLanding is an excelent example of that use. Each frame is calculated separately than the main view sharing only CPU time, not drawing time. Therefore is faster, even with the combination of for e.g a regular view at the top and an animating view at the bottom.
But you have to set an interval if you are in that shared environment. That interval is used for the FPS cap. If you don't set FPS cap then the CPU will running wild managing to get good animation to the SurfaceView if it was alone. Capping it at 60fps or even less will do the trick to draw all views efficiently with no CPU overload.
So see the drawing thread of the Lunar Landing from the API demos and set a FPS cap.
private long timeNow;
private long timeDelta;
private long timePrevFrame;
private void capFps(int fps) {
timeNow = System.currentTimeMillis();
timeDelta = timeNow - timePrevFrame;
try {
//ps you can always set 16 instead of 1000/fps for 60FPS to avoid the calculation every time
Thread.sleep((1000 / fps) - timeDelta);
} catch (InterruptedException e) {
}
timePrevFrame = System.currentTimeMillis();
}
and then the drawing thread will look something like this:
#Override
public void run() {
Canvas c;
while (run) {
c = null;
sleepFps(60, false);
try {
synchronized (surfaceHolder) {
c = surfaceHolder.lockCanvas(null);
widgetView.doDraw(c);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
I'm making a game that displays some numbers on a canvas (score, time, etc).
The way that I currently do this is with the drawtext command on a canvas
// score is some int
draw(Canvas c) {
c.drawText(score+"", x, y, paintSyle);
}
I hear that object creation and garbage collection are expensive operations, and I think this is creating a new string every time it is called.
Right now my game with all bitmap drawing and everything jumps around from 25 to 60 fps. I'd like it to stay closer to the higher number and I'm trying to find ways to speed it up.
Would it be faster/better to make(or find?) some mutable subclass of string and work around this problem? Is there another way to solve this issue? Or is this just how it is?
Introduce two new private member variables String renderedScoreString and int rederedScore and rewrite your draw()-method like that:
draw(Canvas c) {
if (this.score != this.renderedScore || this.renderedScoreString == null) {
this.renderedScore = this.score;
this.renderedScoreString = Integer.toString(this.renderedScore);
}
c.drawText(this.renderedScore, x, y, paintStyle);
}
that should save you a lot! of object creations. You could also hide the boilerplate code behind a getter method, e.g. String getScoreString() which does the same, so you don't have it in the draw()-method.
A friend of mine tipped me in on a solution to this problem. When you want to draw something over time, one of the best (and simplest) mechanisms to do so is to split up what you need to do into two completely separate processes.
ie. Only use the draw command exclusively for drawing stuff, keep logic/assignment in Draw() to an absolute minimum.
private final long TIMER_PERIOD = 500;
private String timeString;
private Runnable updateRunnable;
private Handler updateHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
updateRunnable = new Runnable() {
#Override
public void run() {
timeString = GetTimeString();
updateHandler.postDelayed(updateRunnable, TIMER_PERIOD);
}
}
}
Draw(Canvas c) {
c.drawText(timeString, x, y, paintStyle);
}
In this example the Draw command simply takes timeString in its current state and draws it to the screen. This is highly efficient use of the draw function as it does not require any object creation, and no logic is present that is not immediately required for any drawing to occur. . In the background a Runnable is executing the run() function every 500 miliseconds (approximately). Simply update the Run() function with whatever logic you need to calculate the time (example has a dummy function GetTimeString())
I hope this is helpful.
I know I'm resurrecting a dead thread, but there is one extra optimisation you can add to this which restricts String creation to a one-time thing and thus only triggers the GC once at the start and not during the game (which is quite important for an android game).
Somewhere during the start of your game (onCreate, onResume, as part of a singleton during application startup, etc) create a large String[] which can hold the maximum score (my game fills an array of 10000, so the max score would be 9999). Then loop over it with a for loop, filling each index with a String.valueOf(i).
for (int i = 0; i <scoreStrings.length; i++)
{
scoreStrings[i] = String.valueOf(i);
}
Now, when you need to draw the score, just use the int you use to store the score in as an index to that array, and "hey, presto!", you get the correct string for your score.
canvas.drawText(scoreStrings[score], x, y, paint);
I based my game off of the lunar lander demo, although heavily modified, and I can get around 40-50fps but the problem is it fluctuates between 40-50fps so much that it causes the moving graphics to jitter! Its very annoying and makes my game look really shitty when in fact its running at a good frame rate.
I tried setting the thread priority higher but that just made it worse... now it will fluctuate between 40-60fps...
I was thinking of limiting the FPS to about 30 so that it will be constant. Is this a good idea and does anyone else have experience or a different solution?
Thanks!
This is my run loop
#Override
public void run() {
while (mRun) {
Canvas c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if(mMode == STATE_RUNNING){
updatePhysics();
}
doDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
private void updatePhysics() {
now = android.os.SystemClock.uptimeMillis();
elapsed = (now - mLastTime) / 1000.0;
posistionY += elapsed * speed;
mLastTime = now;
}
Don't base your game's logic (object movement, etc.) updating rate on the framerate. In other words, put your drawing and logic updating code in two separate components/threads. This way your game logic is completely independent from your framerate.
Logic updating should be based on how much time has passed since the last update (let's call it delta). Therefore, if you have an object moving at 1px/millisecond, then during each update your object should do something like this:
public void update(int delta) {
this.x += this.speed * delta;
}
So now even if your FPS lags, it won't affect your object's movement speed, since the delta will just be larger, making the object move farther to compensate (there are complications in some cases, but that's the gist of it).
And this is one way of calculating delta within your logic updating object (running in some thread loop):
private long lastUpdateTime;
private long currentTime;
public void update() {
currentTime = System.currentTimeMillis();
int delta = (int) (currentTime - lastUpdateTime);
lastUpdateTime = currentTime;
myGameObject.update(delta); // This would call something like the update method above.
}
Hope that helps! Please ask if you have any other questions; I've been making Android games myself. :)
Sample code:
Copy these two snippets (1 activity and 1 view) and run the code. The result should be a white dot smoothly falling down your screen, no matter what your FPS is. The code looks kinda complicated and long, but it's actually quite simple; the comments should explain everything.
This activity class isn't too important. You can ignore most of the code in it.
public class TestActivity extends Activity {
private TestView view;
public void onCreate(Bundle savedInstanceState) {
// These lines just add the view we're using.
super.onCreate(savedInstanceState);
setContentView(R.layout.randomimage);
RelativeLayout rl = (RelativeLayout) findViewById(R.id.relative_layout);
view = new TestView(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
10000, 10000);
rl.addView(view, params);
// This starts our view's logic thread
view.startMyLogicThread();
}
public void onPause() {
super.onPause();
// When our activity pauses, we want our view to stop updating its logic.
// This prevents your application from running in the background, which eats up the battery.
view.setActive(false);
}
}
This class is where the exciting stuff is!
public class TestView extends View {
// Of course, this stuff should be in its own object, but just for this example..
private float position; // Where our dot is
private float velocity; // How fast the dot's moving
private Paint p; // Used during onDraw()
private boolean active; // If our logic is still active
public TestView(Context context) {
super(context);
// Set some initial arbitrary values
position = 10f;
velocity = .05f;
p = new Paint();
p.setColor(Color.WHITE);
active = true;
}
// We draw everything here. This is by default in its own thread (the UI thread).
// Let's just call this thread THREAD_A.
public void onDraw(Canvas c) {
c.drawCircle(150, position, 1, p);
}
// This just updates our position based on a delta that's given.
public void update(int delta) {
position += delta * velocity;
postInvalidate(); // Tells our view to redraw itself, since our position changed.
}
// The important part!
// This starts another thread (let's call this THREAD_B). THREAD_B will run completely
// independent from THREAD_A (above); therefore, FPS changes will not affect how
// our velocity increases our position.
public void startMyLogicThread() {
new Thread() {
public void run() {
// Store the current time values.
long time1 = System.currentTimeMillis();
long time2;
// Once active is false, this loop (and thread) terminates.
while (active) {
try {
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
time2 = System.currentTimeMillis(); // Get current time
int delta = (int) (time2 - time1); // Calculate how long it's been since last update
update(delta); // Call update with our delta
time1 = time2; // Update our time variables.
}
}
}.start(); // Start THREAD_B
}
// Method that's called by the activity
public void setActive(boolean active) {
this.active = active;
}
}
I am thinking there might be, not really something wrong with some of the above code, but rather an inefficiency. I am talking about this code...
// The important part!
// This starts another thread (let's call this THREAD_B). THREAD_B will run completely
// independent from THREAD_A (above); therefore, FPS changes will not affect how
// our velocity increases our position.
public void startMyLogicThread() {
new Thread() {
public void run() {
// Store the current time values.
long time1 = System.currentTimeMillis();
long time2;
// Once active is false, this loop (and thread) terminates.
while (active) {
try {
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
time2 = System.currentTimeMillis(); // Get current time
int delta = (int) (time2 - time1); // Calculate how long it's been since last update
update(delta); // Call update with our delta
time1 = time2; // Update our time variables.
}
}
}.start(); // Start THREAD_B
}
Specifically, I am thinking about the following lines...
// This is your target delta. 25ms = 40fps
Thread.sleep(25);
It seems to me that just having the thread hang out doing nothing is a waste of valuable processing time, when in fact what you want to be doing is performing the updates, then, if the updates have taken less time than the 25 millis, then sleep the thread for the difference of what was used during the update and 25 millis (or whatever your chosen frame rate is). In this way the update will happen while the current frame is being rendered, and will be completed so the next frame update uses the updated values.
The only problem I can think of here is that some kind of syncronization will need to occur so that the current frame render does not use partially updated values. Perhaps update into a new instance of your set of values, and then make the new instance the current instance just before rendering.
I think I remember reading something in a graphics book about the goal being to perform as many updates as you can while staying within your desired frame rate, then, and only them, perform a screen update.
This of course will require one thread to drive the updates - if you use a SurfaceView, the render is controlled by this thread when you lock the canvas (in theory, according to my understanding anyway).
So, in code, it would be more like...
// Calculate next render time
nextRender = System.currentTimeInMillis() + 25;
while (System.currentTimeInMillis() < nextRender)
{
// All objects must be updated here
update();
// I could see maintaining a pointer to the next object to be updated,
// such that you update as many objects as you can before the next render, and
// then continue the update from where you left off in the next render...
}
// Perform a render (if using a surface view)
c = lockCanvas() blah, blah...
// Paint and unlock
// If using a standard view
postInvalidate();
Good luck and any feedback from anyone using this would surely help us all learn something...
rpbarbati
I think it's about Garbage collector
I would use SurfaceView instead of View if your game is action heavy. If you don't need to update the GUI rapidly then View is fine but for 2D games it's always better to use SurfaceView.
I have a similar issue, the jitter makes large object moves look uneven. Even though the "speed" is the same, different lengths of steps make the movements look jumpy.
Broody - You say a SurfaceView is beter, however, this is not true after Android 3.0 as the View is HW accelerated but the canvas returned by .lockCanvas is not.
Steven - Yes, this is likely causing poroblems, but is easy to detect.
/Jacob