00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.map;
00023
00024 import com.realtime.crossfire.jxclient.animations.Animation;
00025 import com.realtime.crossfire.jxclient.server.crossfire.messages.Map2;
00026 import java.util.ArrayList;
00027 import java.util.Collection;
00028 import java.util.HashMap;
00029 import java.util.Map;
00030 import java.util.Random;
00031 import java.util.WeakHashMap;
00032 import org.jetbrains.annotations.NotNull;
00033
00038 public class CfMapAnimations {
00039
00044 @NotNull
00045 private final Random random = new Random();
00046
00050 private int width = 0;
00051
00055 private int height = 0;
00056
00060 @NotNull
00061 private final AnimationMap animations = new AnimationMap();
00062
00066 @NotNull
00067 private final Map<AnimationState, Void> animationStates = new WeakHashMap<AnimationState, Void>();
00068
00072 @NotNull
00073 private final Map<Integer, AnimationState> syncAnimationStates = new HashMap<Integer, AnimationState>();
00074
00079 @NotNull
00080 private final Collection<AnimationState> pendingTickUpdates = new ArrayList<AnimationState>();
00081
00085 public void clear() {
00086 animations.clear();
00087 animationStates.clear();
00088 syncAnimationStates.clear();
00089 pendingTickUpdates.clear();
00090 }
00091
00099 public void add(@NotNull final MapUpdaterState mapUpdaterState, @NotNull final Location location, @NotNull final Animation animation, final int type) {
00100 assert 0 <= location.getX();
00101 assert 0 <= location.getY();
00102 assert 0 <= type && type < 4;
00103
00104 final AnimationState animationState;
00105 final boolean addToPendingTickUpdates;
00106 switch (type) {
00107 default:
00108 case Map2.ANIM_NORMAL:
00109 animationState = new AnimationState(animation, 0);
00110 addToPendingTickUpdates = true;
00111 break;
00112
00113 case Map2.ANIM_RANDOM:
00114 animationState = new AnimationState(animation, random.nextInt(animation.getFaces()));
00115 addToPendingTickUpdates = true;
00116 break;
00117
00118 case Map2.ANIM_SYNC:
00119 final int animationId = animation.getAnimationId();
00120 final AnimationState tmp = syncAnimationStates.get(animationId);
00121 if (tmp != null) {
00122 animationState = tmp;
00123 addToPendingTickUpdates = false;
00124 } else {
00125 animationState = new AnimationState(animation, 0);
00126 syncAnimationStates.put(animationId, animationState);
00127 addToPendingTickUpdates = true;
00128 }
00129 break;
00130 }
00131
00132 animationStates.put(animationState, null);
00133 animations.add(mapUpdaterState, location, animationState);
00134 if (addToPendingTickUpdates) {
00135 pendingTickUpdates.add(animationState);
00136 }
00137 }
00138
00144 public void remove(final int x, final int y) {
00145 for (int layer = 0; layer < Map2.NUM_LAYERS; layer++) {
00146 animations.remove(new Location(x, y, layer));
00147 }
00148 }
00149
00154 public void remove(@NotNull final Location location) {
00155 animations.remove(location);
00156 }
00157
00164 public void updateSpeed(@NotNull final MapUpdaterState mapUpdaterState, @NotNull final Location location, final int speed) {
00165 animations.updateSpeed(mapUpdaterState, location, speed);
00166 }
00167
00174 public void scroll(final int dx, final int dy) {
00175 animations.scroll(dx, dy, width, height);
00176 }
00177
00183 public void tick(@NotNull final MapUpdaterState mapUpdaterState, final int tickNo) {
00184 for (final AnimationState animationState : pendingTickUpdates) {
00185 animationState.setTickNo(tickNo);
00186 }
00187 pendingTickUpdates.clear();
00188 final Iterable<AnimationState> animationStatesToUpdate = new ArrayList<AnimationState>(animationStates.keySet());
00189 synchronized (mapUpdaterState.mapBegin()) {
00190 for (final AnimationState animationState : animationStatesToUpdate) {
00191 animationState.updateTickNo(mapUpdaterState, tickNo);
00192 }
00193 mapUpdaterState.mapEnd(false);
00194 }
00195 }
00196
00202 public void setMapSize(final int width, final int height) {
00203 this.width = width;
00204 this.height = height;
00205 clear();
00206 }
00207
00208 }