PDA

View Full Version : List Index Out Of Bounds



Cer3brus
19-04-2009, 01:41 PM
This relates to DelphiX.
I've been trying to make a remake of 1942(the top-down scrolling shooter) and my code for shooting bullets looks as follows:

The Bullet Class:


TBullet = class(TImageSprite)
Public
Procedure DoMove(MoveCount: Integer); override;
Procedure DoCollision(Sprite: TSprite; var Done: Boolean); override;
End;
The Shooting Code In The Timer:


Dec(Shot_Rate);
If (Shot_Rate < 0) And (GetKeyState(32) and 128 = 128){<-- The player has pressed Spacebar(32)}
Then
Begin
Shot_Rate := 10;// So as not to shoot continuously
With TBullet.Create(Engine.Engine) Do
Begin
Image := Sprites.Items.Find('Bullet');
X := Hero.X + (Hero.Width DIV 2 - 15);
Y := Hero.Y;
Z := 14;
Width := Image.Width;
Height := Image.Height;
End;//With
End;//If

The DoMove Looks as follows:

procedure TBullet.DoMove(MoveCount: Integer);
begin
inherited;
Collision;
Y := Y - 5;
If Y < (0 - Height)
Then Free;

The Problem is:
If I shoot 1 bullet and let it leave the screen, everything works fine.
However, If I shoot a bullet and then shoot another one BEFORE the first bullet leaves the screen I get the error: "Project Plane_Project Raised Exception Class EListError with message 'List index out of bounds(10)'. Use Step Or Run To Continue"

Without the Free; the program works fine however, If I shoot continuously for a long time, the framerate decreases xx(

Any Ideas?

AthenaOfDelphi
19-04-2009, 02:09 PM
First up... you need to paste the line (and the code) around the error. There is no list manipulation in the code you've given, so without the area around the error, it's going to be pretty difficult to assist.

Cer3brus
19-04-2009, 02:15 PM
The .exe(and source) of the first version can be found at: https://sourceforge.net/projects/delphixdemo/
I hope it helps :)

pstudio
19-04-2009, 02:16 PM
First, what's up with this?


GetKeyState(32) and 128 = 128

Last time I checked 128 equals 128 ;)

Now I don't use DelphiX but it seems to me, that you add the bullets to an engine. But when you free the bullets you don't remove them from the engine. I don't know if this is done automatically, but if not this may cause some errors.

Hope it helps a bit.

AthenaOfDelphi
19-04-2009, 03:49 PM
The .exe(and source) of the first version can be found at: https://sourceforge.net/projects/delphixdemo/
I hope it helps :)


It does, quite substantially... I've just found that unDelphiX includes a unit with the same name as one in the DevExpress component suite, so I've just mailed the maintainer of unDelphiX.

Anyhow... back on topic ;-)

I've just downloaded your code, and the latest version of unDelphiX and having fixed the problem with the conflict between unDelphiX and DevExpress, I've compiled your code. I'm sorry (well... kind of sorry) to say that I can't reproduce the problem. I'm kind of sorry because it implies it's either an unDelphiX bug which could potentially be fixed by the latest version or its a compiler bug.

So, which version of Delphi and unDelphiX are you using? If it's not the latest version of unDelphiX, download that and try recompiling to see if that fixes the problem.

Hope this helps.

Wizard
19-04-2009, 04:17 PM
I think I might have a solution to your problem. Compiled in Delphi 6 and I changed the following:

In your bullet.move procedure instead of calling free, call dead and then in your onTimer event call engine.dead.

Let me know if this works ;)

But...even though the error is fixed your game seems to run slower after a while so something is not freed properly....

User137
19-04-2009, 05:00 PM
Only thing that comes to mind after reading comments, is maybe small debug you can try.

(just for testing all is ok and freed)
1. Add to interface section a new variable to main unit for example SprCount: integer;
2. before Engine.Move; put command SprCount:=0;
3. after Engine.Move; place some code that prints SprCount. This could be form.caption, label or canvas.
4. place inc(SprCount); code to onMove event of every object that spriteengine uses. Place it as first line before any if/for or other statements.

Result:
If SprCount keeps growing up you will know something is not freed. At that point you can remove step 4 code from objects you don't suspect and test again.
If SprCount is stable and steady, then the problem may lie deep in DelphiX or something else.

arthurprs
19-04-2009, 06:33 PM
probably freeing the sprite removes it from the Owner list, this probably is the cause of the problem,

the solution was already pointed by Wizard

let us know if it worked

Cer3brus
19-04-2009, 06:44 PM
Thanks!!
I'll try out the solutions and see what I find and post it up.
I'm actually using an old version of DelphiX, so I think it's probably a version bug.
I think I might get a tutorial going here.... :)

Cer3brus
19-04-2009, 07:16 PM
The new unDelphiX(http://www.micrel.cz/Dx/) refuses point blank to install nicely :(
Maybe I made a mess of the installation? Are there any tutorials around?

Wizard
19-04-2009, 08:01 PM
I installed the newest unDekphiX without any problems. Remember to uninstall the older version first, I think it says so on the install exe ::) Remove the old version from your library path and then run the install file, I think Delphi should be closed as well :)

AthenaOfDelphi
19-04-2009, 08:06 PM
The new unDelphiX(http://www.micrel.cz/Dx/) refuses point blank to install nicely :(
Maybe I made a mess of the installation? Are there any tutorials around?


Basically, you need to add a couple of paths to your library directory, and then open and install the package corresponding to the Delphi version you are using. In my case it added the Source and Source\dcu100 directories.

The installer worked a treat for me, but it fell over because of the conflict between unDelphiX and my DevExpress components. I fixed it by renaming the dxCommon unit of unDelphiX to unDXCommon.

Whilst my comments may indicate it's just a library problem... I've never used the sprites of unDelphiX... I suspect the guys who have commented after me are offering some more solid advice about the actual use of unDelphiX, which may resolve the problem in your code without upgrading to the latest version.

tpascal
19-04-2009, 10:08 PM
.

tpascal
19-04-2009, 10:18 PM
First, what's up with this?


GetKeyState(32) and 128 = 128

Last time I checked 128 equals 128 ;)



Pstudio, that line code is inspecting the byte value from "GetKeyState(32)" and then logical combined using operator "AND" with value 128 "(GetKeyState(32) and 128)" the resulting value may or may not be 128; this is a very commun way for inspect the bits states inside a byte, in this case he is just asking if the value in GetKeyState(32) has the 8th bit turned on.

pstudio
20-04-2009, 01:09 AM
First, what's up with this?


GetKeyState(32) and 128 = 128

Last time I checked 128 equals 128 ;)



Pstudio, that line code is inspecting the byte value from "GetKeyState(32)" and then logical combined using operator "AND" with value 128 "(GetKeyState(32) and 128)" the resulting value may or may not be 128; this is a very commun way for inspect the bits states inside a byte, in this case he is just asking if the value in GetKeyState(32) has the 8th bit turned on.





Yeah, I actually thought about that afterwards. I guees I need to refresh my operator precedence in pascal. I've been coding way to much c++ lately ;) My bad :-[

Wizard
20-04-2009, 07:21 PM
Ok, so I had a closer look at your code and found the problem. Your bullets were not freed when they left the 'top' of the screen...

In your THBullet.doMove you had the following:

If X < 0 then Free;

This must be changed to:

if y <= 0 then // not x!! ???
dead;

Furthermore you need to add Engine.Dead in your procedure TfrmDXTest.MoveTimer :yes:

This works and your fps don't drop after a long period as before but I'm not entirely convinced that your code is 100% correct. Use the method as described by user 137 to see if you free objects correctly. A more OOP approach would be better; once you have the hang of it it's easy and more manageable. I also suggest you take a look at the shoot example which ships with unDelphiX.

Looks good so far :P

Cer3brus
25-04-2009, 06:06 PM
Thanks!!
After looking at the documentation(read:translate.google.com (http://translate.google.com)
I found out that you can't free the bullets but instead you have to call dead;
and in the timer code call engine.dead; what it actually does is process the objects that need to be removed instead of doing something wierd with the sprite engine. I'll finish the demo soon :)

Wizard
25-04-2009, 06:16 PM
No problem :)