3-A basic game loop

Source: Internet
Author: User
Tags gety
Document directory
  • Add and screen interaction

So far, we have understood the structure of the game. Even if you simply know that you have received the input, updated the internal status, and then rendered to the screen, it also plays a sound or vibrate.

 

Let's keep it simple and look at the chart below

In Android, everything happens inside the activity. The activity creates a new view, where the view is where everything happens, like a touch and a final picture. Think of activity as a table, while view is a piece of white paper that allows us to draw things. We use a pencil to draw things. The chemical reactions are all on paper, which produces pictures. It is also suitable for activity and view, as shown in

 

Let's open droidzactivity. Java and check this line of code.

1 setContentView(R.layout.main);

The activity only assigns R. layout. View to the activity during creation. In our example, the value is assigned at the beginning.

Let's create a new view. A view is a simple class that provides event processing and visible rectangles for us to draw. The simplest thing is to expand the surfaceview of Android, we also need to implement surface. callback to obtain the path of the surface change, for example, when the view is destroyed or the device direction changes

Maingamepanel. Java

01 package net.obviam.droidz;  02    03 import android.content.Context;  04 import android.graphics.Canvas;  05 import android.view.MotionEvent;  06 import android.view.SurfaceHolder;  07 import android.view.SurfaceView;  08    09 public class MainGamePanel extends SurfaceView implements 10         SurfaceHolder.Callback {  11    12     public MainGamePanel(Context context) {  13         super(context);  14         // adding the callback (this) to the surface holder to intercept events  15         getHolder().addCallback(this);  16         // make the GamePanel focusable so it can handle events  17         setFocusable(true);  18     }  19    20     @Override 21     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  22     }  23    24     @Override 25     public void surfaceCreated(SurfaceHolder holder) {  26     }  27    28     @Override 29     public void surfaceDestroyed(SurfaceHolder holder) {  30     }  31    32     @Override 33     public boolean onTouchEvent(MotionEvent event) {  34         return super.onTouchEvent(event);  35     }  36    37     @Override 38     protected void onDraw(Canvas canvas) {  39     }  40 } 

 

The above Code only overwrites the methods we are interested in. Except for lines 15 and 17, there is nothing special about others.

1 getHolder().addCallback(this);

This line of code sets the current class as the handler to be processed for events occurring on the actual surface

1 setFocusable(true);

The above Code enables the game panel to get the focus, in order to get the event. We added a callback and made the view focus. We will not lose this view.

The method rewritten after 20 rows will be used, but now let them be empty

Let's create a thread, which will be our actual game loop

01 package net.obviam.droidz;  02    03 public class MainThread extends Thread {  04    05     // flag to hold game state  06     private boolean running;  07     public void setRunning(boolean running) {  08         this.running = running;  09     }  10    11     @Override 12     public void run() {  13         while (running) {  14             // update game state  15             // render state to the screen  16         }  17     }  18 

You can see that it does not do much, and overwrites the run method. When the running mark is true, an infinite loop is made.

The current process is not instantiated. When the screen is loaded, let's run it.

Let's take a look at the modified maingamepanel class.

 

01 package net.obviam.droidz;  02    03 import android.content.Context;  04 import android.graphics.Canvas;  05 import android.view.MotionEvent;  06 import android.view.SurfaceHolder;  07 import android.view.SurfaceView;  08    09 public class MainGamePanel extends SurfaceView implements 10         SurfaceHolder.Callback {  11    12     private MainThread thread;  13    14     public MainGamePanel(Context context) {  15         super(context);  16         getHolder().addCallback(this);  17    18         // create the game loop thread  19         thread = new MainThread();  20    21         setFocusable(true);  22     }  23    24     @Override 25     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  26     }  27    28     @Override 29     public void surfaceCreated(SurfaceHolder holder) {  30         thread.setRunning(true);  31         thread.start();  32     }  33    34     @Override 35     public void surfaceDestroyed(SurfaceHolder holder) {  36         boolean retry = true;  37         while (retry) {  38             try {  39                 thread.join();  40                 retry = false;  41             } catch (InterruptedException e) {  42                 // try again shutting down the thread  43             }  44         }  45     }  46    47     @Override 48     public boolean onTouchEvent(MotionEvent event) {  49         return super.onTouchEvent(event);  50     }  51    52     @Override 53     protected void onDraw(Canvas canvas) {  54     }  55 } 

We added the following code lines:

Row 12 declares that the thread is private.

1 private
MainThread thread;

19 rows. We instantiate this thread.

1 thread = newMainThread();

InsurfaceCreatedMethod We setRunningFlag
True
And we start up the thread (lines 30 and 31). By the time the this method is called the surface is already created and the game loop can be safely started.

Take a look atsurfaceDestroyedMethod.

In the surfacecreated method, we set running to true, and then let the thread start running (lines 30 and 31 ). When the surface is created, the game loop can start running safely.

Let's take a look at the surfacedestroy method.

01 public void surfaceDestroyed(SurfaceHolder holder) {  02     // tell the thread to shut down and wait for it to finish  03     // this is a clean shutdown  04     boolean retry = true;  05     while (retry) {  06         try {  07             thread.join();  08             retry = false;  09         } catch (InterruptedException e) {  10             // try again shutting down the thread  11         }  12     }  13 } 

This method is called before the surface is destroyed. This is not the place where the running mark is set, but the code here ensures that the thread is cleanly closed. We just block the thread and wait for its death.

If we run it on a simulator, we won't be able to see it at all, but we can test it with some logs. Don't worry, I will tell you what is going on later, for more information, see Android site.

Add and screen interaction

We close the program. When we press below the screen, If we click somewhere else, we just record the coordinates.

Add the following lines to the mainthread class:

1 private SurfaceHolder surfaceHolder;  2 private MainGamePanel gamePanel;  3 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {  4     super();  5     this.surfaceHolder = surfaceHolder;  6     this.gamePanel = gamePanel;  7 } 

We declared the variables gamepanel and surfaceholder, and instantiated them in the constructor.

It is very important for us to own them, not just gamepanel, because we need to lock the surface for drawing, and this operation can only be performed through surfaceholder

Change the method in the constructor

1 thread = newMainThread(getHolder(),this);

We passed the current holder and panel, so the thread can access them. We will create a new game update function in the game Panel later, and it will be triggered in the thread, but now we keep the status quo

The tag constant is the first parameter of the android log function.

Log note

Open the log view,

Now you should see the logcat view. this is nothing more than a console where you can follow Android's log. it's a great tool as you can filter for logs containing a specific text or logs with a certain tag which is quite useful.

Back to the Code, mainthread. Java is now like this

01 package net.obviam.droidz;  02  03 import android.util.Log;  04 import android.view.SurfaceHolder;  05  06 public class MainThread extends Thread {  07  08 private static final String TAG = MainThread.class.getSimpleName();  09  10 private SurfaceHolder surfaceHolder;  11 private MainGamePanel gamePanel;  12 private boolean running;  13 public void setRunning(boolean running) {  14 this.running = running;  15 }  16  17 public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {  18 super();  19 this.surfaceHolder = surfaceHolder;  20 this.gamePanel = gamePanel;  21 }  22  23 @Override 24 public void run() {  25 long tickCount = 0L;  26 Log.d(TAG, "Starting game loop");  27 while (running) {  28 tickCount++;  29 // update game state  30 // render state to the screen  31 }  32 Log.d(TAG, "Game loop executed " + tickCount + " times");  33 }  34 } 

In line 8, we define the log tag

In the run function, we define tickcount. When the game loop is executed, it will add 1

Let's go back to the maingamepanel. Java class. Let's modify ontouchevent to process the touch message.

01 public boolean onTouchEvent(MotionEvent event) {  02 if (event.getAction() == MotionEvent.ACTION_DOWN) {  03 if (event.getY() > getHeight() - 50) {  04 thread.setRunning(false);  05 ((Activity)getContext()).finish();  06 } else {  07 Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());  08 }  09 }  10 return super.onTouchEvent(event);  11 } 

Also, droidzactivity is modified.

 
01 package net.obviam.droidz;  02  03 import android.app.Activity;  04 import android.os.Bundle;  05 import android.util.Log;  06 import android.view.Window;  07 import android.view.WindowManager;  08  09 public class DroidzActivity extends Activity {  10 /** Called when the activity is first created. */ 11  12 private static final String TAG = DroidzActivity.class.getSimpleName();  13  14 @Override 15 public void onCreate(Bundle savedInstanceState) {  16 super.onCreate(savedInstanceState);  17 // requesting to turn the title OFF  18 requestWindowFeature(Window.FEATURE_NO_TITLE);  19 // making it full screen  20 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);  21 // set our MainGamePanel as the View  22 setContentView(new MainGamePanel(this));  23 Log.d(TAG, "View added");  24 }  25  26 @Override 27 protected void onDestroy() {  28 Log.d(TAG, "Destroying...");  29 super.onDestroy();  30 }  31  32 @Override 33 protected void onStop() {  34 Log.d(TAG, "Stopping...");  35 super.onStop();  36 }  37 } 

Run the program, click a few times in the upper part of the program, and then click the lower part. The program should exit.

 

Logcat

 

 

Current Tasks

1. Created a full screen program.

2. There is an independent thread control program

3 parse basic gestures, such as touch gestures

4. Close the program elegantly

You can download the code here.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.