package ch.epfl.xblast.server.painter; import ch.epfl.xblast.Direction; import ch.epfl.xblast.PlayerID; import ch.epfl.xblast.SubCell; import ch.epfl.xblast.server.Player; /** * Player painter. * * @author Timothée FLOURE (257420) * @author Pacien TRAN-GIRARD (261948) */ public final class PlayerPainter { private static final byte DEAD_PLAYER_IMAGE_ID = 16; private static final byte DYING_IMAGE_ID = 12; private static final byte LAST_DYING_IMAGE_ID = 13; private static final int BLANK_PLAYER_GROUP = 4; private static final int PLAYER_MULTIPLIER = 20; private static final int DIRECTION_MULTIPLIER = 3; private static final int ANIMATION_POSITION_LOOP = 4; /** * Computes and returns the animation frame byte for the given tick if the player is moving. * * @param dir the direction * @param pos the position * @return the position byte */ private static byte byteForPosition(Direction dir, SubCell pos) { int axialPosition; if (dir == Direction.E || dir == Direction.W) axialPosition = pos.x(); else axialPosition = pos.y(); int cycleTick = axialPosition % ANIMATION_POSITION_LOOP; return (byte) (cycleTick % 2 == 0 ? 0 : cycleTick / 2 + 1); } /** * Returns the byte for the given Direction. * * @param d the Direction * @return the directional byte */ private static byte byteForDirection(Direction d) { return (byte) (d.ordinal() * DIRECTION_MULTIPLIER); } /** * Returns the player image byte for the given PlayerID. * * @param pid the PlayerID * @return the image byte for the player */ private static byte byteForPlayerID(PlayerID pid) { return (byte) (pid.ordinal() * PLAYER_MULTIPLIER); } /** * Returns the player image byte for the blank player. * * @return the image byte for the player */ private static byte byteForPlayerID() { return (byte) (BLANK_PLAYER_GROUP * PLAYER_MULTIPLIER); } /** * Returns the image ID for the dying state according to the number of remaining lives. * * @param lives the number of remaining lives * @return the dying image ID */ private static byte byteForDyingState(int lives) { return lives == 1 ? LAST_DYING_IMAGE_ID : DYING_IMAGE_ID; } /** * Returns the byte related to the image corresponding to the actual state of the given player. * * @param player the given player * @param tick the actual tick of the game * @return the byte related to the image of the the actual state of the player */ public static byte byteForPlayer(Player player, int tick) { switch (player.lifeState().state()) { case DEAD: return DEAD_PLAYER_IMAGE_ID; case DYING: return (byte) (byteForPlayerID(player.id()) + byteForDyingState(player.lives())); case INVULNERABLE: if (tick % 2 == 0) return (byte) (byteForPlayerID() + byteForDirection(player.direction()) + byteForPosition(player.direction(), player.position())); default: return (byte) (byteForPlayerID(player.id()) + byteForDirection(player.direction()) + byteForPosition(player.direction(), player.position())); } } }