Sprite и AnimatedSprite


У меня есть Спрайт класса и AnimatedSprite подкласс, и я хотел бы разделить эти их и поддерживать взаимозаменяемости, в соответствии с Лисков принципа замещения. Я считаю, что при работе с указателями на спрайты я всегда использую GetFrameWidth и GetFrameHeight вместо GetWidth и GetHeightтолько в том случае, если указатель на самом деле указывает на AnimatedSprite, что требует только рамка ширина или высота, а не весь спрайт лист.

Спрайт.ч

#ifndef CSPRITE_H
#define CSPRITE_H

#include <utility>
#include <allegro\fixed.h>
#include <allegro\fmaths.h>
#include <allegro\draw.h>
#include <allegro\file.h>
#include <allegro\datafile.h>
#include <allegro\color.h>
#include <string>
#include <vector>

#include "CBitmapCache.h"

class Sprite {

public:

static Sprite* CreateSprite(BITMAP* file, int centerX, int centerY);
static Sprite* CreateSprite(std::string file, int width, int height);
static Sprite* CreateSprite(std::string file, int width, int height, int centerX, int centerY);
static Sprite* CreateSprite(const Sprite& sprite);
virtual ~Sprite();
std::string* GetFilename() const;
virtual BITMAP* GetImage() const;
double GetX() const;
double GetY() const;
double GetZ() const;
Point GetPosition() const;
virtual int GetWidth() const;
virtual int GetHeight() const;
int GetFrameWidth() const;
int GetFrameHeight() const;
int GetCenterX() const;
int GetCenterY() const;
double GetRotation() const;
double GetScaleX() const;
double GetScaleY() const;
fixed GetScaleAsFixed() const;
int GetTint() const;
unsigned char GetTintIntensity() const;
unsigned char GetAlpha() const;
int GetRotationRadius() const;
void SetX(double x);
void SetY(double y);
void SetZ(double z);
void SetPosition(double x, double y);
void SetPosition(double x, double y, double z);
void SetPosition(const Point& position);
void SetCenterX(int x);
void SetCenterY(int y);
void SetScaleX(double x);
void SetScaleY(double y);
void SetRotation(double angle);
void SetTint(unsigned int tint);
void SetTintIntensity(unsigned char intensity);
void SetAlpha(unsigned char alpha);
void SetRadius(int radius);
Sprite& Clone(const Sprite& sprite);

/////////////////////////////////////////////////////////////////
// FOLLOWING METHODS ARE USED IN DERIVED ANIMATED SPRITE CLASS //
/////////////////////////////////////////////////////////////////

virtual int GetNumFrames() const;
virtual int GetNextFrameNum() const;
virtual int GetCurFrameNum() const;
virtual int GetPrevFrameNum() const;
virtual void Animate(int start, double deltaTime);
virtual void Animate(int start, int end, double deltaTime);
virtual int GetNumColumns() const;
virtual BITMAP** GetFrames() const;
virtual void SetFrames(std::vector<BITMAP*> _frames, int frameWidth, int frameHeight, int numCols);
virtual void SetFrames(BITMAP** frames, int frameWidth, int frameHeight, int numFrames, int numCols);
virtual bool CanLoop() const;
virtual void SetLoop(bool canLoop);
virtual void SetFrameRate(double deltaTime);
virtual double GetFrameRate();
virtual void DrawFrame(BITMAP* dest, int frame, int x,  int y, bool transparent);
virtual BITMAP* GetFrame(int numFrame);

protected:

std::string* _file;
BITMAP* _image;

Point* _position;
std::pair<int, int> _dimensions;
std::pair<int, int> _frameDimensions;
std::pair<int, int> _center;
std::pair<double, double> _scaleDimensions;
double _angle;
int _radius;
int _tint;
unsigned char _tintIntensity;
unsigned char _alpha;

void CalcCenterFrame();
virtual void SetImage(BITMAP* image);
virtual void SetCurFrame(int frame);
Sprite(BITMAP* file, int centerX, int centerY);
Sprite(std::string file, int width, int height, int centerX, int centerY);
Sprite(const Sprite& sprite);
Sprite& operator=(const Sprite& rhs);

private:

};

#endif

AnimatedSprite.ч

#ifndef CANIMATEDSPRITE_H
#define CANIMATEDSPRITE_H

#include "CSprite.h"
#include <vector>

struct BITMAP;

class AnimatedSprite : public Sprite {

public:
static AnimatedSprite* CreateAnimatedSprite(BITMAP* file, int frameWidth, int frameHeight, int numFrames, int numCols, double frameRate, bool loop);
static AnimatedSprite* CreateAnimatedSprite(std::string file, int width, int height, int frameWidth, int frameHeight, int numFrames, int numCols, double frameRate, bool loop);
static AnimatedSprite* CreateAnimatedSprite(std::string file, int width, int height, int frameWidth, int frameHeight, int centerX, int centerY, int numFrames, int numCols, double frameRate, bool loop);
static AnimatedSprite* CreateAnimatedSprite(const AnimatedSprite& animatedSprite);
virtual ~AnimatedSprite();
virtual bool CanLoop() const;
virtual int GetNumFrames() const;
virtual int GetNextFrameNum() const;
virtual int GetCurFrameNum() const;
virtual int GetPrevFrameNum() const;
virtual int GetNumColumns() const;
virtual BITMAP* GetImage() const;
virtual BITMAP** GetFrames() const;
virtual void SetLoop(bool canLoop);
virtual void Animate(int start, double deltaTime);
virtual void Animate(int start, int end, double deltaTime);
AnimatedSprite& Clone(const AnimatedSprite& animatedSprite);
virtual void SetFrameRate(double deltaTime);
virtual double GetFrameRate();
virtual void SetFrames(std::vector<BITMAP*> _frames, int frameWidth, int frameHeight, int numCols);
virtual void SetFrames(BITMAP** frames, int frameWidth, int frameHeight, int numFrames, int numCols);
protected:

virtual void SetImage(BITMAP* image);
virtual BITMAP* GetFrame(int numFrame);
virtual void DrawFrame(BITMAP* dest, int frame, int x,  int y, bool transparent);
virtual void SetCurFrame(int frame);
void GrabFrame(BITMAP* image, int width, int height, int startx, int starty, int columns, int numFrame);
AnimatedSprite(BITMAP* file, int frameWidth, int frameHeight, int centerX, int centerY, int numFrames, int numCols, double frameRate, bool loop);
AnimatedSprite(std::string file, int width, int height, int frameWidth, int frameHeight, int centerX, int centerY, int numFrames, int numCols, double frameRate, bool loop);
AnimatedSprite(const AnimatedSprite& animSprite);
AnimatedSprite& operator=(const AnimatedSprite& rhs);

private:

int _curFrame;
int _numFrames;
bool _loop;
int _numColumns;
BITMAP** _frames;
BITMAP* _frameImage;
double _frameRate;

};

#endif


454
4
задан 16 августа 2011 в 07:08 Источник Поделиться
Комментарии
3 ответа

Глядя на ваш код и комментарии, я бы предложил другую стратегию?

AnimatedSprite можно рассматривать как совокупность отдельных спрайтов. Вместо того, чтобы получать от Спрайта, использовать состав для resuse объекта Sprite внутри AnimatedSprite.

Если существует реальная необходимость использовать оба попеременно (не зная конкретно, есть ли у вас Sprite или AnimatedSprite) я хотел создать абстрактный класс (интерфейс), который собирает общие подходы и реализация в каждой из Спрайта и AnimatedSprite.

4
ответ дан 16 августа 2011 в 05:08 Источник Поделиться

Решение 1:


  • иметь фактуру класс/ИМГ с GetImgWidth/GetImgHeight. эти возвращения
    размеры физическую текстуру, поэтому в случае спрайт-лист,
    размер всего листа

  • сделать спрайт расширить изображение. getwidth/getheight возвращает размер
    спрайт, т. е. один кадр

  • сделать animatedsprite расширить спрайт. getwidth/getheight возвращает размер одного кадра.

Так что если вы принимаете только экземпляры класса Спрайта, вы можете быть уверены, что вы не всегда получение права собственности, а у вас еще есть шанс получить размер всего изображения на листе спрайт. Это решение также легко распространяется на другие методы, как упакованные текстуры.

Решение 2 (Если вы можете жить с накладными расходами):

Использовать RTTI и задать для динамического типа объекта. Бросок с полной уверенности<>() и если это анимированный спрайт вместо простой спрайт, вызываем соответствующие методы. ИМХО, это не очень хорошее решение.

1
ответ дан 16 августа 2011 в 08:08 Источник Поделиться

Как другие упомянули.... Я бы ввести больше классов, чтобы сделать интерфейс проще ( изображения, точки и т. д. )

Затем экстракт интерфейс, как спрайт и анимированные использовать спрайт.

Но....может быть, совершенно другой взгляд на это...

Я бы сначала спросите себя, действительно ли я нужен спрайт и анимированный спрайт? Или это то, что я думаю как "спрайт" только один кадр анимированных спрайтов?

Поэтому просто переименуйте animatedsprite как спрайт.

0
ответ дан 17 августа 2011 в 03:08 Источник Поделиться