Android Development - How to draw a 2d triangle

Published December 17, 2009
Advertisement
When it comes to game development on a new platform, the first step is to draw something on the screen. Since I am mainly doing 2d in 3d development, I will show you how to set up a 2d drawing area and display a triangle on the screen.

The first thing that needs to be done is to implement all of the necessary classes to use OpenGL ES. For a basic OpenGL ES application on Android, you will need to start with three classes. These classes are the Activity, View, and Renderer. I have provided a skeleton using classes with the names GameActivity, GameView, and GameRenderer:

GameActivity.java
package com.example.AndroidDev;import android.app.Activity;import android.os.Bundle;public class GameActivity extends Activity {    private GameView gameView;	    @Override    protected void onPause()    {        super.onPause();        gameView.onPause();    }        @Override    protected void onResume()    {        super.onResume();        gameView.onResume();    }    	    @Override    public void onCreate(Bundle savedInstanceState)     {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        gameView = new GameView(this);        setContentView(gameView);    }	}


GameView.java
package com.example.AndroidDev;import android.content.Context;import android.opengl.GLSurfaceView;public class GameView extends GLSurfaceView {    private GameRenderer renderer;	    public GameView(Context context)    {        super(context);        renderer = new GameRenderer();        setRenderer(renderer);        setFocusable(true);		    }}


GameRenderer.java
package com.example.AndroidDev;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLSurfaceView;public class GameRenderer implements GLSurfaceView.Renderer {    @Override    public void onSurfaceCreated(GL10 gl, EGLConfig config)     {    }     @Override    public void onSurfaceChanged(GL10 gl, int w, int h)     {        gl.glViewport(0, 0, w, h);    }     @Override    public void onDrawFrame(GL10 gl)     {        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);    }}


These base classes will handle everything necessary to run your Android application smoothly. When the user switches from your application, it will be paused until the user switches back to it.

The game will only be played in portrait mode so we will need to add two things to force the phone to stay in portrait mode. Your android project should have an AndroidManifest.xml file. Open this up and edit the xml. You will want to add the following line as an attribute to your activity element:

android:screenOrientation="portrait"


This will ensure that the application stays in portrait mode. Though, if the application starts in landscape mode, we should make sure that it is switched to portrait. Add the following line of code to the onCreate function in the GameActivity class:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);


At this point, you should be able to run the application in the emulator with the following result:

Blank Android Screen

Since we are doing 2d in 3d, we will need to set up an orthogonal projection. Not all androids have the same resolution screen, but most of them use 320x480. We will go ahead and use those dimensions for our screen coordinates. Here are the two functions that will enable and disable 2d drawing mode:

private void enable2d(GL10 gl){    gl.glMatrixMode(GL10.GL_PROJECTION);    gl.glPushMatrix();    gl.glLoadIdentity();    gl.glOrthof(0.0f, 320.0f, 480.0f, 0.0f, -1.0f, 1.0f);    gl.glMatrixMode(GL10.GL_MODELVIEW);    gl.glPushMatrix();    gl.glLoadIdentity();		}	private void disable2d(GL10 gl){    gl.glMatrixMode(GL10.GL_PROJECTION);    gl.glPopMatrix();       gl.glMatrixMode(GL10.GL_MODELVIEW);    gl.glPopMatrix();			}


These can be placed in the GameRenderer class.

The next function we will create will be a function to draw a triangle. This function will only draw a single triangle using the coordinates that you pass it. Obviously, you wouldn't want to use this function to draw a large number triangles.

private void drawTriangle(GL10 gl, float x1, float y1, float x2, float y2, float x3, float y3, float red, float green, float blue){    int numberVertices = 3;    int coordinatesPerVertex = 3;    int numberIndices = 3;    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);    // Create Vertex Buffer    ByteBuffer vBuffer = ByteBuffer.allocateDirect(numberVertices * coordinatesPerVertex * 4);    vBuffer.order(ByteOrder.nativeOrder());    FloatBuffer vertexBuffer = vBuffer.asFloatBuffer();    // Create Index Buffer    ByteBuffer iBuffer = ByteBuffer.allocateDirect(numberIndices * 2);    iBuffer.order(ByteOrder.nativeOrder());    ShortBuffer indexBuffer = iBuffer.asShortBuffer();    // Specify the vertices of the triangle    float[] coords = {        x1, y1, 0.0f, // (x1, y1, z1)        x2, y2, 0.0f, // (x2, y2, z2)        x3, y3, 0.0f // (x3, y3, z3)    };    // Specify the order the triangle is to be drawn in    short[] indices = {0, 1, 2};    // Place vertices and indices in the buffers    vertexBuffer.put(coords);    indexBuffer.put(indices);    // Set the buffer position back to zero    vertexBuffer.position(0);    indexBuffer.position(0);    gl.glColor4f(red, green, blue, 1.0f);    gl.glVertexPointer(coordinatesPerVertex, GL10.GL_FLOAT, 0, vertexBuffer);    gl.glDrawElements(GL10.GL_TRIANGLES, numberIndices, GL10.GL_UNSIGNED_SHORT, indexBuffer);    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);}


I have added comments so you can better understand what is being done in the function. OpenGL ES does not have the begin and end functions found in OpenGL. Instead, you must create vertex and index buffers to draw objects.

To people who may be used to rendering things in a game loop, it may not be apparent what you need to do to draw things each frame. The onDrawFrame function in the GameRenderer class is called automatically for you in a separate thread. This is where you place all of your rendering code. Using the code that we have now, I decided to render a Triforce. Here is the code and the result:

@Overridepublic void onDrawFrame(GL10 gl) {    gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);    enable2d(gl);    drawTriangle(gl, 160.0f, 100.0f, 110.0f, 200.0f, 210.0f, 200.0f, 1.0f, 1.0f, 0.0f);    drawTriangle(gl, 110.0f, 200.0f, 60.0f, 300.0f, 160.0f, 300.0f, 1.0f, 1.0f, 0.0f);    drawTriangle(gl, 210.0f, 200.0f, 160.0f, 300.0f, 260.0f, 300.0f, 1.0f, 1.0f, 0.0f);    disable2d(gl);}


Here is the final result:

Triforce

Next time I will show you how to load textures and create a blit function. This is actually a fairly easy thing to do. Unfortunately, some android phones will not load the textures correctly using helper functions. That means you have to write all the conversion code yourself.
0 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement
Advertisement