Java tutorial
package com.davidykay.shootout; /* * Copyright 2010 Mario Zechner (contact@badlogicgames.com), Nathan Sweet (admin@esotericsoftware.com) * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ import java.io.InputStream; import java.util.ArrayList; import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Graphics; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.Mesh; import com.badlogic.gdx.graphics.PerspectiveCamera; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.graphics.VertexAttribute; import com.badlogic.gdx.graphics.VertexAttributes.Usage; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g3d.loaders.ModelLoaderOld; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.math.Vector3; import com.davidykay.shootout.simulation.Alien; import com.davidykay.shootout.simulation.Block; import com.davidykay.shootout.simulation.Explosion; import com.davidykay.shootout.simulation.RayShot; import com.davidykay.shootout.simulation.Ship; import com.davidykay.shootout.simulation.Simulation; /** * The renderer receives a simulation and renders it. * @author mzechner * */ public class Renderer { private static final String TAG = "Renderer"; /** sprite batch to draw text **/ private SpriteBatch spriteBatch; /** the moon mesh **/ private Mesh moonMesh; /** the moon texture **/ private Texture moonTexture; /** the ship mesh **/ private Mesh shipMesh; /** the ship texture **/ private Texture shipTexture; /** the alien mesh **/ private Mesh alienMesh; /** the alien texture **/ private Texture alienTexture; /** the block mesh **/ private Mesh blockMesh; /** the shot mesh **/ private Mesh shotMesh; /** the ray mesh **/ private Mesh rayMesh; /** the background texture **/ private Texture backgroundTexture; /** the earth texture **/ private Texture earthTexture; /** the explosion mesh **/ private Mesh explosionMesh; /** the explosion texture **/ private Texture explosionTexture; /** the bomb explosion texture **/ private Texture bombExplosionTexture; /** the font **/ private BitmapFont font; /** the rotation angle of all aliens around y **/ private float alienAngle = 0; /** status string **/ private String status = ""; /** keeping track of the last score so we don't constantly construct a new string **/ private int lastScore = 0; private int lastLives = 0; private int lastWave = 0; /** view and transform matrix for text rendering **/ private Matrix4 viewMatrix = new Matrix4(); private Matrix4 transformMatrix = new Matrix4(); /** perspective camera **/ private PerspectiveCamera camera; public Renderer(Application app) { try { spriteBatch = new SpriteBatch(); InputStream in = Gdx.files.internal("data/emplacement.obj").read(); shipMesh = ModelLoaderOld.loadObj(in); in.close(); in = Gdx.files.internal("data/moon.obj").read(); moonMesh = ModelLoaderOld.loadObj(in); in.close(); //in = Gdx.files.internal("data/alien.obj").read(); in = Gdx.files.internal("data/ufo.obj").read(); alienMesh = ModelLoaderOld.loadObj(in); in.close(); in = Gdx.files.internal("data/block.obj").read(); blockMesh = ModelLoaderOld.loadObj(in); in.close(); //in = Gdx.files.internal("data/shot.obj").read(); //in = Gdx.files.internal("data/laser.obj").read(); in = Gdx.files.internal("data/bomb.obj").read(); shotMesh = ModelLoaderOld.loadObj(in); in.close(); rayMesh = shotMesh; moonTexture = new Texture(Gdx.files.internal("data/moon.png"), Format.RGB565, true); moonTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear); shipTexture = new Texture(Gdx.files.internal("data/battery.png"), Format.RGB565, true); shipTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear); //alienTexture = new Texture(Gdx.files.internal("data/alien.png"), Format.RGB565, true); alienTexture = new Texture(Gdx.files.internal("data/ufo.png"), Format.RGB565, true); alienTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear); //alienTexture.setFilter(TextureFilter.MipMap, TextureFilter.MipMap); //alienTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); backgroundTexture = new Texture(Gdx.files.internal("data/starfield512.png"), Format.RGB565, true); backgroundTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear); earthTexture = new Texture(Gdx.files.internal("data/marble128.jpg"), Format.RGB565, true); earthTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear); explosionTexture = new Texture(Gdx.files.internal("data/explode.png"), Format.RGBA4444, true); explosionTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear); bombExplosionTexture = new Texture(Gdx.files.internal("data/explode-bomb.png"), Format.RGBA4444, true); bombExplosionTexture.setFilter(TextureFilter.MipMap, TextureFilter.Linear); explosionMesh = new Mesh(true, 4 * 16, 0, new VertexAttribute(Usage.Position, 3, "a_position"), new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord")); float[] vertices = new float[4 * 16 * (3 + 2)]; int idx = 0; for (int row = 0; row < 4; row++) { for (int column = 0; column < 4; column++) { vertices[idx++] = 1; vertices[idx++] = 1; vertices[idx++] = 0; vertices[idx++] = 0.25f + column * 0.25f; vertices[idx++] = 0 + row * 0.25f; vertices[idx++] = -1; vertices[idx++] = 1; vertices[idx++] = 0; vertices[idx++] = 0 + column * 0.25f; vertices[idx++] = 0 + row * 0.25f; vertices[idx++] = -1; vertices[idx++] = -1; vertices[idx++] = 0; vertices[idx++] = 0f + column * 0.25f; vertices[idx++] = 0.25f + row * 0.25f; vertices[idx++] = 1; vertices[idx++] = -1; vertices[idx++] = 0; vertices[idx++] = 0.25f + column * 0.25f; vertices[idx++] = 0.25f + row * 0.25f; } } explosionMesh.setVertices(vertices); font = new BitmapFont(Gdx.files.internal(ShootOut.FONT10_FNT), Gdx.files.internal(ShootOut.FONT10_PNG), false); camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); } catch (Exception ex) { ex.printStackTrace(); } } public void render(Application app, Simulation simulation) { GL10 gl = app.getGraphics().getGL10(); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glViewport(0, 0, app.getGraphics().getWidth(), app.getGraphics().getHeight()); renderBackground(gl); renderEarth(gl); gl.glDisable(GL10.GL_DITHER); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_CULL_FACE); //setProjectionAndCamera(app.getGraphics(), simulation.ship, app); setProjectionAndCameraAugmentedReality(app.getGraphics(), simulation, app); setLighting(gl); gl.glEnable(GL10.GL_TEXTURE_2D); renderMoon(gl, simulation.ship); renderShip(gl, simulation.ship, app); renderAliens(gl, simulation.aliens); gl.glDisable(GL10.GL_TEXTURE_2D); renderBlocks(gl, simulation.blocks); gl.glDisable(GL10.GL_LIGHTING); //renderShots(gl, simulation.shots); //renderRays(gl, simulation.mRays, true); renderAlienRays(gl, simulation.mAlienRays); renderPlayerRays(gl, simulation.mShipRays); gl.glEnable(GL10.GL_TEXTURE_2D); renderExplosions(gl, simulation.explosions); renderBombExplosions(gl, simulation.bombExplosions); gl.glDisable(GL10.GL_CULL_FACE); gl.glDisable(GL10.GL_DEPTH_TEST); spriteBatch.setProjectionMatrix(viewMatrix); spriteBatch.setTransformMatrix(transformMatrix); spriteBatch.begin(); if (simulation.ship.lives != lastLives || simulation.score != lastScore || simulation.wave != lastWave) { status = "lives: " + simulation.ship.lives + " wave: " + simulation.wave + " score: " + simulation.score; lastLives = simulation.ship.lives; lastScore = simulation.score; lastWave = simulation.wave; } spriteBatch.enableBlending(); spriteBatch.setBlendFunction(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA); font.draw(spriteBatch, status, 0, 320); spriteBatch.end(); alienAngle += app.getGraphics().getDeltaTime() * 90; if (alienAngle > 360) alienAngle -= 360; } private void renderBackground(GL10 gl) { // TODO: Eliminate fixed number ortho projection. //viewMatrix.setToOrtho2D(0, 0, 400, 320); viewMatrix.setToOrtho2D(0, 0, 480, 320); spriteBatch.setProjectionMatrix(viewMatrix); spriteBatch.setTransformMatrix(transformMatrix); spriteBatch.begin(); spriteBatch.disableBlending(); spriteBatch.setColor(Color.WHITE); spriteBatch.draw(backgroundTexture, 0, 0, 480, 320, 0, 0, 512, 512, false, false); spriteBatch.end(); } private void renderEarth(GL10 gl) { // TODO: Eliminate fixed number ortho projection. final int TEXTURE_SIZE = 128; viewMatrix.setToOrtho2D(0, 0, 480, 320); spriteBatch.setProjectionMatrix(viewMatrix); spriteBatch.setTransformMatrix(transformMatrix); spriteBatch.begin(); spriteBatch.disableBlending(); spriteBatch.setColor(Color.WHITE); spriteBatch.draw(earthTexture, 288, 48, TEXTURE_SIZE, TEXTURE_SIZE, 0, 0, TEXTURE_SIZE, TEXTURE_SIZE, false, false); spriteBatch.end(); } final Vector3 dir = new Vector3(); private void setProjectionAndCameraAugmentedReality(Graphics graphics, Simulation simulation, Application app) { //camera.position.set(0, 6, 2); //camera.direction.set(0, 0, -4).sub(camera.position).nor(); //camera.rotate(simulation.getPitch() , 1 , 0 , 0); //camera.rotate(simulation.getRoll() , 0 , 1 , 0); //camera.rotate(simulation.getAzimuth() , 0 , 0 , 1); // Note that these are taken from StackOverflow: // http://stackoverflow.com/questions/5274514/how-do-i-use-the-android-compass-orientation-to-aim-an-opengl-camera camera.position.set(0, 1, 2); camera.direction.set(0, 0, 1); camera.up.set(0, 1, 0); camera.rotate(simulation.getAzimuth(), 0, 1, 0); Vector3 pivot = camera.direction.cpy().crs(camera.up); camera.rotate(simulation.getPitch(), pivot.x, pivot.y, pivot.z); camera.rotate(simulation.getRoll(), camera.direction.x, camera.direction.y, camera.direction.z); camera.update(); camera.apply(Gdx.gl10); } private void setProjectionAndCamera(Graphics graphics, Ship ship, Application app) { //camera.position.set(ship.position.x, 6, 2); camera.position.set(0, 6, 2); camera.direction.set(ship.position.x, 0, -4).sub(camera.position).nor(); camera.update(); camera.apply(Gdx.gl10); } float[] direction = { 1, 0.5f, 0, 0 }; private void setLighting(GL10 gl) { gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, direction, 0); gl.glEnable(GL10.GL_COLOR_MATERIAL); } private void renderMoon(GL10 gl, Ship ship) { moonTexture.bind(); gl.glPushMatrix(); final float MOON_RADIUS = 10.0f; final float MOON_SCALE = MOON_RADIUS; //gl.glTranslatef(ship.position.x, ship.position.y - MOON_RADIUS, ship.position.z); gl.glTranslatef(0.0f, ship.position.y - MOON_RADIUS, 0.0f); gl.glScalef(MOON_SCALE, MOON_SCALE, MOON_SCALE); //gl.glRotatef(45 * (-app.getInput().getAccelerometerY() / 5), 0, 0, 1); //gl.glRotatef(180, 0, 1, 0); moonMesh.render(GL10.GL_TRIANGLES); gl.glPopMatrix(); } private void renderShip(GL10 gl, Ship ship, Application app) { if (ship.isExploding) return; shipTexture.bind(); gl.glPushMatrix(); gl.glTranslatef(ship.position.x, ship.position.y, ship.position.z); gl.glRotatef(45 * (-app.getInput().getAccelerometerY() / 5), 0, 0, 1); gl.glRotatef(180, 0, 1, 0); shipMesh.render(GL10.GL_TRIANGLES); gl.glPopMatrix(); } private void renderAliens(GL10 gl, ArrayList<Alien> aliens) { alienTexture.bind(); for (int i = 0; i < aliens.size(); i++) { Alien alien = aliens.get(i); gl.glPushMatrix(); gl.glTranslatef(alien.position.x, alien.position.y, alien.position.z); gl.glRotatef(alienAngle, 0, 1, 0); alienMesh.render(GL10.GL_TRIANGLES); gl.glPopMatrix(); } } private void renderBlocks(GL10 gl, ArrayList<Block> blocks) { gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); gl.glColor4f(0.2f, 0.2f, 1, 0.7f); for (int i = 0; i < blocks.size(); i++) { Block block = blocks.get(i); gl.glPushMatrix(); gl.glTranslatef(block.position.x, block.position.y, block.position.z); blockMesh.render(GL10.GL_TRIANGLES); gl.glPopMatrix(); } gl.glColor4f(1, 1, 1, 1); gl.glDisable(GL10.GL_BLEND); } // private void renderShots (GL10 gl, ArrayList<Shot> shots) { // gl.glColor4f(1, 1, 0, 1); // for (int i = 0; i < shots.size(); i++) { // Shot shot = shots.get(i); // gl.glPushMatrix(); // gl.glTranslatef(shot.position.x, shot.position.y, shot.position.z); // shotMesh.render(GL10.GL_TRIANGLES); // gl.glPopMatrix(); // } // gl.glColor4f(1, 1, 1, 1); // } private void renderPlayerRays(GL10 gl, ArrayList<RayShot> rays) { //0, 215, 237 gl.glColor4f(0, 215 / 255.0f, 237 / 255.0f, 1); for (RayShot ray : rays) { gl.glPushMatrix(); gl.glTranslatef(ray.position.x, ray.position.y, ray.position.z); gl.glScalef(ray.radius, ray.radius, ray.radius); rayMesh.render(GL10.GL_TRIANGLES); gl.glPopMatrix(); } // Reset color to white?. gl.glColor4f(1, 1, 1, 1); } private void renderAlienRays(GL10 gl, ArrayList<RayShot> rays) { gl.glColor4f(1, 1, 0, 1); for (RayShot ray : rays) { gl.glPushMatrix(); gl.glTranslatef(ray.position.x, ray.position.y, ray.position.z); gl.glScalef(ray.radius, ray.radius, ray.radius); rayMesh.render(GL10.GL_TRIANGLES); gl.glPopMatrix(); } // Reset color to white?. gl.glColor4f(1, 1, 1, 1); } private void renderExplosions(GL10 gl, ArrayList<Explosion> explosions) { gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); explosionTexture.bind(); for (int i = 0; i < explosions.size(); i++) { Explosion explosion = explosions.get(i); gl.glPushMatrix(); gl.glTranslatef(explosion.position.x, explosion.position.y, explosion.position.z); explosionMesh.render(GL10.GL_TRIANGLE_FAN, (int) ((explosion.aliveTime / Explosion.EXPLOSION_LIVE_TIME) * 15) * 4, 4); gl.glPopMatrix(); } gl.glDisable(GL10.GL_BLEND); } private void renderBombExplosions(GL10 gl, ArrayList<Explosion> explosions) { gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); bombExplosionTexture.bind(); for (int i = 0; i < explosions.size(); i++) { Explosion explosion = explosions.get(i); gl.glPushMatrix(); gl.glTranslatef(explosion.position.x, explosion.position.y, explosion.position.z); explosionMesh.render(GL10.GL_TRIANGLE_FAN, (int) ((explosion.aliveTime / Explosion.EXPLOSION_LIVE_TIME) * 15) * 4, 4); gl.glPopMatrix(); } gl.glDisable(GL10.GL_BLEND); } //////////////////////////////////////// // Utility //////////////////////////////////////// public Camera getCamera() { return camera; } public void unproject(Vector3 touchLocation) { Vector3 newLocation = new Vector3(touchLocation); camera.unproject(touchLocation); //Gdx.app.log(TAG, String.format("unproject from: (%s) to: (%s)", // newLocation.toString(), // touchLocation.toString() // )); } public void dispose() { spriteBatch.dispose(); shipTexture.dispose(); alienTexture.dispose(); backgroundTexture.dispose(); explosionTexture.dispose(); font.dispose(); explosionMesh.dispose(); shipMesh.dispose(); alienMesh.dispose(); shotMesh.dispose(); blockMesh.dispose(); } }