android game development

33
Android Game Development Android basics

Upload: xanthe

Post on 22-Mar-2016

129 views

Category:

Documents


1 download

DESCRIPTION

Android Game Development. Android basics. About Android. Linux based operating system Open source Designed for handheld devices Developed by Android Inc. Google (2005) Open Handset Alliance (2007) Very successful system (75% sales in 2012). Top mobile operating systems. - PowerPoint PPT Presentation

TRANSCRIPT

Billboard, Particle System

Android Game Development Android basics1About AndroidLinux based operating systemOpen sourceDesigned for handheld devicesDeveloped byAndroid Inc.Google (2005)Open Handset Alliance (2007)Very successful system (75% sales in 2012)2Top mobile operating systems

Source: http://gs.statcounter.com

3Android basicsCan run Java code on Dalvik VMMulti-user system (each application is a different user)Unique user IDHas its own virtual machineHas its own Linux processPrinciple of least privilegeApplications can share dataThe Android system can run managed Java code on its own virtual machine, the Dalvik Virtual Machine (it is not compatible with Sun JVM). It is a multi user system where each application is run as a different user. The system gives a unique user ID to the processes. The system sets permissions for all the files in an application so that only the user ID assigned to that application can access them. The processes has their own virtual machine and run on their own Linux process. The Android system implements the principle of least privilege. That is, each application, by default, has access only to the components that it requires to do its work and no more. This creates a very secure environment in which an application cannot access parts of the system for which it is not given permission. However, there are ways for an application to share data with other applications and for an application to access system services.4Application componentsBuilding blocks of an application4 typesActivitySingle screen with UIServiceBackgroud process without UIContent providerManages a shared set of application dataBroadcast receiverResponds to system-wide broadcast announcementsApplication components are the essential building blocks of an Android application. There exists four types, from which we will talk about only Activities. An activity represents a single screen with a user interface.5ApplicationsAll components of an application runs in the same processThe system tries to keep a process as long as possibleApplications are stored in a stackThe systems duty to destroy the applicationsThe system uses importance hierarchyForeground processesVisible processService processBackground processEmpty processThe Android system tries to maintain an application process for as long as possible, but eventually needs to remove old processes to reclaim memory for new or more important processes. To determine which processes to keep and which to kill, the system places each process into an "importance hierarchy" based on the components running in the process and the state of those components. The started applications are stored in a stack, when pressing the back button the system switches to the previous application. Applications should not be closed by the application itself (though the API defines methods for this), they are destroyed by the system if needed. There are five levels in the importance hierarchy. An activity is a foreground process if it is the activity the user is interacting with. It is a visible process if it is not in the foreground but still visible (e.g. it is occluded by a dialog). A not visible activity is a background process. An empty process doesnt hold any active application components.6Activity lifecycle

And here we came to an important part we must be familiar with when writing our own activities: activity lifecycle.Detailed information can be found here:http://developer.android.com/guide/components/activities.htmlThe activities can be in three main states: activity starting, activity is running, activity is hut down. The entire lifecycle is between onCreate and onDestroy. The visible lifetime is between onStart and onStop. The foreground lifetime is between onResume and onPause. We have to implement these callbacks in our own activities properly.

It is important to realize that an activity can be killed after onDestroy, but after onStop and onPause too, is the system requires more resources. If this happens our activity will not receive any event about this, so we might consider saving important data even in onPause.7Android developmentAndriod SDK (http://developer.android.com/sdk)Java API libraries for different platformsSDK managerAVD Manager (emulator)Developer IDEEclipse with ADT (Juno has it by default)Netbeans with NBAndroid pluginAndroid device USB DriverEnable USB debuggingUseful link: http://developer.android.comLets make a list of what we need to develop our android application. First we need the Android SDK which contains the Java API libraries necessary to build for an Android platform. It has an SDk Manager tool from which we can easily download several target APIs, development tools or drivers. It also has a virtual device manager called AVD Manager, where we can create and run Andoid device emulators.

We need some IDE for effective development. Officially the Eclipse IDE is supported. The mobile version of Eclipse named Juno already contains an Android development plugin (Android Development Tools, ADT). We can also use NetBeans, and an additional plugin for it (NBAndroid). Both systems are easy to use and makes development much easier. In our projects we used NetBeans, but Eclipse can also be used if prefered.

We should also have an Android device to test our programs on a real system. Some device will need drivers from its vendors, some will work with drivers downloadable with the SDK manager. We should also set USB debugging enabled on our device.

We will make great use of the official android developer website.8IDE basicsNetBeanshttps://kenai.com/projects/nbandroid/pages/Installhttps://kenai.com/projects/nbandroid/pages/IntroEclipseFor ADT bundle everything is set uphttp://developer.android.com/sdk/installing/bundle.htmlFor Juno install is not required, for other existing Eclipse installs:http://developer.android.com/sdk/installing/adding-packages.htmlAdd platforms and packageshttp://developer.android.com/sdk/installing/adding-packages.htmlLittle bit more information on IDEs. For Netbeans we have to download a third party plugin NBAndroid. We can find detailed descriptions on how to install and set up the plugin and the Android environment on the project website.

If we choose to download the ADT bundle we will have a fully configured Eclipse IDE and Android SDK, we can start development right away. If we choose to install the SDK and Eclipse separately we have to download and configure the ADT plugin. The Juno version alredy contains the plugin so we only have to configure it.

After we set up our IDE we have to download at least one Android platform API. This can be done with the SDK manager.9Set up virtual devices

If we dont have a device connected to our PC we have to use an emulator, a virtual device to test our applications. We should always take into account that emulators are much slower that real devices, and some features might be missing (OpenGL ES 2.0 emulation is one of these). We can create virtual devices with opening the Android Virtual Device Manager (AVD manager)., and pressing the new button.10Set up virtual devices

PresetsA new dialog will pop up, where we can specify the details of the virtual device. The presets will probably be good starting configurations for us.11API levels

http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels :

API Level is an integer value that uniquely identifies the framework API revision offered by a version of the Android platform. Each successive version of the Android platform can include updates to the Android application framework API that it delivers. Updates to the framework API are designed so that the new API remains compatible with earlier versions of the API. That is, most changes in the API are additive and introduce new or replacement functionality. As parts of the API are upgraded, the older replaced parts are deprecated but are not removed, so that existing applications can still use them.

We can use the API level to state the minimal supported Android version of our application. We can also define the version our application is optimally designed for (target API level), and also the maximum Android version (newer platforms are usually maintain backward compatibility, but in some cases earlier features can be entirely removed for robustness reasons).12

API levelsSource: http://developer.android.com/about/dashboards/index.html

When starting to develop our application we should decide the API level we are building for. The lowest level we choose the more user can access our application, but we might not be able to use some important features (like OpenGL ES 2.0 and the programmable pipeline is not supported by Eclair or older systems). We should check the relative number of devices running a given version of the Android platform to make a good decision.13New Project (NetBeans)

Lets start to develop our first Android application. Open NetBeans and create a new Android Project.14New Project

The new project dialog will ask for the target API, which can be API level 7 (note that almost all of the currently used devices support this API level), ask for a package name and the name of the Activity.15New Project

After the project is created the project directory tree contains all the necessary files for our application. Here we should mention the ./src folder where the java source files are located, the ./gen folder where generated sources are placed, the ./res folder where resource files like layout files are. Layout files can define the UI elements that our application will use. These files has an easy to read xml format. From our code we can refer to the UI elements attributes and string defined in the xml files with their unique id number which is auto generated and will be defined in the R class.16AndroidManifest.xml

Our application versionActivity to startIcon label of our ActivityWe can change this to e.g.:MyPlatformGameOne important configuration file can be found in the root of the project directors and is called AndroidManifest.xml . Here we can give the version number of our application, the name of the activity to start, the name which should appear under our application icon. We can also add special permissions, min/target/max API level values, etc.17Start a virtual device

To test this base code we should start a virtual device. From AVD manager we can choose an already added virtual device and start it. It may take a while to boot, but after boot we will get full functional android interface. After running our applications we should not close the emulator because of the long loading time.18MainActivity.java:setContentView(R.layout.main);

Main.xml

Build and run the project

Now we can build and run our project. The application will be run on the first running virtual device. This application displays a message on screen. This message is displayed because we told that the main view we want to use should be loaded from a layout configuration, and this configuration is named main. Now the system will load the layout defined in the Main.xml, which defines a TextView with the given message.19OpenGL ES MainActivity.javaimport android.app.Activity;import android.opengl.GLSurfaceView;import android.os.Bundle;

public class MainActivity extends Activity{ private GLSurfaceView mGLView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mGLView = new MainSurfaceView(this); setContentView(mGLView); }}Now we make a big step and modify our code to create a OpenGL window. We can add views not only using predefined layout files, but also from code. We will use the GLSurfaceView class as a main view of our activity.We have to create an instance of our own MainSurfaceView class which extends GLSurfaceView and set it as content view.20OpenGL ES MainSurfaceView.javapackage gamedev.android.UEngine.PlatformGame;

import android.content.Context;import android.opengl.GLSurfaceView;

public class MainSurfaceView extends GLSurfaceView { private MainRenderer mRenderer; public MainSurfaceView(Context context) { super(context); this.mRenderer = new MainRenderer(getContext()); setRenderer(this.mRenderer); }}Create the MainSurfaceView.java file and paste these code lines to it. The MainSurfaceView extends the GLSurfaceView class. SurfaceView class is a blank area where we can draw and GLSurfaceView class is a draw area with an OpenGL context. GLSurfaceView classes will need a renderer class which controls what is drawn on the view.21OpenGL ES MainRenderer.javapackage gamedev.android.UEngine.PlatformGame;

import android.content.Context;import android.opengl.GLSurfaceView;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;

public class MainRenderer implements GLSurfaceView.Renderer{ private Context context; public MainRenderer(Context context) { this.context = context; } public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.5F, 0.5F, 1.0F, 1.0F); } public void onDrawFrame(GL10 gl) { gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT ); } public void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); }}Create the MainRenderer.java file and paste these code lines. This class is a GLSurfaceViewRenderer implementation and has callback functions when the OpenGL surface is created, changed (resized for e.g.), and when a new frame is drawn. When these callbacks are called the OpenGL context of the surface is ready, so we can now call OpenGL functions. If we have a look at this code we will find some familiar calls. Basically we have a wrapper class with type GL10, which has the same functions that are defined in the OpenGL API. So setting the clear color is simply calling the well known glClearColor method of the GL10 opject. Constants like GL_COLOR_BUFFER_BIT are also defined in this class. If we are familiar with glut for example we can say that we can place the initialization code we usually write before glutMainLoop in onSurfaceCreated. We place the code that handles window resize in onSurfaceChanged, and we should place rendering calls in onDrawFrame. By default onDrawFrame is called continuously, but we can also make it refresh only on demand.22Build and run

Now if we compile and run the application we should see a bluish background which was rendered with OpenGL.23Draw something - MainRendererNew importsimport java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;

New data memberprotected FloatBuffer VB = null;public float rotAngle = 0;Now we should really render something: a quad for example. Our quad will need a float buffer that stores the vertex coordinates, we make the VB datamember to store this buffer. The quad will continuously rotate and the current rotation angle is stored in rotAngle24Draw something - MainRendererpublic void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.5F, 0.5F, 1.0F, 1.0F); float[] VCoords = { -1.0F, -1.0F, 0.0F, 1.0F, -1.0F, 0.0F, 1.0F, 1.0F, 0.0F, -1.0F, -1.0F, 0.0F, 1.0F, 1.0F, 0.0F, -1.0F, 1.0F, 0.0F }; ByteBuffer vbb = ByteBuffer.allocateDirect(VCoords.length * 4); vbb.order(ByteOrder.nativeOrder()); this.VB = vbb.asFloatBuffer(); this.VB.put(VCoords); this.VB.position(0); }We have to create the vertex position buffer in initialization time: create a float array, fill it with vertex positions, and create a FloatBuffer from it.25Draw something - MainRendererpublic void onDrawFrame(GL10 gl) { gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT ); gl.glMatrixMode(gl.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0,0,-6); gl.glColor4f(1, 0, 0, 1); gl.glRotatef(rotAngle, 0, 1, 0); gl.glEnableClientState(gl.GL_VERTEX_ARRAY); gl.glVertexPointer(3, gl.GL_FLOAT, 0, this.VB); gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6); gl.glDisableClientState(gl.GL_VERTEX_ARRAY);

rotAngle += 2.5f; }Our drawing function will clear the window first, then fill up the transformation matrix with a translation and a rotation. The rotation angle will be incremented in each frame, the rotation axis is the up(y) direction. Rendering is done with vertex arrays. We set vertex color to a red color. This will keep its value until the next glColor.. call (remember the state machine behavior of render APIs). First we state that the vertex positions will be filled from a vertex array, we give the pointer to the data storing position information and tell that each vertex will have a 3 component float position data, and finally draw 2 triangles (6 vertex, 3 for each triangle). Note that we use OpenGL ES 1 here which is similar to OpenGL 1.3. We have all the fixed function things but glBegin-glEnd type of rendering is not allowed, we have to use vertex arrays.26Draw something - MainRendererpublic void onSurfaceChanged(GL10 gl, int width, int height) { gl.glViewport(0, 0, width, height); float ratio = (float) width / height; gl.glMatrixMode(gl.GL_PROJECTION); gl.glLoadIdentity(); gl.glFrustumf(-ratio, ratio, -1, 1, 1.0f, 10); }We should also set a projection matrix, we do it if the window is resized, as aspect ratio is needed. We used a perspective projection here.27Build and run

Build and run the project and you should see a rotating red quad.28Input handling - MainSurfaceViewprotected float lastX = -1; public boolean onTouchEvent(MotionEvent e) { float x = e.getX(); switch (e.getAction()) { case MotionEvent.ACTION_MOVE: float dx = lastX == -1 ? 0 : x - lastX; mRenderer.rotAngle += dx * 1.0f; break; } lastX = x; return true; }Also remove rotAngle += 2.5f;fromMainRenderer.onDrawFrameNow will see how to react to user touch events. The GLSurfaceView class will receive touch events in its onTouchEvent callback. From the input parameter we can get the information about the concrete position where the user touched the screen. This callback is similar to the mousemotionfunc and mousefunc callback of the glut system or other mouse input handler systems (like awt). We can modify our code to rotate the quad only if we move our finger horizontally on the touch screen.29Build and runQuad can be rotated with the mouse in emulatorOrientation Full screenFix orientation to landscape (typical in games)Activity::onCreate():setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); Set to full screen (typical in games) Activity::onCreate():requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);Rotate emulator to landscape mode: Ctrl+F12A few more little trick useful for games is to force landscape mode, or to make the surface as big as possible (fullscreen like behaviour). The emulators are in portrait mode by default, and we have no buttons to switch it to landscape mode, but we have a shortcut for it. Extend our code, build and run to try it!31Compile and run

Now we know the basics of Android development, we know how to draw triangles on screen using OpenGL. We also know how to handle user touch events. To create a basic game now we should design our game and write the logic behind it. For simple games we probably wont need much of the services the Android API provides, so we will not discuss them. In the next lessons we will build a simple engine that is reusable for many types of games, we learn how to load and apply a texture to our objects, how to add 2D physics, create animated textures and many more to finally build a platformer game.

The final project can be downloaded:http://cg.iit.bme.hu/gamedev/KIC/11_AndroidDevelopment/11_01_Android_Basics_Final.zip32The End33