package gjt.animation;
import java.awt.*;
import java.util.Vector;
import gjt.Assert;
import gjt.Stopwatch;
import gjt.Util;
/**
* A sequence of images which are animated and moved about on
* a Playfield.
*
* Each Sprite is constructed with a reference to it's
* Playfield, a Sequence, and a beginning position for it's
* upper left hand corner.
*
* A Sprite's animation is controlled by invoking the following
* methods:
*
*- setMoveVector(Point)
*
- setMoveInterval(long)
*
- setImageChangeInterval(long)
*
- setMainSequence(Sequence)
*
- setSequence(Sequence)
*
*
* @version 1.0, Apr 1 1996
* @author David Geary
* @see Sequence
* @see Playfield
* @see SpriteCollisionDetector
* @see gjt.test.SimpleAnimationTest
* @see gjt.test.BumpAnimationTest
* @see gjt.test.TwoDrinkersAnimationTest
*/
public class Sprite {
private Playfield field;
private Sequence currentSequence, mainSequence;
private Stopwatch moveTimer = new Stopwatch();
private Point ulhc = new Point(0,0);
private Point start = new Point(0,0);
private Point moveVector = new Point(1,1);
private Rectangle clip = new Rectangle(0,0);
private Rectangle curBounds, lastBounds;
private int width, height;
private long moveInterval = 0;
public Sprite(Playfield field,
Sequence sequence,
Point ulhc) {
Assert.notNull(field);
Assert.notNull(sequence);
Assert.notNull(ulhc);
this.field = field;
this.ulhc = ulhc;
start.x = ulhc.x;
start.y = ulhc.y;
setSequence(sequence);
setMainSequence(sequence);
initializeBounds();
moveTimer.start();
currentSequence.start();
}
public Playfield getPlayfield() { return field; }
public Rectangle clipRect () { return clip; }
public Rectangle curBounds () { return curBounds; }
public int width () { return width; }
public int height () { return height; }
public void reverseX () { moveVector.x = 0-moveVector.x; }
public void reverseY () { moveVector.y = 0-moveVector.y; }
public void reverse () { reverseX(); reverseY(); }
public Point start () { return start; }
public void setMoveVector (Point p) { moveVector = p; }
public Point getMoveVector() { return moveVector; }
public void play(Sequence sequence, long cycles) {
setSequence(sequence);
sequence.setCyclesPerAnimation(cycles);
sequence.setCurrentCycle(0);
}
public void animate() {
if(currentSequence.animationOver())
currentSequence = mainSequence;
if(timeToChangeImage()) currentSequence.advance();
if(timeToMove()) move();
if(needsRepainting()) field.paintSprite(this);
}
public void setMainSequence(Sequence sequence) {
mainSequence = sequence;
}
public Sequence getMainSequence() {
return mainSequence;
}
public void setSequence(Sequence sequence) {
currentSequence = sequence;
if(curBounds != null)
updateBounds();
}
public Sequence getSequence() {
return currentSequence;
}
public boolean intersects(Sprite otherSprite) {
return curBounds().intersects(otherSprite.curBounds());
}
public boolean willIntersect(Sprite otherSprite) {
return
nextBounds().intersects(otherSprite.nextBounds());
}
public boolean timeToMove() {
return moveTimer.elapsedTime() > moveInterval;
}
public boolean timeToChangeImage() {
return currentSequence.timeToAdvanceCell();
}
public void moveTo(Point p) {
ulhc = p;
moveTimer.reset();
}
public boolean needsRepainting() {
return currentSequence.needsRepainting(ulhc);
}
public void setMoveInterval(long interval) {
moveInterval = interval;
}
public void setImageChangeInterval(long interval) {
currentSequence.setAdvanceInterval(interval);
}
public void move() {
ulhc.x += moveVector.x;
ulhc.y += moveVector.y;
updateBounds();
moveTimer.reset();
}
public Point location() {
return ulhc;
}
public Point nextLocation() {
return new Point(ulhc.x + moveVector.x,
ulhc.y + moveVector.y);
}
public Rectangle nextBounds() {
Image nextImage = currentSequence.getNextImage();
Point nextLoc = nextLocation();
return new Rectangle(
nextLoc.x, nextLoc.y, width, height);
}
public void paint(Graphics g) {
currentSequence.paint(g, ulhc.x, ulhc.y, field);
}
private void initializeBounds() {
Image curImage = currentSequence.getCurrentImage();
width = curImage.getWidth (field);
height = curImage.getHeight(field);
curBounds =
new Rectangle(ulhc.x, ulhc.y, width, height);
lastBounds = new Rectangle(curBounds.x,
curBounds.y,
curBounds.width,
curBounds.height);
clip = lastBounds.union(curBounds);
}
private void updateBounds() {
Image curImage = currentSequence.getCurrentImage();
lastBounds.width = curBounds.width;
lastBounds.height = curBounds.height;
curBounds.width = width = curImage.getWidth(field);
curBounds.height = height = curImage.getHeight(field);
lastBounds.move(curBounds.x, curBounds.y);
curBounds.move (ulhc.x, ulhc.y);
clip = lastBounds.union(curBounds);
}
}