Archived

This topic is now archived and is closed to further replies.

theObserver

Array of classes

Recommended Posts

I have a map struct for my 2d game defined like: typedef struct __MAPTILE{ char *Owner; int Flags; cSprite *Sprite; } MAPTILE; where cSprite it that class to handles the drawing, storage etc of the bitmap. Later on in my main class I have : public: MAPTILE Map[MAPSIZE]; So when I want to create a sprite I do this: Map[1].Sprite = new cSprite; Map[1].Sprite->Create(); The create method just sets all the variables inside cSprite to 0. eg BOOL cSprite::Create() { Graphic = 0; Timer =0; CurrectTimer =0; } Trouble is it doesnt work. The new statement doesnt seem to assign any actual memory to the pointer because when I put a watch on Graphic or Timer, it shows up as not having any memory or value. So when Create is called and tries to init Graphic to 0, the program just crashes. Any idea why it doesnt work? Thanks.

Share this post


Link to post
Share on other sites
a) You''re using C++. The ''typedef trick'' of declaring structs should ONLY be used when programming in C.

b) You are expressely forbidden to use any name starting with two underscores, as well as names starting with a single underscore and a capital letter. They are reserved for the implementation and as such are off-limits. Forget __MAPTILE.

c) The code you have put in cSprite::Create rightly belongs in the constructor''s initialization list. Try the following for your cSprite constructor :

cSprite::cSprite() : Graphic(0), Timer(0), CurrentTimer(0) {}


d) Why is cSprite::Create declared as returning a BOOL ?? I see no return statement in your code.

e) With standard-compliant compilers, when new fails to allocate memory, it throws an exception. Older compilers have it return zero - did you check the return value ?




[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]

Share this post


Link to post
Share on other sites
I replaced the structure with a class but it still doesnt make any differnce.

The code I showed in cSprite:Create was just something I made up on the fly and is not the actual code because it is not really relevant.

If I do this:

cSprite *Temp = NULL;
Temp = new cSprite;

I can see that what Temp points to a valid cSprite class and I can access all the members with Temp->Whatever and everything works fine.But If I do this:

cSprite *Temp = NULL;
Temp = new cSprite;

Map[1].Sprite = Temp;

It doesnt work. The memory location that Map[1].Sprite points to remains unchanged even after I have assigned Temp to it and the program will crash if I try to access and members within cSprite. So the problem is not with the new statement as I thought but with assigning the pointer to Map[1].Sprite .And it doesnt make much sence to me.

[edited by - theObserver on September 1, 2003 5:12:13 PM]

Share this post


Link to post
Share on other sites
I created some dummy classes and used your code and mine works without issues.... doing this

cSprite *Temp = NULL;
Temp = new cSprite;
Map[1].Sprite = Temp;

Given that cSprite is a class, with some member variables and a create function.

What is map though? In your earlier post you said

"Later on in my main class I have :
public:
MAPTILE Map[MAPSIZE];"

So i assummed that was part of a class, so i stuck it inside a class.

upon doing that i have something like



class map
{
public:
MAPTILE Map[1024];
};

void main()
{
map a;

cSprite *Temp = 0;
Temp = new cSprite;

a.Map[1].Sprite = Temp;

// access data here as temp, or a.Map[1].Sprite

}


If i misunderstood where your map structure is, and its a global variable let me know

~ Chris

Share this post


Link to post
Share on other sites
Thanks for taking the time to try and help. I appreciate it. This is the new class I made to replace the Map structure.(I stripped everything but the pointer that handles the actual drawing out)


class cCreature{
private:
protected:
public:
cSprite *Sprite;

Creature(){};
~Creature(){};
};



I am only trying to make a simple one screen no scrolling game so I want every possible tile location stored in an array. If the tile is empty then it points to NULL otherwise it points to a cCreature class containing the tile information. That way I can just index into the array to find what the user clicked on the screen with the mouse.

This is my main class that is executed on startup and contains the map array. Its derived form cWinShell which just does the basic window house cleaning tasks like creating a registering a window class,entering a mesage loop etc. GameInit() is called just before the main message/game loop is entered and is where I am trying to initilise the map array.


class cChaos : public cWinShell
{
private:
LPDIRECTDRAWSURFACE7 lpddsMonsters;
LPDIRECTDRAWSURFACE7 lpddsPointer;
LPDIRECTDRAWSURFACE7 lpddsBackground;
cDirectInput Input;
cSprite SpellList[16];
cSprite MousePtr;
BOOL CreateSpells();
protected:
public:
cChaos() {lpdds = NULL; lpddsBackground = NULL;}
~cChaos() {}
cCreature Map[MAPSIZE];
cGraphics2d Graphics;
BOOL GameInit();
int GameLoop();
BOOL GameExit();
};

////////////////////////////////



And this is the section of GameInit() where I try to assign a pointer to a cSprite to map[0].cSprite


BOOL cChaos::GameInit()
{
//Other init stuff before this

cSprite *Temp = NULL;
Temp = new cSprite;

Map[1].Sprite = Temp;
Map[1].Sprite->Create(&Graphics,lpdds);
}


The same problem occurs. Temp points to memory assigned by the New statment.I assign it but the containts of Map[1].Sprite is not changed and the program crashes on the next line.

Share this post


Link to post
Share on other sites
I used your code again, without problems. Given mine doesnt do the graphic manipulation yours does, but are you sure this is why it crashes?

And is it crashing on the assignment? or when you access the data? Because if the Map variable isnt being assigned you shouldnt be able to call Create on it...unless that is where its crashing.


class cSprite
{
};

class cCreature
{
private:
protected:
public:
cSprite *Sprite;
cCreature(){};
~cCreature(){}
};

// The graphics stuff is irrelevant for me

class cChaos
{
private:
cCreature Map[100];

public:
void GameInit()
{
//Other init stuff before this

cSprite *Temp = 0;
Temp = new cSprite;
Map[1].Sprite = Temp;

if(Map[1].Sprite == Temp)
cout << "Pointers are equal" << endl;
// Map[1].Sprite->Create();

}
};
int main(int argc, char* argv[])
{
cChaos a;
a.GameInit();
}


~ Chris

Share this post


Link to post
Share on other sites
It crashes in cSprite::Create on the very first line which is:

BOOL cSprite::Create(cGraphics2d * GraphicSource,LPDIRECTDRAWSURFACE7 SSurface,int Index,int Timer,int X,int Y)
{
if (!(Graphics = GraphicSource))
return false;

Graphics is a member of cSprite and from tracing though the code, I can see that GraphicSource has the correct value that is passed to it while Graphics doesnt have any value attacted and the program crashes as soon as the line is read. Grrrrrrrrrrrrr!

Share this post


Link to post
Share on other sites
Well first off i hope thats a typo....

if(! (Graphics == GraphicsSource) )

= is assignment, == is equal to

As for graphics being null, i assume thats the cGraphics2d class inside your window class. Its not a pointer so it has to have SOME value....

~ Chris

Share this post


Link to post
Share on other sites
Here is the cSprite class declaration


class cSprite
{
private:
RECT Sprites[6];
RECT *Next;
LPDIRECTDRAWSURFACE7 SourceSurface;
int AnimationTimer;
int CurrentTimer;
cGraphics2d *Graphics;
protected:
public:
cSprite() {Graphics = NULL;SourceSurface=NULL;AnimationTimer = 0;Next=NULL;DrawX=-1;DrawY=-1;}
~cSprite();
BOOL Create(cGraphics2d * GraphicSource,LPDIRECTDRAWSURFACE7 SSurface,int Index=0,int Timer=0,int X=-1,int Y=-1);
BOOL Animate();
BOOL Draw(int ScaleX=1,int ScaleY=1,int X=-1,int Y=-1);
BOOL GetCords(int Index, RECT *Bounds);
int DrawX;
int DrawY;
};


And cGraphic


class cGraphics2d
{
private:
LPDIRECTDRAW7 lpdd;
LPDIRECTDRAWPALETTE lpddpal;
LPDIRECTDRAWSURFACE7 lpddsprimary;
LPDIRECTDRAWSURFACE7 lpddsback;
LPDIRECTDRAWCLIPPER lpddclipper;
protected:
public:
cGraphics2d();
~cGraphics2d();
BOOL Shutdown();
BOOL Init(int Width,int Height,int BPP,HWND MainWin);
BOOL DDraw_Attach_Clipper(int num_rects,LPRECT clip_list);
LPDIRECTDRAWSURFACE7 NewSurface(LPDIRECTDRAWSURFACE7 Surface,int Width,int Height,int Transparent = -1, int Flags = VIDEOMEMORY);
BOOL SetPalette(LPPALETTEENTRY Palette);
BOOL Clear(int ClearColour);
BOOL Draw(RECT *Dest,RECT *Source, LPDIRECTDRAWSURFACE7 Surface);
BOOL Flip();
};


Now I am going to bang my head off a nice hard wall. The desk isnt hard enough for me anymore.

Share this post


Link to post
Share on other sites
BOOL cSprite::Create(cGraphics2d * GraphicSource,LPDIRECTDRAWSURFACE7 SSurface,int Index,int Timer,int X,int Y)
{
if (!(Graphics == GraphicSource))
return false;

This code before is in the Create function of cSprite. Unless your setting cSprite.Graphics to something prior to this (which is doubtful as this is the create method) then it will have either a garbage value in it if you didnt initialize it properlly or NULL(0) value if you did.

Example:

cSprite()::cSprite()
{
Graphics = NULL;
}

if thats somewhere before create then ou should have a zero value there, and thus dont need/should be doing that test at all.

~ Chris

Share this post


Link to post
Share on other sites
its:
Graphics = GraphicSource

because I need to store the pointer to a graphic class. The if statement is just to make sure that GraphicSource is not null.

The problem is (I think) that cSprite::Create is getting called from a pointer that doesnt actually point to anything but garbage so the graphics pointer doesnt actully exit. When I put a watch on graphics its value is ??????.

I can take that line out and it would just crash on the next line.

Also I if I were to do this

Map[1].Sprite = NULL;
The value stored in Map[1].Sprite also remains unchanged. And for another strange reason Map[0].Sprite->Create doesnt crash but every index higher than zero (map[2],map[10]) does. But even with Map[0] I still cant change the value of Map[0].Sprite->Sprite. It seems that they are already memory allocated to it.

It doesnt make any sence!!!!!!!!

[edited by - theObserver on September 1, 2003 9:45:13 PM]

Share this post


Link to post
Share on other sites
Oh Duh. lol sorry i didnt even see that and i thought programmers get smarter with age? lol

Umm. No that really doesnt make any sence lol. Basically i dont know how to help without picking through code myself. If you want you can post it(if its small) or you can email/icq/aim it to me and ill figure out whats wrong, and explain it for you.

~ Chris

Share this post


Link to post
Share on other sites
Got it!

Inspiration came with my morning cup of coffee and bowl of Fruit and Fiber.

Map is already a predefinded class in MFC. So I changed

cCreature Map[MAPSIZE];
to
cCreature TheMap[MAPSIZE];

and everything is working fine. I would have thought the stupid compiler would have kicked up an error over Map already being defined. Only took me two weeks to figure it out. *hangs head in shame*

But thanks for all you help. I appreciate it

Share this post


Link to post
Share on other sites