Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package rosthouse.rosty.loader; import com.badlogic.ashley.core.Engine; import com.badlogic.ashley.core.Entity; import com.badlogic.gdx.Application; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.maps.MapLayer; import com.badlogic.gdx.maps.MapObject; import com.badlogic.gdx.maps.MapProperties; import com.badlogic.gdx.maps.objects.EllipseMapObject; import com.badlogic.gdx.maps.objects.PolygonMapObject; import com.badlogic.gdx.maps.objects.RectangleMapObject; import com.badlogic.gdx.maps.objects.TextureMapObject; import com.badlogic.gdx.maps.tiled.TiledMap; import com.badlogic.gdx.maps.tiled.TmxMapLoader; import com.badlogic.gdx.math.Ellipse; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Polygon; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.BodyDef; import com.badlogic.gdx.physics.box2d.ChainShape; import com.badlogic.gdx.physics.box2d.CircleShape; import com.badlogic.gdx.physics.box2d.FixtureDef; import com.badlogic.gdx.physics.box2d.PolygonShape; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import rosthouse.rosty.GameConstants; import rosthouse.rosty.MapObjects; import rosthouse.rosty.components.OrthographicCameraComponent; import rosthouse.rosty.components.PhysicsComponent; import rosthouse.rosty.components.PositionComponent; import rosthouse.rosty.components.ScriptComponent; import rosthouse.rosty.components.SensorComponent; import rosthouse.rosty.components.SpriteComponent; import rosthouse.rosty.components.TiledMapComponent; import rosthouse.rosty.components.collision.EllipseComponent; import rosthouse.rosty.components.collision.PolygonComponent; import rosthouse.rosty.components.collision.RectangleComponent; import rosthouse.rosty.entities.MovingPicture; import rosthouse.rosty.scripting.scripts.ClearMarbleScript; import rosthouse.rosty.scripting.scripts.EndLevelScript; import rosthouse.rosty.scripting.scripts.FireTileScript; import rosthouse.rosty.scripting.scripts.WallCollisionScript; import rosthouse.rosty.scripting.scripts.WaterTileScript; import rosthouse.rosty.scripting.scripts.WoodScript; import rosthouse.rosty.systems.PhysicsSystem; /** * Loads a TMX map * * @author Rosthouse */ public class MapLoader { public void loadMap(String path, AssetManager assetManager, Engine engine, PhysicsSystem physicsSystem, final float unitScale) { TmxMapLoader.Parameters mapParameters = new TmxMapLoader.Parameters(); mapParameters.convertObjectToTileSpace = true; assetManager.setLoader(TiledMap.class, new TmxMapLoader()); assetManager.load(path, TiledMap.class, mapParameters); assetManager.finishLoading(); TiledMap map = assetManager.get(path); for (MapLayer layer : map.getLayers()) { String layerName = layer.getName(); if (layerName.equals("Collisions")) { loadCollisionLayer(layer, physicsSystem, engine); } else if (layerName.equals("Level")) { loadLevelLayer(map, layer, unitScale, physicsSystem, engine); } else if (layerName.equals("Sensors")) { loadSensorLayer(layer, physicsSystem, engine); } } Entity mapEntity = new Entity(); mapEntity.add(new TiledMapComponent(map, unitScale)); engine.addEntity(mapEntity); } private void loadLevelLayer(TiledMap map, MapLayer layer, final float unitScale, PhysicsSystem physicsSystem, Engine engine) { for (MapObject object : layer.getObjects()) { if ("Start".equals(object.getName())) { float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); OrthographicCamera camera = new OrthographicCamera(); camera.setToOrtho(false, (w / h) * 10, 10); Texture tex = new Texture(Gdx.files.internal("Level/marble.png")); Ellipse ellipse = ((EllipseMapObject) object).getEllipse(); MovingPicture entity = new MovingPicture(tex, ellipse.x, ellipse.y); entity.setSize(new Vector2(ellipse.width, ellipse.height)); Gdx.app.debug("LOADING", String.format("START: Position [X: %s|Y: %s]", ellipse.x, ellipse.y)); CircleShape circleShape = new CircleShape(); circleShape.setRadius(ellipse.height / 2); FixtureDef fd = new FixtureDef(); fd.density = 5; fd.friction = 5; fd.restitution = 0.3f; PhysicsComponent<CircleShape> marble = physicsSystem.createPhysicsComponent( BodyDef.BodyType.DynamicBody, circleShape, new Vector2(ellipse.x, ellipse.y), fd); entity.add(marble); Vector2 mapSize = new Vector2(map.getProperties().get("width", Integer.class), map.getProperties().get("height", Integer.class)); entity.add(new OrthographicCameraComponent(camera, mapSize)); engine.addEntity(entity); marble.fixture.setUserData(entity.getId()); } else { Entity ent = new Entity(); engine.addEntity(ent); Boolean isSensor = Boolean.valueOf(object.getProperties().get("isSensor", "false", String.class)); loadObject(object, physicsSystem, ent, isSensor); } } } private void loadCollisionLayer(MapLayer layer, PhysicsSystem physicsSystem, Engine engine) { for (MapObject object : layer.getObjects()) { MapProperties properties = object.getProperties(); Entity mapObjectEntity = new Entity(); engine.addEntity(mapObjectEntity); loadObject(object, physicsSystem, mapObjectEntity, false); if (properties.containsKey(MapObjects.TYPE.toString())) { String type = properties.get(MapObjects.TYPE.toString(), String.class); if (type.equals("WoodTile")) { ScriptComponent scriptComponent = new ScriptComponent(); scriptComponent.addScript(GameConstants.START_COLLISION, new WoodScript()); mapObjectEntity.add(scriptComponent); } } System.out.println(object); } } private void loadObject(MapObject object, PhysicsSystem physicsSystem, Entity mapObjectEntity, boolean isSensor) { if (object instanceof PolygonMapObject) { createPolygon((PolygonMapObject) object, physicsSystem, mapObjectEntity, isSensor); } else if (object instanceof RectangleMapObject) { createRectangle((RectangleMapObject) object, physicsSystem, mapObjectEntity, isSensor); } else if (object instanceof TextureMapObject) { createTexture((TextureMapObject) object, physicsSystem, mapObjectEntity, isSensor); } else if (object instanceof EllipseMapObject) { createEllipse((EllipseMapObject) object, physicsSystem, mapObjectEntity, isSensor); } if (object.getProperties().containsKey("onCollision")) { ScriptComponent script = createCollisionScript( object.getProperties().get("onCollision", "", String.class)); mapObjectEntity.add(script); } } private void createPolygon(PolygonMapObject polygon, PhysicsSystem physicsSystem, Entity entity, boolean isSensor) { Polygon ply = polygon.getPolygon(); PolygonComponent plyCmp = new PolygonComponent(ply); ChainShape polygonShape = new ChainShape(); Vector2[] vertices = new Vector2[plyCmp.polygon.getVertices().length / 2]; for (int i = 0; i < plyCmp.polygon.getTransformedVertices().length; i += 2) { vertices[i / 2] = new Vector2(plyCmp.polygon.getVertices()[i], plyCmp.polygon.getVertices()[i + 1]); } try { polygonShape.createLoop(vertices); } catch (Exception e) { System.out.println(e.getMessage()); } FixtureDef fixtureDef = new FixtureDef(); fixtureDef.density = 0; fixtureDef.friction = 1; fixtureDef.restitution = 0.2f; PhysicsComponent<ChainShape> cmpPhys; if (isSensor) { cmpPhys = physicsSystem.createSensorComponent(BodyDef.BodyType.StaticBody, polygonShape, new Vector2(ply.getX(), ply.getY()), fixtureDef); } else { cmpPhys = physicsSystem.createPhysicsComponent(BodyDef.BodyType.StaticBody, polygonShape, new Vector2(ply.getX(), ply.getY()), fixtureDef); } entity.add(plyCmp); entity.add(cmpPhys); cmpPhys.fixture.setUserData(entity.getId()); } private void createTexture(TextureMapObject texture, PhysicsSystem physicsSystem, Entity mapObjectEntity, boolean isSensor) { SpriteComponent spriteComponent = new SpriteComponent(texture.getTextureRegion()); PositionComponent positionComponent = new PositionComponent(); float width = texture.getProperties().get("width", Float.class); float height = texture.getProperties().get("height", Float.class); float rotation = texture.getRotation(); float x = texture.getX(); float y = texture.getY() + height; String name = texture.getName(); spriteComponent.sprite.setOrigin(texture.getOriginX() - width * 0.5f, texture.getOriginY() - height * 0.5f); spriteComponent.sprite.setSize(width, height); PolygonShape polygonShape = new PolygonShape(); polygonShape.setAsBox(width * 0.5f, height * 0.5f, new Vector2(width * 0.5f, height * 0.5f), MathUtils.degreesToRadians * rotation); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.density = 0; fixtureDef.friction = 1; fixtureDef.restitution = 0.2f; PhysicsComponent<PolygonShape> cmpSensor; if (isSensor) { cmpSensor = physicsSystem.createSensorComponent(BodyDef.BodyType.StaticBody, polygonShape, new Vector2(x, y), fixtureDef); } else { cmpSensor = physicsSystem.createPhysicsComponent(BodyDef.BodyType.StaticBody, polygonShape, new Vector2(x, y), fixtureDef); } cmpSensor.fixture.getBody().setTransform(x, y, MathUtils.degreesToRadians * rotation); mapObjectEntity.add(cmpSensor); cmpSensor.fixture.setUserData(mapObjectEntity.getId()); mapObjectEntity.add(spriteComponent); mapObjectEntity.add(positionComponent); } private void createRectangle(RectangleMapObject rectangleObject, PhysicsSystem physicsSystem, Entity mapObjectEntity, boolean isSensor) { Rectangle rectangle = rectangleObject.getRectangle(); RectangleComponent rectComponent = new RectangleComponent(rectangle); PolygonShape polygonShape = new PolygonShape(); polygonShape.setAsBox(rectangle.width * 0.5f, rectangle.height * 0.5f); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.density = 0; fixtureDef.friction = 1; fixtureDef.restitution = 0.2f; PhysicsComponent<PolygonShape> cmpPhys; if (isSensor) { cmpPhys = physicsSystem.createSensorComponent(BodyDef.BodyType.StaticBody, polygonShape, rectangle.getCenter(Vector2.Zero), fixtureDef); } else { cmpPhys = physicsSystem.createPhysicsComponent(BodyDef.BodyType.StaticBody, polygonShape, rectangle.getCenter(Vector2.Zero), fixtureDef); } mapObjectEntity.add(rectComponent); mapObjectEntity.add(cmpPhys); cmpPhys.fixture.setUserData(mapObjectEntity.getId()); } private void createEllipse(EllipseMapObject ellipseMapObject, PhysicsSystem physicsSystem, Entity entity, boolean isSensor) { Ellipse ellipse = ellipseMapObject.getEllipse(); EllipseComponent cmpEllipse = new EllipseComponent(ellipse); CircleShape circleShape = new CircleShape(); circleShape.setRadius(ellipse.height / 2f); FixtureDef fixtureDef = new FixtureDef(); fixtureDef.density = 0; fixtureDef.friction = 1; fixtureDef.restitution = 0.2f; PhysicsComponent<CircleShape> cmpPhys; if (isSensor) { cmpPhys = physicsSystem.createSensorComponent(BodyDef.BodyType.StaticBody, circleShape, new Vector2(ellipse.x + ellipse.height / 2, ellipse.y + ellipse.height / 2), fixtureDef); } else { cmpPhys = physicsSystem.createPhysicsComponent(BodyDef.BodyType.StaticBody, circleShape, new Vector2(ellipse.x, ellipse.y), fixtureDef); } entity.add(cmpEllipse); entity.add(cmpPhys); cmpPhys.fixture.setUserData(entity.getId()); } private void loadSensorLayer(MapLayer layer, PhysicsSystem physicsSystem, Engine engine) { for (MapObject object : layer.getObjects()) { MapProperties properties = object.getProperties(); EllipseMapObject obj = (EllipseMapObject) object; CircleShape circleShape = new CircleShape(); circleShape.setRadius(obj.getEllipse().height / 2); FixtureDef fd = new FixtureDef(); fd.density = 5; fd.friction = 5; fd.restitution = 0.3f; Entity entity = new Entity(); SensorComponent<CircleShape> sensor = physicsSystem.createSensorComponent(BodyDef.BodyType.StaticBody, circleShape, new Vector2(obj.getEllipse().x + obj.getEllipse().width / 2, obj.getEllipse().y + obj.getEllipse().height / 2), fd); engine.addEntity(entity.add(sensor)); sensor.fixture.setUserData(entity.getId()); ScriptComponent scriptComponent = new ScriptComponent(); scriptComponent.addScript(GameConstants.END_COLLISION, new ClearMarbleScript()); entity.add(scriptComponent); } } private ScriptComponent createCollisionScript(String collisionScriptDefinition) { ScriptComponent cmpScript = new ScriptComponent(); String scriptName = getScriptName(collisionScriptDefinition); List<String> parameters = getScriptParameters(collisionScriptDefinition); switch (scriptName) { case "FireScript": cmpScript.addScript(GameConstants.START_COLLISION, new FireTileScript()); Gdx.app.debug("MAPLOADING", "Loading Fire script"); break; case "WaterScript": cmpScript.addScript(GameConstants.START_COLLISION, new WaterTileScript()); Gdx.app.debug("MAPLOADING", "Loading Water script"); break; case "WoodScript": cmpScript.addScript(GameConstants.START_COLLISION, new WoodScript()); Gdx.app.debug("MAPLOADING", "Loading Wood script"); break; case "EndLevelScript": cmpScript.addScript(GameConstants.START_COLLISION, new EndLevelScript(parameters)); Gdx.app.debug("MAPLOADING", "Loading Finish script"); break; case "WallCollisionScript": cmpScript.addScript(GameConstants.POST_SOLVE, new WallCollisionScript()); Gdx.app.debug("MAPLOADING", "Loading WallCollisionScript"); break; default: break; } return cmpScript; } String getScriptName(String collisionScriptDefinition) { Pattern pattern = Pattern.compile("([a-z,A-Z]{1}[a-z,A-Z,0-9]*)[\\(]{0}"); Matcher matcher = pattern.matcher(collisionScriptDefinition); if (matcher.find()) { return matcher.group(); } else { return ""; } } List<String> getScriptParameters(final String collisionScriptDefinition) { ArrayList<String> results = new ArrayList<String>(); if (collisionScriptDefinition.contains("(")) { int index = collisionScriptDefinition.indexOf("("); String parameters = collisionScriptDefinition.substring(index); parameters = parameters.replace("(", ""); parameters = parameters.replace(")", ""); String[] parameterList = parameters.split(","); for (String parameter : parameterList) { results.add(parameter.trim()); } } return results; } }