package com.xtremelabs.devicewallmarblerun.engine;
import java.util.Stack;
import org.jbox2d.callbacks.ContactImpulse;
import org.jbox2d.callbacks.ContactListener;
import org.jbox2d.collision.Manifold;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.contacts.Contact;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RadialGradient;
import android.graphics.Paint.Style;
import android.graphics.Shader.TileMode;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
//import com.xtremelabs.devicewallmarblerun.Box2DDrawableWorld.CollisionContacts;
import com.xtremelabs.devicewallmarblerun.Box2DDrawableWorld;
import com.xtremelabs.devicewallmarblerun.utils.JSONProperties;
import com.xtremelabs.devicewallmarblerun.utils.ScreenProperties;
public class Box2DWorldEngine {
Box2DDrawableWorld drawableWorld;
private Vec2 ballStartPosition = new Vec2(0, 2f);
private int ID = 1;
public int PORTAL_A_ID = 22;
public int PORTAL_B_ID = 44;
public long lastPortalShiftTime = 0;
public int lastPortalPut = PORTAL_B_ID;
public PortalObject portalA;
public PortalObject portalB;
long elapsedTime = 0;
long startTime = 0;
public Stack<Pair<Vec2, Float>> pendingPortalRequests = new Stack<Pair<Vec2, Float>>();
JSONObject sendingJSONObject = new JSONObject();
// JSONObject sendingJSONObjectIds = new JSONObject();
SparseArray<String> sendingJSONStrings = new SparseArray<String>();
BodyDef ground = new BodyDef();
public void setDrawable(Box2DDrawableWorld drawable){
drawableWorld = drawable;
Log.d("", "Drawable world set");
}
public Box2DWorldEngine(){
}
public void initialize(){
GameProperties.reset();
new RectPhysicsObject(BodyType.STATIC, new Vec2(-35f, 0.0f), 5.0f, 25f, 0, getNewId(GameProperties.GAME_ELEMENT_GROUND), this);
new RectPhysicsObject(BodyType.STATIC, new Vec2(35f, 0.0f), 5.0f, 25f, 0, getNewId(GameProperties.GAME_ELEMENT_GROUND), this);
new RectPhysicsObject(BodyType.STATIC, new Vec2(0.0f, -20.0f), 30.0f, 5.0f, 0, getNewId(GameProperties.GAME_ELEMENT_GROUND), this);
new RectPhysicsObject(BodyType.STATIC, new Vec2(0.0f, 20.0f), 30.0f, 5.0f, 0, getNewId(GameProperties.GAME_ELEMENT_GROUND), this);
new RectPhysicsObject(BodyType.DYNAMIC, new Vec2(-1.5f, -8f), 1.2f, 1.2f, 0, getNewId(GameProperties.GAME_ELEMENT_STABLE_WALL), this);
new RectPhysicsObject(BodyType.DYNAMIC, new Vec2(8f, -4f), 1f, 4f, 0, getNewId(GameProperties.GAME_ELEMENT_STABLE_WALL), this);
new RectPhysicsObject(BodyType.DYNAMIC, new Vec2(-8f, -5f), 3f, 5f, 0, getNewId(GameProperties.GAME_ELEMENT_STABLE_WALL), this);
new RectPhysicsObject(BodyType.DYNAMIC, new Vec2(-8f, 2.3f), 1f, 2f, 0, getNewId(GameProperties.GAME_ELEMENT_STABLE_WALL), this);
new CirclePhysicsObject(BodyType.DYNAMIC, ballStartPosition, new Vec2(0f, 5f), 1.2f, 0.95f, 5.0f, getNewId(GameProperties.GAME_ELEMENT_ACTIVE_BALL), this);
new PortalObject(new Vec2(6, 6), 25, PORTAL_A_ID = getNewId(GameProperties.GAME_ELEMENT_PORTAL), this);
new PortalObject(new Vec2(-13.5f, 6), -45, PORTAL_B_ID = getNewId(GameProperties.GAME_ELEMENT_PORTAL), this);
lastPortalPut = PORTAL_B_ID;
GameProperties.getWorld().setContactListener(new CollisionContacts());
startTime = System.currentTimeMillis();
Log.i("", "Finished initializing engine.");
}
public void processFrame(){
if(System.currentTimeMillis() < startTime + 1000) return;
GameProperties.getWorld().step(0.07f, 10, 8);
for(PhysicsObject object : GameProperties.getGamePropsInstance().objectsList)
object.postProcess();
for(int i = 0; i < 2 && !pendingPortalRequests.isEmpty(); i++){
// Log.d("YK", "Found something in pending portal");
Pair<Vec2, Float> pair = pendingPortalRequests.pop();
int id = (lastPortalPut == PORTAL_A_ID) ? PORTAL_B_ID : PORTAL_A_ID;
if(id == PORTAL_A_ID)
portalA.moveTo(pair);
else
portalB.moveTo(pair);
lastPortalPut = id;
}
pendingPortalRequests.clear();
for(PhysicsObject object : GameProperties.getGamePropsInstance().objectsList)
object.anythingToSend();
// Log.e("", "process frame...");
}
public int getNewId(int type){
return (ID++)*GameProperties.ELEMENT_DIVIDER + type;
}
private class CollisionContacts implements ContactListener{
@Override
public void beginContact(Contact arg0) {
Manifold mani = arg0.getManifold();
PhysicsObject phys1 = (PhysicsObject)arg0.getFixtureA().getUserData();
PhysicsObject phys2 = (PhysicsObject)arg0.getFixtureB().getUserData();
Log.w("TAG", "Contact!" + phys1.id);
putToDrawables(phys1.id, "{\"" + JSONProperties.CONTACT_TIME + "\": " + System.currentTimeMillis() +
", \"" + JSONProperties.CONTACT_LOCATION + "\": [" + mani.localPoint.x + ", " + mani.localPoint.y + "]}");
PhysicsObject ballPhys = null, portalPhys = null;
if(System.currentTimeMillis() - lastPortalShiftTime > GameProperties.PORTAL_GRACE_TIME)
if((ballPhys = phys1).id % GameProperties.ELEMENT_DIVIDER == GameProperties.GAME_ELEMENT_ACTIVE_BALL ||
(ballPhys = phys2).id % GameProperties.ELEMENT_DIVIDER == GameProperties.GAME_ELEMENT_ACTIVE_BALL){
if((portalPhys = phys1).id % GameProperties.ELEMENT_DIVIDER == GameProperties.GAME_ELEMENT_PORTAL ||
(portalPhys = phys2).id % GameProperties.ELEMENT_DIVIDER == GameProperties.GAME_ELEMENT_PORTAL){
Log.w("TAG", "Portal hit!");
putToDrawables(portalPhys.id, "{\"" + JSONProperties.PROPERTIES + "\":" +
"{\"" + JSONProperties.COLOR + "\": " + Integer.valueOf(0xFFFF9999).intValue() + "} }");
((CirclePhysicsObject)ballPhys).setMove((PortalObject)portalPhys, ((CirclePhysicsObject)ballPhys).body.getLinearVelocity());
}
}
}
@Override
public void endContact(Contact arg0) {
PhysicsObject phys = (PhysicsObject)arg0.getFixtureA().getUserData();
if(phys != null && phys.id != GameProperties.GAME_ELEMENT_GROUND){
// phys.basePaint = new Paint(phys.basePaint);
}
phys = (PhysicsObject)arg0.getFixtureB().getUserData();
if(phys != null && phys.id != GameProperties.GAME_ELEMENT_GROUND){
// phys.basePaint = new Paint(phys.basePaint);
}
}
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
// TODO Auto-generated method stub
}
@Override
public void preSolve(Contact contact, Manifold oldManifold) {
// TODO Auto-generated method stub
}
}
public void shootNewMarble(Vec2 start, Vec2 end){
new CirclePhysicsObject(BodyType.DYNAMIC, end, start.sub(end), 1.2f, 0.95f, 5.0f, getNewId(GameProperties.GAME_ELEMENT_ACTIVE_BALL), this);
}
public void putToProcess(JSONObject json){
if(json.has(JSONProperties.RESET_CODE)) reset();
if(json.has(JSONProperties.PORTAL)){
try {
if(json.get(JSONProperties.PORTAL) instanceof Pair<?, ?>){
pendingPortalRequests.push((Pair<Vec2, Float>)json.get(JSONProperties.PORTAL));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
if(json.has(JSONProperties.Shot.SHOT_RELEASE)){
try {
Vec2 stVec = null, endVec = null;
JSONObject js = json.getJSONObject(JSONProperties.Shot.SHOT_RELEASE);
if(js.has(JSONProperties.Shot.START_POINT)){
JSONArray str_arr = js.getJSONArray(JSONProperties.Shot.START_POINT);
stVec = new Vec2((float)str_arr.getDouble(0), (float)str_arr.getDouble(1));
}
if(js.has(JSONProperties.Shot.END_POINT)){
JSONArray end_arr = js.getJSONArray(JSONProperties.Shot.END_POINT);
endVec = new Vec2((float)end_arr.getDouble(0), (float)end_arr.getDouble(1));
}
if(stVec != null && endVec != null)
shootNewMarble(stVec, endVec);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void putToDrawables(int id, String jsonString){
String currJson = sendingJSONStrings.get(id);
sendingJSONStrings.put(id, currJson == null ? jsonString : currJson + ", " + jsonString);
}
public void sendToDrawables(){
if(sendingJSONObject.names() != null)
Log.i("", "Send to drawables: " + sendingJSONObject.toString());
JSONObject totalJSON = new JSONObject();
try {
sendingJSONObject.put(JSONProperties.TIMESTAMP, System.currentTimeMillis());
int key = 0;
for(int i = 0; i < sendingJSONStrings.size(); i++) {
key = sendingJSONStrings.keyAt(i);
JSONObject json = new JSONObject(sendingJSONStrings.get(key));
totalJSON.put(Integer.valueOf(key).toString(), json);
}
sendingJSONObject.put(JSONProperties.IDS, totalJSON);
} catch (JSONException e) {
e.printStackTrace();
}
if(drawableWorld != null)
drawableWorld.receiveFromEngine(sendingJSONObject);
sendingJSONObject = new JSONObject();
sendingJSONStrings = new SparseArray<String>();
}
public void reset() {
initialize();
}
}