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 java.util.Collection;
00026 import java.util.Collections;
00027 import java.util.HashSet;
00028 import java.util.Iterator;
00029 import java.util.Set;
00030 import org.jetbrains.annotations.NotNull;
00031
00036 public class AnimationState implements Iterable<Location> {
00037
00041 @NotNull
00042 private final Animation animation;
00043
00047 private int speed = 1;
00048
00052 private int tickNo = 0;
00053
00058 private int index;
00059
00063 private int lastFace = -1;
00064
00068 @NotNull
00069 private final Set<Location> locations = new HashSet<Location>();
00070
00076 public AnimationState(@NotNull final Animation animation, final int index) {
00077 this.animation = animation;
00078 this.index = index%animation.getFaces();
00079 }
00080
00086 public void setSpeed(@NotNull final MapUpdaterState mapUpdaterState, final int speed) {
00087 assert speed > 0;
00088 if (this.speed == speed) {
00089 return;
00090 }
00091 final int tmpIndex = index/this.speed;
00092 final int tmpDelay = Math.min(index%this.speed, speed-1);
00093 this.speed = speed;
00094 index = tmpIndex*speed+tmpDelay;
00095 updateFace(mapUpdaterState);
00096 }
00097
00102 public void setTickNo(final int tickNo) {
00103 this.tickNo = tickNo;
00104 }
00105
00111 public void updateTickNo(@NotNull final MapUpdaterState mapUpdaterState, final int tickNo) {
00112 final int diff = tickNo-this.tickNo;
00113 if (tickNo < this.tickNo) {
00114 System.err.println("Ignoring inconsistent tick value: current tick number is "+tickNo+", previous tick number was "+this.tickNo+".");
00115 } else {
00116 index = (index+diff)%(speed*animation.getFaces());
00117 }
00118 this.tickNo = tickNo;
00119 updateFace(mapUpdaterState);
00120 }
00121
00126 private void updateFace(@NotNull final MapUpdaterState mapUpdaterState) {
00127 final int face = animation.getFace(index/speed);
00128 if (face == lastFace) {
00129 return;
00130 }
00131 lastFace = face;
00132 for (final Location location : locations) {
00133 mapUpdaterState.mapFace(location, face, false);
00134 }
00135 }
00136
00142 public void allocate(@NotNull final MapUpdaterState mapUpdaterState, @NotNull final Location location) {
00143 if (!locations.add(location)) {
00144 throw new IllegalArgumentException();
00145 }
00146 if (lastFace != -1) {
00147 mapUpdaterState.mapFace(location, lastFace, false);
00148 }
00149 }
00150
00155 public void free(@NotNull final Location location) {
00156 if (!locations.remove(location)) {
00157 throw new IllegalArgumentException();
00158 }
00159 }
00160
00164 @NotNull
00165 @Override
00166 public Iterator<Location> iterator() {
00167 return Collections.unmodifiableSet(locations).iterator();
00168 }
00169
00177 public void scroll(final int dx, final int dy, final int width, final int height) {
00178 final Collection<Location> tmp = new HashSet<Location>();
00179 for (final Location location : locations) {
00180 if (0 <= location.getX() && location.getX() < width && 0 <= location.getY() && location.getY() < height) {
00181 final int newX = location.getX()-dx;
00182 final int newY = location.getY()-dy;
00183 if (0 <= newX && newX < width && 0 <= newY && newY < height) {
00184 final Location newLocation = new Location(newX, newY, location.getLayer());
00185 tmp.add(newLocation);
00186 }
00187 }
00188 }
00189 locations.clear();
00190 locations.addAll(tmp);
00191 }
00192
00193 }