Please check this link. Following code is from this link. I am not sure why it says we have to use thread sleep to limit number of touch events.
I have a surfaceview and gamethread which processes events pushed by touch event. Is this sleep required or should I handle the sleep in gamethread instead by controlling framerate.
try {
Thread.sleep(16);
} catch (InterruptedException e) {
}
return true;
}
whole code
#Override
public boolean onTouchEvent(MotionEvent event) {
// we only care about down actions in this game.
try {
// history first
int hist = event.getHistorySize();
if (hist > 0) {
// add from oldest to newest
for (int i = 0; i < hist; i++) {
InputObject input = inputObjectPool.take();
input.useEventHistory(event, i);
gameThread.feedInput(input);
}
}
// current last
InputObject input = inputObjectPool.take();
input.useEvent(event);
gameThread.feedInput(input);
} catch (InterruptedException e) {
}
// don't allow more than 60 motion events per second
try {
Thread.sleep(16);
} catch (InterruptedException e) {
}
return true;
}
Your link points to an article that has been posted in 2009, you should really try to find one that is more up to date.
The code itself looks wrong, the author explains that his code is designed to avoid blocking the UI thread but then calls Thread.sleep(16) in onTouchEvent() which is called from the UI thread and blocks it.
What about this example? I haven't read it in detail, but the code looks much better : https://www.codeproject.com/Articles/827608/Android-Basic-Game-Loop
Related
I am new in Android (Java) coding . I have a small game program downloaded. In that to terminate the thread , have the code
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
try {
thread.setRunning(false);
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
retry = false;
}
}
Here the code author says if catch the exception , the code will go to try part not to the statement retry = false;
I could not believe that. please advise the flow is correct.
Please advise
Thanks
Anes
The loop will be run once. No matter if an Exception is thrown since retry will always be set to false after the first run. If you wanted the loop to continue until no Exception is thrown, you could place the retry = false; directly after the thread.join(); in the try block so it's only being called when you don't get to the catch block.
I want to make a program which will tell me the number of seconds I kept holding the button.
for example if I clicked the button for 5 seconds, it should tell me the button remained pressed for 5 seconds.
is this achievable in android?
This is how I tried, didn't work because when I put the while loop in, the button stays clicked even I press it for just one second. The program doesn't crash but the button remains clicked and I think it freezes.
thread = new HandlerThread("");
btn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
while(btn.isPressed())
{
try {
thread.sleep(1000);
total = total++;
temp = temp++;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Toast.makeText(MainActivity.this, ""+temp+" "+total, 0).show();
}
});
You could use time stamps, and an OnTouchListener to achieve this.
When your OnTouchListener receives an ACTION_DOWN event, store the first time stamp. When it receives an ACTION_UP event, store the second time stamp and calculate the difference between the two.
As mentioned by Raghunandan, you should never block on the UI thread using calls such as thread.sleep, as this will cause the UI to stop responding, and in some cases can cause the program to be killed because of this.
Here is an example of what I've outlined above. Please note, this code was written from memory, and has not been tested, but you should get the general gist of it.
btn.setOnTouchListener(new OnTouchListener() {
private long firstTouchTS = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_DOWN) {
this.firstTouchTS = System.currentTimeMillis();
} else if (event.getaction()==MotionEvent.ACTION_UP) {
Toast.makeText(MainActivity.this,((System.currentTimeMillis()-this.firstTouchTS)/1000)+" seconds",0).show();
}
}
});
References: OnTouchListener MotionEvent
thread.sleep(1000);
Calling sleep on the ui thread hence it freezes. Do not call sleep on the ui thread. It blocks the ui thread.
Read
http://developer.android.com/training/articles/perf-anr.html.
Use a Handler if you want to repeat some task
I am developing app and I need that my app will be doing two actions at the same time. For example - I can drag marker and the map will be scrolling at the same time.
I tried to update map while dragging marker, everything would be okay, except thing that when thread starts, maps starts scrolling continuously and I cand do anything more. Here is the code, I call it in onCreate() method. I tried to do Runnable and AsyncTask and the results were the same. Any suggestions?
private void update() {
new Thread() {
public void run() {
while (true) {
runOnUiThread(new Runnable() {
#Override
public void run() {
while (drag)
mMap.animateCamera(CameraUpdateFactory.scrollBy(10, 0), 2, null);
}
});
try {
Thread.sleep(2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
}
You don't have the code to interrupt your thread. That's why your map keep scrolling. Try to use drag event to drive this animation, and add some code to terminate the thread at some point.
I am making a board game. The board doesn't ever move, but pieces on top of it sometimes do depending on user interaction. There are also UI elements which may update periodically.
Right now the way I set it up is by overwriting the onDraw() method of a SurfaceView subclass. I have a drawing thread that constantly calls postInvalidate() in a while loop:
class PanelThread extends Thread
{
//...
long sleepTime = 0;
long nextGameTick = System.currentTimeMillis();
#Override
public void run()
{
Canvas c;
while (_run)
{ // When setRunning(false) occurs, _run is
c = null; // set to false and loop ends, stopping thread
try
{
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder)
{
// Insert methods to modify positions of items in onDraw()
_panel.postInvalidate();
}
} finally
{
if (c != null)
{
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
nextGameTick += MILLISECONDS_PER_FRAME;
sleepTime = nextGameTick - System.currentTimeMillis();
if(sleepTime >= 0)
{
try
{
sleep(sleepTime, 0);
} catch (InterruptedException e)
{
continue;
}
}
else
{
//we're behind, oh well.
System.out.println("behind!");
nextGameTick = System.currentTimeMillis();
}
}
}
This is not efficient and is taking a lot of CPU. Is there a easy way to get android to only update when something changes?
You have the right idea, but it needs a bit of refinement.
You definitely do not want to loop as fast as the CPU can handle it though.
You should be sleeping your Thread in every loop for a little while. You most certainly do not need to do everything in your loop every millisecond.
I found this guide to FPS control to be incredible helpful in designing a game loop.
This Android-specific game loop guide also provides a lot of great sample code and an in-depth explanation.
I am building a 2D game with Android SurfaceView. When I touch the screen the game animation runs slowly. Why, and how can I avoid this?
The touch events are stubs just like onTouchEvents(MotionEvents ev){ empty };. All of the game logic and graphics draw code are in run() in an extends Thread class.
Sleeping the UI thread for 16-20ms will keep the touch event handling code from being called too many times per second.
Example:
#Override
public boolean onTouchEvent(MotionEvent event) {
//Event handling logic
try {
Thread.sleep(16);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}
Touch events are dispatched as quickly as the UI thread can read them, by sleeping the thread you are able to skip a number of event dispatches. (Though not a noticeable amount for your game logic or the user)
Have you looked at the tutorials at http://www.droidnova.com ? They are good intro game tuts and ran very quickly when I did them. If they run slowly on your device with touch it is probably not a dev issue
#Override
public void run ( )
{
while(irunning)
{
while(paused)
{
sleep(2);
synchronized ( holder )
{
canvas = holder.lockCanvas(null);
//updateEvents();
//updatePsgstate();
//updateRole();
sortImages();
drawBgland();
drawImages();
drawAdminicle();
holder.unlockCanvasAndPost(canvas);
}
}
sleep(10);
}
}
#Override
public boolean dispatchTouchEvent ( MotionEvent ev )
{
try
{
Thread.sleep( 32 );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
synchronized ( ev )
{
Log.i( "T" , "onTouch" );
}
return true;
}
#Override
public void surfaceCreated(SurfaceHolder holder)
{
mThread.start();
// if (hasFocus())
// {
// return;
// }
// else
// {
// requestFocusFromTouch();
// }
}
this is base method that i used.
that's my code. any problem about it ?