package com.deftwun.zombiecopter; import com.badlogic.ashley.core.Component; import com.badlogic.ashley.core.Entity; import com.badlogic.ashley.core.Family; import com.badlogic.ashley.core.PooledEngine; import com.badlogic.ashley.utils.ImmutableArray; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.Input.TextInputListener; import com.badlogic.gdx.math.Matrix4; 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.BodyDef.BodyType; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.CircleShape; import com.badlogic.gdx.physics.box2d.PolygonShape; import com.badlogic.gdx.physics.box2d.World; import com.badlogic.gdx.physics.box2d.joints.WheelJoint; import com.badlogic.gdx.physics.box2d.joints.WheelJointDef; import com.badlogic.gdx.utils.Logger; public class GameEngine{ private final Logger logger = new Logger("Engine", Logger.INFO); private boolean paused = false; private float timestep = 1f/60f , timeAccumulator = 0, timeModifier = 1; public final float PIXELS_PER_METER = 32, viewWidth = 800, viewHeight = 600; private final int entityPoolInitialSize = 1, entityPoolMaxSize = 50, componentPoolInitialSize = 1, componentPoolMaxSize = 100; private final PooledEngine entityEngine = new PooledEngine(entityPoolInitialSize, entityPoolMaxSize, componentPoolInitialSize, componentPoolMaxSize); private Level level; public final UserInterface ui = new UserInterface(); public final Rectangle entityBounds = new Rectangle(0,0,viewWidth * 3 / PIXELS_PER_METER,viewHeight * 3 / PIXELS_PER_METER); public final ComponentMappers mappers = new ComponentMappers(); public final EntityBuilder factory = new EntityBuilder(); public Systems systems; // == Debugging stuff (Entity spawning / debug rendering) == private final DebugRenderer debugRenderer = new DebugRenderer(); private float debugEntitySpawnAcc = 0, debugEntitySpawnRate = .1f; private class DebugConsole implements TextInputListener{ public String myText = ""; public void input(String text) { myText = text; String[] args = text.split(" "); if (args.length > 1){ if (args[0].equals("level")){ System.out.println(args[1]); App.engine.loadLevel(args[1]); } } } public void canceled() {} } DebugConsole debugConsole = new DebugConsole(); /* TextInputListener textInput = new TextInputListener(){ private String myText = ""; public String toString() {return myText;} public void input(String text) {myText = text;} public void canceled() {} }; */ public void initialize(){ logger.debug("Initializing"); systems = new Systems(entityEngine); Gdx.input.setInputProcessor(systems.player); } public void loadLevel(String fileName){ logger.info("Loading level " + fileName); reset(); level = new Level(fileName); } public void test_deserializeBug(Vector2 pos){ /* Entity e = factory.build("jeep",pos); PhysicsComponent p = mappers.physics.get(e); WheelJoint j = (WheelJoint) p.getJoint("leftWheelJoint"); logger.debug("Factory \n anchorA: " + j.getAnchorA() + "\n anchorB:" + j.getAnchorB() + " \n localAxis: "+ j.getLocalAxisA() + " \n damping: " + j.getSpringDampingRatio() + "\n frequency" + j.getSpringFrequencyHz()); String data = factory.serialize(e); removeEntity(e); e = factory.deserialize(data); p = mappers.physics.get(e); j = (WheelJoint) p.getJoint("leftWheelJoint"); logger.debug("Deserialized \n anchorA: " + j.getAnchorA() + "\n anchorB:" + j.getAnchorB() + " \n localAxis: "+ j.getLocalAxisA() + " \n damping: " + j.getSpringDampingRatio() + "\n frequency" + j.getSpringFrequencyHz()); addEntity(e); */ World world = App.engine.systems.physics.world; BodyDef bd = new BodyDef(); bd.type = BodyType.DynamicBody; Body body = world.createBody(bd), wheel = world.createBody(bd); PolygonShape rect = new PolygonShape(); rect.setAsBox(2, 1); CircleShape circle = new CircleShape(); circle.setRadius(1); body.createFixture(rect,1); wheel.createFixture(circle,1); Vector2 localAnchor = new Vector2(0,0), localAxis = new Vector2(0,1); WheelJointDef jd = new WheelJointDef(); jd.initialize(body, wheel, localAnchor , localAxis); WheelJoint joint = (WheelJoint)world.createJoint(jd); System.out.println("Local Axis = " + joint.getLocalAxisA()); System.out.println("Local Anchor A = " + joint.getLocalAnchorA()); //joint.getLocalAxisA() seems to be returning localAnchorA } public void debugInput(float deltaTime){ // debugEntitySpawnAcc += deltaTime; if (debugEntitySpawnAcc >= debugEntitySpawnRate){ //Slo-mo if (Gdx.input.isKeyPressed(Keys.Q)){ timeModifier = .1f; } else timeModifier = 1; Vector2 coords = new Vector2(Gdx.input.getX(),Gdx.input.getY()), worldCoords = systems.camera.unproject(coords).scl(1/PIXELS_PER_METER); if (Gdx.input.isKeyPressed(Keys.T)){ test_deserializeBug(worldCoords); } if (Gdx.input.isKeyPressed(Keys.R)){ debugRenderer.drawPhysics = !debugRenderer.drawPhysics; } if (Gdx.input.isKeyPressed(Keys.TAB)){ Gdx.input.getTextInput(debugConsole, "Debug Console","", ""); } if (Gdx.input.isKeyPressed(Keys.CONTROL_LEFT)){ factory.build(debugConsole.myText,worldCoords); } if (Gdx.input.isKeyPressed(Keys.NUM_1)){ systems.camera.getCamera().zoom = 1; } if (Gdx.input.isKeyPressed(Keys.NUM_2)){ systems.camera.getCamera().zoom = 2; } if (Gdx.input.isKeyPressed(Keys.NUM_3)){ systems.camera.getCamera().zoom = 3; } if (Gdx.input.isKeyPressed(Keys.NUM_4)){ systems.camera.getCamera().zoom = 4; } if (Gdx.input.isKeyPressed(Keys.NUM_5)){ systems.camera.getCamera().zoom = 5; } if (Gdx.input.isKeyPressed(Keys.NUM_6)){ systems.camera.getCamera().zoom = 6; } if (Gdx.input.isKeyPressed(Keys.P)){ paused = !paused; logger.info("Paused = " + paused); } debugEntitySpawnAcc = 0; } } public void update(float deltaTime){ debugInput(deltaTime); //Not doing this every render frame can cause flickering // note: This is updated during entityEngine.update also. // sshould it not? systems.camera.update(deltaTime); if (paused) return; //If frame rate drops to below half of update rate then we'll pause the simulation // while it tries to catch up. Basically we stop adding real time to the accumulator if (Gdx.graphics.getFramesPerSecond() < 1 / (timestep * 2)){ logger.debug("Low Frame Rate Detected. Waiting for simulation to catch up."); } else timeAccumulator += deltaTime; while (timeAccumulator >= timestep){ entityEngine.update(timestep * timeModifier); timeAccumulator -= timestep; debugRenderer.update(); } } public void render(float deltaTime){ Matrix4 projection = systems.camera.getCamera().combined; level.render(projection); //level.render("background",projection); //level.render("midBack",projection); systems.spriteRender.render(); systems.particle.render(deltaTime); //level.render("midFront",projection); //level.render("foreground",projection); ui.render(); debugRenderer.render(); } public void windowResized(int w, int h){ logger.debug("Window resized to " + w + "x" + h); systems.camera.resize(w,h); } public void addEntity(Entity e){ logger.debug("Entity Added " + e.getId()); entityEngine.addEntity(e); } public Entity getEntity(long id){ return entityEngine.getEntity(id); } public int getEntityCount(){ return entityEngine.getEntities().size(); } public ImmutableArray<Entity> getEntitiesFor(Family family){ return entityEngine.getEntitiesFor(family); } public void removeEntity(Entity e){ logger.debug("Entity Removed: " + e.getId()); entityEngine.removeEntity(e); } public void removeAllEntities(){ logger.debug("Removing all entities"); entityEngine.removeAllEntities(); } public void reset(){ logger.debug("Reset"); removeAllEntities(); entityEngine.clearPools(); if (level != null) level.clear(); level = null; } public Entity createEntity() { return entityEngine.createEntity(); } public <T extends Component> T createComponent (Class<T> componentType) { return entityEngine.createComponent(componentType); } public Level getLevel(){ return level; } }