/* * Copyright (c) 2012, 2013 Hemanta Sapkota. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Hemanta Sapkota (laex.pearl@gmail.com) */ package com.laex.cg2d.render.impl; import java.io.IOException; import java.util.List; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.physics.box2d.Body; import com.badlogic.gdx.physics.box2d.BodyDef; import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer; import com.badlogic.gdx.physics.box2d.FixtureDef; import com.badlogic.gdx.physics.box2d.JointDef; import com.badlogic.gdx.physics.box2d.JointEdge; import com.badlogic.gdx.physics.box2d.World; import com.badlogic.gdx.utils.Array; import com.laex.cg2d.model.ScreenModel.CGEntity; import com.laex.cg2d.model.ScreenModel.CGEntityAnimation; import com.laex.cg2d.model.ScreenModel.CGJoint; import com.laex.cg2d.model.ScreenModel.CGLayer; import com.laex.cg2d.model.ScreenModel.CGScreenModel; import com.laex.cg2d.model.ScreenModel.CGShape; import com.laex.cg2d.render.BodyVisitor; import com.laex.cg2d.render.Box2DBody; import com.laex.cg2d.render.ScreenManager; import com.laex.cg2d.render.ScreenScaffold; import com.laex.cg2d.render.impl.bodies.BoxBody; import com.laex.cg2d.render.impl.bodies.CircleBody; import com.laex.cg2d.render.impl.bodies.EdgeBody; import com.laex.cg2d.render.impl.bodies.EntityBody; import com.laex.cg2d.render.util.AppExceptionUtil; import com.laex.cg2d.render.util.ProtoBufTypeConversionUtil; /** * The Class AbstractGameComponentManager. * * {@link ScreenManagerImpl} * * @author hemantasapkota */ public class ScreenManagerImpl implements ScreenScaffold, ScreenManager { /** The world. */ private World world; /** The model. */ private CGScreenModel model; /** The ptm ratio. */ private int ptmRatio; /** The camera. */ private Camera camera; /** The entity manager. */ private EntityManager entityManager; /** The background manager. */ private BackgroundManager backgroundManager; /** The debug draw. */ private Box2DDebugRenderer debugDraw; /** The sprite batch. */ private SpriteBatch spriteBatch; /** * Instantiates a new abstract game component manager. * * @param model * the model * @param world * the world * @param camera * the camera * @param batch * the batch */ public ScreenManagerImpl(CGScreenModel model, World world, Camera camera, SpriteBatch batch) { this.world = world; this.model = model; this.camera = camera; this.spriteBatch = batch; this.ptmRatio = model.getScreenPrefs().getWorldPrefs().getPtmRatio(); this.entityManager = new EntityManager(this, batch); this.backgroundManager = new BackgroundManager(this, batch); initBox2d(); } /** * Inits the box2d. */ private void initBox2d() { debugDraw = new Box2DDebugRenderer(); debugDraw.setDrawAABBs(model.getScreenPrefs().getDebugDrawPrefs().getDrawAABB()); debugDraw.setDrawBodies(model.getScreenPrefs().getDebugDrawPrefs().getDrawBodies()); debugDraw.setDrawInactiveBodies(model.getScreenPrefs().getDebugDrawPrefs().getDrawInactiveBodies()); debugDraw.setDrawJoints(model.getScreenPrefs().getDebugDrawPrefs().getDrawJoints()); } // Standard visitor to box2d world /** * Accept body visitor. * * @param bv * the bv */ public void acceptBodyVisitor(BodyVisitor bv) { Array<Body> bodies = new Array<Body>(); world.getBodies(bodies); for (Body b : bodies) { if (b == null) { continue; } CGShape shape = (CGShape) b.getUserData(); bv.visit(b, shape); } } /** * Creates the joints. * * @param shape * the shape */ public void createJoints(CGShape shape) { List<CGJoint> joints = shape.getJointsList(); for (CGJoint joint : joints) { String sourceId = joint.getSourceShapeId(); String targetId = joint.getTargetShapeId(); Body bodyA = null; Body bodyB = null; Array<Body> bodies = new Array<Body>(); world.getBodies(bodies); for (Body b : bodies) { CGShape shp = (CGShape) b.getUserData(); if (shp != null) { String shpId = shp.getId(); if (shpId.equals(sourceId)) { bodyA = b; } else if (shpId.equals(targetId)) { bodyB = b; } } } // Init the joints JointDef jd = initJoints(joint, bodyA, bodyB); if (jd != null) { world.createJoint(jd); } } } /** * Inits the joints. * * @param joint * the joint * @param bodyA * the body a * @param bodyB * the body b * @return the joint def */ public JointDef initJoints(CGJoint joint, Body bodyA, Body bodyB) { JointDef jd = null; switch (joint.getType()) { case DISTANCE: jd = ProtoBufTypeConversionUtil.asDistanceJointDef(bodyA, bodyB, joint); break; case FRICTION: jd = ProtoBufTypeConversionUtil.asFrictionJointDef(bodyA, bodyB, joint); break; case PRISMATIC: jd = ProtoBufTypeConversionUtil.asPrimasticJointDef(bodyA, bodyB, joint); break; case PULLEY: jd = ProtoBufTypeConversionUtil.asPulleyJointDef(bodyA, bodyB, joint); break; case REVOLUTE: jd = ProtoBufTypeConversionUtil.asRevoluteJoint(bodyA, bodyB, joint); break; case WELD: jd = ProtoBufTypeConversionUtil.asWeldJointDef(bodyA, bodyB, joint); break; case ROPE: break; case GEAR: break; case MOUSE: break; case UNKNOWN: break; case WHEEL: break; default: break; } return jd; } /** * Creates the body. * * @param shape * the shape * @param entity * the entity * @param ea * the ea * @return the body */ public Body createBody(CGShape shape, CGEntity entity, CGEntityAnimation ea) { BodyDef bodyDef = ProtoBufTypeConversionUtil.asBodyDef(shape.getBodyDef()); FixtureDef fixtureDef = ProtoBufTypeConversionUtil.asFixtureDef(shape.getFixtureDef()); Body b = null; Box2DBody b2Body; switch (shape.getEditorShapeType()) { case SIMPLE_SHAPE_BOX: { b2Body = new BoxBody(shape, this); b = b2Body.create(bodyDef, fixtureDef); } break; case SIMPLE_SHAPE_CIRCLE: { b2Body = new CircleBody(shape, this); b = b2Body.create(bodyDef, fixtureDef); } break; case SIMPLE_SHAPE_HEDGE: case SIMPLE_SHAPE_VEDGE: { b2Body = new EdgeBody(shape, this); b = b2Body.create(bodyDef, fixtureDef); } break; case ENTITY_SHAPE: { b2Body = new EntityBody(shape, this, entityManager, entity, ea); b = b2Body.create(bodyDef, fixtureDef); } break; case BACKGROUND_SHAPE: default: break; } return b; } /** * Handle exception. * * @param t * the t */ public void handleException(Throwable t) { AppExceptionUtil.handle(t); } /** * Update state time. * * @param stateTime * the state time */ public void updateStateTime(float stateTime) { this.entityManager.updateStateTime(stateTime); } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenScaffold#create() */ @Override public void create() { backgroundManager.create(); entityManager.create(); } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenScaffold#render() */ @Override public void render() { backgroundManager.render(); entityManager.render(); if (model.getScreenPrefs().getDebugDrawPrefs().getDrawDebugData()) { debugDraw.render(world, camera.combined); } } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenScaffold#dispose() */ @Override public void dispose() { // backgroundManager.dispose(); entityManager.dispose(); } /** * Ptm ratio. * * @return the int */ public int ptmRatio() { return this.ptmRatio; } /** * Camera. * * @return the camera */ @Override public Camera camera() { return this.camera; } /** * World. * * @return the world */ @Override public World world() { return this.world; } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenManager#createEntityFrom(java.lang.String) */ @Override public Body createEntityFrom(final String id, final String animationName) { Body b = null; for (CGLayer layer : model.getLayersList()) { for (CGShape shape : layer.getShapeList()) { if (!shape.getId().equals(id)) { continue; } try { b = entityManager.createEntity(shape, animationName); createJoints(shape); } catch (IOException e) { AppExceptionUtil.handle(e); } } } return b; } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenManager#switchAnimation(java.lang.String, * java.lang.String) */ @Override public Body switchAnimation(final String id, final String animationName) { Body switchedBody = null; Array<Body> bodies = new Array<Body>(); world.getBodies(bodies); for (Body bod : bodies) { CGShape shape = (CGShape) bod.getUserData(); if (id.equals(shape.getId())) { try { Vector2 positionToCopy = new Vector2(bod.getTransform().getPosition()); float rotation = bod.getTransform().getRotation(); world.destroyBody(bod); entityManager.removeEntity(shape); switchedBody = entityManager.createEntity(shape, animationName); if (switchedBody != null) { switchedBody.setTransform(positionToCopy, rotation); } } catch (IOException e) { AppExceptionUtil.handle(e); } } } return switchedBody; } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenManager#getEntityById(java.lang.String) */ @Override public Body getEntityById(String id) { Array<Body> bodies = new Array<Body>(); for (Body b : bodies) { CGShape shape = (CGShape) b.getUserData(); if (shape.getId().equals(id)) { return b; } } return null; } /* * (non-Javadoc) * * @see * com.laex.cg2d.render.ScreenManager#getEntityId(com.badlogic.gdx.physics * .box2d.Body) */ @Override public String getEntityId(Body b) { return ((CGShape) b.getUserData()).getId(); } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenManager#newVector(float, float) */ @Override public Vector2 newVector(float x, float y) { return new Vector2(x, y); } /* * (non-Javadoc) * * @see com.laex.cg2d.render.ScreenManager#drawText(java.lang.String, float, * float) */ @Override public void drawText(String text, float x, float y) { BitmapFont font = new BitmapFont(); spriteBatch.begin(); font.getRegion().getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); font.setScale(0.1f); font.draw(spriteBatch, text, x, y); spriteBatch.end(); } /* * (non-Javadoc) * * @see * com.laex.cg2d.render.ScreenManager#destroyJointForEntity(java.lang.String) */ @Override public void destroyJointForEntity(String id) { Body b = getEntityById(id); Array<JointEdge> jointList = b.getJointList(); for (JointEdge je : jointList) { world.destroyJoint(je.joint); } } @Override public CGScreenModel model() { return model; } }