PDA

View Full Version : Help!? Classes, Sprites and files



hammer
19-02-2004, 04:28 PM
Hello,
i am not sure that my problem is for here but as they say you'll never know inless you ask so here i go:

i am creating a game turn based strategy to be exact and i am almost done the one last thing that i need to do is create some different map than a random generated squares so i started creating a map editor.
In the map editor i have a


TTile = class(TImageSprite)
private
public
TileSize: integer;
TilePicture: TBitmap;
TileType:integer;
TilePos : record
X : integer;
Y : integer;
end;
TileExist:Boolean;
type and a


Tile: array [1..5000] of TTile;

var so i create the map and then save it using the procedure

procedure SaveTheTiles;
var f:file of TTile;i:integer;
begin
assignfile(f,'tmp.map');
rewrite(f);

for i:=1 to 5000 do
if (Tile[i] <> Nil) then
write(f,Tile[i]);

CloseFile(f);

end;

i know its not the best way to do it but lets leave that behind for now.
So anyway i save the map and then try to load it in the game

procedure TMap.Load;
var f:file of TTile;
begin
assignfile(f,'tmp.map');
reset(f);

while not eof(f) do begin
numberunits.tiles :=numberunits.tiles+1; // this is defined as global var and also the starting value is 0
Tile[numberunits.tiles]:=TTile.Create(form1.dxspriteengine1.Engine);
read(f,Tile[numberunits.tiles]);
end;
closefile(f);
end;

so far so good but when i try to access some value in the array of Tiles
example:
showmessage(inttostr(tile[1].tilesize));
i get an error :

project1.exe raised an exception class bla bla access violation at address 004667A0 bla bla and so on....

i dont get it why do i get an error ??!?!?!?!?!?!!??
if someone can help PLEASEEEEEEEE help me
thanks[/pascal]

Useless Hacker
19-02-2004, 05:14 PM
That won't work because when you do
write(f,Tile[i]);
it is just writing a pointer to the class into the file.
So, when you load it you are loading pointers which (probably) don't point to anything anymore, hence the access violation.

You will need to create a method to save the values in the tile class to a file. Unfortunately, this will not be easy since TImageSprite doesn't have any method for saving either, so you would have to save that data also. When you want to load the map you will then have to create new tiles and read in the saved values to them.

Bobby
19-02-2004, 05:40 PM
Hey, I have a map editor that I made in delphiX a while ago if you would like to take a look at the source. If you do, let me know and I will email it to you.

Thanks

Bobby

WiZz
19-02-2004, 08:05 PM
could you e-mail me this editor, becouse i'm creating game too and have some problems with it.

Ultra
19-02-2004, 10:08 PM
Useless Hacker is correct, you'll need to save and load the properties of the sprite and not the sprite itself. Write(f, Tile[i].Whatever); Write(f, Tile[i].Whatever2); etc.

You'll also want to Free the tiles in your loading code before you use TTile.Create() on them. Otherwise the tiles that you had before will still exist in memory but with nothing to point at them.

hammer
19-02-2004, 10:21 PM
this is damn weird
cous when i've generated the map inside the main program it have no problem but if i use a program then save it, and then load the map in the main program it crashes, but if i recall it was no problem using the write(f,record_type) atleast in pascal worked ?!??!?!?!

hammer
19-02-2004, 10:29 PM
at Ultra:
i cant use Write(f, Tile[i].Whatever2);
cous the file is of type TTile i.e. Tile[x] so i cant save them this way so i guess i will have to save them in a text file or if its supported via a stream but then Useless Hacker told that this method is not implented, and the text file method is quite slow and hard to create so if anyone have any idea how can i make it easy or atleast faster i will be very happy to be told :)

Crisp_N_Dry
19-02-2004, 11:06 PM
Also you're gonna have problems with the tile picture part of your class. By giving each individual tile it's own TBitmap you are gonna use a heck of a lot of memory for bitmaps for each indivudual tile. 5000 bitmaps takes up a of a lot of memory. Let's say each of these tiles is 32*32 with a depth of 16. 32*32*16*5000 is a whole lot of memory. It would be much better to have make the TilePicture reference another array of images that is used to store ther images for tiles. Then you would only have one bitmap for each different image as opposed to one bitmap for each individual tile.

TilePicture : ^TBitmap;

Tiles[X].TilePicture:=@TileImages[Y];

Useless Hacker
20-02-2004, 11:19 AM
... if i recall it was no problem using the write(f,record_type) atleast in pascal worked ?!??!?!?!Yes, you can write record types like that (unless the record contains pointers,) but in Delphi a class is in fact a pointer to the actual class. When you write Thing := TThing.Create; Delphi allocates memory for the new TThing object and stores a pointer to it in Thing.

The TBitmap member isn't necessary, because TImageSprite already stores a TPictureCollectionItem reference.

Ultra
20-02-2004, 04:45 PM
As so many have said before classes are pointers so if your file is of type TTile it's the same as saying f: File of Pointer; and it just won't work. Instead you can just use f: File;

A small (untested!) way of saving a tile map would be:



type
TTile = class
public
CanWalkOn: Boolean;
Image: Integer;
procedure SaveToFile(var f: File);
procedure LoadFromFile(var f: File);
end;

TTileMap = class
public
Tiles: array[0..9, 0..9] of TTile;
procedure SaveToFile(const FileName: String);
procedure LoadFromFile(const FileName: String);
procedure Clear;
end;

{...}

procedure TTile.SaveToFile(var f: File);
begin
try
BlockWrite(f, CanWalkOn, SizeOf(CanWalkOn));
BlockWrite(f, Image, SizeOf(Image));
except
// something went wrong
end;
end;

procedure TTile.LoadFromFile(var f: File);
begin
try
BlockRead(f, CanWalkOn, SizeOf(CanWalkOn));
BlockRead(f, Image, SizeOf(Image));
except
// something went wrong
end;
end;

procedure TTileMap.SaveToFile(const FileName: String);
var
f: File;
x,y: Integer;
begin
AssignFile(f, FileName);
try
Rewrite(f);
for y := 0 to 9 do
for x := 0 to 9 do
begin
Tiles[x,y].SaveToFile(f);
end;
finally
CloseFile(f);
end;
end;

procedure TTileMap.Clear;
var
x,y: Integer;
begin
for x := 0 to 9 do
for y := 0 to 9 do
begin
if Assigned(Tiles[x,y]) then
begin
Tiles[x,y].Free;
Tiles[x,y] := nil;
end;
end;
end;

procedure TTileMap.LoadFromFile(const FileName: String);
var
f: File;
x,y: Integer;
begin
Clear;
AssignFile(f, FileName);
try
Reset(f);
for y := 0 to 9 do
for x := 0 to 9 do
begin
Tiles[x,y] := TTile.Create;
Tiles[x,y].LoadFromFile(f);
end;
finally
CloseFile(f);
end;
end;

hammer
25-02-2004, 11:00 AM
i've done it but the lamest way :) a text file but now i have a new problem how can i make one tile appear over another cous when i do it the tile i want to be on top goes on back ???

Useless Hacker
25-02-2004, 12:42 PM
Just draw the tile you want to be on top after you draw the tile you want to be underneath.

hammer
25-02-2004, 03:40 PM
hm.. well i draw them via the dxspriteengine.draw so how can i determine which is first ??? isn't there some other way ??? layering perhaps ???

hammer
25-02-2004, 08:59 PM
hm... i've solved the problem but i dont think its the best way
i am using <varname>[counter].dodraw

cairnswm
26-02-2004, 05:51 AM
Have you tried using the Z-order of the Sprites.

(PS I think its the right way but I really dislike using the DXSpriteEngine)

hammer
26-02-2004, 08:55 AM
yeah thanks cairnswm the z-order did it :)
btw why dont you like using the dxspriteengine ?? just your decision or there is some reason ?

cairnswm
26-02-2004, 01:29 PM
I have found the object model used for the dxSpriteEngine very unfriendly and it difficlt to add custom actions to the sprites. I made a game (Desperate defense - look under announcements) with the DXSprite Engine but had so much trouble that I just threw the game away because I couldn't do what I wanted - and it is really a simple game.

Ok - I just went and relooked at my game - The DXSpriteEngine model has no way of allowing custom colision shapes. Based on the feel of the game I needed very small collision blocks within the enemies (Otheriwse the game felt wierd) Because of the logic used to define shapes and their collision rects I had to go and change basic code within the DXSprite.

(Actually my insistence on using DelphiX is a bit pathetic as I only really use the DXImageList and DXDraw objects....)

hammer
27-02-2004, 10:01 AM
cool game 8)