6.8.14. CannonThread: Using a Thread to Create a Game Loop

Figure 6.20 defines a subclass of Thread which updates the game. The thread maintains a reference to the SurfaceView’s SurfaceHolder (line 538) and a boolean indicating whether the thread is running. The class’s run method (lines 556–587) drives the frame-by-frame animations—this is known as the game loop. Each update of the game elements on the screen is performed based on the number of milliseconds that have passed since the last update. Line 559 gets the system’s current time in milliseconds when the thread begins running. Lines 561–586 loop until threadIsRunning is false.


535      // Thread subclass to control the game loop
536      private class CannonThread extends Thread
537      {
538         private SurfaceHolder surfaceHolder; // for manipulating canvas
539         private boolean threadIsRunning = true; // running by default
540
541         // initializes the surface holder
542         public CannonThread(SurfaceHolder holder)
543         {
544            surfaceHolder = holder;
545            setName("CannonThread");
546         }
547
548         // changes running state
549         public void setRunning(boolean running)
550         {
551            threadIsRunning = running;
552         }
553
554         // controls the game loop
555         @Override
556         public void run()
557         {
558            Canvas canvas = null; // used for drawing
559            long previousFrameTime = System.currentTimeMillis();
560
561            while (threadIsRunning)
562            {
563               try
564               {
565                  // get Canvas for exclusive drawing from this thread
566                  canvas = surfaceHolder.lockCanvas(null);
567
568                  // lock the surfaceHolder for drawing
569                  synchronized(surfaceHolder)         
570                  {
571                     long currentTime = System.currentTimeMillis();
572                     double elapsedTimeMS = currentTime - previousFrameTime;
573                     totalElapsedTime += elapsedTimeMS / 1000.0 ;
574                     updatePositions(elapsedTimeMS); // update game state
575                     drawGameElements(canvas); // draw using the canvas  
576                     previousFrameTime = currentTime; // update previous time
577                  }
578               }
579               finally
580               {
581                  // display canvas's contents on the CannonView
582                  // and enable other threads to use the Canvas 
583                  if (canvas != null)                           
584                     surfaceHolder.unlockCanvasAndPost(canvas); 
585               }
586            } // end while
587         } // end method run
588      } // end nested class CannonThread
589   } // end class CannonView


Fig. 6.20 | Runnable that updates the game every TIME_INTERVAL milliseconds.

First we obtain the Canvas for drawing on the SurfaceView by calling SurfaceHolder method lockCanvas (line 566). Only one thread at a time can draw to a SurfaceView. To ensure this, you must first lock the SurfaceHolder by specifying it as the expression in the parentheses of a synchronized block (line 569). Next, we get the current time in milliseconds, then calculate the elapsed time and add that to the total time so far—this will be used to help display the amount of time left in the game. Line 574 calls method updatePositions to move all the game elements, passing the elapsed time in milliseconds as an argument. This ensures that the game operates at the same speed regardless of how fast the device is. If the time between frames is larger (i.e, the device is slower), the game elements will move further when each frame of the animation is displayed. If the time between frames is smaller (i.e, the device is faster), the game elements will move less when each frame of the animation is displayed. Finally, line 575 draws the game elements using the SurfaceView’s Canvas and line 576 stores the currentTime as the previousFrameTime to prepare to calculate the elapsed time between this animation frame and the next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset