• Advertisement
Sign in to follow this  

Hi really need help - Pointer checks

This topic is 3845 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
if a sprite is deleted, it has to be removed from the render manager?

How does one do this?

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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 deletion

vector element actual data
sprite0 -> data
sprite1 -> data
sprite2 -> data
sprite3 -> data
sprite4 -> data

//after deletion

vector element actual data
sprite0 -> data
sprite1 -> data
sprite2 -> 0xfeefee (deleted)
sprite3 -> data
sprite4 -> 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 heap
spritelist.remove(sprite2); //remove the sprite from the renderable sprites list

vector element actual data
sprite0 -> data
sprite1 -> data
sprite3 -> data
sprite4 -> data




again, please forgive if this is plainly obvious and you've already done it

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?.

Share this post


Link to post
Share on other sites
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 head
void 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;
}
}

}
}




Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
Striken, there's a lot more compact version that does the same. The std::vector::erase() function will erase a given object from a vector, but you still have to find at which position it's stored, since it accepts either an iterator, or a start and end iterator.

The std::remove() function takes a begin and end iterator, and the object you want to remove. What this function does, when it finds the given item, is moving all next elements in the vector to the left, which overwrites the found item, but leaves one extra item at the end of the list. Once it's finished, it returns an iterator to the end of the list, minus the number of items removed.

Combining the two allows you to remove all found items, and then erase the leftover items at the end of the list, by calling std::vector::erase() with the iterator that std::remove() returned, and std::vector::end() as the end iterator. In the end, this saves you from writing search code, as std::remove() will find all occurences of the item you want to remove.

// Clear up the object that itemToBeRemoved pointed to:
delete itemToBeRemoved;

// Now erase that pointer from our vector of sprite pointers:
spriteContainer.erase( std::remove( spriteContainer.begin(), spriteContainer.end(), itemToBeRemoved ), spriteContainer.end() );

Share this post


Link to post
Share on other sites
oh that's sweet :) thanks, i've always thought the way I did it was a bit of a mouthful! I presume that implementation is faster? as i'm using mutexes with this search embedded during locks (for my networking code) that little snippet will be most useful!

Share this post


Link to post
Share on other sites
Hi i have another problem say for example i make an entityManager which handles the sprite and rendering etc i have a removeEntity method which deletes the entity sprite vector and calls the remove sprite method from the renderManager aswell but the engine crashes?

here is some code for the entityManager



////ENTITY MANAGER HEADER
#ifndef ENTITYMANAGER_H
#define ENTITYMANAGER_H

#include "Globals.h"

class Sprite;
class RenderManager;

class EntityManager
{
public:
EntityManager();
~EntityManager();

void AddEntity(Sprite *const entityToAdd);
void RemoveEntity(Sprite *const entityToRemove);

const size_t EntitySize() {return m_EntityList.size();}
Sprite *GetEntity(Sprite *const entityToFind);

void Update();
void Render();

private:
RenderManager *RM;

protected:
vector<Sprite *> m_EntityList;
};

extern EntityManager *pEM;

#endif

///ENTITY MANAGER CPP
#include "EntityManager.h"
#include "Sprite.h"
#include "RenderManager.h"

EntityManager *pEM = NULL;

EntityManager::EntityManager()
{
pEM=this;
RM = new RenderManager();
}

EntityManager::~EntityManager()
{
if(!m_EntityList.empty()){
vector<Sprite *>::iterator iEntity;
for(iEntity = m_EntityList.begin(); iEntity != m_EntityList.end(); iEntity++){
if((*iEntity)){
delete (*iEntity);
(*iEntity)=NULL;
}
}
}

if(RM){delete RM; RM=NULL;}
}

void EntityManager::AddEntity(Sprite *const entityToAdd)
{
if(entityToAdd != NULL){
m_EntityList.push_back(entityToAdd);
if(RM)RM->AddSprite(entityToAdd);
}
}

void EntityManager::RemoveEntity(Sprite *const entityToRemove)
{
if(entityToRemove)
{
if(!m_EntityList.empty()){
vector<Sprite *>::iterator iEntity;
for(iEntity = m_EntityList.begin(); iEntity != m_EntityList.end(); iEntity++){
if((*iEntity) == entityToRemove){
delete (*iEntity);
(*iEntity)=NULL;
break;
}
}
}

if(RM)RM->Remove(entityToRemove);
}
}

Sprite *EntityManager::GetEntity(Sprite *const entityToFind)
{
vector<Sprite *>::iterator iEntity;

if(entityToFind)
{
if(!m_EntityList.empty()){
for(iEntity = m_EntityList.begin(); iEntity != m_EntityList.end(); iEntity++){
if((*iEntity) == entityToFind){
return (*iEntity);
break;
}
}
}
}

return (*iEntity);
}

void EntityManager::Update()
{

}

void EntityManager::Render()
{
if(RM)RM->Render();
}





Ok somewhere in main i got this

EM = new EntityManager();
EM->AddEntity(ken = new Ken());

EM->Render();

if(dxuKeyState[DIK_B]){
EM->RemoveEntity(ken); //crashes here
}

the EntityManager initiates an instance of RenderManager and calls the RenderMethod

what i was trying to do is basically have the sprite deleted from all the managers if removed from the entity manager but it seems i have the same problem from before it now complains about RenderManager remove method???

> Fusion.exe!RenderManager::Remove(Sprite * const pSprite=0x003994c0) Line 48 + 0x23 bytes C++

Share this post


Link to post
Share on other sites
Does RenderManager::Remove() also deletes the sprite? If it does, there's your problem - the entity manager already deleted it and you can't call delete an object more than once.

Share this post


Link to post
Share on other sites
Your problem is here:

if(!m_EntityList.empty()){
vector<Sprite *>::iterator iEntity;
for(iEntity = m_EntityList.begin(); iEntity != m_EntityList.end(); iEntity++){
if((*iEntity) == entityToRemove){
delete (*iEntity); <----- hehe
(*iEntity)=NULL;
break;
}
}
}

You are deleting the same pointer more than once.
You should do something like this:

m_EntityList.remove(entityToRemove);
RM->remove(entityToRemove);
delete entityToRemove;

BTW why do you use things like Sprite *const entityToRemove?
Do you need constant pointers?

Share this post


Link to post
Share on other sites
Hi thanx agains guys i think i have sorted it out, one more thing though :)

How would i create a copy of a sprite without pointing to it, what i want is basically to copy all of (sprite A) to (sprite B) but with its own memory, so B doesn't affect A or vice versa, what do i need to do in the SpriteClass in order to achieve this?

Share this post


Link to post
Share on other sites
There are lots of optiopns. You can implement a copy constructor SpriteClass(const SpriteClass& ), write a copy() or clone() function, or implement operator=(SpriteClass& ). I would suggest the first and second options since I presume you don't want to copy one sprite data to an existing sprite.
So basically you write a constructor that copies data from a given sprite (remember to write m_ThisFrame = new FRAME(); etc. instead of copying the pointers). Then write the copy function:

SpriteClass *SpriteClass:copy()
{
return new SpriteClass(*this);
}

the constructor should be smoething like this:

SpriteClass::SpriteClass(const SpriteClass& sc)
{
m_ThisFrame = new FRAME();
m_CurrentAttack = new ATTACK();
m_CurrentAttack->bBox = new BOUNDING_BOX();

m_ThisFrame->SPRITE_ID = sc.m_ThisFrame->SPRITE_ID;
m_ThisFrame->VALID_ID = sc.m_ThisFrame->VALID_ID;

// etc. or you can implement FRAME::operator= and write
// *m_ThisFrame = *sc.m_ThisFrame
}

Share this post


Link to post
Share on other sites
Hmm also how would i instance the vectors that hold the sprite data when cloning?

i.e i have some vectors in the SpriteClass pointing to something, how do copy these?

vector<SPRITE *> m_Sprite how would i copy something like this in the constructor?

[Edited by - lodoss118 on July 14, 2007 5:21:21 PM]

Share this post


Link to post
Share on other sites
std::vector<> has it's operator= implemented. So there's no problem copying the vector. What you should consider is if you want to just copy the pointers in the vector or copy them too (which means using new with copy constructors).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement