Permalink
Browse files

Add the possibility to define a gravity

This can be achieved for all levels using Game.world().setGravity() or on a per level basis using IEnvironment.setGravity().
It's also possible to define this as a custom map property with the key GRAVITY.
  • Loading branch information...
steffen-wilke committed Dec 23, 2018
1 parent 4525364 commit 72c9a2dcd95d30353d4fc9b565e84cab31146e52
@@ -22,6 +22,7 @@
import java.util.logging.Logger;
import java.util.stream.Collectors;

import de.gurkenlabs.litiengine.Direction;
import de.gurkenlabs.litiengine.Game;
import de.gurkenlabs.litiengine.IUpdateable;
import de.gurkenlabs.litiengine.annotation.EntityInfo;
@@ -52,6 +53,7 @@
import de.gurkenlabs.litiengine.graphics.StaticShadowLayer;
import de.gurkenlabs.litiengine.graphics.StaticShadowType;
import de.gurkenlabs.litiengine.graphics.emitters.Emitter;
import de.gurkenlabs.litiengine.physics.GravityForce;
import de.gurkenlabs.litiengine.resources.Resources;
import de.gurkenlabs.litiengine.util.TimeUtilities;
import de.gurkenlabs.litiengine.util.geom.GeometricUtilities;
@@ -62,6 +64,7 @@

private final Map<Integer, ICombatEntity> combatEntities = new ConcurrentHashMap<>();
private final Map<Integer, IMobileEntity> mobileEntities = new ConcurrentHashMap<>();
private final Map<Integer, GravityForce> gravityForces = new ConcurrentHashMap<>();
private final Map<RenderType, Map<Integer, IEntity>> entities = Collections.synchronizedMap(new EnumMap<>(RenderType.class));
private final Map<String, Collection<IEntity>> entitiesByTag = new ConcurrentHashMap<>();

@@ -87,6 +90,8 @@
private IMap map;
private int localIdSequence = 0;

private int gravity;

static {
registerMapObjectLoader(new PropMapObjectLoader());
registerMapObjectLoader(new CollisionBoxMapObjectLoader());
@@ -104,15 +109,12 @@ public Environment(final IMap map) {
this.map = map;
if (this.getMap() != null) {
Game.physics().setBounds(this.getMap().getBounds());
this.setGravity(this.getMap().getIntValue(MapProperty.GRAVITY));
}
}

public Environment(final String mapPath) {
this();
this.map = Resources.maps().get(mapPath);
if (this.getMap() != null) {
Game.physics().setBounds(this.getMap().getBounds());
}
this(Resources.maps().get(mapPath));
}

private Environment() {
@@ -993,6 +995,33 @@ public void render(final Graphics2D g) {
g.scale(1.0 / Game.world().camera().getRenderScale(), 1.0 / Game.world().camera().getRenderScale());
}

public int getGravity() {
return this.gravity;
}

public void setGravity(int gravity) {
this.gravity = gravity;

if (this.getGravity() != 0) {

// if there are gravity forces for all mobile entities, just update the existing forces
if (this.gravityForces.size() == this.getMobileEntities().size()) {
for (GravityForce force : this.gravityForces.values()) {
force.setStrength(this.gravity);
}
} else {
// otherwise create a new force for every mobile entity in the environment
for (IMobileEntity entity : this.getMobileEntities()) {
this.addGravityForce(entity);
}
}
} else {
for (IMobileEntity entity : this.getMobileEntities()) {
this.removeGravity(entity);
}
}
}

private void fireEvent(Consumer<EnvironmentListener> cons) {
for (EnvironmentListener listener : this.listeners) {
cons.accept(listener);
@@ -1140,14 +1169,19 @@ private void load(final IEntity entity) {
if (entity.getEnvironment() != null) {
entity.getEnvironment().remove(entity);
}

// 1. add to physics engine
this.loadPhysicsEntity(entity);

// 2. register for update or activate
this.loadUpdatableOrEmitterEntity(entity);

// 3. attach all controllers
// 3. if a gravity is defined, add a gravity force to the entity
if (entity instanceof IMobileEntity && this.getGravity() != 0) {
this.addGravityForce((IMobileEntity) entity);
}

// 4. attach all controllers
entity.attachControllers();

if (entity instanceof LightSource || entity instanceof StaticShadow) {
@@ -1157,6 +1191,18 @@ private void load(final IEntity entity) {
entity.loaded(this);
}

private void addGravityForce(IMobileEntity entity) {
GravityForce force = new GravityForce(entity, this.getGravity(), Direction.DOWN);
entity.getMovementController().apply(force);
this.gravityForces.put(entity.getMapId(), force);
}

private void removeGravity(IMobileEntity entity) {
if (this.gravityForces.containsKey(entity.getMapId())) {
this.gravityForces.get(entity.getMapId()).end();
}
}

private void loadPhysicsEntity(IEntity entity) {
if (entity instanceof CollisionBox) {
final CollisionBox coll = (CollisionBox) entity;
@@ -1227,6 +1273,10 @@ private void unload(final IEntity entity) {
Game.loop().detach((IUpdateable) entity);
}

if (entity instanceof IMobileEntity) {
this.removeGravity((IMobileEntity) entity);
}

// 3. detach all controllers
entity.detachControllers();

@@ -9,6 +9,7 @@

import de.gurkenlabs.litiengine.Game;
import de.gurkenlabs.litiengine.IUpdateable;
import de.gurkenlabs.litiengine.entities.IMobileEntity;
import de.gurkenlabs.litiengine.environment.tilemap.IMap;
import de.gurkenlabs.litiengine.graphics.ICamera;
import de.gurkenlabs.litiengine.resources.Resources;
@@ -25,6 +26,7 @@

private IEnvironment environment;
private ICamera camera;
private int gravity;

@Override
public void update() {
@@ -44,7 +46,7 @@ public void addLoadedListener(EnvironmentLoadedListener listener) {
this.loadedListeners.add(listener);
}

public void removeLoadedListener(EnvironmentLoadedListener listener) {
public void removeLoadedListener(EnvironmentLoadedListener listener) {
this.loadedListeners.remove(listener);
}

@@ -110,6 +112,10 @@ public IEnvironment environment() {
return this.environment;
}

public int gravity() {
return this.gravity;
}

/**
* Clears the currently active camera and environment, removes all previously loaded environments
* and clears all listener lists.
@@ -207,6 +213,10 @@ public void loadEnvironment(final IEnvironment env) {
if (env != null) {
this.addEnvironment(env);

if (env.getGravity() == 0 && this.gravity() != 0) {
env.setGravity(this.gravity());
}

env.load();
for (final EnvironmentLoadedListener listener : this.loadedListeners) {
listener.loaded(env);
@@ -367,6 +377,19 @@ public void setCamera(final ICamera cam) {
}
}

/**
* Specify the general gravity that will be used as default value for all environments that are loaded.
* The value's unit of measure is pixel/second (similar to the velocity of a <code>IMobileEntity</code>.
*
* @param gravity
* The default gravity for all environments.
*
* @see IMobileEntity#getVelocity()
*/
public void setGravity(int gravity) {
this.gravity = gravity;
}

private static <T> void add(Map<String, Collection<T>> listeners, String mapName, T listener) {
if (mapName == null || mapName.isEmpty()) {
return;
@@ -217,4 +217,8 @@
public void removeRenderable(IRenderable renderable);

public void unload();

public void setGravity(int gravity);

public int getGravity();
}
@@ -5,6 +5,7 @@
public static final String SHADOWCOLOR = "SHADOWCOLOR";
public static final String MAP_DESCRIPTION = "MAP_DESCRIPTION";
public static final String MAP_TITLE = "MAP_TITLE";
public static final String GRAVITY = "GRAVITY";

private MapProperty() {
}
@@ -5,26 +5,13 @@

import de.gurkenlabs.litiengine.entities.ICollisionEntity;

/**
* The Class Force.
*/
public class Force {
/** The cancel on collision. */
private boolean cancelOnCollision;

/** The cancel on force source reached. */
private boolean cancelOnReached;

/** The has ended. */
private boolean hasEnded;

/** The location. */
private Point2D location;

private final float size;

/** The strength. */
private final float strength;
private float strength;

/**
* Instantiates a new force.
@@ -104,4 +91,8 @@ public void setCancelOnReached(final boolean cancelOnReached) {
public void setLocation(final Point2D location) {
this.location = location;
}

public void setStrength(float strength) {
this.strength = strength;
}
}
@@ -4,9 +4,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.ThreadLocalRandom;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.logging.Level;
import java.util.logging.Logger;

0 comments on commit 72c9a2d

Please sign in to comment.