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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| 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); } 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; } } |