May 01, 2024, 07:32:03 AM

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.

J B Wood (Zumwalt)


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

for (int i=0;i<15;i++)
{
#break;
pFootball = FootballList->Add(NEW(sFootball,1));


This adds the first item to the list, but when it loops to the second item, it gives access violation error, what am I doing wrong?
Thanks

Ionic Wind Support Team

I assume FootbalList id defined as CPointerList *FootballList somewhere?

What are you doing after the last statement?

Here is a somewhat complete linked list example that I was using to illustrate CPointerList to someone else:


class MyAPP
{
declare _MyAPP();
declare MyAPP();
declare AddData(C3DMesh *data);
declare PrintData();
declare DeleteData();
declare GenerateData();
declare CollisionTest(),int;
CPointerList *m_pList;
}


MyAPP::MyAPP()
{
//the constructor allocates the list and creates it.
m_pList = new(CPointerList,1);
m_pList->Create();
}

MyAPP::_MyAPP()
{
//The destructor removes all objects and deletes the list
//that was allocated in the constructor.
DeleteData();
delete m_pList;
}

MyAPP::GenerateData()
{
int count = RAND(20,100);
for(int x=0;x < count;x++)
{
//allocate the 'object'
C3DMesh *data = new(C3DMesh,1);
AddData(data);
}

}

MyAPP::AddData(C3DMesh *data)
{
//add a pointer to the list
m_pList->Add(data);
}

MyAPP::PrintData()
{
//You iterate (loop) through any list
//by getting a pointer to the first list node GetFirst
//and using GetNext to get a pointer to the next node.
//A list is just a chain of data.
for(pointer pos = m_pList->GetFirst(); pos; pos=m_pList->GetNext(pos))
{
C3DMesh *pData = m_pList->GetData(pos);
//instead of printing a number we could 'draw' the mesh or change all of there positions
//pData->SetPosition(x,y,z);
//pData->Draw();
//For the moment we'll just pring the address of the mesh
print(hex$(pData));
}
}

MyAPP::DeleteData()
{
//we change and iterate so we can call delete ourselves.
//this is necessary so the destructor of each mesh object is called.
//Since CPointerList doesn't care what the pointers are it will just call delete on a void pointer
//and the class destructor won't get called.
pointer pos = m_pList->GetFirst();
while(pos)
{
C3DMesh *pData = m_pList->GetData(pos);
pos = m_pList->GetNext(pos);
delete pData;
}
m_pList->RemoveAll(false);
}

MyAPP::CollisionTest(),int
{
for(pointer pos=m_pList->GetFirst(); pos; pos=m_pList->GetNext(pos))
{
C3DMesh *pData = m_pList->GetData(pos);
//start with the current pos since there is no need to
//test the mesh twice. 
for(pointer pos2=pos; pos2; pos2=m_pList->GetNext(pos2))
{
if(pos != pos2) //don't test a mesh against itself
{
C3DMesh *pData2 = m_pList->GetData(pos2);
if(pData->ObjectCollided(pData2,false))
return true;
}
}
}
return false;
}

global sub main()
{
MyApp *theApp = new(MyApp,1);
//generate the data
theApp->GenerateData();
//print out the data
theApp->PrintData();
//delete the app class
delete theApp;
//wait for a key
while GetKey() = "";
}
Ionic Wind Support Team

J B Wood (Zumwalt)

Yes its defined elsewhere, going to look over your example.
Making a somewhat simple sprite example that shows an animated footbal zoom across the screen.
This is the link to the avi of the same football I have animated.
Have to save it locally to play though cause IE does this funky open/show/close routine to it.
http://www.gamedevonline.com/subsite/photo_gallery/movies/FootBall.avi

J B Wood (Zumwalt)


for (int i=0;i<15;i++)
{
#break;

pFootball = FootballList->Add(NEW(sFootball,1));
if (i==0)
{
tmpFootball="FootBall00.png";
*(sFootball)pFootball.x = 0;
*(sFootball)pFootball.y = 0;
*(sFootball)pFootball.resourceName = tmpFootball;
*(sFootball)pFootball.visible = TRUE;
}
if (i<10) && (i>0)
{
tmpFootball="FootBall0" + NumToStr(i) + ".png";
*(sFootball)pFootball.x = 0;
*(sFootball)pFootball.y = 0;
*(sFootball)pFootball.resourceName = tmpFootball;
*(sFootball)pFootball.visible = TRUE;
}
else
{
tmpFootball="FootBall" + NumToStr(i) + ".png";
*(sFootball)pFootball.x = 0;
*(sFootball)pFootball.y = 0;
*(sFootball)pFootball.resourceName = tmpFootball;
*(sFootball)pFootball.visible = TRUE;
}
}


That is what I am attempting to do, trying to track down why it thinks there is an access violation.

Ionic Wind Support Team

A)  Always check return values.  There is no guarantee that NEW will succeed.

B) Why this syntax?
*(sFootball)pFootball.x = 0;

Use this and see what happens.

for (int i=0;i<15;i++)
{
SFootball *pFootball = NEW(sFootball,1);
if(pFootball == NULL)
{
MessageBox(NULL,"Failed to create football","Error");
break; //break out of FOR loop
}
FootballList->Add(pFootball);
if (i==0)
{
tmpFootball="FootBall00.png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
if (i<10) && (i>0)
{
tmpFootball="FootBall0" + NumToStr(i) + ".png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
else
{
tmpFootball="FootBall" + NumToStr(i) + ".png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
}


Ionic Wind Support Team

J B Wood (Zumwalt)

Starting debug session...
[dll's loaded]
First chance exception: Address 0x00413DEA Access Violation.
Final chance exception: Address 0x00413DEA Access Violation.

J B Wood (Zumwalt)

This is my entire code at the moment:


#typedef UINT unsigned int;
DECLARE IMPORT,timeGetTime(),UINT;

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 *MySprite;
CPointerList *FootballList;

string tmpFootball;

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();

for (int i=0;i<15;i++)
{
sFootball *pFootball = NEW(sFootball,1);
if(pFootball == NULL)
{
MessageBox(NULL,"Failed to create football","Error");
break; //break out of FOR loop
}
FootballList->Add(pFootball);
if (i==0)
{
tmpFootball="FootBall00.png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
if (i<10) && (i>0)
{
tmpFootball="FootBall0" + NumToStr(i) + ".png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
else
{
tmpFootball="FootBall" + NumToStr(i) + ".png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
}
Screen.CloseScreen();
FootballList->RemoveAll(true);
if (MySprite) delete MySprite;
delete FootballList;
}


Ionic Wind Support Team

What line number?  See the call stack.  Also the line should be highlighted in the IDE when you run in debug mode.
Ionic Wind Support Team

Ionic Wind Support Team

 C3DSprite *MySprite = NULL;

You are never initializing the pointer, and then you are deleting it at the end.
Ionic Wind Support Team

J B Wood (Zumwalt)

November 18, 2006, 03:37:14 PM #9 Last Edit: November 18, 2006, 03:39:43 PM by Jonathan (zumwalt) Wood
Call stack:
Animation2d! C3DSprite@_C3DSprite + 22
Animation2d! main + 1460 File: C:\Program Files\Aurora\projects\animation2d\Football.src, Line: 68
Animation2d! _main + 48
kernel32! RegisterWaitForInputIdle + 73


Edit:
gofigure, like you said, it was the sprite object..
Back to sanity, getting some rootbeer and continuing down this path..

Ionic Wind Support Team

I gave you the answer above your post.  Next time look at the call stack, Line 68 is where the crash was happening, nothing to do with the FOR loop.
Ionic Wind Support Team

J B Wood (Zumwalt)

November 18, 2006, 06:10:40 PM #11 Last Edit: November 18, 2006, 06:13:52 PM by Jonathan (zumwalt) Wood
OUI...

Its giving me an access violation error on line 95 now, and this time I looked before I am typing for help in the call stack.


FootballSprite->Load(Screen,pFootball->resourceName, 43, 42);


Screen is valid
pFootball->resourceName is valid
The image contains 1 frame, so I omit the other 2 values.
It just can't load the image into the sprite.
*scratches head*
The call stack even complains that ...

Call stack:
Animation2d! C3DSprite@Load + 48
Animation2d! main + 2106 File: C:\Program Files\Aurora\projects\animation2d\Football.src, Line: 95
Animation2d! _main + 48
kernel32! RegisterWaitForInputIdle + 73



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;

DEBUG(pFootball->resourceName);
FootballSprite->Load(Screen,pFootball->resourceName, 43, 42);
FootballSprite->SetPosition(pFootball->x,pFootball->y);

Screen.Begin2D();
FootballSprite->Draw();
Screen.End2D();
Screen.RenderScene();
}
}


Anyway, still chugging on it.

Edit:
Well I know one thing that is obvious, I don't want to load a sprite on every pass...

J B Wood (Zumwalt)

Good news.. and bad news for me...
I got it to work... BUT...
Now I need to determine if the object hits the edge of the screen and move it back, or you will never see the football... ever...
ZOOM...

J B Wood (Zumwalt)

This code works, now to figure out how to smooth the animation.

#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;

string tmpFootball;

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;

for (int i=0;i<15;i++)
{
sFootball *pFootball = NEW(sFootball,1);
if(pFootball == NULL)
{
MessageBox(NULL,"Failed to create football","Error");
break; //break out of FOR loop
}
FootballList->Add(pFootball);

if (i<10)
{
if (i==0)
{
tmpFootball="FootBall00.png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
else
{
tmpFootball="FootBall0" + NumToStr(i) + ".png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
pFootball->visible = TRUE;
}
}
else
{
tmpFootball="FootBall" + NumToStr(i) + ".png";
pFootball->x = 0;
pFootball->y = 0;
pFootball->resourceName = tmpFootball;
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, 43, 42);
FootballSprite.SetPosition(pFootball->x,pFootball->y);
Screen.Begin2D();
FootballSprite.Draw();
Screen.End2D();
Screen.RenderScene();
}
fAdjust = (timeGetTime() - startTime) / fTarget;
}

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


J B Wood (Zumwalt)

Paul, how do we make the files physically compile into the binary?
They exist in my list of resources, but the exe doesn't include them inside it...
This program only runs in the compiler, but I can't take the EXE and double clidk on it without it telling me it can't find the images.

Ionic Wind Support Team

You're creating it as a project correct?  When compiling the project the first thing that happens is the resources get compiled so they are in the executable. 

Don't use a file extension as part of the resource name. 
Ionic Wind Support Team

Ionic Wind Support Team

And you're still loading the sprite on every pass, eating up video memory each loop which will eventually cause the sprite loading to fail.

The correct way to animate an image is to use a single image with multiple frames, instead of trying to load a bunch of small ones.  But anyway your structure should have an individual C3DSprite pointer, allocate each one and load.
Ionic Wind Support Team

J B Wood (Zumwalt)

It is a project, and no, it doesn't compile the resources into the project.
I know I need to optimize it, that goes without saying.
Mine won't load the resources unless I include the file extension as part of the resource call in the code.
Unless your talking about the Custom and changing the type?

Ionic Wind Support Team

What I am saying is it is probably failing to load from resources in which case it tries and load it from a file.  Since your using '.png' as part of the resource identifer.  And when you run from the IDE it is finding the source image files on failure.

If it fails in all cases without the .png then you were never loading it from resources.  The identifier is just used to find the resource in the executable.  You can call it "crap" if you want and as long as the name matches it will load.

The resource compiler creates the .res file which gets linked by the linker.  If you're not getting an error in the first stage of compiling when it says "compiling resources..." then the data is there, you're just not accessing it correctly.  You can verify that the resources are included in the executable by using PE Explorer, or a similar program.  If you have VC++ you can open an executable as resources and view the resource tree from there.

Paul.
Ionic Wind Support Team

Ionic Wind Support Team

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.
Ionic Wind Support Team

sapero

here is a second possiblity using nasm macro incbin - include a file as raw data. The file can be any file like text, image, music...
Just define a label amd include the file:
declare file1();

#asm
file1: incbin "c:\boot.ini"
; terminate it with zero
db 0
#endasm

sub main()
{
string *lpsz = &file1;
return MessageBox(0, *lpsz, "");
}

J B Wood (Zumwalt)

Then why does it work in the IDE but doesn' t work stand alone?
I give it a number, I make it Custom, I tell it type PNG
I browse out to the file, select the file, and add it.

I have absolultely zero control over the file name when I browse out and select it from the file system, if you are talking about after I browse out, then edit the file line and remove the file extention from the file line, then ok.. maybe..

BUT, the NAME I give it is a NUMBER, the default is 1 when you click on ADD for a new resource, I change that 1 to another number that is not used.
So I am lost as to what in the earth you are talking about for the name.
Simply put, if I don't use the name in CODE with the extension, it has no clue how to use the resource, I can't use the number I gave it as the name since it doesn't know how to use that number "1" for instance wouldn't work.

I'll take step by step screen shots and post it.

Ionic Wind Support Team

No need.  It won't work with .png files unless saved as I mentioned above. 

You are trying to use the file name as a resource identifier:

tmpFootball="FootBall0" + NumToStr(i) + ".png";

So after it fails to load them from resources it tries to load them from the current directory using that name.  Since you have physical files with those names it is working from the IDE. 

When you add a resource you do not use the file name as an identifier.  You use that number/name that is in the ID box, the one you supposidly changed from "1".  That is the identifier, not the file name.  The file name is only used by the resource compiler to add the data to the executable image.  Understand?

Resources are identified by ID and TYPE.  After they are compiled in the executable the filename no longer exisits.  Don't know how else to explain that  ::)
Ionic Wind Support Team

Ionic Wind Support Team

November 19, 2006, 11:42:36 AM #23 Last Edit: November 19, 2006, 11:44:07 AM by Paul Turley
Perhaps if you just used a bitmap to get used to resources you would understand..

Add a bitmap to the resources and change the ID in the 'Add Resource' dialog to read IMAGE1,  it doesn't have to be a number. 

Load the image using:

sprite.Load(screen, "IMAGE1", width, height);

Where width and height are the dimensions of the bitmap.

Paul.
Ionic Wind Support Team

J B Wood (Zumwalt)

The files don't exist in the current directory, I think I didn't mention that.
The project exists in :
C:\Program Files\Aurora\projects\animation2d

The resources exist in:
C:\Renders\FootBall

So what you are suggesting doesn't make sense to me.
If it couldn't find them and looks in the current working directory, it is a total of 6 levels off, first the IDE would have to know to move from the working directory to the c:\Renders\Football directory...

So I just don't get it.