Ok, like I said I may have missed something, but say I have something like this:
class MyThread extends Thread { run() { while (something) { if (something_else) //perhaps input has changed, or we have data in a socket { //do some work, not idle } else { //no work to do } Thread.sleep(x); //maybe needed, based on implementation } } } So, say I have the game loop logic in a thread like that, using the render fps average as a counter, I've noticed that the fps drops when using more than one thread, even if it's just running in an empty loop. Using a looper object forces me to communicate with the thread by posting messages to its handler. Say I have a network thread that just got a message and wants to let the game loop of a new data available, or the UI thread wants to let the game loop know that the input state has changed. It can be done using a handler, or using a lock to protect a data buffer. So say in the game logic loop we constantly check the state of some variable and doing work accordingly, I have found it's much faster to use a lock around an object than it is to post to a handler. The way I remember timing this was I would constantly send network data to the network thread with a timestamp, then I would check how long it took for that message to make it to the game loop by determining the time difference. I was working directly with bytes, as to avoid any sort of serialization overhead. The game loop I'm using is SUPPOSED to be 60fps but will undoubtedly vary, I use the Timer class's scheduleAtFixedRate to automatically take care of the timestep adjustments/wait time. Since the timer class uses a thread pool, it doesn't have an overhead of thread creation. I don't have to handle calculating how long to sleep to maintain a constant rate, and is quite efficient. I've achieved a smooth display, and the physics progresses a step at each game loop iteration. This has worked well for me. On Sat, Apr 10, 2010 at 12:57 PM, Bob Kerns <r...@acm.org> wrote: > If a thread is hogging the CPU, it is *BY DEFINITION* not idle. And > vice versa. > > An idle thread will be waiting on something. Either a synchronization > lock, or an object using wait(), or some blocking IO call. This may be > buried inside some other code, of course. > > I would suggest wondering why you thought this. How are you > determining what threads are consuming what CPU? Either you have some > sort of methodology error, or interpretation error. > > I would wonder about your statement about a Looper and Handler being > slow. I haven't read the code, but the implementation I would expect > would be very simple, and using wait/notify. In other words, they > SHOULD be fast. If you find them slow, I'd again check your > methodology -- and if you can confirm, I'd suggest filing a bug > report, since that's something that could be improved and would > improve things for the entire platform. > > Re 60 fps game logic -- some alternatives to consider that may be > better choices in some circumstances. I'm only considering physics > here; I'm not sure what the time constraints on other game logic might > be: > > If you're doing your physics calculations correctly, you won't be > constrained to a constant game logic rate. You may be able to vary > your simulation time step to maintain a more steady render rate (at > the cost of some accuracy), and even vary it between different parts > of the model, e.g. critical portions (e.g. collisions) run a higher > rate, while running a longer timestep for portions not subject to time- > varying forces. > > If smooth display is more important than physical accuracy, running > physics after each frame, driven by actual elapsed time, may be the > way to go. You can trigger that as you're about to flip the scene, so > it overlaps the GPU. You may prioritize your fast-moving stuff, and > only update a portion of your model on each frame. > > Also, you may be able to apply Level of Detail (LOD) control to your > scene -- including fewer polygons when the overall frame rate drops > (due to either graphics or physics). > > All that is a lot more complex, of course, but may let you push the > envelope a bit further. > > On Apr 9, 7:42 pm, Miguel Morales <therevolti...@gmail.com> wrote: >> I may be completely wrong on this, but I've found that threads hog the >> CPU even when idle. >> >> The way that has worked well for me is to have the render thread, and >> the logic timer. >> >> (using a looper and communicating via a handler can be slow, from my >> experience locks are faster) >> >> To keep things simply I use a TimerTask to simulate a 60fps game logic >> rate (game_loop_timer.schedule(game_loop_task, 0, 17);). The game >> logic rate can vary based on what needs to be done. (i.e pathfinding, >> network syncing, etc.) and sets a scene to the buffer. >> >> The render thread stays constant by simply drawing what's on the scene >> buffer at every onDraw. >> >> I use a single lock to keep the scene buffer safe between the two threads. >> >> It's actually pretty simple, and I only really need two classes. >> >> I highly recommend reading articles about this, here are some of my >> bookmarks:http://gafferongames.com/game-physics/fix-your-timestep/http://stackoverflow.com/questions/87304/calculating-frames-per-secon... >> >> For input, I use a lock for the state of the hardware. (i.e. when the >> screen is being touched, I set a boolean isTouched to true and use a >> lock to safely read/write from the threads. However, a queue/handler >> is really the way to go when it comes to that since it's not as >> time/latency sensitive. >> >> >> >> On Fri, Apr 9, 2010 at 6:29 PM, Lance Nanek <lna...@gmail.com> wrote: >> > There are a lot of built in classes in Android and Java that you can >> > use to avoid having to write any synchronization or lock code >> > yourself. In my case GLSurfaceView sets up my render thread. I use >> > HandlerThread for my game thread. The game thread sends an update >> > object detailing all the draw commands needed for a frame to the >> > render thread via a BlockingQueue. The render thread returns it via >> > the game thread's Handler. The UI thread tells the game thread about >> > input via the game thread's Handler as well. These classes are in the >> > android.os and java.util.concurrent packages. >> >> > On Apr 9, 6:36 pm, Eddie Ringle <ed...@eringle.net> wrote: >> >> Okay, I figured I could just pass the Activity through parameters, but >> >> wanted to know if a better way was possible. >> >> Thanks for all the help everyone. >> >> >> On Apr 9, 5:56 pm, Mario Zechner <badlogicga...@gmail.com> wrote: >> >> >> > That depends on what kind of input you need. If your game is happy >> >> > with just checking the current state of the accelerometer/touch screen/ >> >> > keyboard/trackball simply polling will do the trick. This means that >> >> > in the UI thread, where you have your event listeners installed, you >> >> > simply save the last state reported to you. In your logic thread you >> >> > can savely access this state even without synchronization as it will >> >> > only be composed of plain old data types like booleans or ints (of >> >> > course there are cases where you catch the x coordinate of the >> >> > previous event and the y coordinate of the current event but i dare >> >> > say that the differences are so tiny, it doesn't make a difference). >> >> >> > Other things might need event based input handling, like a GUI you >> >> > implement yourself with say OpenGL. In that case you will need a queue >> >> > that gets filled in the Android GUI thread by the listeners you have >> >> > installed for the input devices. The logic thread acts as a consumer >> >> > and takes the events from the queue. As you are working with a complex >> >> > data structure you need to synchronize the adding and removing of >> >> > events to and from the queue in both the Android GUI thread and your >> >> > logic thread. This is a classical consumer/producer pattern which can >> >> > be found frequently in multithreaded applications. Check out Robert's >> >> > site athttp://www.rbgrn.net, i think he wrote an article on that sort >> >> > of thing once. >> >> >> > it basicaly boils down to this (pseudo code, written from the top of >> >> > my head, will not compile) >> >> >> > public class GameActivity extends Activity implements >> >> > MotionEventListener >> >> > { >> >> > Queue<Event> events = new Queue<Event>(); >> >> >> > public void onTouch( MotionEvent event ) >> >> > { >> >> > synchronized( events ) >> >> > { >> >> > events.add( new Event( event.getX(), event.getY() ); >> >> > } >> >> > } >> >> >> > } >> >> >> > public class GameLogic >> >> > { >> >> > GameActivity activity; >> >> >> > public GameLogic( GameActivity activity ) >> >> > { >> >> > this.activity = activity; >> >> > } >> >> >> > public void handleInput( ) >> >> > { >> >> > synchronized( gameActivity.events ) >> >> > { >> >> > // proces events here >> >> > } >> >> > } >> >> >> > } >> >> >> > Now, a couple of comments: You don't want to instantiate a new Event >> >> > everytime a listener method in the GameActivity is called. You will >> >> > need to implement a simple object pool and reuse events. That way the >> >> > garbage collector will stay calm. Also note that the design above is a >> >> > bit nasty, i would directly pass the GameActivity to the GameLogic >> >> > among other things. But that's up to you. >> >> >> > Polling input handling would work like above but without a queue and >> >> > without the need for the synchronized blocks. All you do is set some >> >> > members of GameActivity, say touchX and touchY in the onTouch method >> >> > and read those values in the GameLogic class' handleInput method. >> >> >> > hth, >> >> > Mario >> >> >> > On 9 Apr., 22:39, Eddie Ringle <ed...@eringle.net> wrote: >> >> >> > > Robert, >> >> >> > > Silly question, but how do you get input to the logic thread? I have >> >> > > to get sensor and touch data from the main Activity class and somehow >> >> > > get it to the logic thread. >> >> >> > > Current program flow is as follows: >> >> > > onCreate() -> GameView() -> World() & Renderer() & GameLogic() >> >> >> > > On Apr 9, 3:24 pm, Robert Green <rbgrn....@gmail.com> wrote: >> >> >> > > > Eddie, >> >> >> > > > Yes, that'll do the trick. >> >> >> > > > As far as the multiple threads goes, sure you can drive your logic >> >> > > > off >> >> > > > of the call to onDrawFrame but there is a situation in which having >> >> > > > a >> >> > > > separate thread makes sense: >> >> >> > > > After onDrawFrame, the rendering thread is finishing/swapping. That >> >> > > > can actually take a decent amount of time to do in certain cases and >> >> > > > most of it is happening on the GPU, especially on a device like the >> >> > > > Droid which has a discrete CPU/GPU. During that time, the CPU is >> >> > > > available and can be used on the logic thread. Properly >> >> > > > implemented, >> >> > > > in a heavy scene you can get some or all of the logic processed >> >> > > > before >> >> > > > the rendering thread is ready again, which is why I favor it. >> >> >> > > > My question is: onDrawFrame is only called once the GPU is ready >> >> > > > for >> >> > > > another draw. Why waste those precious GPU idle moments just doing >> >> > > > CPU stuff like physics and collisions? You can maximize with >> >> > > > another >> >> > > > thread. >> >> >> > > > Also - 2 (game and UI) or 3 threads (game logic, rendering and UI) >> >> > > > does make sense because you never want to block the UI thread in >> >> > > > Android. Get out of its way as fast as possible! :) >> >> >> > > > On Apr 9, 1:58 pm, Eddie Ringle <ed...@eringle.net> wrote: >> >> >> > > > > Is it as simple as: >> >> >> > > > > In GameView.java (my custom GLSurfaceView class): >> >> > > > > World _world = new World(); >> >> >> > > > > GameRenderer _renderer = new GameRenderer(_world); >> >> >> > > > > In GameRenderer.java: >> >> > > > > public World _world; >> >> >> > > > > public GameRenderer(World world) >> >> > > > > { >> >> > > > > _world = world; >> >> >> > > > > } >> >> >> > > > > In GameRenderer.java, _world would now have the address of world, >> >> > > > > which is the address of GameView.java's _world, right? >> >> >> > > > > On Apr 9, 2:49 pm, Eddie Ringle <ed...@eringle.net> wrote: >> >> >> > > > > > One more thing question and I think I will be set. Coming from >> >> > > > > > a C/C++ >> >> > > > > > background, I enjoyed the use of references. I know that there >> >> > > > > > is a >> >> > > > > > way to pass the reference by value in Java, but am not quite >> >> > > > > > clear on >> >> > > > > > how. Could I, for example, create my World object, then pass >> >> > > > > > that >> >> > > > > > object to the renderer and logic objects when I create them? I >> >> > > > > > did a >> >> > > > > > small bit of reading on this topic, but still am not quite sure. >> >> >> > > > > > On Apr 9, 1:55 pm, Robert Green <rbgrn....@gmail.com> wrote: >> >> >> > > > > > > Yeah, you're going to want to model your game like you would >> >> > > > > > > model the >> >> > > > > > > real world: >> >> >> > > > > > > class World { >> >> > > > > > > public Player player; >> >> > > > > > > public Enemy[] enemies; >> >> > > > > > > public int timeLeft; >> >> > > > > > > public int level; >> >> > > > > > > //etc.. >> >> >> > > > > > > } >> >> >> > > > > > > Then you update the world (usually by calls to player.update, >> >> > > > > > > enemy.update, etc) from your logic thread. >> >> >> > > > > > > Then what I like to do is separate the rendering stuff from >> >> > > > > > > the >> >> > > > > > > simulation so that I have renderers for specific things: >> >> >> > > > > > > class PlayerRenderer extends BaseRenderer { >> >> > > > > > > // knows about player geometry, knows how to draw the >> >> > > > > > > player and >> >> > > > > > > anything player-related.. >> >> >> > > > > > > } >> >> >> > > > > > > Then in my main Renderer, I just call out to the individual >> >> > > > > > > component >> >> > > > > > > renderers: >> >> >> > > > > > > class WorldRenderer implements Renderer { >> >> > > > > > > onDrawFrame(GL gl) { >> >> > > > > > > // clear, set up projection, etc >> >> > > > > > > playerRenderer.draw(gl, world.player); >> >> > > > > > > enemyRenderer.draw(gl, world.enemies); >> >> > > > > > > // etc.. >> >> > > > > > > } >> >> >> > > > > > > } >> >> >> > > > > > > And that's how I do it. I have just a little bit of >> >> > > > > > > initialization >> >> > > > > > > communication from the Renderer side to the game logic so >> >> > > > > > > that we can >> >> > > > > > > set up positioning of touchable UI components but otherwise >> >> > > > > > > it's >> >> > > > > > > always GameThread updates World, WorldRenderer >> >> ... >> >> read more » > > -- > You received this message because you are subscribed to the Google > Groups "Android Developers" group. > To post to this group, send email to android-developers@googlegroups.com > To unsubscribe from this group, send email to > android-developers+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/android-developers?hl=en > > To unsubscribe, reply using "remove me" as the subject. > -- http://diastrofunk.com, http://developingthedream.blogspot.com/, http://www.youtube.com/user/revoltingx, ~Isaiah 55:8-9 -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To post to this group, send email to android-developers@googlegroups.com To unsubscribe from this group, send email to android-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/android-developers?hl=en