package net.alcuria.umbracraft.engine.scripts; import java.util.Set; import net.alcuria.umbracraft.Game; import net.alcuria.umbracraft.annotations.Tooltip; import net.alcuria.umbracraft.editor.Editor; import net.alcuria.umbracraft.engine.components.AnimationCollectionComponent; import net.alcuria.umbracraft.engine.components.AnimationGroupComponent; import net.alcuria.umbracraft.engine.components.AnimationGroupComponent.Direction; import net.alcuria.umbracraft.engine.entities.Entity; import net.alcuria.umbracraft.util.StringUtils; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.ObjectMap; public class ChangeDirectionScriptCommand extends ScriptCommand { private static final int angles[] = { 0, 45, 90, 135, 180, 225, 270, 315, 360 }; /** Given a direction and an entity, attempts to make the entity face that * direction. Requires either an {@link AnimationCollectionComponent} or an * {@link AnimationGroupComponent}. * @param direction the direction to face * @param entity the entity to change */ public static void setDirection(Direction direction, Entity entity) { // update the entity's direction // search for either a collection or a group, prioritizing the former AnimationCollectionComponent component = entity.getComponent(AnimationCollectionComponent.class); if (component != null) { component.setDirection(direction); } else { AnimationGroupComponent group = entity.getComponent(AnimationGroupComponent.class); if (group != null) { group.setDirection(direction); } } } @Tooltip("If we want to only use the 4 cardinal directions") public boolean cardinal; @Tooltip("The direction to face, if fixed. Ignored if the target field is specified") public Direction direction = Direction.DOWN; @Tooltip("The entity we want to change the direction of") public String entity; @Tooltip("If not empty, the entity we want to face") public String target; @Override public ScriptCommand copy() { ChangeDirectionScriptCommand cmd = new ChangeDirectionScriptCommand(); cmd.direction = direction; cmd.entity = entity; cmd.target = target; cmd.cardinal = cardinal; return cmd; } private String direction() { return StringUtils.isNotEmpty(target) ? target : (direction != null ? direction.toString() : ""); } private String entity() { return StringUtils.isNotEmpty(entity) ? entity : ""; } @Override public Set<String> getFilter() { return null; } @Override public String getName() { return "Change Direction: " + entity() + ", " + direction(); } @Override public ObjectMap<String, Array<String>> getSuggestions() { return new ObjectMap<String, Array<String>>() { { put("target", Editor.db().entities().keys()); put("entity", Editor.db().entities().keys()); } }; } @Override public void onCompleted() { } @Override public void onStarted(Entity entity) { Direction newDirection = null; Entity changingEntity = Game.entities().find(this.entity); if (changingEntity != null) { if (StringUtils.isNotEmpty(target)) { Entity targetEntity = Game.entities().find(target); if (targetEntity != null) { // calculate facing float dX = targetEntity.position.x - changingEntity.position.x; float dY = targetEntity.position.y - changingEntity.position.y; if (cardinal) { // for cardinal, we compare delta x/y to determine which is larger and get the subsequent direction from that if (Math.abs(dX) > Math.abs(dY)) { newDirection = dX > 0 ? Direction.RIGHT : Direction.LEFT; } else { newDirection = dY > 0 ? Direction.DOWN : Direction.RIGHT; } } else { // use atan to figure out the angle between two points and the horizontal // 0 degrees = west, 90 degrees = south, 180 degrees = east, 270 degrees = north float angle = (MathUtils.atan2(dY, dX)) * 180 / MathUtils.PI + 180; // get closest angle int closestAngle = 0; int closestValue = Integer.MAX_VALUE; for (int i = 0; i < angles.length; i++) { if (Math.abs(angle - angles[i]) < closestValue) { closestAngle = angles[i]; closestValue = (int) Math.abs(angle - angles[i]); } } newDirection = Direction.from(closestAngle); } } else { // no entity found, print an error Game.error("No entity found with name: " + target); } } else { // no target, just change facing absolutely newDirection = direction; } setDirection(newDirection, changingEntity); } else { Game.error("No entity found with name: " + target); } complete(); } @Override public void update() { } }