May 01, 2024, 05:04:53 PM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


CPointerList issue...

Started by J B Wood (Zumwalt), November 18, 2006, 12:43:02 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Ionic Wind Support Team

The IDE isn't doing anything.  Don't know how else to explain it.  The current directory is wherever the executable is and can be changed by external processes.  Probably the resource compiler is changing the directory to read the files so when you execute from the IDE it is still looking in that directory.

The point is you are not using the resource identifier correctly which is why I suggested something simple.  Start with the suggestion I gave you above your post and go from there.  The resource identifier IS NOT the filename of the resource.  The filename that you browse to is only used by the resource compiler to load in the data.  After it is compiled that name is meaningless, it is only the resource ID and TYPE that has importance.  Get that through your head and ignore the fact that it is running from the IDE.

The Load method of the sprite class is a switch .  What it does is:

#1 Try loading from resources first using the name provided as a resource identifier.

#2 If that fails try loading from a file using the name provided as a file name.

Understanding that realize that the resources are in the execuable under the ID you provide in the 'add resources' dialog.  Not under the filename that they are loaded from. So in all cases the Load method is failing under case #1 as your program is written.

Anyone else care to explain it to him?  Maybe I am just not being clear enough  :-\

Paul.
Ionic Wind Support Team

J B Wood (Zumwalt)

Ok, end result for a single BMP is as follows:
(just create your own BMP and add it as a resource and replace the word "Female" with the name of your resource)
Although the sprite will work with PNG, the resource manager doesn't. It stores them in the exe, but when you try to load them, it has no clue how to handle them.
If you want to use a PNG just load it from disk.
BMP works like a champ. This code has a smooth scrolling image across the screen, no chop.


#typedef UINT unsigned int;
DECLARE IMPORT,timeGetTime(),UINT;
declare import, GetLastError(),DWORD;
declare import, DEBUG alias OutputDebugStringA(string str);

struct sFootBall
{
int x,y; /* upper left corner of the football */
string resourceName; /* Name of the football resource */
int Visible; /* Set visible value */
}

global sub main()
{
C3DScreen Screen;
C3DCamera Camera;
CDirectInput DirectInput;
#break;
float Step = 0.1f;
float SpritePosition = 0.0f;

C3DSprite FootballSprite;
CPointerList *FootballList;

Screen.CreateWindowed(0,0,800,600,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE,0,"Flying Football - By Zumwalt",NULL,true);
Camera.Create(Screen);
DirectInput.Init(Screen);

FootballList = new(CPointerList,1);
FootballList->Create();

float fadjust,fTarget;
fTarget = 1.0f / 60.0f * 1000.0f;
fAdjust = 1.0f;

sFootball *pFootball = NEW(sFootball,1);
if(pFootball == NULL)
{
MessageBox(NULL,"Failed to create football","Error");
}
FootballList->Add(pFootball);
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = "Female";
pFootball->visible = TRUE;

int fps = 0;
int startTime;
pointer pos;

while (!DirectInput.KeyDown(DIK_ESCAPE))
{
Screen.Clear(RGBA(32, 23, 30, 255));
Screen.BeginScene(Camera);
pos = FootballList->GetFirst();
while(pos != NULL)
{
pFootball = FootballList->GetData(pos);
pos = FootballList->GetNext(pos);
//pFootball->x=pFootball->x + SpritePosition + Step* fAdjust;
pFootball->x=pFootball->x + 1;// * fAdjust;
DEBUG(pFootball->resourceName);
FootballSprite.Load(Screen,pFootball->resourceName,100, 98);
FootballSprite.SetPosition(pFootball->x,pFootball->y);
Screen.Begin2D();
FootballSprite.Draw();
Screen.End2D();
Screen.RenderScene();
}
fAdjust = (timeGetTime() - startTime) / fTarget;
}

Screen.CloseScreen();
FootballList->RemoveAll(true);
delete FootballList;
}

J B Wood (Zumwalt)

Another version where the image only loads into memory 1 time, and not in the loop...

#typedef UINT unsigned int;
DECLARE IMPORT,timeGetTime(),UINT;
declare import, GetLastError(),DWORD;
declare import, DEBUG alias OutputDebugStringA(string str);

struct sFootBall
{
int x,y; /* upper left corner of the football */
string resourceName; /* Name of the football resource */
int Visible; /* Set visible value */
}

global sub main()
{
C3DScreen Screen;
C3DCamera Camera;
CDirectInput DirectInput;
#break;
float Step = 0.1f;
float SpritePosition = 0.0f;

C3DSprite FootballSprite;
CPointerList *FootballList;

Screen.CreateWindowed(0,0,800,600,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE,0,"Flying Football - By Zumwalt",NULL,true);
Camera.Create(Screen);
DirectInput.Init(Screen);

FootballList = new(CPointerList,1);
FootballList->Create();

float fadjust,fTarget;
fTarget = 1.0f / 60.0f * 1000.0f;
fAdjust = 1.0f;

sFootball *pFootball = NEW(sFootball,1);
if(pFootball == NULL)
{
MessageBox(NULL,"Failed to create football","Error");
}
FootballList->Add(pFootball);
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = "Female";
pFootball->visible = TRUE;

int fps = 0;
int startTime;
pointer pos;

pos = FootballList->GetFirst();
pFootball = FootballList->GetData(pos);
pos = FootballList->GetNext(pos);
//pFootball->x=pFootball->x + SpritePosition + Step* fAdjust;
DEBUG(pFootball->resourceName);
FootballSprite.Load(Screen,pFootball->resourceName,100, 98);
while (!DirectInput.KeyDown(DIK_ESCAPE))
{
Screen.Clear(RGBA(32, 23, 30, 255));
Screen.BeginScene(Camera);
pFootball->x=pFootball->x + 1;// * fAdjust;
FootballSprite.SetPosition(pFootball->x,pFootball->y);
Screen.Begin2D();
FootballSprite.Draw();
Screen.End2D();
Screen.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;
}
Screen.CloseScreen();
FootballList->RemoveAll(true);
delete FootballList;
}

Kale

Quote from: Jonathan (zumwalt) Wood on November 20, 2006, 06:52:36 AM
Although the sprite will work with PNG, the resource manager doesn't. It stores them in the exe, but when you try to load them, it has no clue how to handle them.

I've also had no luck embedding PNGs into exes for sprite use. ???

J B Wood (Zumwalt)

The file is embeded in the exe, its using it that I have a problem with.
Here is more code, this one causes the image to scroll back and forth depending on if it reaches the edge of the screen.
This is now my base code for my space invaders :)

#typedef UINT unsigned int;
#define screen_width 800
#define screen_height 600

DECLARE IMPORT,timeGetTime(),UINT;
declare import, GetLastError(),DWORD;
declare import, DEBUG alias OutputDebugStringA(string str);

struct sFootBall
{
int x,y; /* upper left corner of the football */
string resourceName; /* Name of the football resource */
int Visible; /* Set visible value */
}

global sub main()
{
C3DScreen Screen;
C3DCamera Camera;
CDirectInput DirectInput;
#break;
float Step = 0.1f;
float SpritePosition = 0.0f;

C3DSprite FootballSprite;
CPointerList *FootballList;

Screen.CreateWindowed(0,0,screen_width,screen_height,AWS_CAPTION|AWS_VISIBLE|AWS_SIZE,0,"Flying Football - By Zumwalt",NULL,true);
Camera.Create(Screen);
DirectInput.Init(Screen);

FootballList = new(CPointerList,1);
FootballList->Create();

float fadjust,fTarget;
fTarget = 1.0f / 60.0f * 1000.0f;
fAdjust = 1.0f;

sFootball *pFootball = NEW(sFootball,1);
if(pFootball == NULL)
{
MessageBox(NULL,"Failed to create football","Error");
}
FootballList->Add(pFootball);
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = "Female";
pFootball->visible = TRUE;

int fps = 0;
int startTime;
pointer pos;
int scrollState=0;

pos = FootballList->GetFirst();
pFootball = FootballList->GetData(pos);
pos = FootballList->GetNext(pos);
//pFootball->x=pFootball->x + SpritePosition + Step* fAdjust;
DEBUG(pFootball->resourceName);
FootballSprite.Load(Screen,pFootball->resourceName,100, 98);
while (!DirectInput.KeyDown(DIK_ESCAPE))
{
Screen.Clear(RGBA(32, 23, 30, 255));
Screen.BeginScene(Camera);

if (pFootball->x+100 > Screen_Width)
{
scrollState=1;

}
else if (pFootball->x < 0)
{
scrollState=0;
}


switch (scrollState)
{
case 0:
pFootball->x=pFootball->x + 1;
case 1:
pFootball->x=pFootball->x - 1;
}

FootballSprite.SetPosition(pFootball->x,pFootball->y);
Screen.Begin2D();
FootballSprite.Draw();
Screen.End2D();
Screen.RenderScene();
fAdjust = (timeGetTime() - startTime) / fTarget;

}
Screen.CloseScreen();
FootballList->RemoveAll(true);
delete FootballList;
}


Ignore the fact I got the word football all over the place, that was an ill begotten effort of mine.

Ionic Wind Support Team

Quote from: Kale on November 20, 2006, 07:38:04 AM
Quote from: Jonathan (zumwalt) Wood on November 20, 2006, 06:52:36 AM
Although the sprite will work with PNG, the resource manager doesn't. It stores them in the exe, but when you try to load them, it has no clue how to handle them.

I've also had no luck embedding PNGs into exes for sprite use. ???

Kale,
If you read my description above you will see that you can't directly use them in a resource like a bitmap.  For whatever reason Microsoft decided to use the resource type RCDATA for other types of image files in the d3dx library.  So to use a .png file from resources it has to be converted to an ASCII file first, just like the old DATA statements in BASIC.  Each word in the .png file is outputted to the text file as a hex value.  Then you can cut an paste that data in between the BEGIN and END block of a "Data" resource.  Only then will the D3DXCreateTextureFromResourceEx function load it.  Which is what the sprite class uses to load the image from resources.

Not my choice of course.  It is just the way DirectX handles it.

Paul.
Ionic Wind Support Team

Kale


Ionic Wind Support Team

If I ever get a free moment I'll whip up a little converter.
Ionic Wind Support Team

J B Wood (Zumwalt)


Kale

Quote from: Paul Turley on November 18, 2006, 09:41:10 PM
And reading the Microsoft docs on the  D3DXCreateTextureFromResourceEx function, which is what the 3D engine uses to load a texture from resources yields this info:

Quote
    The resource being loaded must be of type RT_BITMAP or RT_RCDATA. Resource type RT_RCDATA is used to load formats other than bitmaps (such as .tga, .jpg, and .dds).

It doesn't specifically mention .png however that is not the only problem.  RCDATA resources are entered as text for the resouce compiler so the bytes of the image file would need to be converted to ASCII word values to go in between the BEGIN and END macros.  If you add a data resource you will see what I mean.

BEGIN
   0x0000 0x3f22 0x1122... etc
END

It is not too difficult to convert the file into words.

You could also try and add a custom resource with the type set to something like "PNG", which does add a data resource, however the D3DXCreateTextureFromResourceEx function will probably not be able to find it if its not an BITMAP or DATA resource.  Just something to experiment with.

Paul.

I tried converting a PNG file to hex words and copied into my project as a resource. Still no success. :( The attached file is the output of the convertor i've written.

J B Wood (Zumwalt)

It probably won't work anyway, I tried a resource as a gif and a jpg also, using the scalable image type, and it didn't recognize any gif or any jpg, the only thing it recognizes is a bmp. Thats just my 2 cents.

Ionic Wind Support Team

Give me some time.   How did you read write the words?  You have to remember endian order if your reading the file a byte at a time,
Ionic Wind Support Team

J B Wood (Zumwalt)

Ok, now on to remove, how do I remove an item from the list from any point in the list as long as I know its list position?
objlist->remove(pos)??

Ionic Wind Support Team

By position I assume you meant the pointer returned by the GetNext method.  And if so then that would be correct.

objlist->remove(pos,TRUE);

Would remove the node and delete the associated pointer.  If you are storing classes then you need to delete the associated pointer yourself.

See CList in the users guide which is the base class for CPointerList.
Ionic Wind Support Team

J B Wood (Zumwalt)

Ok, this is what I got that is working, but for some reason, my invaders slow down incrimentally as I remove them from the list.

posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->Invader.SetPosition(pObject->x,pObject->y);
if (pObject->currentHP > 0)
{
pObject->Invader.Draw();
posGroup = objList->GetNext(posGroup);
}
else
{
objList->Remove(posGroup,true);
posGroup = objList->GetFirst();
}


Which is very odd, the bullet should disappear but it is not, the aliens should continue down there original speed but there not, I got something funky going on, can't nail it down yet, has to be a logical error, since there is no physical errors causing a crash.

Ionic Wind Support Team

Because your using GetFirst after a remove which causes the loop to continue


...else
{
     posGroup =  objList->Remove(posGroup,true);
     
}

Remove returns the next element of the list or NULL if the list end has been reached.
Ionic Wind Support Team

J B Wood (Zumwalt)

But this causes it to crash when I kill an invader, the getfirst allows it to work.
But it doesn't work against the saucer, since when I remove it, it is the only one in the list.
OUI...
I got so far with this to be hitting a brick wall now.

So, what I need to do, is remove the invaders from the list, have the list shrink in size somehow with out the remaining invaders, then continue.
If the list is empty, delete the list and not reuse it.
If I just make the invaders invisible, the movement routine still makes them check against the edges, so I would have to look into both the collision routine and the movement routine to work around the fact that they are visible or not.

I know, this part can't be that hard, it has to be something simple I am over looking.

Ionic Wind Support Team

I only gave you a solution to the code you presented.  You have to check the return of Remove for NULL to be sure you don't dereference a null pointer.  If it is the last element of the list then don't access it.

There is no 'shinking and growing' of a list, it is stored as a linked chain of pointers.  Once you remove the node it is removed from the chain.

Paul.
Ionic Wind Support Team

J B Wood (Zumwalt)

Took a dinner break, now getting back on this, I think I'll just check against an internal structure element that I am already using and deal with the list that way.
I don't understand what is wrong in my movement logic at the moment, but once I get the attack logic done I'll rework the movement logic some.
I haven't decided how to handle sound yet, I don't think you have directsound implimented yet.

John Syl.

November 26, 2006, 05:11:20 AM #44 Last Edit: November 26, 2006, 05:15:38 AM by John Syl. (puddytat)
 I think your problem is that as you delete you delay then ending of the loop by restarting the loop, so any further routines are not serviced.ÂÃ,  Taken to the extreme if there is always some thing to deleted it never gets out of the loop untill everything is deleted.ÂÃ,  What I do isÂÃ,  get the data, check if it is to be deleted, if it is to be deleted I then get the next pointer and save in a temp variable, remove the pointer including data, then set the pointer variable to the temp value and continue.
this will then got to the end of the list allowing an exit for the rest of the routines to be serviced at a reasonable time.

If it is not deleted just get the next pointer.

A quick mod to your code gives :-

posGroup=objList->GetFirst();
while(posGroup != NULL)
{
pObject = objList->GetData(posGroup);
pObject->Invader.SetPosition(pObject->x,pObject->y);
if (pObject->currentHP > 0)
{
pObject->Invader.Draw();
posGroup = objList->GetNext(posGroup);
}
else
{
ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  ÂÃ,  tempptr=objList->GetNext(posGroup);
objList->Remove(posGroup,true);
posGroup = tempptr;
}

If that makes sense.

John
Intel 3.6 p4 ht, XP home,2 gb mem, 400 gb hd 20gb raid 0, Nvidia 6600le.
AMD k6-2 500, 40gb.

Started on PDP11 Assembler, BASIC, GWBASIC, 6502, Z80, 80x86, Java, Pascal, C, C++, 
IBasic (std & pro), Aurora, EBasic.  (Master of none, but it's been fun!)