Hey all, it’s me again asking for more object oriented help. :
I have an abstract sprite class (used to be called “Entity” but I changed it to sprite for some reason) and I wasn’t sure how each type of sprite would draw itself, so I made a DrawStrategy interface and each Sprite holds one of these. So for instance, some sprites have 8 different images depending on what direction they are heading, some always use the same. Some have an animation cycle, some do not. I created different DrawStrategy classes for each type of drawing needed, and just add this to the Sprite when I create it.
The thing is, some strategies need more info than others. So I add methods like setDirection(Direction d) to a DirectionAnimationStrategy class (Direction is an Enum, BTW). But if a certain sprite child class (like Enemy) needs to call this, then I am forced to cast the DrawStrategy to DirectionAnimationStrategy. Here is what I am talking about:
package towerdefence.sprite;
import java.awt.geom.Point2D;
import towerdefence.GameWorld;
import towerdefence.graphics.DirectionAnimationStrategy;
import towerdefence.graphics.DrawStrategy;
import towerdefence.path.Path;
public class Enemy extends Sprite {
private Path path;
private double dist = 0;
private double speed = 3;
public Enemy(Point2D.Double l, double w, double h, GameWorld wo, DrawStrategy d) {
super(l, w, h, wo, d);
path = wo.getLevel().getPath();
}
public void updateMe() {
Point2D.Double lastLoc = location;
setBounds();
dist += speed;
if(dist > path.length())
dist = 0;
location = path.getPointFromDistance(dist);
double angle = Math.atan2(location.y - lastLoc.y, location.x - lastLoc.x);
((DirectionAnimationStrategy)drawStrat).setDirection(Direction.directionFromAngle(angle));
((DirectionAnimationStrategy)drawStrat).update();
}
}
This seems a little messy to me. Is there a better way to do this?
By the way, Path is a class which tells the Enemy how it is to walk around the game world. I am making a tower defense game, just in case you missed my earlier thread, so enemies just walk along a predetermined path. I figured the best way to do this is to store the path as a spline.
EDIT:
For reference, here is my Sprite class:
package towerdefence.sprite;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import towerdefence.GameWorld;
import towerdefence.graphics.DrawStrategy;
public abstract class Sprite {
protected Point2D.Double location;
protected GameWorld world;
protected DrawStrategy drawStrat;
private Rectangle2D.Double bounds;
private double width, height;
private boolean drawingBounds;
public Sprite(Point2D.Double l, double w, double h, GameWorld wo, DrawStrategy d) {
location = l;
world = wo;
drawStrat = d;
width = w;
height = h;
bounds = new Rectangle2D.Double();
setBounds();
}
public void setDrawStrategy(DrawStrategy d) {
drawStrat = d;
}
public void drawMe(Graphics2D g) {
g.translate(location.x - width/2, location.y - height/2);
drawStrat.draw(g);
g.translate(-location.x + width/2, -location.y + height/2);
if(drawingBounds)
g.draw(bounds);
}
public abstract void updateMe();
protected void setBounds() {
bounds.setRect(location.x - width/2.0, location.y - height/2.0, width, height);
}
// Methods for collision detection:
public Rectangle2D getBounds() {
return bounds;
}
public boolean collidesWith(Rectangle2D r) {
return bounds.intersects(r);
}
public boolean collidesWith(Sprite s) {
return collidesWith(s.getBounds());
}
public boolean isDrawingBounds() {
return drawingBounds;
}
public void setDrawingBounds(boolean drawingBounds) {
this.drawingBounds = drawingBounds;
}
}