package com.deftwun.zombiecopter; import com.badlogic.ashley.core.Component; import com.badlogic.ashley.core.Entity; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Sprite; 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.CircleShape; import com.badlogic.gdx.physics.box2d.FixtureDef; import com.badlogic.gdx.physics.box2d.PolygonShape; import com.badlogic.gdx.physics.box2d.joints.WheelJointDef; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.Logger; import com.badlogic.gdx.utils.ObjectMap; import com.deftwun.zombiecopter.box2dJson.*; import com.deftwun.zombiecopter.components.*; import com.deftwun.zombiecopter.components.TeamComponent.Team; import com.deftwun.zombiecopter.EntityConfig; public class EntityBuilder{ private final Logger logger = new Logger("EntityBuilder",Logger.INFO); private final Vector2 tmpVector = new Vector2(); public EntityBuilder(){ logger.debug("Initializing"); } public String serialize(Entity entity){ Json json = new Json(); logger.debug("Serialize Entity: " + entity.getId()); return json.toJson(entity.getComponents().toArray()); } public Entity deserialize(String data){ Json json = new Json(); logger.debug("Deserialize Entity"); Array<Component> comps = json.fromJson(null,data); if (comps == null) { logger.error("Deserialization failed: " + data); return null; } Entity e = App.engine.createEntity(); for (Component c : comps){ e.add(c); } logger.debug("Entity deserialized: " + e.getId()); return e; } public Entity build(String name){return this.build(name, tmpVector.set(0,0),tmpVector,0);} public Entity build(String name, Vector2 position){return this.build(name, position,tmpVector.set(0,0), 0);} public Entity build(String name, Vector2 position, Vector2 velocity){return this.build(name, position,velocity, 0);} public Entity build(String name, Vector2 position, Vector2 velocity, float rotation){ Entity e = null; EntityConfig cfg = App.assets.getEntityConfig(name); if (cfg == null) { logger.error("Config file not found for '" + name + "'"); return null; } logger.debug(String.format("Building '%s' ; Model=%s",name,cfg.model)); //Create physics & sprite model if (cfg.model.equals("humanoid")) e = createHumanoid(cfg); else if (cfg.model.equals("car")) e = createCar(cfg); else if (cfg.model.equals("helicopter")) e = createHelicopter(cfg); else if (cfg.model.equals("bullet")) e = createBullet(cfg); else if (cfg.model.equals("ball")) e = createBall(cfg); else { logger.error("Entity model '" + cfg.model + "' not recognized."); return null; } //Set physics position, velocity, & rotation PhysicsComponent physics = App.engine.mappers.physics.get(e); if (physics != null){ physics.collisionEffect = cfg.collisionEffect; physics.setPosition(position); physics.setLinearVelocity(velocity); physics.setRotation(rotation); logger.debug(String.format(" Set Position & Velocity : %f,%f / %f,%f ", physics.getPosition().x,physics.getPosition().y, physics.getLinearVelocity().x,physics.getLinearVelocity().y)); } //Controller (all entities have this) logger.debug(" Attach Controller"); ControllerComponent controller = App.engine.createComponent(ControllerComponent.class); e.add(controller); //Player if (cfg.player){ logger.debug(" Attach Player"); PlayerComponent player = App.engine.createComponent(PlayerComponent.class); e.add(player); } //Brain if (cfg.brain) { logger.debug(" Attach Brain"); BrainComponent brain = App.engine.createComponent(BrainComponent.class); if (cfg.thinkTime > 0) brain.thinkTime = cfg.thinkTime; e.add(brain); } //Team if (!cfg.team.equals("")){ TeamComponent team = App.engine.createComponent(TeamComponent.class); if (cfg.team.equals("player")) team.team = Team.PLAYER; else if (cfg.team.equals("bullet")) team.team = Team.BULLET; else if (cfg.team.equals("enemy")) team.team = Team.ENEMY; else if (cfg.team.equals("wild")) team.team = Team.WILD; else logger.error(" Team '" + cfg.team + "' not recognized."); e.add(team); logger.debug(" Attach Team : " + team.team); } //Weapons if (cfg.weapon != ""){ WeaponConfig weaponCfg = App.assets.getWeaponConfig(cfg.weapon); if (weaponCfg != null){ //Json json = new Json(); logger.debug(" Attach Gun: " + cfg.weapon); GunComponent gun = App.engine.createComponent(GunComponent.class); gun.projectileName = weaponCfg.projectileName; gun.spreadAngle = weaponCfg.spreadAngle; gun.bulletSpeed = weaponCfg.bulletSpeed; gun.range = weaponCfg.range; gun.cooldown = weaponCfg.cooldown; gun.offset.set(cfg.weaponOffsetX,cfg.weaponOffsetY); e.add(gun); } } //Health if (cfg.health > 0){ logger.debug(" Attach Health: " + cfg.health); HealthComponent health = App.engine.createComponent(HealthComponent.class); health.value = cfg.health; health.max = cfg.health; health.collisionDamageThreshold = cfg.collisionDamageThreshold; health.corpse = cfg.corpse; health.drop = cfg.drop; health.dropRate = cfg.dropRate; health.damageEffect = cfg.damageEffect; health.deathEffect = cfg.deathEffect; health.gibbedEffect = cfg.gibbedEffect; e.add(health); } //Time To live if (cfg.timeToLive > 0){ logger.debug(" Attach TimeToLive: " + cfg.timeToLive); TimeToLiveComponent ttl = App.engine.createComponent(TimeToLiveComponent.class); ttl.timeLimit = cfg.timeToLive; e.add(ttl); } //Collectable if (cfg.collectable){ logger.debug(" Attach Collectable"); Collectable collectable = App.engine.createComponent(Collectable.class); e.add(collectable); } //Collector if (cfg.collector){ logger.debug(" Attach Collector"); Collector collector = App.engine.createComponent(Collector.class); e.add(collector); } //Look if (cfg.viewDistance > 0){ logger.debug(" Attach Look"); LookComponent look = App.engine.createComponent(LookComponent.class); look.controlSpriteFlip = cfg.lookControlSpriteFlip; e.add(look); } //Walker if (cfg.walker){ logger.debug(" Attach Walk"); WalkComponent walk = App.engine.createComponent(WalkComponent.class); walk.topSpeed = cfg.speed; e.add(walk); } //Jump if (cfg.jumpPower > 0){ logger.debug(" Attach Jump"); JumpComponent jump = App.engine.createComponent(JumpComponent.class); jump.power = cfg.jumpPower; jump.coolDown = cfg.jumpCooldown; e.add(jump); } //Helicopter if (cfg.helicopter){ logger.debug(" Attach Helicopter"); HelicopterComponent copter = App.engine.createComponent(HelicopterComponent.class); copter.topSpeed = cfg.speed; copter.lateralPower = cfg.lateralPower; copter.verticalPower = cfg.verticalPower; copter.maxAltitude = cfg.maxAltitude; e.add(copter); } //Bullet if (cfg.damage > 0){ logger.debug(" Attach Bullet: dmg=" + cfg.damage); BulletComponent bullet = App.engine.createComponent(BulletComponent.class); bullet.damage = cfg.damage; e.add(bullet); } //Vehicle if (cfg.vehicle){ logger.debug(" Attach vehicle"); VehicleComponent vehicle = App.engine.createComponent(VehicleComponent.class); e.add(vehicle); } //Vehicle Operator if (cfg.vehicleOperator){ logger.debug(" Attach VehicleOperator"); VehicleOperatorComponent operator = App.engine.createComponent(VehicleOperatorComponent.class); e.add(operator); } //Car if (cfg.car){ logger.debug(" Attach CarComponent"); CarComponent car = App.engine.createComponent(CarComponent.class); car.speed = cfg.speed; car.downForce = cfg.downForce; car.frontWheelDrive = cfg.frontWheelDrive; car.rearWheelDrive = cfg.rearWheelDrive; if (!car.frontWheelDrive && !car.rearWheelDrive){ car.frontWheelDrive = true; } e.add(car); } //Thruster if (cfg.thruster){ logger.debug(" Attach ThrusterComponent"); ThrusterComponent thruster = App.engine.createComponent(ThrusterComponent.class); thruster.power = cfg.thrustPower; thruster.duration = cfg.thrustDuration; thruster.delay = cfg.thrustDelay; thruster.topSpeed = cfg.thrustSpeed; e.add(thruster); } //Leader if (cfg.leader){ logger.debug(" Attach LeaderComponent"); LeaderComponent leader = App.engine.createComponent(LeaderComponent.class); e.add(leader); } //Sticky if (!cfg.stickyFixture.equals("")){ logger.debug(" Attach StickyComponent"); StickyComponent sticky = App.engine.createComponent(StickyComponent.class); sticky.fixtureName = cfg.stickyFixture; e.add(sticky); } //Melee if (cfg.meleeDamage > 0){ logger.debug(" Attach MeleeComponent"); MeleeComponent melee = App.engine.createComponent(MeleeComponent.class); melee.damage = cfg.meleeDamage; melee.range = cfg.meleeRange; melee.coolDown = cfg.meleeCoolDown; e.add(melee); } if (cfg.ledgeHanger){ logger.debug(" Attach LedgeHang"); LedgeHangComponent ledge = App.engine.createComponent(LedgeHangComponent.class); e.add(ledge); } App.engine.addEntity(e); logger.debug("Entity #" + e.getId() + " finished building."); return e; } public Entity createHumanoid(EntityConfig config){ Entity e = App.engine.createEntity(); PhysicsComponent physics = App.engine.createComponent(PhysicsComponent.class); SpriteComponent sprite = App.engine.createComponent(SpriteComponent.class); //Physics float size = config.size > 0 ? config.size : .5f, density = .1f, friction = .1f, restitution = 0; //Main body BodyDef bd = new BodyDef(); bd.fixedRotation = true; bd.type = BodyType.DynamicBody; BodyModel body = new BodyModel("body",bd); //Vision Body bd.fixedRotation = false; BodyModel visionBody = new BodyModel("visionBody",bd); //Main Body Fixture float[] verts = {size/3,size,-size/3,size,0,-size}; PolygonShape polygon = new PolygonShape(); polygon.set(verts); FixtureDef fd = Box2dHelper.fixtureDef(density, friction, restitution, polygon ,false); fd.filter.categoryBits = CollisionBits.Character; fd.filter.maskBits = CollisionBits.Mask_Character; body.fixtures.add(new FixtureModel(fd)); //Arm fixture /* bd.fixedRotation = false; polygon.setAsBox(size/4, size/8, new Vector2(size/8,size/16),0); fd.shape = polygon; visionBody.fixtures.add(new FixtureModel(fd)); */ //Vision Sensor //fd = Box2dHelper.circleFixtureDef(config.viewDistance,new Vector2(),0,0,0,true); CircleShape circle = new CircleShape(); circle.setRadius(config.viewDistance); fd.shape = circle; fd.isSensor = true; fd.density = 0; fd.filter.categoryBits = CollisionBits.VisionSensor; fd.filter.maskBits = CollisionBits.Mask_VisionSensor; visionBody.fixtures.add(new FixtureModel("visionSensor",fd)); //Static Sensor Fixtures fd.shape = polygon; fd.filter.categoryBits = CollisionBits.TouchSensor; fd.filter.maskBits = CollisionBits.Mask_TouchSensor; polygon.setAsBox(.05f, size/3f,new Vector2(-size,0),0); body.fixtures.add(new FixtureModel("leftSensor",fd)); polygon.setAsBox(.05f,size/3f,new Vector2(size,0),0); body.fixtures.add(new FixtureModel("rightSensor",fd)); polygon.setAsBox(size/2,.05f,new Vector2(0,size),0); body.fixtures.add(new FixtureModel("topSensor",fd)); polygon.setAsBox(size/2, .05f, new Vector2(0,-size),0); body.fixtures.add(new FixtureModel("bottomSensor",fd)); polygon.setAsBox(size/2, .05f, new Vector2(-size,size),0); body.fixtures.add(new FixtureModel("topLeftSensor",fd)); polygon.setAsBox(size/2, .05f, new Vector2(size,size),0); body.fixtures.add(new FixtureModel("topRightSensor",fd)); polygon.setAsBox(size/2, .05f, new Vector2(-size,-size),0); body.fixtures.add(new FixtureModel("bottomLeftSensor",fd)); polygon.setAsBox(size/2, .05f, new Vector2(size,-size),0); body.fixtures.add(new FixtureModel("bottomRightSensor",fd)); //Add Bodies physics.addBody(body); physics.addBody(visionBody); physics.setPrimaryBody("body"); //Vision Joint /* RevoluteJointDef jd = new RevoluteJointDef(); jd.initialize(physics.getBody("body"),physics.getBody("visionBody"),physics.getPosition()); physics.addJoint(new JointModel("visionJoint",jd,"body","visionBody")); */ //use 'images' field (deserializes to an objectMap<bodyName,stringName>) for (ObjectMap.Entry<String,String> bodySpritePair : config.images.entries()){ String bodyName = bodySpritePair.key, imgName = bodySpritePair.value; Texture t = App.assets.getTexture(imgName); if (t != null){ Sprite s = new Sprite(t); s.setOriginCenter(); sprite.spriteMap.put(bodyName,s); } } e.add(sprite) .add(physics); return e; } public Entity createHelicopter(EntityConfig config){ Entity e = App.engine.createEntity(); PhysicsComponent physics = App.engine.createComponent(PhysicsComponent.class); SpriteComponent sprite = App.engine.createComponent(SpriteComponent.class); // Physics float size = config.size > 0 ? config.size : 1, density = .2f, friction = .1f, restitution = 0, linearDamping = .65f; //Main Body BodyDef bd = new BodyDef(); bd.fixedRotation = true; bd.type = BodyType.DynamicBody; bd.linearDamping = linearDamping; BodyModel bodyModel = new BodyModel("body",bd); //Main Fixture //FixtureDef fd = Box2dHelper.circleFixtureDef(size,new Vector2(),density,friction,restitution,false); PolygonShape shape = new PolygonShape(); shape.setAsBox(size*2, size); FixtureDef fd = new FixtureDef(); fd.density = density; fd.friction = friction; fd.restitution = restitution; fd.shape = shape; fd.filter.categoryBits = CollisionBits.Character; fd.filter.maskBits = CollisionBits.Mask_Character; bodyModel.fixtures.add(new FixtureModel("bodyFixture",fd)); //Ground Sensor Vector2 sensorDimensions = new Vector2(size/2,.05f), sensorPosition = new Vector2(0,-size); fd = Box2dHelper.rectangleFixtureDef(sensorPosition,sensorDimensions,0,0,0,true); fd.filter.categoryBits = CollisionBits.TouchSensor; fd.filter.maskBits = CollisionBits.Mask_TouchSensor; bodyModel.fixtures.add(new FixtureModel("bottomSensor",fd)); //Visual Sensor bd.type = BodyType.KinematicBody; bd.fixedRotation = false; BodyModel visionBodyModel = new BodyModel("visionBody",bd); fd = Box2dHelper.circleFixtureDef(config.viewDistance,new Vector2(),0,0,0,true); fd.filter.categoryBits = CollisionBits.VisionSensor; fd.filter.maskBits = CollisionBits.Mask_VisionSensor; visionBodyModel.fixtures.add(new FixtureModel("visionSensor",fd)); //Add bodies physics.addBody(bodyModel); physics.addBody(visionBodyModel); physics.setPrimaryBody("body"); //Vision Joint /* RevoluteJointDef jd = new RevoluteJointDef(); jd.initialize(physics.getBody("body"),physics.getBody("visionBody"),physics.getPosition()); Joint j = App.engine.systems.physics.world.createJoint(jd); physics.addJoint(j); * */ //physics.addJoint(new JointModel("visionJoint",jd,"body","visionBody")); //Sprite Texture t = App.assets.getTexture(config.image); if (t != null){ Sprite s = new Sprite(t); s.setOriginCenter(); sprite.spriteMap.put("body", s); } e.add(sprite) .add(physics); return e; } public Entity createCar(EntityConfig config){ Entity e = App.engine.createEntity(); PhysicsComponent physics = App.engine.createComponent(PhysicsComponent.class); SpriteComponent sprite = App.engine.createComponent(SpriteComponent.class); // Physics float size = config.size, density = .1f, friction = .5f, restitution = .01f, linearDamping = 1; //Main Body BodyDef bd = new BodyDef(); bd.fixedRotation = false; bd.type = BodyType.DynamicBody; bd.linearDamping = linearDamping; BodyModel bodyModel = new BodyModel("body",bd); //Trapezoid body FixtureDef fd = new FixtureDef(); fd.density = density; fd.friction = friction; fd.restitution = restitution; PolygonShape polyShape = new PolygonShape(); float[] verts = {-size/2,size/2, -size * 1.7f,-size/2, size * 1.7f,-size/2, size/2,size/2}; polyShape.set(verts); fd.shape = polyShape; fd.filter.categoryBits = CollisionBits.Character; fd.filter.maskBits = CollisionBits.Mask_Character; bodyModel.fixtures.add(new FixtureModel(fd)); //Wheels fd.density = .7f; fd.friction = 1.5f; BodyModel leftWheelModel = new BodyModel("leftWheel",bd), rightWheelModel = new BodyModel("rightWheel",bd); CircleShape shape = new CircleShape(); shape.setPosition(new Vector2(-size * .75f,-size * .5f)); shape.setRadius(size/2); fd.shape = shape; leftWheelModel.fixtures.add(new FixtureModel(fd)); shape.setPosition(new Vector2(size * .75f,-size * .5f)); fd.shape = shape; rightWheelModel.fixtures.add(new FixtureModel(fd)); //Vision Body / Sensor bd.type = BodyType.KinematicBody; bd.fixedRotation = false; BodyModel visionBodyModel = new BodyModel("visionBody",bd); fd = Box2dHelper.circleFixtureDef(config.viewDistance,new Vector2(),0,0,0,true); fd.filter.categoryBits = CollisionBits.VisionSensor; fd.filter.maskBits = CollisionBits.Mask_VisionSensor; visionBodyModel.fixtures.add(new FixtureModel("visionSensor",fd)); //Create Physics physics.addBody(bodyModel); physics.addBody(leftWheelModel); physics.addBody(rightWheelModel); physics.addBody(visionBodyModel); physics.setPrimaryBody("body"); //Wheel Joints WheelJointDef wjd = new WheelJointDef(); wjd.maxMotorTorque = config.torque; wjd.frequencyHz = config.suspension; wjd.initialize(physics.getBody("body"), physics.getBody("leftWheel"), physics.getBody("leftWheel").getWorldCenter(),new Vector2(0,1)); physics.addJoint(new JointModel("leftWheelJoint",wjd,"body","leftWheel")); wjd.initialize(physics.getBody("body"), physics.getBody("rightWheel"), physics.getBody("rightWheel").getWorldCenter(),new Vector2(0,1)); physics.addJoint(new JointModel("rightWheelJoint",wjd,"body","rightWheel")); //Vision Joint /* RevoluteJointDef rjd = new RevoluteJointDef(); rjd.initialize(physics.getBody("body"),physics.getBody("visionBody"),physics.getPosition()); physics.addJoint(new JointModel("visionJoint",rjd,"body","visionBody")); */ //use 'images' field (deserializes to an objectMap<bodyName,stringName>) for (ObjectMap.Entry<String,String> bodySpritePair : config.images.entries()){ String bodyName = bodySpritePair.key, imgName = bodySpritePair.value; Texture t = App.assets.getTexture(imgName); if (t != null){ Sprite s = new Sprite(t); s.setOriginCenter(); sprite.spriteMap.put(bodyName,s); } } e.add(sprite); e.add(physics); return e; } public Entity createBullet(EntityConfig config){ Entity e = App.engine.createEntity(); PhysicsComponent physics = App.engine.createComponent(PhysicsComponent.class); SpriteComponent sprite = App.engine.createComponent(SpriteComponent.class); //Physics float density = .1f, restitution = .1f, friction = .5f; BodyDef bd = new BodyDef(); bd.type = BodyType.DynamicBody; bd.bullet = true; PolygonShape shape = new PolygonShape(); shape.setAsBox(config.size, config.size/4); FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.density = density; fd.friction = friction; fd.restitution = restitution; fd.isSensor = false; fd.filter.categoryBits = CollisionBits.Bullet; fd.filter.maskBits = CollisionBits.Mask_Bullet; BodyModel bodyModel = new BodyModel("body",bd); bodyModel.fixtures.add(new FixtureModel("fixture",fd)); physics.addBody(bodyModel); //Sprite Texture t = App.assets.getTexture(config.image); if (t != null){ Sprite s = new Sprite(App.assets.getTexture(config.image)); s.setOriginCenter(); sprite.spriteMap.put("body",s); } e.add(sprite) .add(physics); return e; } public Entity createBall(EntityConfig config){ Entity e = App.engine.createEntity(); PhysicsComponent physics = App.engine.createComponent(PhysicsComponent.class); SpriteComponent sprite = App.engine.createComponent(SpriteComponent.class); //Physics float density = .6f, restitution = .1f, friction = .5f; BodyDef bd = new BodyDef(); bd.type = BodyType.DynamicBody; CircleShape shape = new CircleShape(); shape.setRadius(config.size/2); FixtureDef fd = new FixtureDef(); fd.shape = shape; fd.density = density; fd.friction = friction; fd.restitution = restitution; fd.isSensor = false; //fd.filter.categoryBits = CollisionBits; //fd.filter.maskBits = CollisionBits.Mask_Bullet; BodyModel bodyModel = new BodyModel("body",bd); bodyModel.fixtures.add(new FixtureModel("fixture",fd)); physics.addBody(bodyModel); //Sprite Texture t = App.assets.getTexture(config.image); if (t != null){ Sprite s = new Sprite(App.assets.getTexture(config.image)); s.setOriginCenter(); sprite.spriteMap.put("body",s); } e.add(sprite) .add(physics); return e; } }