270 likes | 458 Views
Android Game Development. Game level , game objects. Base project. Download our base project and open it in NetBeans cg.iit.bme.hu/ gamedev /KIC/11_AndroidDevelopment/11_02_Android_EngineBasics_Final.zip Change the android sdk location path Per-user properties ( local.properties )
E N D
Android Game Development Game level, gameobjects
Base project • Downloadourbase project and open it inNetBeans • cg.iit.bme.hu/gamedev/KIC/11_AndroidDevelopment/11_02_Android_EngineBasics_Final.zip • Changetheandroidsdklocationpath • Per-userproperties (local.properties) • sdk.dir=changepath here • Start an emulator • Build • Run
Game levels • The game is builtupfrom game objects (GameObjectclass) • Game objectsarethevisibleobjects, theactors of the game • Theyareunique • Theywill be managedbytheLevelclass • Ourlevelswill be generatedproceduralybytheLevelGeneratorclass • Theseclassesare game specific • PlacethemtothePlatformGamepackage and nottotheEngine
GameObject • CreatetheGameObjectclass public class GameObject { public enumObjectType{ Unknown, Ground, Pit, Floor1, Floor2, MainCharacter, Monster, UsefulThings, Item } protectedObjectType type = ObjectType.Unknown; protected String name; public GameObject(String name){ this.name = name; initImpl(); } public void setType(ObjectType type){ this.type = type; } public ObjectTypegetType(){ return type; } public String getName() { return this.name; } public void preUpdate(float t, float dt){} public void update(float t, float dt){} public void postUpdate(float t, float dt){} public void destroy(){} protectedvoidinitImpl(){} }
GenericGameObject I. • CreateGenericGameObjectclass publicclassGenericGameObjectextendsGameObject { protectedMeshEntityrenderO = null; protectedSceneNoderenderNode = null; publicGenericGameObject(Stringname, MeshEntityentity) { super(name); if (entity != null) { this.renderO = entity; this.renderNode = SceneManager.getSingleton().getRootNode().createChild(); this.renderNode.attachObject(this.renderO); } } publicvoiddestroy() { if (renderO != null) { renderNode.detachObject(renderO); renderNode.getParent().removeChild(renderNode); } }
GenericGameObject II. public void update(float t, float dt) { if (this.renderNode != null) { this.renderO.update(t, dt); } } public void setPosition(float x, float y, float z) { if (this.renderNode != null) { this.renderNode.setPosition(x, y, z); } } public void setOrientation(float yaw, float pitch, float roll) { if (this.renderNode != null) { this.renderNode.setOrientation(yaw, pitch, roll); } } public Vector3 getPosition() { return this.renderNode.getPosition(); } public Vector3 getVelocity() { return Vector3.ZERO; } public SceneNodegetRenderNode() { return renderNode; } }
Level I. • CreateLevelclass public class Level { private HashMap<String, GameObject> gameObjectMap = new HashMap(); private LinkedList<GameObject> gameObjects = new LinkedList(); public void update(float t, float dt) { for (GameObject o : this.gameObjects) o.update(t, dt); } public void preUpdate(float t, float dt) { for (GameObject o : this.gameObjects) o.preUpdate(t, dt); } public void postUpdate(float t, float dt) { for (GameObject o : this.gameObjects) o.postUpdate(t, dt); }
Level II. public void addGameObject(GameObject o) throws Exception { if (this.gameObjectMap.containsKey(o.getName())) { throw new Exception("Unable to add game object. Game object with the same name already exists : " + o.getName()); } this.gameObjectMap.put(o.getName(), o); this.gameObjects.add(o); } public void removeGameObject(String name){ GameObject go = gameObjectMap.get(name); if(go != null) { this.gameObjectMap.remove(name); this.gameObjects.remove(go); go.destroy(); } } public GameObjectgetGameObject(String name) { return (GameObject)this.gameObjectMap.get(name); } }
LevelGenerator I. • CreateLevelGeneratorclass public class LevelGenerator { protected Level level; protected intlevelSize = 30; protected float cameraFov; protected float cameraDist; protected float cameraAspect; public LevelGenerator(Level level, float cameraFov, float cameraAspect, float cameraDistance, Character2D mainCharacter) { this.cameraFov = maxCameraFov; this.cameraDist = maxCameraDistance; this.cameraAspect = cameraAspect; this.level = level; } public Point getPlayerStartPos(){ return new Point(-levelSize + 1, 0); }
LevelGenerator II. protected void createMaterial(String name, String textureName, boolean blended, inttextureRepeat){ Texture t1 = new Texture(name); t1.setFileName(textureName); t1.setRepeatU(textureRepeat); t1.load(); TextureManager.getSingleton().add(t1); Material m1 = new Material(name); m1.setTexture(t1); m1.load(); if(blended) m1.setAlhpaBlendMode(Material.ALPHA_BLEND_MODE_BLEND); MaterialManager.getSingleton().add(m1); } protected void createMaterials(){ createMaterial("g_Background", "g_background.jpg", false, 1); createMaterial("g_Middleground", "g_middleground.png", true, levelSize / 10); createMaterial("g_Ground", "g_ground.jpg", false, 1); createMaterial("Platform", "platform1.png", false, 1); createMaterial("g_Item", "g_item.png", false, 1); createMaterial("g_Box", "g_box.jpg", false, 1); }
LevelGenerator III. protected GenericGameObjectcreatePlane(String name, String materialName, float scaleX, float scaleY) throws Exception{ MeshEntity me = new MeshEntity(name, "UnitQuad"); me.setMeshScale(scaleX, scaleY, 1); me.setMaterial(materialName); GenericGameObject go = new GenericGameObject(name, me); level.addGameObject(go); return go; }
LevelGenerator IV. public Level generate() { if (level == null) { level = new Level(); } createMaterials(); try { //set up backgrounds float backgroundDist1 = 1000; float background1Width = (float) (cameraAspect * Math.tan(cameraFov * 0.5f) * (backgroundDist1 + cameraDist) + levelSize); float background1Height = (float) (Math.tan(cameraFov * 0.5f) * (backgroundDist1 + cameraDist)); GenericGameObject background1 = createPlane("background1", "g_Background", background1Width, background1Height); background1.setPosition(0, 0, -backgroundDist1); float backgroundDist2 = 30; float background2Width = (float) (cameraAspect * Math.tan(cameraFov * 0.5f) * (backgroundDist2 + cameraDist) + levelSize); float background2Height = (float) (Math.tan(cameraFov * 0.5f) * (backgroundDist2 + cameraDist)); GenericGameObject background2 = createPlane("background2", "g_Middleground", background2Width, background2Height); background2.setPosition(0, 0, -backgroundDist2); } catch(Exception e) { android.util.Log.e("LevelGenerator", "unable to generate level " + e.toString()); } return level; }
Try our classes • MainEngine: public class MainEngine { private long timeStart = 0; private long lastTime = 0; Level level; Camera camera; public void init(float ratio) { GLES10.glClearColor(0.5F, 0.5F, 1.0F, 1.0F); GLES10.glHint(GLES10.GL_PERSPECTIVE_CORRECTION_HINT, GLES10.GL_NICEST); try { camera = new Camera("mainCamera"); camera.setType(Camera.TYPE_PERSECTIVE); camera.setPerspFov(0.5f); camera.setNear(0.1f); camera.setFar(1100.0f); camera.setAspect(ratio); SceneNodecamNode = SceneManager.getSingleton().getRootNode().createChild(); camNode.attachObject(camera); }catch (Exception e){ android.util.Log.e("MainEngineinit","Unable to create camera ", e); } LevelGenerator LG = new LevelGenerator(null, 0.5f, ratio,12.0f); level = LG.generate(); camera.getParent().setPosition(LG.getPlayerStartPos().x, 0, 12.0f); }
Try our classes public void update() { //get elapsed time … level.preUpdate(t, dt); //update state level.update(t, dt); //render GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT | GLES10.GL_DEPTH_BUFFER_BIT); camera.apply(); SceneManager.getSingleton().render(); level.postUpdate(t, dt); }
Level generation I. • LevelGenerator new member variables: protected MeshEntitygroundME; protected MeshEntity floor1ME; protected MeshEntity floor2ME; // protected MeshEntitypitME;
Level generation II. • LevelGenerator new method: protected void createMeshes(){ try{ groundME = new MeshEntity("ground", "UnitQuad"); groundME.setMeshScale(1.0f, 1, 1); groundME.setMaterial("g_Ground"); //pitME = new MeshEntity("pit", "UnitQuad"); //pitME.setMeshScale(1.0f, 1, 1); //pitME.setMaterial("Pit"); //also create this material!! floor1ME = new MeshEntity("floor1", "UnitQuad"); floor1ME.setMeshScale(1.0f, 0.1f, 1); floor1ME.setMaterial("Platform"); floor2ME = new MeshEntity("floor2", "UnitQuad"); floor2ME.setMeshScale(1.0f, 0.1f, 1); floor2ME.setMaterial("Platform"); //we can choose an other material too }catch(Exception e){ android.util.Log.e("LevelGenerator", "Unable to create mesh entities " + e.getMessage()); } }
Level generation III. • LevelGenerator.generate() after createMaterials call: createMeshes(); • LevelGenerator.generate() after background creation: … for(inti = 0; i < 3; i++) { GenericGameObjectgroundL = new GenericGameObject("ground_l_" + i, groundME); groundL.setPosition(- levelSize - 2 * i - 1.0f, -3.f, 0); level.addGameObject(groundL); GenericGameObjectgroundR = new GenericGameObject("ground_r_" + i, groundME); groundR.setPosition(levelSize + 1.0f + 2.0f * i, -3.f, 0); level.addGameObject(groundR); }
Level generation IV. protected intgroundCount = 0; protected void createGroundElement(float posX) throws Exception{ GenericGameObject ground = new GenericGameObject("ground_" + groundCount, groundME); ground.setType(GameObject.ObjectType.Ground); ground.setPosition(posX, -3.f, 0); level.addGameObject(ground); groundCount++; } protected intpitCount = 0; protected void createPitElement(float posX) throws Exception{ GenericGameObject pit = new GenericGameObject("pit_" + pitCount, null);// , pitME); pit.setType(GameObject.ObjectType.Pit); pit.setPosition(posX, -4.5f, 0); level.addGameObject(pit); pitCount++; }
Level generation V. protected int floor1Count = 0; protected void createFloor1Element(float posX) throws Exception{ GenericGameObject floor1 = new GenericGameObject("floor1_" + floor1Count, floor1ME); floor1.setType(GameObject.ObjectType.Floor1); floor1.setPosition(posX, -0.8f, 0); level.addGameObject(floor1); floor1Count++; } protected int floor2Count = 0; protected void createFloor2Element(float posX) throws Exception{ GenericGameObject floor2 = new GenericGameObject("floor2_" + floor2Count, floor2ME); floor2.setType(GameObject.ObjectType.Floor2); floor2.setPosition(posX, 0.6f, 0); level.addGameObject(floor2); floor2Count++; }
Level generation VI. protected intmonsterCount = 0; protected void generateMonster(float x, float y)throws Exception{ } protected intitemCount = 0; protected void createItem(float x, float y) throws Exception{ } protected intboxCount = 0; protected void createBox(float x, float y) throws Exception{ }
Level generation VI. • generate() after border floors generation: for(inti = 0; i < levelSize; ++i){ float posX = (float) i * 2 - (float) levelSize + 1.0f; double r = Math.random(); if(r > 0.2f || i < 3){ createGroundElement(posX); if(i > 3){ double rm = Math.random(); if(rm > 0.8f){ generateMonster(posX, -1.0f); } double ri = Math.random(); if(ri > 0.4f){ createItem(posX, -2.0f); }else if(ri > 0.2f){ createBox(posX, -2.0f); } } } …
Level generation VI. else{ createPitElement(posX); } r = Math.random(); if(r > 0.6f){ createFloor1Element(posX); double ri = Math.random(); if(ri > 0.4f){ createItem(posX, -0.8f); }else if(ri > 0.2f){ createBox(posX, -0.8f); } r = Math.random(); if(r > 0.7f){ createFloor2Element(posX); ri = Math.random(); if(ri > 0.4f){ createItem(posX, 0.6f); }else if(ri > 0.2f){ createBox(posX, 0.6f); } } } }
Explore the level • MainEngineonTouchEvent: protected float lastX = 0; public booleanonTouchEvent(MotionEvent e) { if(e.getAction() == MotionEvent.ACTION_MOVE){ float x = e.getX(); float dx = (x - lastX) * 0.005f; Vector3 oldPos = camera.getParent().getPosition(); camera.getParent().setPosition(oldPos.x() + dx, oldPos.y(), oldPos.z()); } if(e.getAction() == MotionEvent.ACTION_DOWN){ lastX = e.getX(); } return true; }