View Full Version : I decided to start my RPG game in DelphiX and Im very happy
Karaman
13-02-2003, 07:18 PM
Hi 2 all
I am making a RPG Final Fantasy Style Tile Based
the project has no name yet :)))
You can check some demo at
http://www.plovdivart.com/karaman/dnd.zip
Project has one GameEngine.Pas file which is not include, but will be when the game is finished, because I want it to become popular like FF4,5,6 series
Now It has support for Map Tiles (Solid with up to 10 Z levels (4 is Player))
And Doors (They open and close)
Right now I am developing Exits (to jump from map to map)
but am too hungry so may be tommorow
UNFORTUNATELY
I am NOT using my own graphics, but I dont care, I am very bad at drawing, or very slow
you can see my manga pics at
http://www.plovdivart.com/karaman/
And finally for this post
chose Load then load the only map from level/inn.map :)[/url]
Traveler
14-02-2003, 08:09 AM
It's looking good :)
Did notice some things you might want to look into:
- when you click on picture at the main page the two buttons disappear
- when you start walking towards to top of the room the scrolling is very smooth(fps 200) at the beginning, but when you reach the top scrolling is a lot slower(fps 80).
- I was able to walk on top of the pile of firewood and the oven, it looked a bit strange...
Keep on working,... it sure is a nice start!
Btw,.. where did you get those tiles from?
iLLUNis
14-02-2003, 11:50 AM
reminds me of Ultima times..:P....nice
Karaman
14-02-2003, 12:37 PM
Yeah, There are some bugs, may be because I didnot read the help of DelphiXGUI,
for the speed: I tried various tricks with TDXDRaw options and managed to get it work at my system display 85FPS, When you are pressing SHIFT while walking the knight ( Falcir :) ) moves at grater speed and the FPS move a little bit higher:) I dont know why it is so BTW
Hmm, may be because I am using 24 bit graphics and not 256 ones
The game is still at planning mode, too many things are just experimental :)
for the strange walking, well, I try it to look not from above but from an angle, hope it is not very confusing but otherwise I will have to recut the tiles i am using and it is very tiring job, I made a delphi prg which reads the tile file and then cuts it into small pieces of 32x32 to be used with the game editor.
This night I decided to try MASKed terrain,
the terrain has two tiles - 1 visual with all graphics as a simple picture
the other tile will be black and white only
black - solid
white -walkable
then the player tile should have the same two tiles
and when one moves the player around it should check whether the
BITWISE adition of the two masks is equal to ZERO, if yes then we do not have overllaping of the walkable with not walkable parts (or the masked ones) but I am not finished it yet, only planning. I think this is the way they did it at the Baldur's Gate 2 Graphic engine, or it looks like it :)
and the tiles are to be found at:
http://www.molotov.nu/?page=graphics
tronied
15-02-2003, 12:27 PM
I think we are using the same tilesets :D
Your demo shows what it would look like if I had done mine using DelphiX. Have you thought about an editor yet? If not... check mine out at http://groups.yahoo.com/group/tronied. For mine I just used basic delphi components which has caused me to lose most of the advantages associated with using DirectX (i.e. Smooth walking, Different layers etc). Maybe at a later date I will start a new project like yours... but for now I am just experimenting with what is possible using my method.
By the way... feel free to use my tileset images. I got most of them off sites and edited them to suit how I wanted them displayed.
Also, I get a minimum of 135fps and max of about 230 for your rpg. You should start worrying when it gets below 30... not for the FR's i got.
Ultra
15-02-2003, 11:18 PM
It looks good. I'm looking forward to see where it'll end. :)
I'm doing a similar project myself (actually it's my 20+ try :wink: ). It's still to early to show anything (or know if it'll be completed at all) however.
Karaman
16-02-2003, 10:14 PM
I have an editor, but It is not finished yet
You can add tiles, view and edit tile states, load and save maps
but no undo so far :cry: :cry:
here is the updated game, editor included, bug with splashscreen fixed
added support for exits
!!!IMPORTANT: copy file *.dxg in the ./editor/*.dxg
http://www.plovdivart.com/karaman/dnd.zip
cairnswm
18-02-2003, 06:19 AM
There is a feature in DXGui that whenever you click an object it is imediatly brought to front. I have been able to take this feature away by modifying the original DXDrawGUI component.
tronied
19-02-2003, 12:54 PM
Just out of interest... you say you are using DelphiX. I too now have decided to start a new project and have got my grid all setup with the movement keys and collision detection pretty much to hand. However, I am only getting 60fps max and it wont go higher than that... even with a blank screen with nothing on it (DXDraw Component). How have you managed to get the high FR's on your game?
Alimonster
19-02-2003, 01:51 PM
That sounds very much like v-sync. Your vertical monitor's refresh rate will be 60Hz, probably? The idea here is that the screen has to refresh itself at regular amount of times per-second. Therefore, it starts at the top-left of the screen and goes down the way, updating each line in turn.
Now, you have two options when drawing a scene - wait for the start of a retrace (when it'll be sitting at the screen top-left) or draw anyway, regardless of the current position. The first case will limit you to your monitor update speed (in this case, 60Hz), so you won't be able to get any higher. On the other hand, each frame will be displayed correctly, assuming you can get that speed. On the third hand :drunk:, if your drawing code takes too long per frame and you just miss v-sync, your frame rate will alternate: 1/2 monitor speed, full monitor speed, 1/2 monitor speed, etc. E.g. 30FPS, 60FPS, 30FPS, 60FPS...
If you don't wait for a retrace then you might, for example, start drawing a new scene while the CRT gun (uh, I forget the correct term - think that's right) is half-way down the screen. This means that half of the old frame will be visible at the bottom, and half of your new frame will be visible at the top (at least for a little while) -- this is the "tearing" that you might have seen if you turn quickly in a 3d game without v-sync. You might notice the result if you're paying attention (my brother doesn't see this effect, which never ceases to amaze me!).
V-sync only makes a difference to your FPS in full-screen mode, not windowed mode AFAIK.
You can disable or enable v-sync in your graphics card setup (it'll probably be under control panel->display->settings->advanced, somewhere). It depends on what you want: only complete frames drawn, or pure FPS. I prefer the latter usually (it better represents the mouse input, coz with slower FPS your mouse isn't as well represented - it's sampled at the same rate but the screen updates don't show all the in-between stages).
Btw, 60Hz is a bit low for a monitor these days - you should try at least 75Hz if your monitor supports it. Your eyes will thank you! (control panel->display->settings->advanced->monitor, or thereabouts - if there's a refresh rate combo box, set it to "optimal", otherwise have a look around other tabs). That's separate from the v-sync option (which will be under your graphics card options).
There's probably a way to say whether to draw with v-sync enabled in DelphiX, but I've never used the thing so I can't be sure. If not then don't worry about it until your frame rate drops below the monitor refresh, or tell the end users to disable v-sync manually.
The above info has been dredged up in a moment of boredom. It's possible that most of the above is nonsense, so clarifications/corrections are, as always, welcome.
[Bonus question: how bored do you think I am at the moment? :|]
tronied
19-02-2003, 03:01 PM
Thanks Alimonster...
I am not sure how I have the DXDraw component setup at the moment, but I am pretty sure there is some setting (boolean) relating to the VSync and so I will try this tonight.
Also, about your bonus question... I would have to say on the near suicidal bordom stage to write that much :D But, I am glad you did as it has provided me a good understanding.
Karaman
19-02-2003, 05:06 PM
object DXDraw: TDXDraw
Left = 0
Top = 0
Width = 320
Height = 320
AutoInitialize = False
AutoSize = True
Color = clBtnFace
Display.BitCount = 24
Display.FixedBitCount = True
Display.FixedRatio = True
Display.FixedSize = False
Display.Height = 600
Display.Width = 800
Options = [doAllowReboot, doAllowPalette256, doCenter, doFlip, do3D, doDirectX7Mode, doRetainedMode, doHardware, doSelectDriver, doZBuffer]
SurfaceHeight = 320
SurfaceWidth = 320
OnFinalize = DXDrawFinalize
OnInitialize = DXDrawInitialize
TabOrder = 0
end
BTW, I have a question, how can I save and load an array of any data to a stream without knowing the data only the name of the array :?:
tronied
19-02-2003, 10:06 PM
Thanks
I have got mine running at a steady 80fps (on my machine) no matter what is displayed now. I also have another question...
Because my tiles are somewhat smaller and were stretched in my original version of this game using a group of TImage components, I wanted to do the same thing on this. However when I use the StretchDraw() function, my framerate drops to about 2 or 3fps (from 80)... strange that. Anyone got any ideas? Or will I have to find new larger tilesets.
Alimonster
20-02-2003, 10:37 AM
BTW, I have a question, how can I save and load an array of any data to a stream without knowing the data only the name of the array :?:
You can use the WriteBuffer/ReadBuffer or Write/Read functions. However, you have to be careful when saving strings or dynamic arrays, and pointers are a little annoying too.
For a standard array, SizeOf(Array_Thing) will give you the size in bytes; this lets you save the info directly:
procedure SaveMe(const Mem: TStream);
var
x: array[0..2] of Integer;
begin
// todo: init x somehow
Mem.WriteBuffer(x[0], SizeOf(x));
end;
The above works fine for standard types that don't need memory allocation. You'd use ReadBuffer to read in the info again. However, if you're using dynamic memory then sizeof(x) will always give 4 (bytes), since the dynamic array is actually a pointer to memory behind the scenes. In that case, you'd have to save the length of the array first, then the array contents if necessary:
procedure Save(const str: TStream);
var
x: array of Integer; // dynamic array here
Size: Integer;
begin
SetLength(x, 4); // allocate 4 elements
// now the tricky part: we have to save the length first,
// then calculate the size of the array in bytes
Size := Length(x);
// write the length
str.WriteBuffer(x, SizeOf(x));
if Size > 0 then
str.WriteBuffer(x[0], Size * SizeOf(x[0]));
end;
procedure Load(const str: TStream);
var
x: array of Integer;
Size: Integer;
begin
// get the length
Mem.ReadBuffer(Size, SizeOf(Integer));
SetLength(x, Size);
if Size > 0 then
Mem.ReadBuffer(x[0], Size * SizeOf(x[0]));
end;
Much the same idea for strings, too (not ShortStrings though, which are different). Save the length, then save the contents if necessary.
You can't directly save arrays that store pointers to things; instead, you'd have to save the pointed-to memory and reconstruct the object when loading. Unfortunately, pointers aren't useful if they don't point to valid objects/memory. This rules out saving-in-one-line of code strings, dynamic arrays, and classes.
Note that open arrays ("array of", but in a procedure (or function) parameter list) behave correctly with sizeof (I think!).
Karaman
20-02-2003, 11:45 AM
I am using MultiDimensional Arrays for GameData and I think It will not work correctly, but I will try
100x a LOT
Alimonster
20-02-2003, 12:49 PM
If you're using a normal 2D multidimensional array (same width for each row), rather than a jagged one, then you could do this (note: really, really, untested - check it works!):
[background=#FFFFFF][comment=#0000FF][normal=#000000]
[number=#C00000][reserved=#000000][string=#00C000]type
TTile = record
x, y: Integer;
PicIndex: Byte;
Flags: Byte;
end;
PTile = ^TTile;
T2DArray = array of array of TTile;
procedure SaveMe(const arr: T2DArray; const Mem: TStream);
var
RowCount, ColCount: Integer;
y, WidthOfRow: Integer;
begin
RowCount := Length(arr);
if RowCount > 0 then
ColCount := Length(arr[0])
else
ColCount := 0;
// write out the array dimensions
Mem.WriteBuffer(RowCount, SizeOf(RowCount));
Mem.WriteBuffer(ColCount, SizeOf(ColCount));
if (RowCount > 0) and (ColCount > 0) then
begin
WidthOfRow := ColCount * SizeOf(arr[0][0]);
for y := Low(arr) to High(arr) do
Mem.WriteBuffer(arr[y][0], WidthOfRow);
end;
end;
procedure LoadMe(var arr: T2DArray; const Mem: TStream);
var
Rows, Cols: Integer;
y: Integer;
SizeOfRow: Integer;
begin
Mem.ReadBuffer(Rows, SizeOf(Rows));
Mem.ReadBuffer(Cols, SizeOf(Cols));
SetLength(arr, rows, cols);
if (rows > 0) and (cols > 0) then
begin
SizeOfRow := Cols * SizeOf(arr[0][0]);
for y := 0 to rows - 1 do
begin
Mem.ReadBuffer(arr[y][0], SizeOfRow);
end;
end;
end;
I think that the above will work, though I've not run it to find out. As always, it's not this simple if your game data contains classes, strings (but not shortstrings) or pointers to allocated memory. If it contains any of those, then you'll have to write functions to save the data instead of using a few calls to ReadBuffer/WriteBuffer.
Ultra
20-02-2003, 03:36 PM
When I save/load an 2D array in my code I use something like:
TTile = record
TileType: TTileType; //holds whether the player can walk on the tile etc
TileIndex: Integer; // image
end;
TEvent = record
Trigger: TEventTrigger; //What triggers the event, if the player steps on the tile or something else?
Action: TEventAction; //What event will it be, change map, execute script?
Param: String[10]; // For changing map and execute script files name etc.
TileX, TileY: Integer; // which tile will have this event?
PlayerPos: TPoint; // when changing map, where will the player start?
end;
TTransTile = record
Xpos, Ypos: Integer; //Position
TileImage: Integer; //Image
end;
TMapConfig = record
MapWidth,
MapHeight: Integer; //Map size
TransTiles: Integer; //transparent tiles, for this I use a 1d array
Events: Integer; //events, also 1d array
Name: String[10];
end;
var
MapConfig: TMapConfig;
TileMap: array of array of TTile;
TransTiles: array of TTransTile;
Events: array of TEvent;
procedure SaveMap(FileName: String);
var
Stream: TFileStream;
X,Y,i: Integer;
begin
try
Stream := TFileStream.Create(FileName, fmOpenReadWrite);
except
Stream := TFileStream.Create(FileName, fmCreate);
end;
try
Stream.WriteBuffer(MapConfig, SizeOf(MapConfig));
for y := 0 to MapConfig.MapHeight -1 do
for x := 0 to MapConfig.MapWidth -1 do
begin
Stream.WriteBuffer(TileMap[x,y], SizeOf(TileMap[x,y]));
end;
for i := 0 to MapConfig.TransTiles -1 do
begin
Stream.WriteBuffer(TransTiles[i], SizeOf(TransTiles[i]));
end;
for i := 0 to MapConfig.Events -1 do
begin
Stream.WriteBuffer(Events[i], SizeOf(Events[i]));
end;
finally
Stream.Free;
end;
end;
procedure LoadMap(FileName: String);
var
Stream: TFileStream;
X,Y,i: Integer;
begin
try
Stream := TFileStream.Create(FileName, fmOpenRead);
except
ShowMessage('Error loading file.');
Exit;
end;
try
Stream.ReadBuffer(MapConfig, SizeOf(MapConfig));
SetLength(TileMap, MapConfig.MapWidth, MapConfig.MapHeight);
SetLength(TransTiles, MapConfig.TransTiles);
SetLength(Events, MapConfig.Events);
for y := 0 to MapConfig.MapHeight -1 do
for x := 0 to MapConfig.MapWidth -1 do
begin
Stream.ReadBuffer(TileMap[x,y], SizeOf(TileMap[x,y]));
end;
for i := 0 to MapConfig.TransTiles -1 do
begin
Stream.ReadBuffer(TransTiles[i], SizeOf(TransTiles[i]));
end;
for i := 0 to MapConfig.Events -1 do
begin
Stream.ReadBuffer(Events[i], SizeOf(Events[i]));
end;
finally
Stream.Free;
end;
end;
I haven't loooked at Alimonster's code, it might be that his is much more efficient but this has worked for me so far at least.
Alimonster
20-02-2003, 04:02 PM
I haven't loooked at Alimonster's code, it might be that his is much more efficient but this has worked for me so far at least.
It looks like your code does pretty the same thing, but with one problem. You mentioned the word "efficient," which has jogged my memory about what I missed in the previous post.
I don't know how 2D dynamic arrays are stored in memory. If they're entirely consecutive (rather than each row being in a different area of memory), as with normal 2D arrays, then you only need one WriteBuffer/ReadBuffer for the entire map - sod all the loops :).
[background=#FFFFFF][comment=#0000FF][normal=#000000]
[number=#C00000][reserved=#000000][string=#00C000]type
TTile = record
// stuff goes here
end;
T2DArray = array of array of TTile;
procedure SaveMe(const arr: T2DArray; const mem: TStream);
var
SizeX, SizeY: Integer;
begin
SizeX := Length(arr);
if SizeX > 0 then
SizeY := Length(arr[0])
else
SizeY := 0;
// write the map size
mem.WriteBuffer(SizeX, SizeOf(SizeX));
mem.WriteBuffer(SizeY, SizeOf(SizeY));
// and the **entire map in one go :) **
if (SizeX > 0) and (SizeY > 0) then
mem.WriteBuffer(arr[0][0], SizeX * SizeY * SizeOf(arr[0][0]));
end;
...and the same deal for loading :).
What's important here: the hard disc is bloody slow, as with all input devices (think about when your computer thrashes the hard disc getting virtual memory; that's much slower than using RAM). As a result, you want to do as few reads as you possibly can, reading in big chunks. This will minimize the slowness of the hard disc I/O. RAM is very quick - read in stuff to memory, and parse it *there* ;).
Your code, Ultra, seems to be doing a read/write per tile (there will be a lot of 'em remember!). Think about this: each tile will be tightly packed together in the map, which means you can write many at the same time. If you write a tile[y,x], SizeOf(Tile[y,x]), then you're writing one tile. If you do the same, but 2 * SizeOf(Tile[y,x]), then you'll be writing two tiles at the same time (the expected one, plus the next one)! Remember that all your objects in the array, by definition, will be the same element type, and hence, the same size.
My previous code snippet was done because I'm not sure if dynamic 2D arrays are sequential in memory. I'd guess they are, but without checking, I couldn't be certain. As a result, the least disc activity possible is to write out one row per outer loop. I'm absolutely sure that the rows of a 2D array will be stored sequential (anything else is unthinkable!). However, if my new assumption that the entire array will be contiguous holds, then no loops are necessary at all.
If you're planning on doing lots of fiddling with a file then read as much of it into memory as you can each time, For example, you could use a TMemoryStream and TFileStream together - Create your filestream, use the memory one's CopyFrom, and use the *in memory* version. This will give big speed-ups (big, big ones!).
Karaman
20-02-2003, 10:14 PM
now my game has an official web page :)
http://www.plovdivart.com/karaman/dnd/
Updates:
added support for
1. Triggers
2. Switches
3. Containers
4. Better Doors
created encryption system (NOT enabled for convenience)
Ultra
20-02-2003, 11:43 PM
Thanks for the tips Alimonster. I'm a bit to tired now and then I'll be gone for a couple of days, but then I will have a second look at my code based on your reply. If I get any troubles I know who to call. :wink:
Karaman
26-02-2003, 10:14 PM
I have updated all files of the game
graphics, maps, items (new), editor, core game
Tommorow will improve Display Engine
BTW, there will be 7 Hero Classes
Fighter, Cleric, Necromant, Thief, Assasin, Magicuser, Ranger
I need names though, can anyone sugest some :)
Thank YOU :)
Alimonster
26-02-2003, 10:23 PM
Hmm, suggestions you say... you know, you should never encourage me :mrgreen:
Tomorrow Boy
Power(s): Explodes, Super spelling
Source of powers: Magic
Weapon: Holy Talons
Transportation: Gorilla Bulldozer
Monsieur Bullet
Power(s): Glows in the dark, Extra-dimensional travel, Body transformation
Source of powers: Mystic
Weapon: Power Garrote
Transportation: Captain Zip-line
Sky Prowler
Power(s): Super ventriloquism
Source of powers: Ancient lore
Weapon: Flash Rod
Transportation: Archzepplin
Warwave
Power(s): Sharp shooting, Laser vision, Precognition
Source of powers: Solar
Weapon: Slime Ionizer
Transportation: Wind Donkey
----------------------
Deathstreak
Power(s): Flight, Weather prediction, Autonomic function control
Source of powers: Undead
Weapon: Light Belt
Transportation: Turbo Griffon
Traveler
27-02-2003, 08:16 AM
Gorilla Bulldozer, Captain Zip-line, Archzepplin, Wind Donkey?!?! :lol:
Where do you get this stuff!! :lol: :joker:
Karaman
02-03-2003, 09:41 AM
Alimonster: I am speechless :)
Karaman
24-03-2003, 10:18 PM
Dear Delphi Gamers :)
Ar last I managed to update my game, too busy these days, a lot of exams at school :)
Please visit the game site for more info:
http://www.plovdivart.com/karaman/dnd/
there are new screenshots also (bigger ones:))
farcodev
26-03-2003, 09:56 AM
Your game looks very cool, good work ! :lol:
Alimonster
29-03-2003, 08:35 PM
Keep up the good work! :cat:
Karaman
01-04-2003, 09:28 PM
New Alpha version Released of my RPG Karaman's Final Fantasy
http://www.plovdivart.com/karaman/dnd/
some improvements, music added
ethan_hunt
29-04-2003, 03:09 PM
YEAh they are right, your work is great. :wink: 8)
But i have a question, will the project be opensource ?
Because, i will do program a RPG to and your engine is really great i think. And becaus of this i will use your engine when it will be open source..... :lol:
Karaman
04-05-2003, 05:57 PM
Sure, IT will be open source, but after 2-4 days
Alimonster
05-05-2003, 08:56 AM
Open source rocks http://www.gamedev.net/community/forums/icons/icon14.gif -- it's how I learned Delphi (no books, just source code from other people and the help files).
Karaman
06-05-2003, 08:14 AM
My Project goes Open Source
You can modify it now as you like, but you have to mention me as the
creator of the idea. Please send me any improvements that might be
implemented in the project. You can send links to your projects' sites
if you are using my engine :) (if you wish of course)
http://www.plovdivart.com/karaman/?op=delphi_fantasy
I hope you liked the source
ethan_hunt
06-05-2003, 03:44 PM
Sorry, its already OpenSource :oops:
Karaman
17-05-2003, 06:35 PM
I abandon my this project for 2 months
cause I am going to have a STRESS Exam Session
:x :cry: :cry: :cry: :cry: :cry:
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.