Hi really need help - Pointer checks

Started by
18 comments, last by rozz666 16 years, 9 months ago
Hi in my Engine i have a render manager class, which takes a pointer of type sprite and stores it in a vector now the problem is if i want to delete this sprite anytime in main the game crashes? I have done the checks in RenderManager to see if the pointer is not NULL etc but it still crashes. When looking at the debug data it is pointer to the sprites vector in SpriteClass class the Sprite class stores a vector of sprites from the SpriteClass i.e this is in the Sprite class vector<SpriteClass *> m_Sprite; i'll post some code, but if anyone could take 5 mins to help me out over msn or something that would be appreciated as the class i have are abit big?


//------------SPRITE CLASS HEADER--------------//

#ifndef SPRITECLASS_H
#define SPRITECLASS_H

/*-------------------------------------------------------------------

						 SPRITE CLASS V1.0

	We could create a tool to do this automatically - each frame must 
	contain an attack box and bounding box, if in an attacking state.

 --------------------------------------------------------------------*/

#include "Globals.h"
#include "DirectoryHandler.h"
#include "MaskingBox.h" 

enum sizeType{
	//is this m_Sprite an array of images or a cutsprite.
	DEFAULT=1, CUTSPRITE=2,
};

enum shadowType{
	SHADOW_BASIC, SHADOW_COMPLEX
};

enum shadowDecide{
	SHADOW_OFF, SHADOW_ON 
};

typedef struct
{
	int SPRITE_ID;		  
	int VALID_ID;	
	//misc flag to lock current frame.
	bool lockFrame;	
	//is this frame complete.
	bool isMoveComplete;
	//flag for frame completed once.
	int frameCycle;
	//used with m_UpdateType 3.	
	int switchFlag;		    
	int spriteType;		  
	int spriteState;
	int attackType;
	int attackMode;
	int attackStrength;
	int spritePriority;
	//ratio should be equivlalent to the amount of frames available for this m_Sprite.
	vector<double *> ratio; 
	//holds frame ratio.
	double temp;
	//offset scaleX.
	float sX;	
	//offset scaleY.
	float sY; 
	//offset posX.
	float oX; 
	//offset posY.
	float oY;
	//used with m_UpdateType 3.
	int x1;	
	//used with m_UpdateType 3.
	int x2;	
	//used to determine max frame to stop at
	//max1 used in m_UpdateType 2.
	int max1;
	//max2 used in m_UpdateType 5 - reverse max frame.
	int max2;
	//individual anchor point for each m_Sprite
	int anchorPoint;
	//shadow position offsets
	float shadOffX;
	float shadOffY;
	//the angle offset, of this sprite shadow
	int shadAngleX;
	int shadAngleY;

}FRAME, *LPFRAME;

typedef struct 
{
	vector<int *> currentHitBox;
	vector<int *> currentBodyBox;
	int aliveFrame;
	int deadFrame;
	bool deadZone;
	bool checkLocalCollision;

}BOUNDING_BOX, *LPBOUNDING_BOX;

typedef struct
{
	int ATTACK_ID;
	int distX;
	int distZ;
	int strength;
	int damage;
	int painTime;
	int shockTime;
	bool canAttack;
	int rangeStart;
	int rangeEnd;
	float force;
	bool unblockable;
	int hitX;
	int hitY;
	int hitZ;
	int attackPriority;
	BOUNDING_BOX *bBox;

}ATTACK, *LPATTACK;

class SpriteClass
{
public:
	SpriteClass(){}
	SpriteClass(const int SPRITE_ID, const int uT);
	virtual ~SpriteClass();

	void AddCutSprite(string asset, int frames, COLOUR_TABLE *const colour);
	void CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue);
	void CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, double d);
	void CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, int perColumn, int perRow);
	void CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, int sX, int sY, double d=0.33);
	void CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, int sX, int sY, int perRow);

	void AddSprite(string asset, COLOUR_TABLE *const colour);
	void AddImage(char *path);
	void AddImage(char *path, UCHAR red, UCHAR green, UCHAR blue);
	void AddImage(char *path, UCHAR red, UCHAR green, UCHAR blue, double d);

	void AddDelay(double d);
	void AddDelay(int index, double d);

	void AddBbox(const int bType, TCHAR *path, POSITION_LAYER *const bPos);
	void AddBbox(int frame, const int bType, TCHAR *path, POSITION_LAYER *const bPos);
	void AddMaxBbox(int maxFrames, const int bType, TCHAR *path, int x1, int y1, double scale);

	void ReleaseSprite();

	bool InAttackFrame();
	int FindAttackFrame();
	bool InBodyFrame();
	int FindBodyFrame();

	const int GetFrames();
	int GetCurrentFrame();
	const int GetUpdateType();
	const size_t BBoxSize(int bType);
	const size_t SpriteSize();

	MaskingBox *GetBbox(int bType, int frame) const;
	DXUSPRITE *GetCurrentSprite(int frame) const;
	DXUSPRITE const GetCurrentAttack();  
	DXUSPRITE const GetCurrentBody();  

	DirectoryHandler GetDir() const{return m_DirHandler;}
	ATTACK *CurrentAttack() const;
	FRAME *ThisFrame() const;

	void Update();
	void Update(int max);
	void Update(int x1, int x2);
	//special case, reverse aniamtion.
	void Reverse();
	void Reverse(int max);
	void UpdateFrames(int type);

	void SetColour(int alpha);
	void SetColour(int alpha, int r, int g, int b);
	void SetColour(int r, int g, int b);
	void SetCurrentFrame(int pos);
	void SetSpriteID(const int SPRITE_ID);
	void SetUpdateType(int type);

	void Draw(POSITION_LAYER *const bPos=NULL, RGB_TABLE *const colour=NULL);
	void DrawComplexShadow(POSITION_LAYER *const bPos=NULL, RGB_TABLE *const colour=NULL);
	void DrawBbox(float x, float y, float z, bool left);

protected:
	vector<DXUIMAGE *> m_Image;
	vector<DXUSPRITE *> m_Sprite;
	vector<MaskingBox *> m_HitMask;
	vector<MaskingBox *> m_BodyMask;
	
private:
	//cut sprite image
	DXUIMAGE m_CImage;

	int m_CurrentFrame;
	int m_UpdateType;
	//we need to know what type this m_Sprite is, so we can use the appropriate delete method.
	//is this a cutsprite animation.
	bool m_IsCutSprite;
	//is this a normal animation.
	bool m_IsNormalSprite;

	//import structures.
	FRAME *m_ThisFrame;
	ATTACK *m_CurrentAttack;

	DirectoryHandler m_DirHandler;

	void ResizeFrame(int type=DEFAULT);
	void SetSprite(int index);
};

#endif


//------------SPRITE CLASS CPP--------------//
#include "SpriteClass.h"

SpriteClass::SpriteClass(const int SPRITE_ID, const int uT):m_CurrentFrame(0), m_UpdateType(uT)
{
	m_ThisFrame = new FRAME();
	m_CurrentAttack = new ATTACK();
	m_CurrentAttack->bBox = new BOUNDING_BOX();

	m_ThisFrame->SPRITE_ID=SPRITE_ID;
	m_ThisFrame->VALID_ID=SPRITE_ID;
	m_ThisFrame->frameCycle=0;
	m_ThisFrame->isMoveComplete=false;
	m_ThisFrame->lockFrame=false;
	m_ThisFrame->switchFlag=1;
	m_ThisFrame->spriteType=NOT_VALID;
	m_ThisFrame->spriteState=NOT_VALID;
	m_ThisFrame->attackType=NOT_VALID;
	m_ThisFrame->attackMode=NOT_VALID;
	m_ThisFrame->attackStrength=NOT_VALID;
	m_ThisFrame->spritePriority=0;
	m_ThisFrame->sX=0.0f;
	m_ThisFrame->sY=0.0f;
	m_ThisFrame->oX=0.0f;
	m_ThisFrame->oY=0.0f;
	m_ThisFrame->x1=m_CurrentFrame+1;
	m_ThisFrame->x2=m_CurrentFrame+1;
	m_ThisFrame->temp=0.0;
	m_ThisFrame->max1=m_CurrentFrame+1;
	m_ThisFrame->max2=m_CurrentFrame+1;
	m_ThisFrame->anchorPoint=0;
	m_ThisFrame->shadOffX=0;
	m_ThisFrame->shadOffY=0;
	m_ThisFrame->shadAngleX=0;
	m_ThisFrame->shadAngleY=80;

	m_CurrentAttack->ATTACK_ID=INVALID_ID;
	m_CurrentAttack->damage=10;
	m_CurrentAttack->distX=160;
	m_CurrentAttack->distZ=22;
	m_CurrentAttack->strength=0;
	m_CurrentAttack->damage=0;
	m_CurrentAttack->painTime=0;
	m_CurrentAttack->shockTime=0;
	m_CurrentAttack->canAttack=false;
	m_CurrentAttack->rangeStart=0;
	m_CurrentAttack->rangeEnd=0;
	m_CurrentAttack->force=0.0f;
	m_CurrentAttack->unblockable=false;
	m_CurrentAttack->hitX=0;
	m_CurrentAttack->hitY=0;
	m_CurrentAttack->hitZ=0;
	m_CurrentAttack->attackPriority=NOT_VALID;

	m_CurrentAttack->bBox->aliveFrame=0;
	m_CurrentAttack->bBox->deadFrame=0;
	m_CurrentAttack->bBox->deadZone=false;
	m_CurrentAttack->bBox->checkLocalCollision=true;
	
	m_IsCutSprite=false;
	m_IsNormalSprite=false;

	//make sure we set current frame to 0
	SetCurrentFrame(1);

	//explicit call to the debugger
	startConsoleWin(80, 100, "log.txt");
}

SpriteClass::~SpriteClass()
{
	ReleaseSprite();
	wprintf("\nSpriteClass de-constructor called");
}

void SpriteClass::ResizeFrame(int type)
{
	if(type==DEFAULT){
		m_Image.push_back(new DXUIMAGE());
		m_Sprite.push_back(new DXUSPRITE());
		m_ThisFrame->ratio.push_back(new double(0.0));
	}
	else if(type==CUTSPRITE){	
		for(int i=0; i<(int)m_Sprite.size(); i++){
			m_Sprite=new DXUSPRITE();
			m_ThisFrame->ratio=new double(0.0);
			m_CurrentAttack->bBox->currentHitBox=new int(-1);
			m_CurrentAttack->bBox->currentBodyBox=new int(-1);
		}
	}
}

void SpriteClass::AddCutSprite(string asset, int frames, COLOUR_TABLE *const colour)
{
	string dirPath = "Resources//" + asset + "//";
	string filePath = dirPath + asset + ".png";
	char *file = new char[filePath.length()+1];
	strcpy(file, filePath.c_str());
	//wprintf("\nFileName: %s", file);
	CutImage(frames, file, colour->red, colour->green, colour->blue);
	delete [] file;
}

//rows are left to right(horizontal), columns are top to bottom(vertical).
//manual cut m_Image method, but only needs to know how many frames, fastest of all methods, this method should follow
//that each cut m_Sprite be in the range of 8 max rows. 8x8 system.
void SpriteClass::CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue)
{
	m_Sprite.resize(frames);
	m_ThisFrame->ratio.resize(frames);
	m_CurrentAttack->bBox->currentHitBox.resize(frames);
	m_CurrentAttack->bBox->currentBodyBox.resize(frames);
	ResizeFrame(CUTSPRITE);

	if(!DXULoadImage(&m_CImage, path, DXURGB(red, green, blue))){
		for(int i=0; i<(int)m_Sprite.size(); i++){
			m_Sprite=NULL;
		}
	}
	else{
		//should this be width/perRow and height/perColumn??
		//maximum perRow should be 8.
		int perRow=8;
		int perColumn=(int)((perRow+frames)/perRow);
		if(frames <= 8){
			perRow=frames;
			perColumn=(int)perRow/frames;
		}

		int sX=(int)m_CImage.info.Width/perRow;
		int sY=(int)m_CImage.info.Height/perColumn;

		for(int i=0; i<(int)m_Sprite.size(); i++){
			DXUCutSprite(&m_CImage, m_Sprite, (i%perRow)*sX, (i/perRow)*sY, 
									((i%perRow+1))*sX, (i/perRow+1)*sY, 0, 0);
			AddDelay(i+1, 0.33);
		}

		m_IsCutSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

//rows are left to right(horizontal), columns are top to bottom(vertical).
//manual cut m_Image method, but only needs to know how many frames, fastest of all methods, this method should follow
//that each cut m_Sprite be in the range of 8 max rows. 8x8 system.
void SpriteClass::CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, double d)
{
	m_Sprite.resize(frames);
	m_ThisFrame->ratio.resize(frames);
	m_CurrentAttack->bBox->currentHitBox.resize(frames);
	m_CurrentAttack->bBox->currentBodyBox.resize(frames);
	ResizeFrame(CUTSPRITE);

	if(!DXULoadImage(&m_CImage, path, DXURGB(red, green, blue))){
		for(int i=0; i<(int)m_Sprite.size(); i++){
			m_Sprite=NULL;
		}
	}
	else{
		//should this be width/perRow and height/perColumn??
		//maximum perRow should be 8.
		int perRow=8;
		int perColumn=(int)((perRow+frames)/perRow);
		if(frames <= 8){
			perRow=frames;
			perColumn=(int)perRow/frames;
		}

		int sX=(int)m_CImage.info.Width/perRow;
		int sY=(int)m_CImage.info.Height/perColumn;

		for(int i=0; i<(int)m_Sprite.size(); i++){
			DXUCutSprite(&m_CImage, m_Sprite, (i%perRow)*sX, (i/perRow)*sY, 
									((i%perRow+1))*sX, (i/perRow+1)*sY, 0, 0);
			AddDelay(i+1, d);
		}

		m_IsCutSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

//rows are left to right(horizontal), columns are top to bottom(vertical).
//manual cut m_Image method, but takes how many rows and columns there are, faster than first method.
void SpriteClass::CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, int perColumn, int perRow)
{
	m_Sprite.resize(frames);
	m_ThisFrame->ratio.resize(frames);
	m_CurrentAttack->bBox->currentHitBox.resize(frames);
	m_CurrentAttack->bBox->currentBodyBox.resize(frames);
	ResizeFrame(CUTSPRITE);

	if(!DXULoadImage(&m_CImage, path, DXURGB(red, green, blue))){
		for(int i=0; i<(int)m_Sprite.size(); i++){
			m_Sprite=NULL;
		}
	}
	else{
		//should this be width/perRow and height/perColumn??
		int sX=(int)m_CImage.info.Width/perColumn;
		int sY=(int)m_CImage.info.Height/perRow;

		for(int i=0; i<(int)m_Sprite.size(); i++){
			DXUCutSprite(&m_CImage, m_Sprite, (i%perRow)*sX, (i/perRow)*sY, 
									((i%perRow+1))*sX, (i/perRow+1)*sY, 0, 0);
			AddDelay(i+1, 0.33);
		}

		m_IsCutSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

//rows are left to right(horizontal), columns are top to bottom(vertical).
//manual cut m_Image method, slowest of them all.
void SpriteClass::CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, int sX, int sY, double d)
{
	m_Sprite.resize(frames);
	m_ThisFrame->ratio.resize(frames);
	m_CurrentAttack->bBox->currentHitBox.resize(frames);
	m_CurrentAttack->bBox->currentBodyBox.resize(frames);
	ResizeFrame(CUTSPRITE);

	if(!DXULoadImage(&m_CImage, path, DXURGB(red, green, blue))){
		for(int i=0; i<(int)m_Sprite.size(); i++){
			m_Sprite=NULL;
		}
	}
	else{
		//should this be width/perRow and height/perColumn??
		//maximum perRow should be 8.
		int perRow=8;

		for(int i=0; i<(int)m_Sprite.size(); i++){
			DXUCutSprite(&m_CImage, m_Sprite, (i%perRow)*sX, (i/perRow)*sY, 
									((i%perRow+1))*sX, (i/perRow+1)*sY, 0, 0);
			AddDelay(i+1, d);
		}

		m_IsCutSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

//rows are left to right(horizontal), columns are top to bottom(vertical).
//manual cut m_Image method, slowest of them all.
void SpriteClass::CutImage(int frames, char *path, UCHAR red, UCHAR green, UCHAR blue, int sX, int sY, int perRow)
{
	m_Sprite.resize(frames);
	m_ThisFrame->ratio.resize(frames);
	m_CurrentAttack->bBox->currentHitBox.resize(frames);
	m_CurrentAttack->bBox->currentBodyBox.resize(frames);
	ResizeFrame(CUTSPRITE);

	if(!DXULoadImage(&m_CImage, path, DXURGB(red, green, blue))){
		for(int i=0; i<(int)m_Sprite.size(); i++){
			m_Sprite=NULL;
		}
	}
	else{
		for(int i=0; i<(int)m_Sprite.size(); i++){
			DXUCutSprite(&m_CImage, m_Sprite, (i%perRow)*sX, (i/perRow)*sY, 
									((i%perRow+1))*sX, (i/perRow+1)*sY, 0, 0);
			AddDelay(i+1, 0.33);
		}

		m_IsCutSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

void SpriteClass::AddSprite(string asset, COLOUR_TABLE *const colour)
{
	int iNumberOfFiles=0;
	string dirPath = "Resources//" + asset + "//";
	iNumberOfFiles = m_DirHandler.CountFiles(dirPath, "*", false);

	if(iNumberOfFiles == -1){
		wprintf("\nError no files found in: %s", dirPath.c_str());
	}
	else
	{
		for(int i=0; i<iNumberOfFiles; i++)
		{
			stringstream count;
			string offset="0";
			if(i > 8)offset="";
			count << i+1;
			string filePath = dirPath + asset + " " + offset + count.str() + ".png";
			char *file = new char[filePath.length()+1];
			strcpy(file, filePath.c_str());
			//wprintf("\nFileName: %s", file);
			AddImage(file, colour->red, colour->green, colour->blue);
			delete [] file;
		}
	}
}

void SpriteClass::AddImage(char *path)
{
	ResizeFrame(DEFAULT);

	if(!DXULoadImage(m_Image[(int)m_Sprite.size()-1], path, DXUCK_NOCOLOURKEY)){
		m_Image[(int)m_Sprite.size()-1]=NULL;
		m_Sprite[(int)m_Sprite.size()-1]=NULL;
	}
	else{ 
		SetSprite((int)m_Sprite.size());
		AddDelay((int)m_Sprite.size(), 0.33);
		m_CurrentAttack->bBox->currentHitBox.push_back(new int(-1));
		m_CurrentAttack->bBox->currentBodyBox.push_back(new int(-1));
		m_IsNormalSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

void SpriteClass::AddImage(char *path, UCHAR red, UCHAR green, UCHAR blue)
{
	ResizeFrame(DEFAULT);

	if(!DXULoadImage(m_Image[(int)m_Sprite.size()-1], path, DXURGB(red, green, blue))){
		m_Image[(int)m_Sprite.size()-1]=NULL;
		m_Sprite[(int)m_Sprite.size()-1]=NULL;
	}
	else{
		SetSprite((int)m_Sprite.size());
		AddDelay((int)m_Sprite.size(), 0.33);
		m_CurrentAttack->bBox->currentHitBox.push_back(new int(-1));
		m_CurrentAttack->bBox->currentBodyBox.push_back(new int(-1));
		m_IsNormalSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

void SpriteClass::AddImage(char *path, UCHAR red, UCHAR green, UCHAR blue, double d)
{
	ResizeFrame(DEFAULT);

	if(!DXULoadImage(m_Image[(int)m_Sprite.size()-1], path, DXURGB(red, green, blue))){
		m_Image[(int)m_Sprite.size()-1]=NULL;
		m_Sprite[(int)m_Sprite.size()-1]=NULL;
	}
	else{
		SetSprite((int)m_Sprite.size());
		AddDelay((int)m_Sprite.size(), d);
		m_CurrentAttack->bBox->currentHitBox.push_back(new int(-1));
		m_CurrentAttack->bBox->currentBodyBox.push_back(new int(-1));
		m_IsNormalSprite=true;
		m_ThisFrame->max1=(int)m_Sprite.size();
		m_ThisFrame->x1=(int)m_Sprite.size();
		if(m_ThisFrame->x2 > 0)m_ThisFrame->x2=m_ThisFrame->x1-3;
		else m_ThisFrame->x2=m_ThisFrame->x1;
	}
}

void SpriteClass::AddDelay(double d)
{
	for(int i=0; i<(int)m_Sprite.size(); i++)
		*m_ThisFrame->ratio=d;
}

void SpriteClass::AddDelay(int index, double d)
{
	*m_ThisFrame->ratio[index-1]=d;
}

void SpriteClass::SetSprite(int index)
{
	DXUSetSprite(m_Image[index-1], m_Sprite[index-1], 0, 0);
}

void SpriteClass::AddBbox(const int bType, TCHAR *path, POSITION_LAYER *const bPos)
{
	if(m_IsNormalSprite){
		if(bType==HIT_BOX){
			m_HitMask.push_back(new MaskingBox(bType, path, bPos));
			*m_CurrentAttack->bBox->currentHitBox[(int)m_Sprite.size()-1]=(int)m_Sprite.size()-1;
		}
		else if(bType==BODY_BOX){
			m_BodyMask.push_back(new MaskingBox(bType, path, bPos));
			*m_CurrentAttack->bBox->currentBodyBox[(int)m_Sprite.size()-1]=(int)m_Sprite.size()-1;
		}
	}
}

void SpriteClass::AddBbox(int frame, const int bType, TCHAR *path, POSITION_LAYER *const bPos)
{
	if(m_IsNormalSprite || m_IsCutSprite){
		if(frame >= (int)m_Sprite.size())frame=(int)m_Sprite.size();
		if(bType==HIT_BOX){
			m_HitMask.push_back(new MaskingBox(bType, path, bPos));
			*m_CurrentAttack->bBox->currentHitBox[frame-1]=frame-1;
		}
		else if(bType==BODY_BOX){
			m_BodyMask.push_back(new MaskingBox(bType, path, bPos));
			*m_CurrentAttack->bBox->currentBodyBox[frame-1]=frame-1;
		}
	}
}

void SpriteClass::AddMaxBbox(int maxFrames, const int bType, TCHAR *path, int x1, int y1, double scale)
{
	for(int i=0; i<(int)maxFrames; i++){
		AddBbox(i+1, bType, path, new POSITION_LAYER(x1, y1, scale));
	}
}

void SpriteClass::ReleaseSprite()
{
	if(m_IsCutSprite){
		DXUReleaseImage(&m_CImage);
		for(int i=0; i<(int)m_Sprite.size(); i++){
			if(m_Sprite){
				DXUReleaseSprite(m_Sprite);
				delete m_Sprite;
				m_Sprite=NULL;
			}
		}
	}
	else if(m_IsNormalSprite){
		for(int i=0; i<(int)m_Image.size(); i++){
			if(m_Image){
				DXUReleaseImage(m_Image);
				delete m_Image;
				m_Image=NULL;
			}
		}
		for(int i=0; i<(int)m_Sprite.size(); i++){
			if(m_Sprite){
				DXUReleaseSprite(m_Sprite);
				delete m_Sprite;
				m_Sprite=NULL;
			}
		}
	}

	for(int i=0; i<(int)m_ThisFrame->ratio.size(); i++){
		if(m_ThisFrame->ratio){
			delete m_ThisFrame->ratio;
			m_ThisFrame->ratio=NULL;
		}
	}

	for(int i=0; i<(int)m_CurrentAttack->bBox->currentHitBox.size(); i++){
		if(m_CurrentAttack->bBox->currentHitBox){
			delete m_CurrentAttack->bBox->currentHitBox;
			m_CurrentAttack->bBox->currentHitBox=NULL;
		}
	}

	for(int i=0; i<(int)m_CurrentAttack->bBox->currentBodyBox.size(); i++){
		if(m_CurrentAttack->bBox->currentBodyBox){
			delete m_CurrentAttack->bBox->currentBodyBox;
			m_CurrentAttack->bBox->currentBodyBox=NULL;
		}
	}

	for(int i=0; i<(int)m_HitMask.size(); i++){
		if(m_HitMask){
			delete m_HitMask;
			m_HitMask=NULL;
		}
	}

	for(int i=0; i<(int)m_BodyMask.size(); i++){
		if(m_BodyMask){
			delete m_BodyMask;
			m_BodyMask=NULL;
		}
	}

	if(m_ThisFrame!=NULL){delete m_ThisFrame;m_ThisFrame=NULL;}
	if(m_ThisFrame!=NULL){delete m_CurrentAttack;m_CurrentAttack=NULL;}
	if(m_ThisFrame!=NULL){delete m_CurrentAttack->bBox;m_CurrentAttack->bBox=NULL;}
}

const int SpriteClass::GetFrames()
{
	return static_cast<int>(this->SpriteSize());
}

int SpriteClass::GetCurrentFrame()
{
	return m_CurrentFrame+1;
}

const int SpriteClass::GetUpdateType()
{
	return m_UpdateType;
}

const size_t SpriteClass::BBoxSize(int bType)
{
	size_t boxSize=0;

	if(bType==HIT_BOX){
		boxSize=m_HitMask.size();
	}
	else if(BODY_BOX){
		boxSize=m_BodyMask.size();
	}
	
	return boxSize;
}

const size_t SpriteClass::SpriteSize()
{
	return m_Sprite.size();
}

MaskingBox *SpriteClass::GetBbox(int bType, int frame) const  
{
	vector<MaskingBox *>::const_iterator bBox;
	MaskingBox *currentBox=NULL;

	if(bType==HIT_BOX)
	{
		if(m_HitMask.size() > 0){
			for(bBox=m_HitMask.begin(); bBox!=m_HitMask.end(); bBox++){
				if(*bBox==m_HitMask[frame-1]){
					currentBox=*bBox;
					break;
				}
			}
		}
	}
	else if(bType==BODY_BOX)
	{
		if(m_BodyMask.size() > 0){
			for(bBox=m_BodyMask.begin(); bBox!=m_BodyMask.end(); bBox++){
				if(*bBox==m_BodyMask[frame-1]){
					currentBox=*bBox;
					break;
				}
			}
		}
	}

	return currentBox;
}

DXUSPRITE *SpriteClass::GetCurrentSprite(int frame) const
{
	vector<DXUSPRITE *>::const_iterator cSprite;
	DXUSPRITE *currentSprite=NULL;

	if(m_Sprite.size() > 0){
		for(cSprite=m_Sprite.begin(); cSprite!=m_Sprite.end(); cSprite++){
			if(*cSprite==m_Sprite[frame-1]){
				currentSprite=*cSprite;
				break;
			}
		}
	}

	return currentSprite;
}

DXUSPRITE const SpriteClass::GetCurrentAttack() 
{
	return GetBbox(HIT_BOX, FindAttackFrame())->GetSprite();
}

DXUSPRITE const SpriteClass::GetCurrentBody() 
{
	return GetBbox(BODY_BOX, FindBodyFrame())->GetSprite(); 
}

bool SpriteClass::InAttackFrame()
{
	bool attackFrame=false;

	if(m_CurrentFrame==*m_CurrentAttack->bBox->currentHitBox[m_CurrentFrame]){
		attackFrame=true;
	}

	return attackFrame;
}

int SpriteClass::FindAttackFrame()
{
	int currentFrame=0;

	if(m_CurrentFrame==*m_CurrentAttack->bBox->currentHitBox[m_CurrentFrame]){
		currentFrame=*m_CurrentAttack->bBox->currentHitBox[m_CurrentFrame];
	}

	return currentFrame+1;
}

bool SpriteClass::InBodyFrame()
{
	bool bodyFrame=false;

	if(m_CurrentFrame==*m_CurrentAttack->bBox->currentBodyBox[m_CurrentFrame]){
		bodyFrame=true;
	}

	return bodyFrame;
}
	
int SpriteClass::FindBodyFrame()
{
	int currentFrame=0;

	if(m_CurrentFrame==*m_CurrentAttack->bBox->currentBodyBox[m_CurrentFrame]){
		currentFrame=*m_CurrentAttack->bBox->currentBodyBox[m_CurrentFrame];
	}

	return currentFrame+1;
}

ATTACK *SpriteClass::CurrentAttack() const
{
	return m_CurrentAttack;
}

FRAME *SpriteClass::ThisFrame() const
{
	return m_ThisFrame;
}

void SpriteClass::Update()
{
	(double)m_ThisFrame->temp+=(double)*m_ThisFrame->ratio[m_CurrentFrame]*GAME_SPEED;

	if((double)m_ThisFrame->temp > (double)1.0){
		m_CurrentFrame++;
		if(m_CurrentFrame > (int)m_Sprite.size()-1){
			m_CurrentFrame=0;
			m_ThisFrame->frameCycle=1;
		}

		(double)m_ThisFrame->temp=(double)0.0;
	}
}

void SpriteClass::Update(int max)
{
	(double)m_ThisFrame->temp+=(double)*m_ThisFrame->ratio[m_CurrentFrame]*GAME_SPEED;

	if((double)m_ThisFrame->temp > (double)1.0){
		m_CurrentFrame++;
		if(m_CurrentFrame > (int)max-1){
			m_CurrentFrame=(int)max-1;
			m_ThisFrame->frameCycle=1;
		}

		(double)m_ThisFrame->temp=(double)0.0;
	}
}

void SpriteClass::Update(int x1, int x2)
{
	(double)m_ThisFrame->temp+=(double)*m_ThisFrame->ratio[m_CurrentFrame]*GAME_SPEED;

	if((double)m_ThisFrame->temp > (double)1.0){
		m_CurrentFrame++;
		if(m_ThisFrame->switchFlag==1){
			if(m_CurrentFrame > (int)m_Sprite.size()-1){
				m_ThisFrame->frameCycle=1;
				m_CurrentFrame=x1-1; 
				m_ThisFrame->switchFlag=2;		
			}
		}
		else if(m_ThisFrame->switchFlag==2){
			if(m_CurrentFrame > x1-1){
				m_ThisFrame->frameCycle=1;
				m_CurrentFrame=x2-1;
				m_ThisFrame->switchFlag=1;
			}
		}
		else{
			m_CurrentFrame=0;
			m_ThisFrame->frameCycle=0;
			m_ThisFrame->switchFlag=1;
		}

		(double)m_ThisFrame->temp=(double)0.0;
	}
}

void SpriteClass::Reverse()
{
	(double)m_ThisFrame->temp+=(double)*m_ThisFrame->ratio[m_CurrentFrame]*GAME_SPEED;

	if((double)m_ThisFrame->temp > (double)1.0){
		m_CurrentFrame--;
		if(m_CurrentFrame <= 0){
			m_CurrentFrame=(int)m_Sprite.size()-1;
			m_ThisFrame->frameCycle=1;
		}

		(double)m_ThisFrame->temp=(double)0.0;
	}
}

void SpriteClass::Reverse(int max)
{
	(double)m_ThisFrame->temp+=(double)*m_ThisFrame->ratio[m_CurrentFrame]*GAME_SPEED;

	if((double)m_ThisFrame->temp > (double)1.0){
		m_CurrentFrame--;
		if(m_CurrentFrame <= max-1){
			m_CurrentFrame=max-1;
			m_ThisFrame->frameCycle=1;
		}

		(double)m_ThisFrame->temp=(double)0.0;
	}
}

void SpriteClass::UpdateFrames(int type)
{
	switch(type){
		case 1: if(!m_ThisFrame->lockFrame && !pause)Update();
		break;
		case 2: if(!m_ThisFrame->lockFrame && !pause)Update(m_ThisFrame->max1);
		break;
		case 3: if(!m_ThisFrame->lockFrame && !pause)Update(m_ThisFrame->x1, m_ThisFrame->x2);
		break;
		case 4: if(!m_ThisFrame->lockFrame && !pause)Reverse();
		break;
		case 5: if(!m_ThisFrame->lockFrame && !pause)Reverse(m_ThisFrame->max2);
		break;
	}

	if(m_ThisFrame->SPRITE_ID==m_ThisFrame->VALID_ID){
		//if current frame position is at the start frame, then we know this m_Sprite is not complete yet.
		if(m_CurrentFrame==0)m_ThisFrame->isMoveComplete=false;
		//if current frame position is at the last frame, then we know this m_Sprite is complete
		//and the first cycle is achieved.
		if(m_CurrentFrame==((int)m_Sprite.size()-1)){
			m_ThisFrame->isMoveComplete=true;
			m_ThisFrame->frameCycle=1;
		}
	}
}

void SpriteClass::SetColour(int alpha)
{
	//transparency effects.
	for(int i=0; i<(int)m_Sprite.size(); i++)
		m_Sprite->colour=DXUARGB(alpha, 255, 255, 255);
}

void SpriteClass::SetColour(int alpha, int r, int g, int b)
{
	//transparency effects.
	for(int i=0; i<(int)m_Sprite.size(); i++)
		m_Sprite->colour=DXUARGB(alpha, r, g, b);
}

void SpriteClass::SetColour(int r, int g, int b)
{
	//transparency effects.
	for(int i=0; i<(int)m_Sprite.size(); i++)
		m_Sprite->colour=DXUARGB(255, r, g, b);
}

void SpriteClass::SetCurrentFrame(int frame)
{
	m_CurrentFrame=frame-1;
}

void SpriteClass::SetSpriteID(const int SPRITE_ID)
{
	m_ThisFrame->SPRITE_ID=SPRITE_ID;
}

void SpriteClass::SetUpdateType(int type)
{
	m_UpdateType=type;
}

void SpriteClass::Draw(POSITION_LAYER *const bPos, RGB_TABLE *const colour)
{
	//cannot use camera on this sprite
	if(!bPos || !colour)return;
	if(m_Sprite.size() > 0){
		if(GetCurrentSprite(GetCurrentFrame()) != NULL){
			UpdateFrames(GetUpdateType());
			DXUScaleSprite(GetCurrentSprite(GetCurrentFrame()), 
				bPos->scaleX + m_ThisFrame->sX, bPos->scaleY + m_ThisFrame->sY);
			SetColour(colour->alphaCh1, colour->red, colour->green, colour->blue);

			if(bPos->left){
				DXUMoveSprite(GetCurrentSprite(GetCurrentFrame()), bPos->x - (bPos->offX - m_ThisFrame->oX), 
					bPos->y + (bPos->offY + m_ThisFrame->oY) + bPos->z + bPos->offZ);
			}
			else{
				DXUMoveSprite(GetCurrentSprite(GetCurrentFrame()), bPos->x + (bPos->offX + m_ThisFrame->oX), 
					bPos->y + (bPos->offY + m_ThisFrame->oY) + bPos->z + bPos->offZ);
			}

			DXUDrawSprite(GetCurrentSprite(GetCurrentFrame()));
		}
	}
}

void SpriteClass::DrawComplexShadow(POSITION_LAYER *const bPos, RGB_TABLE *const colour)
{
	//cannot use camera on this sprite
	if(!bPos || !colour)return;
	if(m_Sprite.size() > 0){
		if(GetCurrentSprite(GetCurrentFrame()) != NULL){
			UpdateFrames(GetUpdateType());
			DXUScaleSprite(GetCurrentSprite(GetCurrentFrame()), bPos->scaleX, 
									sin(bPos->scaleY + m_ThisFrame->shadAngleY));
			SetColour(120, 0, 0, 0);

			if(bPos->left){
				DXUMoveSprite(GetCurrentSprite(GetCurrentFrame()), bPos->x - (bPos->offX 
					- m_ThisFrame->oX - m_ThisFrame->shadOffX), bPos->y + (bPos->offY 
					+ m_ThisFrame->oY + m_ThisFrame->shadOffY) + bPos->z + bPos->offZ);
			}
			else{
				DXUMoveSprite(GetCurrentSprite(GetCurrentFrame()), bPos->x + (bPos->offX 
					+ m_ThisFrame->oX + m_ThisFrame->shadOffX), bPos->y + (bPos->offY 
					+ m_ThisFrame->oY + m_ThisFrame->shadOffY) + bPos->z + bPos->offZ);
			}

			DXUDrawSprite(GetCurrentSprite(GetCurrentFrame()));
		}
	}
}

//draw box only in right frame.
void SpriteClass::DrawBbox(float x, float y, float z, bool left)
{
	if(m_HitMask.size() > 0){
		for(int i=0; i<(int)m_HitMask.size(); i++){
			if(m_HitMask){
				m_HitMask->GetPosition()->x=x;
				m_HitMask->GetPosition()->y=y;
				m_HitMask->GetPosition()->z=z;
				m_HitMask->SetLeft(left, 1);
			}
		}

		if(this->GetBbox(HIT_BOX, this->FindAttackFrame()))
			this->GetBbox(HIT_BOX, this->FindAttackFrame())->Draw();
	}

	if(m_BodyMask.size() > 0){
		for(int i=0; i<(int)m_BodyMask.size(); i++){
			if(m_BodyMask){
				m_BodyMask->GetPosition()->x=x;
				m_BodyMask->GetPosition()->y=y;
				m_BodyMask->GetPosition()->z=z;
				m_BodyMask->SetLeft(left, 1);
			}
		}

		if(this->GetBbox(BODY_BOX, this->FindBodyFrame()))
			this->GetBbox(BODY_BOX, this->FindBodyFrame())->Draw();
	}
}


//------------SPRITE HEADER--------------//
#ifndef SPRITE_H
#define SPRITE_H

#include "SpriteClass.h"
#include "EntityStates.h"
#include "RenderManager.h"

enum managerMode{
	_ADD=1, _DELETE=0, _SKIP=DELETE
};

enum boxGlobalStates{
	NORMAL_STATE, JUMP_STATE, FALLING_STATE, KNOCKED_STATE
};

class Sprite : public Layer
{
public:
	Sprite(string name, const int type, POSITION_LAYER *const position, int addToManager=_SKIP);
	virtual ~Sprite();

	virtual void LoadSprite(int type=1){};

	void CreateSprite(const int SPRITE_ID, const int updateType, int spriteType=-1, int spriteState=-1, 
					int attackType=-1, int attackMode=-1, int attackStrength=-1, int attackPriority=-1);

	void AddMarker(const int boxType, TCHAR *path, COLOUR_TABLE *const colour, POSITION_LAYER *const position);
	void AddGlobalBox(const int boxType, int globalType, TCHAR *path, COLOUR_TABLE *const colour,
																  POSITION_LAYER *const position);

	const size_t SpriteSize(){return m_Sprite.size();}
	const size_t ShadowSize(){return m_Shadow.size();}

	SpriteClass *GetSpriteToRender() const{return m_CurrentSprite;}
	SpriteClass *GetSprite(const int SPRITE_ID) const;
	SpriteClass *GetShadowToRender() const{return m_CurrentShadow;}
	SpriteClass *GetShadow(const int SPRITE_ID) const;

	EntityStates *GetEntityState() const {return m_EntityState;}
	MaskingBox *GetGlobalBox() const;
	MaskingBox *CurrentGlobalBox(int globalType) const;
	MaskingBox *GetGlobalBox(int pos) const;
	MaskingBox *GetMarker(int pos) const;

	string GetName(){return m_Name;}
	int GetType(){return m_Type;}
	int GetShadowType(){return m_ShadowType;}

	void SetShadowType(int type){m_ShadowType=type;}
	//void SetSprite();
	void SetState(int state, int _override=0);
	void SetSpriteToRender(SpriteClass *sprite);
	void SetShadowToRender(SpriteClass *shadow);
	void OverrideSprite(SpriteClass *sprite);
	void OverrideShadow(SpriteClass *shadow);

	void Draw();
	void DrawbBox();
	void DrawGlobalBox();
	void DrawComplexShadows();

private:
	string m_Name;
	int m_Type;
	int m_ShadowType;
	
	EntityStates *m_EntityState;
	
	vector<SpriteClass *> m_Sprite;
	SpriteClass *m_CurrentSprite;

	vector<SpriteClass *> m_Shadow;
	SpriteClass *m_CurrentShadow;

	vector<MaskingBox *> m_GlobalBox;
	vector<MaskingBox *> m_Marker;
};

#endif

//------------SPRITE CPP--------------//
#include "Sprite.h"

Sprite::Sprite(string name, const int type, POSITION_LAYER *const position, int addToManager):Layer(position),
m_Name(name), m_Type(type), m_ShadowType(SHADOW_COMPLEX), m_CurrentSprite(NULL), m_CurrentShadow(NULL)
{
	m_EntityState = new EntityStates(this);
	Sprite::LoadSprite();

	if(addToManager==_ADD){
		pRM->AddSprite(this);
	}
}

Sprite::~Sprite()
{
	if(m_EntityState != NULL){delete m_EntityState; m_EntityState=NULL;}
	if(m_CurrentSprite != NULL){delete m_CurrentSprite; m_CurrentSprite=NULL;}
	if(m_CurrentShadow != NULL){delete m_CurrentShadow; m_CurrentShadow=NULL;}
}

void Sprite::CreateSprite(const int SPRITE_ID, const int updateType, int spriteType, int spriteState, 
							  int attackType, int attackMode, int attackStrength, int attackPriority)
{
	this->m_Sprite.push_back(new SpriteClass(SPRITE_ID, updateType));
	this->m_Sprite.back()->ThisFrame()->spriteType=spriteType;
	this->m_Sprite.back()->ThisFrame()->spriteState=spriteState;
	this->m_Sprite.back()->ThisFrame()->attackType=attackType;
	this->m_Sprite.back()->ThisFrame()->attackMode=attackMode;
	this->m_Sprite.back()->ThisFrame()->spritePriority=attackPriority;
	this->m_Sprite.back()->CurrentAttack()->attackPriority=attackPriority;

	if(drawShadows && this->GetShadowType()==SHADOW_COMPLEX){
		//this->m_Shadow.push_back(new SpriteClass(SPRITE_ID, updateType));
	}
}

void Sprite::AddMarker(const int boxType, TCHAR *path, COLOUR_TABLE *const colour, POSITION_LAYER *const position)
{
	this->m_Marker.push_back(new MaskingBox(boxType, path, colour, position));
}

void Sprite::AddGlobalBox(const int boxType, int globalType, TCHAR *path, COLOUR_TABLE *const colour, POSITION_LAYER *const position)
{
	this->m_GlobalBox.push_back(new MaskingBox(boxType, path, colour, position));
	this->m_GlobalBox.back()->SetGlobalType(globalType);
}

SpriteClass *Sprite::GetSprite(const int SPRITE_ID) const
{
	vector<SpriteClass *>::const_iterator iSprite;

	struct sameIdFunctor{
		const int id;
		sameIdFunctor(int id):id(id){}
		bool operator()(SpriteClass *sprite) const{
			return sprite->ThisFrame()->SPRITE_ID==id;
		}
	};

	iSprite = find_if(m_Sprite.begin(), m_Sprite.end(), sameIdFunctor(SPRITE_ID));

	if(iSprite != m_Sprite.end())
		return *iSprite;
	else
		return NULL;
}

MaskingBox *Sprite::GetGlobalBox() const
{
	MaskingBox *bodyBox=NULL;

	if(this->GetEntityMove()->isJump){
		if(CurrentGlobalBox(JUMP_STATE))
			bodyBox=CurrentGlobalBox(JUMP_STATE);
	}
	else if(this->GetEntityMove()->isKnocked || this->GetEntityMove()->isFlyKnocked){
		if(CurrentGlobalBox(KNOCKED_STATE))
			return CurrentGlobalBox(KNOCKED_STATE);
	}
	else if(this->GetEntityMove()->isFall){
		if(CurrentGlobalBox(FALLING_STATE))
			bodyBox=CurrentGlobalBox(FALLING_STATE);
	}
	else
	{
		if(CurrentGlobalBox(NORMAL_STATE))
			bodyBox=CurrentGlobalBox(NORMAL_STATE);
	}

	return bodyBox;
}

MaskingBox *Sprite::GetGlobalBox(int pos) const
{
	vector<MaskingBox *>::const_iterator bBox;
	MaskingBox *currentBox=NULL;

	if(m_GlobalBox.size() > 0){
		for(bBox=m_GlobalBox.begin(); bBox!=m_GlobalBox.end(); bBox++){
			if(*bBox==m_GlobalBox[pos-1]){
				currentBox=*bBox;
				break;
			}
		}
	}

	return currentBox;
}

MaskingBox *Sprite::CurrentGlobalBox(int globalType) const
{
	vector<MaskingBox *>::const_iterator bBox;

	struct sameIdFunctor{
		const int global_ID;
		sameIdFunctor(int id):global_ID(id){}
		bool operator()(MaskingBox *box) const{
			return box->GetGlobalType()==global_ID;
		}
	};

	bBox = find_if(m_GlobalBox.begin(), m_GlobalBox.end(), sameIdFunctor(globalType));

	if(bBox != m_GlobalBox.end())
		return *bBox;
	else
		return NULL;
}

SpriteClass *Sprite::GetShadow(const int SPRITE_ID) const
{
	vector<SpriteClass *>::const_iterator iShadow;

	struct sameIdFunctor{
		const int id;
		sameIdFunctor(int id):id(id){}
		bool operator()(SpriteClass *shadow) const{
			return shadow->ThisFrame()->SPRITE_ID==id;
		}
	};

	iShadow = find_if(m_Shadow.begin(), m_Shadow.end(), sameIdFunctor(SPRITE_ID));

	if(iShadow != m_Shadow.end())
		return *iShadow;
	else
		return NULL;
}

MaskingBox *Sprite::GetMarker(int pos) const
{
	vector<MaskingBox *>::const_iterator marker;
	MaskingBox *currentMarker=NULL;

	if(m_Marker.size() > 0){
		for(marker=m_Marker.begin(); marker!=m_Marker.end(); marker++){
			if(*marker==m_Marker[pos-1]){
				currentMarker=*marker;
				break;
			}
		}
	}

	return currentMarker;
}

void Sprite::SetState(int state, int _override)
{
	if(_override==0){
		this->m_State=state;
		if(this->GetShadow(state))SetShadowToRender(GetShadow(state));
		if(this->GetSprite(state))SetSpriteToRender(GetSprite(state));
		else return;
	}
	else{
		this->m_State=state;
		if(this->GetShadow(state))OverrideSprite(GetShadow(state));
		if(this->GetSprite(state))OverrideSprite(GetSprite(state));
		else return;
	}
}

void Sprite::SetSpriteToRender(SpriteClass *sprite)
{
	if(sprite){
		m_CurrentSprite=sprite;
		vector<SpriteClass *>::iterator iSprite;
		for(iSprite=m_Sprite.begin(); iSprite!=m_Sprite.end(); iSprite++){
			if((*iSprite)==sprite){
				continue;
			}
			else{
				if((*iSprite)){
					(*iSprite)->ThisFrame()->switchFlag=1;
					(*iSprite)->ThisFrame()->frameCycle=0;
					(*iSprite)->ThisFrame()->isMoveComplete=false;
					(*iSprite)->ThisFrame()->temp=(double)0.0;
					(*iSprite)->SetCurrentFrame(1);
				}
			}
		}
	}
	else
		return ;
}

void Sprite::SetShadowToRender(SpriteClass *shadow)
{
	if(shadow){
		m_CurrentShadow=shadow;
		vector<SpriteClass *>::iterator iShadow;
		for(iShadow=m_Shadow.begin(); iShadow!=m_Shadow.end(); iShadow++){
			if((*iShadow)==shadow){
				continue;
			}
			else{
				if((*iShadow)){
					(*iShadow)->ThisFrame()->switchFlag=1;
					(*iShadow)->ThisFrame()->frameCycle=0;
					(*iShadow)->ThisFrame()->isMoveComplete=false;
					(*iShadow)->ThisFrame()->temp=(double)0.0;
					(*iShadow)->SetCurrentFrame(1);
				}
			}
		}
	}
	else
		return ;
}

void Sprite::OverrideSprite(SpriteClass *sprite)
{
	if(sprite){
		m_CurrentSprite=sprite;
		vector<SpriteClass *>::iterator iSprite;
		for(iSprite=m_Sprite.begin(); iSprite!=m_Sprite.end(); iSprite++){
			if((*iSprite)){
				(*iSprite)->ThisFrame()->switchFlag=1;
				(*iSprite)->ThisFrame()->frameCycle=0;
				(*iSprite)->ThisFrame()->isMoveComplete=false;
				(*iSprite)->ThisFrame()->temp=(double)0.0;
				(*iSprite)->SetCurrentFrame(1);
			}
		}
	}
	else
		return ;
}

void Sprite::OverrideShadow(SpriteClass *shadow)
{
	if(shadow){
		m_CurrentShadow=shadow;
		vector<SpriteClass *>::iterator iShadow;
		for(iShadow=m_Shadow.begin(); iShadow!=m_Shadow.end(); iShadow++){
			if((*iShadow)){
				(*iShadow)->ThisFrame()->switchFlag=1;
				(*iShadow)->ThisFrame()->frameCycle=0;
				(*iShadow)->ThisFrame()->isMoveComplete=false;
				(*iShadow)->ThisFrame()->temp=(double)0.0;
				(*iShadow)->SetCurrentFrame(1);
			}
		}
	}
	else
		return ;
}

void Sprite::Draw()
{
	if(this)if(this->GetSpriteToRender())
		this->GetSpriteToRender()->Draw(this->GetPosition(), this->GetColour());
	else return;
}

void Sprite::DrawbBox()
{
	float x=this->GetPosX()+this->GetPosition()->offX;
	float y=this->GetPosY()+this->GetPosition()->offY;
	float z=this->GetPosZ()+this->GetPosition()->offZ;

	if(this->GetShadowToRender())
		this->GetShadowToRender()->DrawBbox(x, y, z, this->IsLeft());
}

void Sprite::DrawGlobalBox()
{
	float x=this->GetPosX()+this->GetPosition()->offX;
	float y=this->GetPosY()+this->GetPosition()->offY;
	float z=this->GetPosZ()+this->GetPosition()->offZ;

	for(int i=0; i<(int)m_GlobalBox.size(); i++){
		m_GlobalBox->SetPosX(x);
		m_GlobalBox->SetPosY(y);
		m_GlobalBox->SetPosZ(z);
		m_GlobalBox->SetLeft(this->IsLeft(), 1);
	}

	if(GetGlobalBox())GetGlobalBox()->Draw();
}

void Sprite::DrawComplexShadows()
{
	if(this->GetShadowToRender())
		this->GetShadowToRender()->DrawComplexShadow(this->GetPosition(), this->GetColour());
}

//------------RENDERMANAGER HEADER--------------//
#ifndef RENDERMANAGER_H
#define RENDERMANAGER_H

#include "Globals.h"

class Sprite;

class RenderManager
{
public:
	RenderManager();
	virtual ~RenderManager();

	void AddSprite(Sprite *pSprite);
	//void AddLevel(Level *pLevel);

	const size_t SpriteSize() {return m_Sprite.size();}

	void Render();

private:
	vector<Sprite *> m_Sprite;
	//vector<Level *> level;
	DXUSPRITE *m_Temp;

	bool static CompareSprites(Sprite *s1, Sprite *s2);
	//void LevelBackLayer();
	//void LevelMiddleLayer();
	//void LevelFrontLayer();
	void RenderShadows();
	void RenderSprites();
};

extern RenderManager *pRM;

#endif

//------------RENDERMANAGER CPP--------------//
#include "RenderManager.h"
#include "Sprite.h"

RenderManager *pRM=NULL;

RenderManager::RenderManager():m_Temp(NULL)
{
	pRM=this;
}

RenderManager::~RenderManager()
{
	for(int i=0; i<(int)m_Sprite.size(); i++)
	{
		if(m_Sprite != NULL){delete m_Sprite; m_Sprite=NULL;}
	}
}

void RenderManager::AddSprite(Sprite *pSprite)
{
	if(pSprite != NULL){

		if(m_Sprite.size() > 0)
		{
			vector<Sprite *>::iterator iSprite;

			for(iSprite = m_Sprite.begin(); iSprite != m_Sprite.end(); iSprite++)
			{
				if(pSprite->GetPosZ() > (*iSprite)->GetPosZ())
				{
					m_Sprite.insert(iSprite, pSprite);
					return;
				}
			}
		}

		m_Sprite.push_back(pSprite);
	}
}

bool RenderManager::CompareSprites(Sprite *s1, Sprite *s2)
{
	return s1->GetPosZ() < s2->GetPosZ();		
}

void RenderManager::RenderShadows()
{
	for(int i=0; i<(int)m_Sprite.size(); i++)
	{
		if(drawShadows && m_Sprite->GetShadowType()==SHADOW_COMPLEX)
		{
			m_Sprite->DrawComplexShadows();
		}
		else if(drawShadows && m_Sprite->GetShadowType()==SHADOW_BASIC)
		{
			
		}
		else
			return ;
	}
}

void RenderManager::RenderSprites()
{
	//WTF IS WRONG ARGHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
	vector<Sprite *>::iterator iSprite;

	for(iSprite = m_Sprite.begin(); iSprite != m_Sprite.end(); iSprite++)
	{
		if((*iSprite) != NULL)
		{
			(*iSprite)->Draw();
		}
	}

	/*if(m_Sprite.size() > 0)
	{
		//this->RenderShadows();

		for(int i=0; i<(int)m_Sprite.size(); i++)
		{
			if(m_Sprite != NULL)
			{
				if(m_Sprite->GetSpriteToRender())
				{
					if(m_Sprite->GetSpriteToRender()->SpriteSize() > 0)
					{
						if(m_Sprite->IsAlive())
						{
							int updateType=m_Sprite->GetSpriteToRender()->GetUpdateType();

							if(!m_Sprite->IsPause())
							{
								m_Sprite->GetSpriteToRender()->SetColour(m_Sprite->GetColour()->alphaCh1, m_Sprite->GetColour()->red,
																			  m_Sprite->GetColour()->green, m_Sprite->GetColour()->blue);

								m_Sprite->GetSpriteToRender()->UpdateFrames(updateType);
							}

							int currentFrame=m_Sprite->GetSpriteToRender()->GetCurrentFrame();
							m_Temp=m_Sprite->GetSpriteToRender()->GetCurrentSprite(currentFrame);

							if(m_Temp != NULL)
							{
								DXUScaleSprite(m_Temp, m_Sprite->GetPosition()->scaleX + m_Sprite->GetSpriteToRender()->ThisFrame()->sX, 
													  m_Sprite->GetPosition()->scaleY + m_Sprite->GetSpriteToRender()->ThisFrame()->sY);

								if(m_Sprite->IsLeft()){
									DXUMoveSprite(m_Temp, m_Sprite->GetPosX() - (m_Sprite->GetPosition()->offX - m_Sprite->GetSpriteToRender()->ThisFrame()->oX), 
										m_Sprite->GetPosY() + (m_Sprite->GetPosition()->offY + m_Sprite->GetSpriteToRender()->ThisFrame()->oY) 
										+ m_Sprite->GetPosZ() + m_Sprite->GetPosition()->offZ);
								}
								else{
									DXUMoveSprite(m_Temp, m_Sprite->GetPosX() + (m_Sprite->GetPosition()->offX + m_Sprite->GetSpriteToRender()->ThisFrame()->oX), 
										m_Sprite->GetPosY() + (m_Sprite->GetPosition()->offY + m_Sprite->GetSpriteToRender()->ThisFrame()->oY) 
										+ m_Sprite->GetPosZ() + m_Sprite->GetPosition()->offZ);
								}

								DXUDrawSprite(m_Temp);
							}
						}
					}
				}
			}
		}
	}*/
}

void RenderManager::Render()
{
	//sort all sprites according to their z values before rendering
	sort(m_Sprite.begin(), m_Sprite.end(), CompareSprites);

	//start rendering
	RenderSprites();
}




So i have a sprite of ken and when i delete him in main, i.e i have already added him to the render manager? If i don't add ken to the render Manager and try to delete him in main then it doesn't crash. the debugger is saying > Fusion.exe!std::vector<DXUSPRITE *,std::allocator<DXUSPRITE *> >::size() Line 703 + 0x3 bytes C++ > Fusion.exe!SpriteClass::Draw(POSITION_LAYER * const bPos=0xfeeefeee, RGB_TABLE * const colour=0xfeeefeee) Line 801 + 0xb bytes C++ > Fusion.exe!Sprite::Draw() Line 274 C++ > Fusion.exe!RenderManager::RenderSprites() Line 74 C++ if anyone is interested my msn is tbillyforever@hotmail.com, i really need to sort this out and you guys are my only hope :(. [Edited by - lodoss118 on July 13, 2007 5:40:17 AM]
Advertisement
This is probably because the render manager is calling Draw() on a sprite that's been deleted. Note that calling delete on a pointer does *NOT* set it to NULL (and even if it did, it wouldn't matter, because the vector stores a copy of the pointer).

Using a smart pointer (like boost::shared_ptr) might be a good option here (and will make your life easier in general), but it sounds like your design needs changing - if a sprite is deleted, it has to be removed from the render manager.
if a sprite is deleted, it has to be removed from the render manager?

How does one do this?
There are several approaches.

The sprite can hold a pointer to the render manager, and when it's destroyed, it will "notify" the render manager about it so it can do whatever it wants (like remove it from it's list). This is very simple to code, but it has the disadvantage that now the sprite class has to "know" about the render manager, and it's best to keep your classes as uncoupled as possible.

A more general implementation of the above would be to use the Observer design-pattern, because then the sprite class no longer needs to know about the render manager (or any other class that needs notifications from it).
Forgive me if you've done this, I only very briefly skim read:

You're using a vector of pointers, and deleting the the data
But where are you actually removing vector element that now points to the delete (and hence baddd) data?

so you have:

//before deletionvector element      actual datasprite0            -> datasprite1            -> datasprite2            -> datasprite3            -> datasprite4            -> data//after deletionvector element      actual datasprite0            -> datasprite1            -> datasprite2            -> 0xfeefee (deleted)sprite3            -> datasprite4            -> data//so you've looped through the list of sprites, it STILL thinks element [2] points to valid data..//should be something like this:iterator sprite2;delete (*sprite2); //free the sprite's memory allocated on the heapspritelist.remove(sprite2); //remove the sprite from the renderable sprites listvector element      actual datasprite0            -> datasprite1            -> datasprite3            -> datasprite4            -> data


again, please forgive if this is plainly obvious and you've already done it
- Teach a programmer an answer, he can code for a day. Show a programmer the documentation, he can code for a lifetime.
well in main i have a sprite called ken

which is added to the render manager sprite vector

i then delete ken i.e if(ken){delete ken; ken=NULL;} in main

so in renderManager the vector sprite should be NUll?
A slight variant on Gage's first idea is what I use. However, instead of making the sprite (I call them renderables) notify the manager, I have whatever wants to have the sprite deleted notify the manager. Since that something already had to know about the manager, this doesn't increase coupling between classes at all. Check out this psuedo-code example

rm = new RenderManager();

r = new Renderable()
rm.Add( r );

...

rm.Remove( r ); //This instead of 'delete r'


RenderManager::Remove() will delete the renderable for you. Basically, ownership of the renderable is passed to the manager when you Add() the renderable. From that point on, no one other than the manager can delete the renderable, but others can tell the manager to delete something.

And internally, the manager can simply call the remove() function on stl containers (assuming you're using one of them).

Edit: Though I thought I should just mention smart pointers again. Using a combination of boost::weak_ptr and boost::shared_ptr would be nice. The weak_ptr could go in the manager and the shared ptr in whatever is controlling the lifetime of the object (note: in this case, the manager does *not* own the renderable, whatever creates the renderable does). Then you can just see if the weak ptr has expired() before you use it.
hi i am using a vector not list, if you look at the code i posted earlier you will see the implementation and maybe see what i am doing wrong?.
Quote:Original post by lodoss118
well in main i have a sprite called ken

which is added to the render manager sprite vector

i then delete ken i.e if(ken){delete ken; ken=NULL;} in main

so in renderManager the vector sprite should be NUll?


Expanding on what Ezbez said, here's some source code for you to examine.

//roughly off the top of my headvoid RenderManager::RemoveSprite(CSprite * const i_sprite){  vector<CSprite*>::iterator spriteIter;  if(!m_spriteList.empty())  {    //Search through the list of sprites we have. ( a.k.a. Find Ken)    for( spriteIter s = m_spriteList.begin(); s != m_spriteList.end(); s++)    {      //If we've found the pointer to Ken      if( (*s) == i_sprite ) // This dereferences the iterator, looking at the pointer value when you did m_spriteList.push_back(kenPtr);      {        delete (*s);        //Free Ken's memory        m_spriteList.erase(s); //Remove Ken from the list of sprites we can render        break;      }    }  }}
- Teach a programmer an answer, he can code for a day. Show a programmer the documentation, he can code for a lifetime.
Quote:
Original post by lodoss118
well in main i have a sprite called ken

which is added to the render manager sprite vector

i then delete ken i.e if(ken){delete ken; ken=NULL;} in main

so in renderManager the vector sprite should be NUll?



No. The vector holds a copy of the pointer, so setting 'ken' to NULL in main() will not affect the pointer stored in the vector.

You need to decide who "owns" the sprite, that is, who is responsible for deleting it.

If it's the render manager, than other code should not delete the sprite but instead should ask the render manager to delete it.

If some other class owns the sprite, you need to make sure that when the sprite is deleted, all classes that store pointers to it remove them (or set them to NULL). For this to happen, these other classes need to be notified when the sprite is deleted. This notification can be done by the class that deletes the sprite, or by the sprite class itself (using the above-mentioned observer pattern, this can be done with no additional coupling, that is, sprite doesn't need to know who is notified. Read the link in my previous reply to better understand this).

This topic is closed to new replies.

Advertisement