package ru.alastar.physics; import java.util.ArrayList; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import ru.alastar.game.Entity; import ru.alastar.game.IUpdate; import ru.alastar.main.Main; import ru.alastar.main.net.ConnectedClient; import ru.alastar.main.net.Server; import ru.alastar.main.net.responses.AddProjectileResponse; import ru.alastar.main.net.responses.RemovePacket; import ru.alastar.main.net.responses.UpdateProjectileResponse; import ru.alastar.world.ServerWorld; import com.alastar.game.enums.ProjectileType; import com.alastar.game.enums.Type; import com.alastar.game.enums.TypeId; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.BodyDef; import com.badlogic.gdx.physics.box2d.CircleShape; import com.badlogic.gdx.physics.box2d.Fixture; import com.badlogic.gdx.physics.box2d.FixtureDef; import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; public abstract class BaseProjectile implements IUpdate, IPhysic { public int id; public Entity shooter; public Vector3 from; public float lifeTime; public float speed; public float maxSpeed; public ServerWorld world; private Date m_StartTime; public boolean m_Shooted = false; public ProjectileType type; private ArrayList<IUpdate> allAround; public float angle; // Physics BodyDef bodyDef; public Body body; FixtureDef fixtureDef; Fixture fixture; CircleShape circle; private Timer updateTimer; private PhysicalData pData; Vector2 add = new Vector2(1,1); public BaseProjectile(int id, Vector3 from, Entity shooter, float angle) { this.id = id; this.from = from; this.shooter = shooter; this.world = shooter.world; this.allAround = new ArrayList<IUpdate>(); this.angle = angle; Server.RegisterProjectile(this); } public void Launch() { m_StartTime = new Date(); // physics bodyDef = new BodyDef(); bodyDef.type = BodyType.DynamicBody; bodyDef.bullet = true; Vector2 vec = new Vector2(from.x, from.y); add.setAngle(-angle); // setting it clockwise, cause from client we getting counter-clockwise angle //Main.Log("[DEBUG]","Angle: " + add.angle()); //add.scl(speed); vec.add(add); bodyDef.position.set(vec.x, vec.y); bodyDef.linearDamping = 1.5F; pData = new PhysicalData((int) from.z, false, this); body = world.getPhysic().createBody(bodyDef); circle = new CircleShape(); circle.setRadius(0.1f); fixtureDef = new FixtureDef(); fixtureDef.shape = circle; fixtureDef.density = 1f; fixtureDef.friction = 1f; fixtureDef.restitution = 0.6f; fixture = body.createFixture(fixtureDef); fixture.setUserData((IPhysic)this); circle.dispose(); if (updateTimer == null) { final BaseProjectile e = this; updateTimer = new Timer(); updateTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { if (lifeTime * 10000 + m_StartTime.getTime() > new Date().getTime()) { if(body.getLinearVelocity().x > -maxSpeed && body.getLinearVelocity().y > -maxSpeed && body.getLinearVelocity().x < maxSpeed && body.getLinearVelocity().y < maxSpeed){ body.applyForceToCenter(/*add.scl(speed)*/ add, true); } Server.UpdatePosition(e); } else { Destroy(); } } }, 0, 100); } m_Shooted = true; world.AddEntity(this); world.UpdateNear(this); } public void Destroy() { updateTimer.cancel(); //body.setActive(false); // body.destroyFixture(fixture); // world.getPhysic().destroyBody(body); Server.RemoveProjectile(this); getWorld().RemoveEntity(this); Main.Log("[DEBUG]","Proj destroy"); } @Override public void UpdateTo(ConnectedClient c) { if(c != null){ AddProjectileResponse r = new AddProjectileResponse(); r.id = this.id; r.projectileType = this.type; r.x = this.getPosition().x; r.y = this.getPosition().y; r.z = this.from.z; Server.SendTo(c, r); } } @Override public void RemoveTo(ConnectedClient c) { if (c != null) // MUST DO IT ALWAYS! RemoveTo() can take an AI // controlled Entity that have no ConnectedClient! { RemovePacket r = new RemovePacket(); r.id = this.id; r.type = TypeId.getTypeId(Type.Projectile); Server.SendTo(c, r); } } @Override public void tryRemoveNear(IUpdate i) { if (allAround.contains(i)) { allAround.remove(i); if (i.getType() == TypeId.getTypeId(Type.Entity)) RemoveTo(Server.getClient((Entity) i)); } } @Override public void tryAddToNear(IUpdate e) { if (!allAround.contains(e)) { allAround.add(e); if (e.getType() == TypeId.getTypeId(Type.Entity)){ UpdateTo(Server.getClient((Entity) e)); } } } @Override public int getType() { return TypeId.getTypeId(Type.Projectile); } @Override public void UpdateAround() { UpdateProjectileResponse r = new UpdateProjectileResponse(); r.id = this.id; r.x = this.getPosition().x; r.y = this.getPosition().y; r.z = this.from.z; r.type = this.type; ConnectedClient c; IUpdate upd; for(int i = allAround.size() - 1; i > -1; i--) { upd = allAround.get(i); if(upd != null) // i told u that it was called sanity? { if(upd.getType() == TypeId.getTypeId(Type.Entity)) { c = Server.getClient((Entity)upd); if(c != null) { Server.SendTo(c, r); } } } } } @Override public ServerWorld getWorld() { return world; } @Override public Vector2 getPosition() { if (m_Shooted) return body.getPosition(); else return new Vector2(from.x, from.y); } @Override public ArrayList<IUpdate> getAround() { return allAround; } @Override public PhysicalData getData() { return pData; } @Override public void UpdatePhysicalData(int z, boolean b) { this.pData.setZ(z); this.pData.setIgnore(b); } @Override public int getId() { return id; } }