Do's And Don'ts ?

Started by
34 comments, last by Olona 23 years, 8 months ago
I have a simple questions: How do you gain speed when programming a game using Delphi / DelphiX ? I''ve read somewhere that you shouldn''t use double data types. But as I don''t know how to test this or or maybe haven''t written a big enough program / game to be able to really test it - is there someone of you who whould know what to do? Basically, what''s the do''s and don''ts when doing a game. thanks guys.
Advertisement
Hi Olona,

Here''s a couple of do''s and don''ts,

- Don''t use round(); use trunc(); instead.

- When creating an imagelib, set all your images to use video memory, don''t set them to use system memory.
When creating a game in 16 bit video mode or higher, use
a program like photoshop or paintshop pro( or equiv) to reduce the amount of colors of your images to 256.
Your images will still look great but at 1/3 of the size of a full 16 bit image. no need to worry about palettes either, you''re in 16 bit mode, every image has it''s own palette( sortof).

Another big no no i''ve seen around is this:

enemyship : array[0..100] of tEnemySpriteship; // from class TimageSprite

Procedure tEnemySpriteship.domove(movecount:integer);
Var
i:integer;
begin
for i:=0 to 99 do
begin
enemyship.x:=somethingelse;
end;
end;

The above is a cpu killer, prolly one of the biggest no no out there

it''s like doing this:
for m:=0 to 99 do
begin
for i:=0 to 99 do
begin
enemyship.x:=somethingelse;<br> end;<br>end;<br><br>Since domove is called for everysprite automatically, there''s no need to call em one by one in a loop.<br><br>you just need to call it like so:<br>Procedure tEnemySpriteship.domove(movecount:integer);<br>begin<br> x:=somethingelse; <br>end;<br><br><br>Well, that''s it for now.<br>There''s tons more i could write about but this is what comes to mind right now.<br><br>Hope it helped a bit.<br>Gook luck.<br><br>Gunner<br>Sysimage inc. </i>
This topic could get quite long, but here are some things I use to speed up DelphiX...

1. Avoid using DxDraw.Canvas at all costs. Use turboPixels, PixelCore, etc. to draw lines and put text on the screen.

2. Avoid DrawAlpha and DrawADD for bigger areas. And if you use it in small areas remember to set your transparent color.

3. Do your own cropping and use BltFast when you can.

4. Keep your DXGs out of your EXE for larger projects.

5. Make check boxes for DoFlip and WaitVBlank -- some newer vid cards and monitors don''t need these options.

6. Don''t use DxImageList.Find(''item'') in your final build. Use DxImageList[item] where item is a CONST.

7. Don''t use DxDraw.Width or DxDraw.Height in your game loop -- these are slower than assigning them to globals.

8. Use 512x384x16 for scrolling/action games/demo code if you can. Its 25% faster then 640x480x16

9. Use 8-bit color if possible (i.e. Diablo, Starcraft, AoE) you can do some neat tricks and it''s very fast.

10. Put a FPS counter on screen and experiment with different ordering and loops.



[ turbo | turbo.gamedev.net ]
[ Michael Wilson | turbo sys-op | turbo.gamedev.net ]
quote:Original post by turbo

3. Do your own cropping and use BltFast when you can.


When using DelphiX''s Draw method, it performs BltFast itself then if it doesn''t work, tries Blt. BTW, the BltFast error code seems to be inconsistent with the DirectX documentation. I would recommend to modify the error checking line in DirectDrawSurface.Draw and replacing it with "if DXResult<>DD_OK" instead of "DXResult=WhateverErrorCodeItUses". That''s what I''m doing for my project.

quote:5. Make check boxes for DoFlip and WaitVBlank -- some newer vid cards and monitors don''t need these options.


DoFlip is only used in fullscreen mode. If disabled, DelphiX will Blt the back surface to the front surface automatically. If enabled, it will flip the back surface with the front surface. It would be wise to leave it when using FS mode, IMHO.


--
Kyodai Mahjongg
kyodai.com
--Kyodai Mahjonggkyodai.com

>When using DelphiX''s Draw method, it performs
>BltFast itself then if it doesn''t work, tries
>Blt. BTW, the BltFast error code seems to be
>inconsistent with the DirectX documentation. I
>would recommend to modify the error checking
>line in DirectDrawSurface.Draw and replacing
>it with "if DXResult<>DD_OK" instead >of "DXResult=WhateverErrorCodeItUses". That''s
>what I''m doing for my project.

I find that BLTFASTing a "cropped" surface, like a scrolling bitmap (i.e. Miniverse) gain about 20% on newish video cards over Hori''s DRAW. This is simply "thinking around" why the BLTFAST would fail in the first place.

quote:Original post by Anonymous Poster
I find that BLTFASTing a "cropped" surface, like a scrolling bitmap (i.e. Miniverse) gain about 20% on newish video cards over Hori''s DRAW. This is simply "thinking around" why the BLTFAST would fail in the first place.


According to the DX SDK help files, BLTFAST is *as fast* as BLT when you use hardware acceleration. If you don''t use it, BLTFAST is faster. But BLTFAST will only work on video to video transfer, etc.
I think that Hori''s DRAW system (Crop first, then try to BltFast, if it doesn''t work then Blt) is the safest of all...


--
Kyodai Mahjongg
kyodai.com
--Kyodai Mahjonggkyodai.com
One big mistak of delphiX coders is to use the main game loop in a timer. Simple set the timer of any package (Native, DelphiX, RXLib) to 0 is not enough for the speed that a game needs. Moreover, you share precious time of graphics render with the fight of Windows messages vs Delphi''s VCL...
The way is to slice the main game turn in two parts and put each one in a clean thread. Part 1: The read of player inputs and other moves calculations. Part 2: Graphic renders.
Ok, all of us have fear of threads, but they are more easy that we think:

// Variables for the thread control
var StopRender, RenderStopped: Boolean;
HRenderThread: DWORD;

procedure Render;
begin
Repeat
// ...
// Do the render stuff here
// ..
until StopRender;
Sleep(X) // Make some calculations if needed to control the velocity
RenderStopped := True;
end;

When the game are ready to begin the main loop, start the thread with:

HRenderThread := CreateThread(nil,0,@Render,nil,0,AnyVarIntegerHere);

This function "CreateThread" is an import of the Kernel32.dll and is declared on windows.pas.

To stop the thread do:

StopRender := True;
Repeat until RenderStopped;
CloseHandle(HRenderThread);

Easy hu? But take care when working with threads... All is happening at the same time, so, do not change or destroy anything that the thread is using!

The reward is the smoothest scrool and draw that you ever seen on a DelphiX game.
Try!

Till the next!
quote:
One big mistak of delphiX coders is to use the main game loop in a timer. Simple set the timer of any package (Native, DelphiX, RXLib) to 0 is not enough for the speed that a game needs. Moreover, you share precious time of graphics render with the fight of Windows messages vs Delphi''s VCL...
The way is to slice the main game turn in two parts and put each one in a clean thread. Part 1: The read of player inputs and other moves calculations. Part 2: Graphic renders.
Ok, all of us have fear of threads, but they are more easy that we think:


I''ve always used Carlos''s threaded timer or the Application.OnIdle event to squeeze that extra speed out. How about whipping up a sample app to show us how it''s done for real?



[ turbo | turbo.gamedev.net ]
[ Michael Wilson | turbo sys-op | turbo.gamedev.net ]
quote:Original post by turbo


I''ve always used Carlos''s threaded timer or the Application.OnIdle event to squeeze that extra speed out. How about whipping up a sample app to show us how it''s done for real?


The simple fact of use a procedure (event, in this case) of a timer call, or the cited Application.OnIdle as loop implies on the game patiently waiting for the Delphi while it is pushing and poping registers of control of execution flow. A basic rule of optimized code on Delphi or any knowed language, since 16 bits apps, mainly now on 32 bits apps is: Less functions and procedures calls on loops, less time wasted with pushs and pops, faster code. So, if we need a loop, better do it on a real loop, on a single place, with a repeat until, or a while do end, without functions, procedure or events calls. But we can''t make this loop on the main thread, so, this is the why of use an independet thread.
About the sample app, well, it is the code above and is sufficiently clearly to anyone use and see the results.

Till the next
I don''t think that two seperated Threads are a good idea.
I use the old simply way.
For me, I use a repeat until loop as "mainloop". It''s started after everything is set up and initialized, runs until certain conditions make it stop (an error, user input etc.) and after that everything is cleared, shutdown etc.
In this loop you first check for User input, react on it then draw everything and finally flip.
Easy huh ? AND fast.
This of course won''t work with DelpiX.

[ Ampaze | www.crazyentertainment.net ]

This topic is closed to new replies.

Advertisement