/** * eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the * <e-UCM> research group. * * Copyright 2005-2010 <e-UCM> research group. * * You can access a list of all the contributors to eAdventure at: * http://e-adventure.e-ucm.es/contributors * * <e-UCM> is a research group of the Department of Software Engineering * and Artificial Intelligence at the Complutense University of Madrid * (School of Computer Science). * * C Profesor Jose Garcia Santesmases sn, * 28040 Madrid (Madrid), Spain. * * For more info please visit: <http://e-adventure.e-ucm.es> or * <http://www.e-ucm.es> * * **************************************************************************** * * This file is part of eAdventure, version 2.0 * * eAdventure is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * eAdventure is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with eAdventure. If not, see <http://www.gnu.org/licenses/>. */ package es.eucm.ead.engine.gameobjects.effects; 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.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.Shape; import com.badlogic.gdx.physics.box2d.World; import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef; import com.google.inject.Inject; import es.eucm.ead.engine.game.Game; import es.eucm.ead.engine.game.ValueMap; import es.eucm.ead.engine.game.interfaces.GUI; import es.eucm.ead.model.elements.effects.enums.PhShape; import es.eucm.ead.model.elements.effects.enums.PhType; import es.eucm.ead.model.elements.effects.physics.PhysicsEf; import es.eucm.ead.model.elements.scenes.Scene; import es.eucm.ead.model.elements.scenes.SceneElement; public class PhysicsEffectGO extends AbstractEffectGO<PhysicsEf> { public static float WORLD_SCALE = 15.0f; private World world; private float timeStep; private int velocityIterations; private int positionIterations; private GUI gui; public static final String VAR_PH_BODY = "ph_body"; public static final String VAR_PH_WORLD = "ph_world"; @Inject public PhysicsEffectGO(Game game) { super(game); this.gui = game.getGUI(); } @Override public void initialize() { super.initialize(); // doStep true = not simulate inactive bodies world = new World(new Vector2(0.0f, 10.0f), true); world.setContinuousPhysics(true); world.setWarmStarting(true); world.setAutoClearForces(true); ValueMap valueMap = game.getGameState(); valueMap.setValue((String) null, VAR_PH_WORLD, world); velocityIterations = 24; positionIterations = 8; for (SceneElement e : effect.getElements()) { createBody(world, e, valueMap); } for (SceneElement e : effect.getJoints()) { createBody(world, e, valueMap); } RevoluteJointDef jd = new RevoluteJointDef(); jd.collideConnected = false; for (int i = 0; i < effect.getJoints().size() - 1; i += 2) { SceneElement e1 = effect.getJoints().get(i); SceneElement e2 = effect.getJoints().get(i + 1); Body b1 = (Body) valueMap.getValue(e1.getId(), VAR_PH_BODY, null); Body b2 = (Body) valueMap.getValue(e2.getId(), VAR_PH_BODY, null); jd.initialize(b2, b1, new Vector2(b1.getPosition().x, b1 .getPosition().y)); world.createJoint(jd); } } @Override public void act(float delta) { super.act(delta); timeStep = delta / 1000.0f; world.step(timeStep, velocityIterations, positionIterations); Scene scene = (Scene) gui.getScene().getElement(); if (scene != null) { for (SceneElement e : scene.getSceneElements()) { ValueMap valueMap = game.getGameState(); Body b = (Body) valueMap.getValue(e.getId(), VAR_PH_BODY, null); if (b != null) { valueMap.setValue(e, SceneElement.VAR_X, (float) (b .getWorldCenter().x * WORLD_SCALE)); valueMap.setValue(e, SceneElement.VAR_Y, (float) (b .getWorldCenter().y * WORLD_SCALE)); valueMap.setValue(e, SceneElement.VAR_ROTATION, (float) Math.toDegrees(b.getAngle())); } } } else { stop(); } } public boolean isQueueable() { return true; } @Override public boolean isFinished() { return false; } public static void createBody(World world, SceneElement e, ValueMap valueMap) { float x = valueMap.getValue(e, SceneElement.VAR_X, 0f) / WORLD_SCALE; float y = valueMap.getValue(e, SceneElement.VAR_Y, 0f) / WORLD_SCALE; float width = valueMap.getValue(e, SceneElement.VAR_WIDTH, 1) / WORLD_SCALE; float height = valueMap.getValue(e, SceneElement.VAR_HEIGHT, 1) / WORLD_SCALE; // TODO what if corner is not center? PhType phType = valueMap.getValue(e, PhysicsEf.VAR_PH_TYPE, PhType.DYNAMIC); PhShape phShape = valueMap.getValue(e, PhysicsEf.VAR_PH_SHAPE, PhShape.RECTANGULAR); Shape s = null; switch (phShape) { case CIRCULAR: s = new CircleShape(); s.setRadius(width / 2); break; default: s = new PolygonShape(); ((PolygonShape) s).setAsBox(width / 2, height / 2); } BodyDef bd = new BodyDef(); switch (phType) { case STATIC: bd.type = BodyType.StaticBody; break; case DYNAMIC: bd.type = BodyType.DynamicBody; break; } bd.position.set(x, y); bd.angle = valueMap.getValue(e, SceneElement.VAR_ROTATION, 0f); FixtureDef fixture = new FixtureDef(); fixture.shape = s; fixture.density = valueMap.getValue(e, PhysicsEf.VAR_PH_DENSITY, 1f); fixture.friction = valueMap.getValue(e, PhysicsEf.VAR_PH_FRICTION, 1f); fixture.restitution = valueMap.getValue(e, PhysicsEf.VAR_PH_RESTITUTION, 1f); Body body = world.createBody(bd); body.createFixture(fixture); body.resetMassData(); valueMap.setValue(e.getId(), VAR_PH_BODY, body); } }