package net.alcuria.umbracraft.engine.components; import net.alcuria.umbracraft.Game; import net.alcuria.umbracraft.definitions.anim.AnimationGroupDefinition; import net.alcuria.umbracraft.engine.components.AnimationCollectionComponent.Pose; import net.alcuria.umbracraft.engine.entities.Entity; import com.badlogic.gdx.utils.ObjectMap; /** A component used for displaying components in particular directions. * @author Andrew Keturi */ public class AnimationGroupComponent implements Component { /** Various animation facing directions * @author Andrew Keturi */ public static enum Direction { DOWN, DOWNLEFT, DOWNRIGHT, LEFT, RIGHT, UP, UPLEFT, UPRIGHT; /** Given an angle in degrees, returns the direction at that angle. 0 * degrees = west, 90 degrees = south, 180 degrees = east, 270 degrees = * north * @param angle * @return */ public static Direction from(int angle) { switch (angle) { case 0: case 360: return Direction.LEFT; case 45: return Direction.DOWNLEFT; case 90: return Direction.DOWN; case 135: return Direction.DOWNRIGHT; case 180: return Direction.RIGHT; case 225: return Direction.UPRIGHT; case 270: return Direction.UP; case 315: return Direction.UPLEFT; default: return Direction.DOWN; } } /** For 2k-style spritesheet templating * @return */ public int getTemplateIndex() { switch (this) { case UP: return 0; case RIGHT: return 1; case DOWN: return 2; case LEFT: return 3; } return 3; } /** @return <code>true</code> if the direction is cardinal (up, down, * left, or right) */ public boolean isCardinal() { return this == Direction.LEFT || this == Direction.DOWN || this == Direction.UP || this == Direction.RIGHT; } } private ObjectMap<Direction, AnimationComponent> animations; private boolean cardinalOnly = false; private AnimationComponent currentComponent; private Direction currentDirection; private final AnimationGroupDefinition definition; private final String template; private final Pose templatePose; private final int templateX, templateY; public AnimationGroupComponent(AnimationGroupDefinition definition) { this(definition, null, null, 0, 0); } public AnimationGroupComponent(AnimationGroupDefinition definition, String template, Pose templatePose, int templateX, int templateY) { this.definition = definition; this.template = template; this.templateX = templateX; this.templateY = templateY; this.templatePose = templatePose; cardinalOnly = definition != null ? definition.cardinalOnly : false; } @Override public void create(Entity entity) { animations = new ObjectMap<Direction, AnimationComponent>(); animations.put(Direction.DOWN, new AnimationComponent(template, templateX, templateY, templatePose, Direction.DOWN, definition != null ? Game.db().anim(definition.down) : null)); animations.put(Direction.LEFT, new AnimationComponent(template, templateX, templateY, templatePose, Direction.LEFT, definition != null ? Game.db().anim(definition.left) : null)); animations.put(Direction.RIGHT, new AnimationComponent(template, templateX, templateY, templatePose, Direction.RIGHT, definition != null ? Game.db().anim(definition.right) : null)); animations.put(Direction.UP, new AnimationComponent(template, templateX, templateY, templatePose, Direction.UP, definition != null ? Game.db().anim(definition.up) : null)); animations.put(Direction.DOWNLEFT, new AnimationComponent(template, templateX, templateY, templatePose, Direction.DOWNLEFT, definition != null ? Game.db().anim(definition.cardinalOnly ? definition.down : definition.downLeft) : null)); animations.put(Direction.DOWNRIGHT, new AnimationComponent(template, templateX, templateY, templatePose, Direction.DOWNRIGHT, definition != null ? Game.db().anim(definition.cardinalOnly ? definition.down : definition.downRight) : null)); animations.put(Direction.UPLEFT, new AnimationComponent(template, templateX, templateY, templatePose, Direction.UPLEFT, definition != null ? Game.db().anim(definition.cardinalOnly ? definition.down : definition.upLeft) : null)); animations.put(Direction.UPRIGHT, new AnimationComponent(template, templateX, templateY, templatePose, Direction.UPRIGHT, definition != null ? Game.db().anim(definition.cardinalOnly ? definition.down : definition.upRight) : null)); for (AnimationComponent anim : animations.values()) { anim.create(entity); } currentComponent = animations.get(Direction.DOWN); } @Override public void dispose(Entity entity) { } public Direction getDirection() { return currentDirection; } @Override public void render(Entity entity) { if (currentComponent != null) { currentComponent.render(entity); } } /** @param cardinalOnly if <code>true</code> this component will only move in * 4-directions. */ public void setCardinalOnly(boolean cardinalOnly) { this.cardinalOnly = cardinalOnly; } public void setDirection(Direction direction) { if (direction == null) { return; } currentDirection = direction; if (animations != null) { currentComponent = animations.get(currentDirection); } } @Override public void update(Entity entity) { Direction tmpDirection = currentDirection; // set mask based on velocity of player int mask = 0b0000; // up, down, left, right final float tolerance = 0.5f; if (entity.velocity.x < -tolerance) { mask = mask ^ 0b0010; } else if (entity.velocity.x > tolerance) { mask = mask ^ 0b0001; } if (entity.velocity.y < -tolerance) { mask = mask ^ 0b0100; } else if (entity.velocity.y > tolerance) { mask = mask ^ 0b1000; } // update current facing direction switch (mask) { case 0b0001: tmpDirection = Direction.RIGHT; break; case 0b0010: tmpDirection = Direction.LEFT; break; case 0b0100: tmpDirection = Direction.DOWN; break; case 0b1000: tmpDirection = Direction.UP; break; case 0b1010: tmpDirection = Direction.UPLEFT; break; case 0b1001: tmpDirection = Direction.UPRIGHT; break; case 0b0101: tmpDirection = Direction.DOWNRIGHT; break; case 0b0110: tmpDirection = Direction.DOWNLEFT; break; } // if it's different, update reference to the current component if (tmpDirection != null && (!cardinalOnly || tmpDirection.isCardinal() && cardinalOnly) && tmpDirection != currentDirection) { currentDirection = tmpDirection; currentComponent = animations.get(tmpDirection); } // update actual current animation if (currentComponent != null) { currentComponent.update(entity); } } }