package com.arretadogames.pilot.render.opengl; import android.app.Activity; import android.opengl.GLES11; import android.opengl.GLSurfaceView; import android.opengl.GLU; import android.view.MotionEvent; import android.view.SurfaceHolder; import com.arretadogames.pilot.MainActivity; import com.arretadogames.pilot.config.GameSettings; import com.arretadogames.pilot.game.Game; import com.arretadogames.pilot.loading.FontLoader; import com.arretadogames.pilot.loading.FontLoader.FontTypeFace; import com.arretadogames.pilot.loading.FontSpecification; import com.arretadogames.pilot.screens.InputEventHandler; import com.arretadogames.pilot.util.Profiler; import com.arretadogames.pilot.util.Profiler.ProfileType; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; /** * GameGLSurfaceView class represents a GLSurfaceView specific for our Game, * which has operations to draw and perform the logic on the Game set into this * class */ public class GameGLSurfaceView extends GLSurfaceView implements GLSurfaceView.Renderer { private GLCanvas gameCanvas; // FPS Settings private float[] fpsBuffer; private int fpsCounter; private FontSpecification fpsFont; private Activity activity; /** * Creates a GameGLSurfaceView using the given context * * @param context * Context to be used */ public GameGLSurfaceView(MainActivity activity) { super(activity); this.activity = activity; } @Override public void onDrawFrame(GL10 gl) { if (GameSettings.DisplayWidth == -1 || GameSettings.DisplayHeight == -1) { GameSettings.DisplayWidth = getWidth(); GameSettings.DisplayHeight = getHeight(); GameSettings.WidthRatio = GameSettings.DisplayWidth / GameSettings.TARGET_WIDTH; GameSettings.HeightRatio = GameSettings.DisplayHeight / GameSettings.TARGET_HEIGHT; } if (Game.getInstance() != null) { run(gl); } } private long frameEndedTime; public void run(GL10 gl) { /* * This method runs the Game Loop and manage the time between each frame */ if (frameEndedTime == 0) frameEndedTime = getCurrentTime(); long frameCurrentTime = getCurrentTime(); float elapsedTime = (frameCurrentTime - frameEndedTime) / 1000f; Profiler.initTick(ProfileType.BASIC); // Game Loop Game.getInstance().step(elapsedTime); Profiler.profileFromLastTick(ProfileType.BASIC, "Game Step Speed"); Profiler.initTick(ProfileType.BASIC); gameCanvas.setGLInterface(gl); gameCanvas.initiate(); Game.getInstance().render(gameCanvas, elapsedTime); Profiler.profileFromLastTick(ProfileType.BASIC, "Game Render Speed"); // End Game Loop // Wait to complete 1/60 of a second long millisToWait = getTargetMilli(frameCurrentTime) - getCurrentTime(); if (millisToWait > 0) { try { synchronized (this) { wait(millisToWait); } } catch (InterruptedException e) { e.printStackTrace(); } } if (GameSettings.SHOW_FPS) { fpsBuffer[fpsCounter] = (1000f/(getCurrentTime() - frameCurrentTime)); fpsCounter = ++fpsCounter % fpsBuffer.length; gameCanvas.drawText("FPS: " + getAverageFPS(), 10, 20, fpsFont, 0.8f, false); } frameEndedTime = frameCurrentTime; int error = GLES11.glGetError(); if (error != 0) { System.out.println("OpenGL Error: " + GLU.gluErrorString(error)); } } private int getAverageFPS() { float sum = 0; for (int i = 0 ; i < fpsBuffer.length ; i++) { sum += fpsBuffer[i]; } return (int) (sum / fpsBuffer.length); } private long getCurrentTime() { return System.nanoTime()/1000000; } private long getTargetMilli(long timeBefore) { return (long) (1000.0 / GameSettings.TARGET_FPS) + timeBefore; } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // Sets the current view port to the new size. GLES11.glViewport(0, 0, width, height); // Select the projection matrix GLES11.glMatrixMode(GL10.GL_PROJECTION); // Reset the projection matrix GLES11.glLoadIdentity(); // Orthographic mode for 2d GLU.gluOrtho2D(gl, 0, width, -height, 0); // Select the modelview matrix GLES11.glMatrixMode(GL10.GL_MODELVIEW); // Reset the modelview matrix GLES11.glLoadIdentity(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // SETTINGS // Set the background color to black ( rgba ). GLES11.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // DRAWING SETUP // NOTES: As we are always drawing with textures and viewing our // elements from the same side all the time we can leave all these // settings on the whole time // Enable face culling. GLES11.glEnable(GL10.GL_CULL_FACE); // What faces to remove with the face culling. GLES11.glCullFace(GL10.GL_BACK); // Enable Transparency GLES11.glEnable(GL10.GL_BLEND); GLES11.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA); // There is a change on SplashScreen and StageSelection } @Override public void surfaceDestroyed(SurfaceHolder holder) { } @Override public boolean onTouchEvent(MotionEvent event) { Game.getInstance().input(new InputEventHandler(event)); return super.onTouchEvent(event); } public void init() { // Specifies the use of OpenGL 2.0 setEGLContextClientVersion(1); // Specifies the Renderer and starts the Rendering Thread setRenderer(this); // Set OnTouchListener setOnTouchListener((MainActivity)activity); gameCanvas = new GLCanvas(); getHolder().setFixedSize((int) GameSettings.TARGET_WIDTH, (int) GameSettings.TARGET_HEIGHT); if (GameSettings.SHOW_FPS) { fpsBuffer = new float[GameSettings.FPS_AVG_BUFFER_SIZE]; for (int i = 0 ; i < fpsBuffer.length ; i++) { fpsBuffer[i] = 0; // initialize all 0 } fpsCounter = 0; fpsFont = FontLoader.getInstance().getFont(FontTypeFace.TRANSMETALS); } } }