PDA

View Full Version : DelphiX (starfighter game)



Wizard
13-11-2006, 05:33 AM
Hi everyone, I attach the unit file of my project (it's a starfighter game written with delphi and delphix) and would be pleased if someone can explain why the frames per second drops from 75 to about 30 after 60 seconds. Thanks for your help :-)


unit pasMain;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, DXSounds, DXSprite, DXClass, DXInput, DXDraws, BackGround;


type
TForm1 = class(TDXForm)
DXDraw1: TDXDraw;
DXImageList1: TDXImageList;
DXTimer1: TDXTimer;
DXInput1: TDXInput;
DXSound1: TDXSound;
DXSpriteEngine1: TDXSpriteEngine;
DXWaveList1: TDXWaveList;
Timer1: TTimer;
procedure DXTimer1Timer(Sender: TObject; LagCount: Integer);
procedure DXDraw1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure DXDraw1KeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure DXDraw1Finalize(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure DXDraw1Initialize(Sender: TObject);

private
procedure StartMain;
{ Private declarations }
public
{ Public declarations }
end;

//This is the player class
TPlayer = class(TImageSprite)
private
Fired: Integer;
public
procedure DoMove(MoveCount: Integer); override;
end;

// This is the attacker class
TAttacker = class(TImageSprite)
private
Fired: Integer;
public
procedure DoMove(MoveCount: Integer); override;
end;

//This is the Enimy class
TEnimy = class(TImageSprite)
private
Movement: Integer;
Speed: Integer;
public
procedure DoMove(MoveCount: Integer); override;
end;

//This is the bullet class
TBullet = class(TImageSprite)
public
procedure DoMove(MoveCount: Integer); override;
procedure DoCollision(Sprite: TSprite; var Done: Boolean);override;
end;

//This is the Bomb class
TBomb = class(TImageSprite)
public
procedure DoMove(MoveCount: Integer); override;
procedure DoCollision(Sprite: TSprite; var Done: Boolean);override;
end;

var
Form1: TForm1;
Player: TPlayer;
Seconds: Integer;
Enimies: Integer;
Bomb : TBomb;
Attacker: TAttacker;

implementation
{$R *.DFM}
{$O+}

var
Explode3x, Explode3y : integer;
Earthx, Earthy : integer;
Explode1x, Explode1y : integer;
Explode2x, Explode2y : integer;
Planetx, Planety : integer;
moveleft, moveright, moveup, movedown : boolean;


procedure TForm1.DXDraw1Initialize(Sender: TObject);
var
i: Integer;
begin
Form1.DoubleBuffered := True;
StartMain;
DXDraw1.Cursor := crNone;
randomize;
Explode3y := DXDraw1.Height - 700;
Explode3x := DXDraw1.Width - 350;
Earthy := DXDraw1.Height - 300;
Earthx := DXDraw1.Width - 300;
Explode1y := DXDraw1.Height -450;
Explode1x := DXDraw1.Width - 900;
Explode2y := DXDraw1.Height - 700;
Explode2x := DXDraw1.Width - 200;
Planetx := DXDraw1.Width - 600;
Planety := DXDraw1.Height -500;
Player := TPlayer.Create(DXSpriteEngine1.Engine);
Player.Image := DXImageList1.Items.Find('Player');
Player.X := 500;
Player.Y := 710;
Player.Width := Player.Image.Width;
Player.Height := Player.Image.Height;
Attacker := TAttacker.Create(DXSpriteEngine1.Engine);

Enimies := 30;
for i := 1 To Enimies do
begin
with TEnimy.Create(DXSpriteEngine1.Engine) do
begin
Image := DXImageList1.Items.Find('EnimyRight');
X := Random(640 * 3) - 640;
Y := Random(450);
Speed := Random(5)+ 3;
Width := Image.Width;
Height := Image.Height;
PixelCheck := True;
AnimLooped := True;
AnimSpeed := 15/1000;
AnimStart := 0;

end;
end;
DXTimer1.Enabled := True;
end;

procedure TForm1.DXDraw1Finalize(Sender: TObject);
begin
DXTimer1.Enabled := False;
end;



procedure TForm1.StartMain;
var
i: integer;
j: integer;
begin
with TBackground.Create(DXSpriteEngine1.Engine) do
begin
SetMapSize(200, 10);
Image:= DXImageList1.Items.Find('Stars');
Y:= 10;
Z:= -22;
FSpeed:= 0.5;
Tile:= TRUE;

for I:= 0 to MapHeight-1 do
for J:= 0 to MapWidth-1 do
begin
Chips[J, I]:= Image.PatternCount-Random(Image.PatternCount div 8);
if Random&#40;100&#41; < 95 then Chips&#91;J, I&#93;&#58;= -1;
end;
end;

with TBackground.Create&#40;DXSpriteEngine1.Engine&#41; do
begin
SetMapSize&#40;200, 10&#41;;
Image&#58;= DXImageList1.Items.Find&#40;'Stars'&#41;;
Y&#58;= 30;
Z&#58;= -21;
FSpeed&#58;= 1;
Tile&#58;= TRUE;

for I&#58;= 0 to MapHeight-1 do
for J&#58;= 0 to MapWidth-1 do
begin
Chips&#91;J, I&#93;&#58;= Image.PatternCount-Random&#40;Image.PatternCount div 4&#41;;
if Random&#40;100&#41; < 95 then Chips&#91;J, I&#93;&#58;= -1;
end;
end;

with TBackground.Create&#40;DXSpriteEngine1.Engine&#41; do
begin
SetMapSize&#40;200, 10&#41;;
Image&#58;= DXImageList1.Items.Find&#40;'Stars'&#41;;
Y&#58;= 40;
Z&#58;= -20;
FSpeed&#58;= 2;
Tile&#58;= TRUE;

for I&#58;= 0 to MapHeight-1 do
for J&#58;= 0 to MapWidth-1 do
begin
Chips&#91;J, I&#93;&#58;= Image.PatternCount-Random&#40;Image.PatternCount div 2&#41;;
if Random&#40;100&#41; <95>0&#41; then
X &#58;= X - 15;

If moveright and
&#40;&#40;X+Form1.DXImageList1.Items.Find&#40;'Player'&#41;.Wid th&#41;<Form1>0&#41; then
Y &#58;= Y - 15;

if Movedown and
&#40;y<form1.DXDraw1.Height-65&#41;then
Y&#58;= Y + 15;

MyX &#58;= X;
MyY &#58;= y;

If isButton1 in Form1.DXInput1.States Then
begin
if Fired <= 5 then //Check if max bullets hasn't been fired yet
begin
Inc&#40;Fired&#41;; //Increase number of fired bullets
with TBullet.Create&#40;Form1.DXSpriteEngine1.Engine&#41; do
begin
Image &#58;= Form1.DXImageList1.Items.Find&#40;'Bullet'&#41;;
Form1.DXWaveList1.Items.Find&#40;'Fire'&#41;.Play&#40;False&#41;;
X &#58;= MyX + 25;
Y &#58;= MyY;
Width &#58;= Image.Width;
Height &#58;= Image.Height;
end;
end;
end;
end;

procedure TBullet.DoMove&#40;MoveCount&#58; Integer&#41;;
begin

Y &#58;= Y - 25;
Collision;
if &#40;Y <0>= Form1.DXDraw1.Height&#41; then
Dead;
end;

procedure TBullet.DoCollision&#40;Sprite&#58; TSprite; var Done&#58; Boolean&#41;;
begin
If &#40;Sprite is TEnimy&#41; Then
begin
Sprite.Collisioned &#58;= False;
Sprite.Dead;
Enimies &#58;= Enimies -1;
Form1.DXWaveList1.Items.Find&#40;'hit'&#41;.Play&#40;False&#41;;
Dead;
end;
end;

procedure TBomb.DoMove&#40;MoveCount&#58; integer&#41;;
begin
Y &#58;= Y + 25;
Collision;
if &#40;Y <= 0&#41; Then
Dead;
end;

procedure TAttacker.DoMove&#40;MoveCount&#58;integer&#41;;
begin
if Fired <2> 640 * 2 Then Movement &#58;= 1;
if X < -640 Then Movement &#58;= 2;

Case Movement of
1&#58;
begin
If Image = Form1.DXImageList1.Items.Find&#40;'EnimyRight'&#41; Then
Image &#58;= Form1.DXImageList1.Items.Find&#40;'EnimyLeft'&#41;;
X &#58;= X - Speed // + 10
end;
2&#58;
begin
If Image = Form1.DXImageList1.Items.Find&#40;'EnimyLeft'&#41; Then
Image &#58;= Form1.DXImageList1.Items.Find&#40;'EnimyRight'&#41;;
X &#58;= X + Speed // - 10
end;
end;
end;


procedure TForm1.DXDraw1KeyDown&#40;Sender&#58; TObject; var Key&#58; Word;
Shift&#58; TShiftState&#41;;
begin
if key=VK_LEFT then moveleft &#58;= True;
if key=VK_RIGHT then moveright &#58;= True;
if key=VK_Up then moveup &#58;= True;
if key=VK_Down then movedown &#58;= True;
if KEY=vk_Escape then application.Terminate;
end;

procedure TForm1.DXDraw1KeyUp&#40;Sender&#58; TObject; var Key&#58; Word;
Shift&#58; TShiftState&#41;;
begin
if key=VK_LEFT then moveleft &#58;= False;
if key=VK_RIGHT then moveright &#58;= False;
if key=VK_UP then moveup &#58;= False;
if key=VK_down then movedown &#58;= False;
end;

procedure TForm1.Timer1Timer&#40;Sender&#58; TObject&#41;;
begin
//Reset the Fired count
Player.Fired &#58;= 0;
Attacker.Fired &#58;= 0;
//Increase the time
Inc&#40;Seconds&#41;;
end;
end.

[/code]

cairnswm
13-11-2006, 05:37 AM
Hi Wizard

Welcome to PGD

Maybe upload your whole project somewhere so that we can actually download it and test it.

(PS. Are you a member on the NAG forum?)

Cheers

Wizard
13-11-2006, 05:56 AM
Hi, thanks for your reply. I need to mention that the display in DXDraw setting is 1024*768, I have tested it on the other display settings and it's the same problem. I have further isolated the problem: when my attacker does not fire bullets there is no fps droppage at all but if it fires bullets the problem starts. I've tested all the 'option' settings in DXDraw also. Sorry, I don't know where I can upload my project :( I'm using the system timer to reset the fired count of my player and attacker and maybe it's the cause of my problem, thing is - I've tried to reset the fired count with the DXTimer but can't get it right :(

I've been programming for 3 years in Delphi and I love it :-)

Thanks again

cairnswm
13-11-2006, 06:04 AM
Its been many years since I last used DelphiX so I might be right off the mark.

Where do you destroy the bullets? I can see you create them when the fire button is pressed - where do you free the memory?

When the bullet is no longer needed you need to free it. So keep track of where the bullet is and free it when
1. It hits something
2. Goes off the screen
3. Exists for more than X seconds.

Wizard
13-11-2006, 07:02 AM
William, u rock!!!!! My player fires bullets upwards and the attacker fires bullets downwards. I freed the player bullets correctly but not the attacker bullets :) I had


if y is smaller or equal to o then dead

and changed it to

if Y is greater or equal to Form1.DXDraw1.Height - 20 Then Dead;

and it works, I now have a frame rate of 75 all the time :-)

Maybe you can explain the y axis to me as I thougt that y at the bottom of the screen would be 0.

You were a GREAT help :-)

cairnswm
13-11-2006, 07:18 AM
As far as I know DelphiX retains the Normal Delphi Positioning with 0 at the top left and moving right and down from there. (Just like on TCanvas).

OpenGL I think uses the bottom Left as 0,0

Wizard
13-11-2006, 09:23 AM
Thanks again, I've learned a lot. Sometimes it's nice to get perspective from someone else. I was looking at the solution but could'nt see it :-)

Great site :-)