/******************************************************************************* * Copyright 2015 See AUTHORS file. * <p/> * 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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. ******************************************************************************/ package com.mygdx.game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.assets.loaders.ModelLoader; import com.badlogic.gdx.assets.loaders.TextureLoader; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g3d.Model; import com.badlogic.gdx.graphics.g3d.particles.ParticleEffectLoader; import com.badlogic.gdx.graphics.g3d.particles.ParticleSystem; import com.badlogic.gdx.graphics.g3d.particles.batches.BillboardParticleBatch; import com.badlogic.gdx.graphics.glutils.MipMapGenerator; import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.physics.bullet.Bullet; import com.badlogic.gdx.physics.bullet.collision.btBoxShape; import com.badlogic.gdx.physics.bullet.collision.btCapsuleShape; import com.badlogic.gdx.physics.bullet.linearmath.btIDebugDraw.DebugDrawModes; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Bits; import com.badlogic.gdx.utils.viewport.FitViewport; import com.badlogic.gdx.utils.viewport.Viewport; import com.mygdx.game.blender.objects.BlenderEmpty; import com.mygdx.game.gdxkit.LoadableGdxScreen; import com.mygdx.game.objects.*; import com.mygdx.game.scene.GameObjectBlueprint; import com.mygdx.game.scene.GameScene; import com.mygdx.game.scene.GameSceneManager; import com.mygdx.game.settings.DebugViewSettings; import com.mygdx.game.settings.GameSettings; import com.mygdx.game.utilities.CameraController; import com.mygdx.game.utilities.GhostCamera; import com.mygdx.game.utilities.ModelFactory; import com.mygdx.game.utilities.Sounds; /** * @author jsjolund */ public class GameScreen extends LoadableGdxScreen<GdxDemo3D> { private final static String TAG = "GameScreen"; public static GameScreen screen; private final Viewport viewport; public GameStage stage; public final GameEngine engine; public final Sounds sounds; private final Color viewportBackgroundColor; private final GhostCamera camera; private final ShapeRenderer viewportBackgroundRenderer; private CameraController cameraController; private final GameRenderer renderer; private final GameSceneManager sceneManager; private final GameScene defaultScene; public GameScreen(GdxDemo3D game) { super(game); // FIXME Ugly hack to access the screen from anywhere GameScreen.screen = this; camera = new GhostCamera(GameSettings.CAMERA_FOV, GdxDemo3D.WIDTH, GdxDemo3D.HEIGHT); camera.near = GameSettings.CAMERA_NEAR; camera.far = GameSettings.CAMERA_FAR; camera.update(); viewport = new FitViewport(GdxDemo3D.WIDTH, GdxDemo3D.HEIGHT, camera); Bullet.init(); MipMapGenerator.setUseHardwareMipMap(true); ModelLoader.ModelParameters modelParameters = new ModelLoader.ModelParameters(); modelParameters.textureParameter.genMipMaps = true; modelParameters.textureParameter.minFilter = Texture.TextureFilter.MipMap; modelParameters.textureParameter.magFilter = Texture.TextureFilter.Linear; TextureLoader.TextureParameter textureParameter = new TextureLoader.TextureParameter(); textureParameter.genMipMaps = true; textureParameter.minFilter = Texture.TextureFilter.MipMap; textureParameter.magFilter = Texture.TextureFilter.Linear; ParticleSystem particleSystem = ParticleSystem.get(); BillboardParticleBatch pointSpriteBatch = new BillboardParticleBatch(); pointSpriteBatch.setCamera(camera); particleSystem.add(pointSpriteBatch); ParticleEffectLoader.ParticleEffectLoadParameter peLoadParam = new ParticleEffectLoader.ParticleEffectLoadParameter(particleSystem.getBatches()); sounds = new Sounds(); engine = new GameEngine(); viewportBackgroundColor = Color.BLACK; renderer = new GameRenderer(viewport, camera, engine); viewportBackgroundRenderer = new ShapeRenderer(); sceneManager = new GameSceneManager(modelParameters, textureParameter, peLoadParam, "particles/", "models/g3db/", ".g3db"); // Create a default scene, which will be the game world. defaultScene = sceneManager.open("scene0"); // Add placeholders consisting of blender objects to the scene, loaded from blender json. // These will later be used in various ways to spawn actual game objects. // The reason for this decoupling is that some models have their collision shapes defined as Blender empties, // coupled by matching string ids. These are later compared, and used for creating game object blueprints. defaultScene.assets.load("models/json/scene0.json"); // Since blender placeholder objects from different .blend scenes might have string name collisions, // load each into a new scene then distribute shared object blueprints among game scenes (only one scene so far). sceneManager.open("human_scene").assets.load("models/json/human.json"); sceneManager.open("dog_scene").assets.load("models/json/dog.json"); } @Override public void loadingFinished() { // Create some game object blueprints which will be shared between game scenes. sceneManager.open("utils_scene").assets.manageDisposableFromPath("marker", "images/marker.png", Texture.class); Texture texture = sceneManager.open("utils_scene").assets.getAsset("marker", Texture.class); Model billboardModel = ModelFactory.buildBillboardModel(texture, 1, 1); sceneManager.open("utils_scene").assets.manageDisposable("markerModel", billboardModel, Model.class); GameObjectBlueprint markerBlueprint = new GameObjectBlueprint(); markerBlueprint.name = "marker"; markerBlueprint.model = billboardModel; sceneManager.addSharedBlueprint("marker", markerBlueprint); GameObjectBlueprint humanBlueprint = new GameObjectBlueprint(); humanBlueprint.position = new Vector3(); humanBlueprint.rotation = new Vector3(); humanBlueprint.scale = new Vector3(1, 1, 1); humanBlueprint.model = sceneManager.open("human_scene").assets.getAsset("human", Model.class); humanBlueprint.name = "human"; humanBlueprint.shape = new btCapsuleShape(0.4f, 1.1f); humanBlueprint.shapeType = "capsule"; // TODO: Create enums humanBlueprint.mass = 1; humanBlueprint.noDeactivate = true; humanBlueprint.ragdollEmpties = new Array<BlenderEmpty>(); sceneManager.open("human_scene").assets.getAllPlaceholders(BlenderEmpty.class, humanBlueprint.ragdollEmpties); humanBlueprint.armatureNodeId = "armature"; humanBlueprint.belongsToFlag = GameEngine.PC_FLAG; humanBlueprint.collidesWithFlag = (short) (GameEngine.OBJECT_FLAG | GameEngine.GROUND_FLAG); sceneManager.addSharedBlueprint("human", humanBlueprint); GameObjectBlueprint dogBlueprint = new GameObjectBlueprint(); dogBlueprint.position = new Vector3(); dogBlueprint.rotation = new Vector3(); dogBlueprint.scale = new Vector3(0.3f, 0.3f, 0.3f); dogBlueprint.model = sceneManager.open("dog_scene").assets.getAsset("dog", Model.class); dogBlueprint.name = "dog"; dogBlueprint.shape = new btCapsuleShape(0.4f, 0.5f); dogBlueprint.shapeType = "capsule"; dogBlueprint.mass = 1; dogBlueprint.noDeactivate = true; dogBlueprint.armatureNodeId = "armature"; dogBlueprint.belongsToFlag = GameEngine.PC_FLAG; dogBlueprint.collidesWithFlag = (short) (GameEngine.OBJECT_FLAG | GameEngine.GROUND_FLAG); sceneManager.addSharedBlueprint("dog", dogBlueprint); GameObjectBlueprint stickBlueprint = new GameObjectBlueprint(); stickBlueprint.position = new Vector3(); stickBlueprint.rotation = new Vector3(); stickBlueprint.scale = new Vector3(0.3f, 0.3f, 0.3f); stickBlueprint.model = sceneManager.open("dog_scene").assets.getAsset("stick", Model.class); stickBlueprint.name = "stick"; Array<BlenderEmpty> emptiesWithId = new Array<BlenderEmpty>(); sceneManager.open("dog_scene").assets.getPlaceholders("stick", BlenderEmpty.class, emptiesWithId); stickBlueprint.shape = new btBoxShape(new Vector3(emptiesWithId.first().scale).scl(0.3f)); stickBlueprint.shapeType = emptiesWithId.first().custom_properties.get("collision_shape"); stickBlueprint.mass = Float.parseFloat(emptiesWithId.first().custom_properties.get("mass")); stickBlueprint.noDeactivate = true; // Generate collision callback in GameEngine when stick collides with something. stickBlueprint.callback = true; stickBlueprint.belongsToFlag = GameEngine.OBJECT_FLAG; // Don't collide with human and dog, causes problems when throwing. stickBlueprint.collidesWithFlag = (short) (GameEngine.GROUND_FLAG | GameEngine.OBJECT_FLAG); stickBlueprint.visibleOnLayers = new Bits(); stickBlueprint.visibleOnLayers.set(0); sceneManager.addSharedBlueprint("stick", stickBlueprint); // Spawn game objects for the house, ground, trees and stuff, // which were defined in the blender scene json. defaultScene.spawnGameObjectsFromPlaceholders(); defaultScene.setToSceneCamera(camera); renderer.setEnvironmentLights(defaultScene.lights, defaultScene.shadowCameraDirection); Billboard markerBillboard = defaultScene.spawnSelectionBillboard("marker", camera); renderer.setSelectionMarker(markerBillboard); cameraController = new CameraController(camera); cameraController.setWorldBoundingBox(defaultScene.worldBounds); stage = new GameStage(engine, viewport, cameraController); stage.addObserver(renderer); stage.addObserver(engine); // Create humans by supplying the name of the shared blueprint "human", along with position HumanCharacter[] humans = new HumanCharacter[]{ defaultScene.spawnHuman("human", new Vector3(20, 1, 0), 0), defaultScene.spawnHuman("human", new Vector3(24, 1, -5)), defaultScene.spawnHuman("human", new Vector3(20, 1, 5)), }; // Create dogs by supplying the name of the shared blueprint "dog", along with position DogCharacter[] dogs = new DogCharacter[]{ defaultScene.spawnDog("dog", "Buddy", new Vector3(7, 0.5f, -10)), defaultScene.spawnDog("dog", "Snoopy", new Vector3(12, 0.5f, 10)), defaultScene.spawnDog("dog", "Rocky", new Vector3(15, 0.5f, 4)) }; Stick[] sticks = new Stick[]{ defaultScene.spawnStick("stick", new Vector3()), defaultScene.spawnStick("stick", new Vector3()), defaultScene.spawnStick("stick", new Vector3()), }; // Assign each dog to a human for (int i = 0, n = Math.min(humans.length, dogs.length); i < n; i++) { humans[i].assignDog(dogs[i]); } stage.btreeController.reset(); // Grabs all the game objects from the scene engine.setScene(defaultScene); // Assign each stick to a human for (int i = 0, n = Math.min(humans.length, sticks.length); i < n; i++) { humans[i].assignStick(sticks[i]); } // Set which scene layers should be visible on start. House scene only has 4 or 5 Bits defaultSceneLayers = new Bits(); for (int i = 0; i <= 5; i++) { defaultSceneLayers.set(i); } stage.setVisibleLayers(defaultSceneLayers); Array<GameObject> trees = new Array<GameObject>(); defaultScene.getGameModelById("tree_0", trees); for (GameObject obj : trees) { GameModel tree = (GameModel) obj; Gdx.app.debug(TAG, "Found tree at " + tree.modelTransform.getTranslation(new Vector3())); } } @Override public void dispose() { stage.dispose(); viewportBackgroundRenderer.dispose(); renderer.dispose(); engine.dispose(); sounds.dispose(); screen = null; } @Override public void render(float delta) { camera.update(delta * GameSettings.CAMERA_LERP_ALPHA); stage.act(delta); delta *= GameSettings.GAME_SPEED; Gdx.gl.glClearColor(0, 0, 0, 1f); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); viewportBackgroundRenderer.begin(ShapeRenderer.ShapeType.Filled); viewportBackgroundRenderer.setColor(viewportBackgroundColor); viewportBackgroundRenderer.rect(0, 0, viewport.getScreenWidth(), viewport.getScreenHeight()); viewportBackgroundRenderer.end(); engine.update(delta); renderer.update(delta); if (DebugViewSettings.drawCollShapes || DebugViewSettings.drawConstraints) { int mode = 0; if (DebugViewSettings.drawConstraints) { mode |= DebugDrawModes.DBG_DrawConstraints; mode |= DebugDrawModes.DBG_DrawConstraintLimits; } if (DebugViewSettings.drawCollShapes) { mode |= DebugDrawModes.DBG_DrawWireframe; } engine.setDebugMode(mode); engine.debugDrawWorld(camera); } stage.draw(); } @Override public void resize(int width, int height) { super.resize(width, height); stage.resize(width, height); } }