Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Ускоренный вывод [Delphi, Windows]


Lockdog ©   (2004-04-29 15:35:00) 

Пишу игру (2D) на Directdraw, но возникла проблема - у меня было 4 поверхности:
фон(земля), два персонажа (спрайта) и одна переключающаяся (для фона).
Когда я ввёл ещё одну - это рисунок для курсора, то когда я двигаю этим курсором, спрайты останавливаются, то есть тормозят!
Как мне избавится от этого?
Размеры спрайтов: 70х70
Фон: 640х480
Курсор: 32х32


Lockdog   (2004-05-01 20:55:00) [1]

Огромнейшее спасибо!!!
Всё работает!


Mihey   (2004-05-01 20:18:00) [2]

В обработке OnMoseMove оставь:

MouseX := X;
MouseY := Y;

а SendMessage(Handle, wm_paint, 0, 0) убери.


Lockdog   (2004-05-01 19:22:00) [3]

А какой тогда функцией воспользоваться, чтобы передавать координаты курсора в поверхность?


Mihey   (2004-05-01 19:09:00) [4]

2 Lockdog:

Рендеринг только по таймеру, т.е. из OnMouseMove убрать.


Lockdog   (2004-05-01 18:07:00) [5]

Ниже приведён код с исправленными ошибками, на которые вы мне указали, но всёравно игра жутко тормозит (как и прежде). Посоветуйте ещё что-нибудь.

Исправленный код:

unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, DirectDraw, DDUtil, AppEvnts, BASS, ExtCtrls;

type
 TForm1 = class(TForm)
   ApplicationEvents1: TApplicationEvents;
   Timer1: TTimer;
   procedure FormCreate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure FormPaint(Sender: TObject);
   procedure ApplicationEvents1Restore(Sender: TObject);
   procedure PlayStrem(Name: string);
   procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
   procedure Timer1Timer(Sender: TObject);
 private
  result: HStream;
  f: PChar;
  FDirectDraw: IDirectDraw7;
  FPrimarySurface: IDirectDrawSurface7;
  FBackgroundSurface: IDirectDrawSurface7;
  FSecondSurface: IDirectDrawSurface7;
  FSpriteSurface: IDirectDrawSurface7;
  SurfaceDesc: TDDSurfaceDesc2;
  HRet: HResult;
  fcaps: TDDSCaps2;
  srcrect: TRect;
  meatmanrect: TRect;
  currect: TRect;
  X, Y, State, LastXState, incparam: Integer;
  msg: TMsg;
  MouseX, MouseY: Integer;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.PlayStrem(Name: string);
begin
f := PChar(Name);
result:= BASS_StreamCreateFile(FALSE, f, 0, 0, BASS_MP3_SETPOS);
if result<>0 then BASS_StreamPlay(result, FALSE, 0);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
incparam := 1;
X := 0;
LastXState := 0;
Y := random(400);

MouseX := 0;
MouseY := 0;

{---Инициализация звука---}
if BASS_GetVersion() <> MAKELONG(1,8) then begin
   ShowMessage('BASS 1.8 не загружен!');
   Halt;
 end;
if not BASS_Init(-1, 44100, 0, handle) then
  ShowMessage('Не могу инициализировать звук!');

BASS_Start;
{----------}

{---Инициализация DirectX 7.0---}
HRet := DirectDrawCreateEx(nil, FDirectDraw, IDirectDraw7, nil);
if HRet <> DD_OK then
begin
 ShowMessage('Установите DirectX 7.0 или выше!');
 Halt;
end;
{----------}
FDirectDraw.SetCooperativeLevel(Handle, DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE);
FDirectDraw.SetDisplayMode(800, 600, 16, 0, 0);

FillChar(SurfaceDesc, SizeOf(SurfaceDesc), 0);
SurfaceDesc.dwSize := SizeOf(SurfaceDesc);
SurfaceDesc.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
SurfaceDesc.dwBackBufferCount := 1;//Кол-во вторичных экранов
SurfaceDesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or
DDSCAPS_FLIP or DDSCAPS_COMPLEX;

FDirectDraw.CreateSurface(SurfaceDesc, FPrimarySurface, nil);

FillChar(fcaps, SizeOf(fcaps), 0);
fcaps.dwcaps := DDSCAPS_BACKBUFFER;
FPrimarySurface.GetAttachedSurface(fcaps, FSecondSurface);;

FBackgroundSurface := nil;
FBackgroundSurface := DDLoadBitmap(FDirectDraw, '1.bmp',
800, 600);

FSpriteSurface := nil;
FSpriteSurface := DDLoadBitmap(FDirectDraw,
'sprite.bmp', 0, 0);
DDSetColorKey(FSpriteSurface, RGB(0,0,0));

ShowCursor(False);

PlayStrem('sounds\play.mp3');
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
BASS_Stop;
BASS_StreamFree(result);
BASS_Free();

FSpriteSurface := nil;
FSecondSurface := nil;
FPrimarySurface := nil;
FDirectDraw := nil;
ShowCursor(True);
Halt;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
FSecondSurface.BltFast(0, 0, FBackgroundSurface, nil, DDBLTFAST_WAIT);

srcrect.Left := 0;
srcrect.Top := State*70;
srcrect.Right := 70;
srcrect.Bottom := State*70+70;
FSecondSurface.BltFast(X, 10, FSpriteSurface, @srcrect,
DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);

meatmanrect.Left := 0;
meatmanrect.Top := 770;
meatmanrect.Right := 70;
meatmanrect.Bottom := 770+70;
FSecondSurface.BltFast(X, 530, FSpriteSurface, @meatmanrect,
 DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);

currect.Left := 0;
currect.Right := 70;
currect.Top := 2030;
currect.Bottom := 2100;
FSecondSurface.BltFast(MouseX, MouseY, FSpriteSurface,
 @currect, DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);

FPrimarySurface.Flip(nil, DDFLIP_WAIT);
end;

procedure TForm1.ApplicationEvents1Restore(Sender: TObject);
begin
if HRet = DDERR_SURFACELOST then
 FPrimarySurface._Restore;
 FSecondSurface._Restore;
 FBackgroundSurface._Restore;
 FSpriteSurface._Restore;
 FBackgroundSurface := DDLoadBitmap(FDirectDraw, '1.bmp', 800, 600);

 FSpriteSurface := DDLoadBitmap(FDirectDraw,
  'sprite.bmp', 0, 0);
 DDSetColorKey(FSpriteSurface, RGB(0,0,0));
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);
begin
MouseX := X;
MouseY := Y;
SendMessage(Handle, wm_paint, 0, 0);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
X := X+1;
  if X-LastXState>10 then
   begin
    State := State+incparam;
     if State=10 then
      incparam := -1;
     if State=0 then
      incparam := 1;
     LastXState := X;
   end;
 SendMessage(Handle, wm_paint, 0, 0);
end;

end.


miek   (2004-04-30 21:06:00) [6]

Ворох ошибок!
1) Во-первых, для хранения спрайтов грамотнее использовать ОДНУ внеэкранную поверхность - зачем целых три? Просто выводить будешь не всю ее, а регион с нужным спрайтом.
2) Во-вторых, если уж используешь двойную буферизацию и переключение страниц, то рисуй на ВТОРИЧНОЙ поверхности, а не на первичной.
3) Ну и отрисовка по событию от мыши или по счетчику п цикле обработки событий - это верх непонимания. Рендеринг (FormPaint) вызывай по таймеру. На худой конец - сойдет и обычный, дельфийский.

По мелочи:
meatmanrect := Rect(0,0,70,70);
meatmanrect.Left := 0;
meatmanrect.Top := State*70;
meatmanrect.Right := 70;
meatmanrect.Bottom := State*70+70;
Интересно, а первая строчка здесь зачем?


Lockdog   (2004-04-30 18:05:00) [7]

unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, DirectDraw, DDUtil, AppEvnts, BASS, ExtCtrls;

type
 TForm1 = class(TForm)
   ApplicationEvents1: TApplicationEvents;
   procedure FormCreate(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
   procedure FormPaint(Sender: TObject);
   procedure FormKeyDown(Sender: TObject; var Key: Word;
     Shift: TShiftState);
   procedure ApplicationEvents1Restore(Sender: TObject);

   procedure PlayStrem(Name: string);
   procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
     Y: Integer);
 private
  result: HStream;
  f: PChar;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

 FDirectDraw: IDirectDraw7;
 FPrimarySurface: IDirectDrawSurface7;
 FImageSurface: IDirectDrawSurface7;
 FBackgroundSurface: IDirectDrawSurface7;
 FBotSurface: IDirectDrawSurface7;
 FMeatmanSurface: IDirectDrawSurface7;
 FCursorSurface: IDirectDrawSurface7;
 SurfaceDesc: TDDSurfaceDesc2;
 HRet: HResult;
 DC: HDC;
 bltfx: TDDBltFx;
 fcaps: TDDSCaps2;
 srcrect: TRect;
 meatmanrect: TRect;
 X, Y, State, LastXState, incparam: Integer;
 msg: TMsg;
 MouseX, MouseY: Integer;

implementation

{$R *.dfm}

procedure TForm1.PlayStrem(Name: string);
begin
f := PChar(Name);
result:= BASS_StreamCreateFile(FALSE, f, 0, 0, BASS_MP3_SETPOS);
if result<>0 then BASS_StreamPlay(result, FALSE, 0);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
incparam := 1;
X := 0;
LastXState := 0;
Y := random(400);

MouseX := 0;
MouseY := 0;

{---Инициализация звука---}
if BASS_GetVersion() <> MAKELONG(1,8) then begin
   ShowMessage('BASS 1.8 не загружен!');
   Halt;
 end;
if not BASS_Init(-1, 44100, 0, handle) then
  ShowMessage('Не могу инициализировать звук!');

BASS_Start;
{----------}

{---Инициализация DirectX 7.0---}
HRet := DirectDrawCreateEx(nil, FDirectDraw, IDirectDraw7, nil);
if HRet <> DD_OK then
begin
 ShowMessage('Установите DirectX 7.0 или выше!');
 Halt;
end;
{----------}
FDirectDraw.SetCooperativeLevel(Handle, DDSCL_FULLSCREEN or DDSCL_EXCLUSIVE);
FDirectDraw.SetDisplayMode(800, 600, 16, 0, 0);

FillChar(SurfaceDesc, SizeOf(SurfaceDesc), 0);
SurfaceDesc.dwSize := SizeOf(SurfaceDesc);
SurfaceDesc.dwFlags := DDSD_CAPS or DDSD_BACKBUFFERCOUNT;
SurfaceDesc.dwBackBufferCount := 1;//Кол-во вторичных экранов
SurfaceDesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE or
DDSCAPS_FLIP or DDSCAPS_COMPLEX;

FDirectDraw.CreateSurface(SurfaceDesc, FPrimarySurface, nil);

FillChar(fcaps, SizeOf(fcaps), 0);
fcaps.dwcaps := DDSCAPS_BACKBUFFER;
FPrimarySurface.GetAttachedSurface(fcaps, FBackgroundSurface);;

FImageSurface := nil;
FImageSurface := DDLoadBitmap(FDirectDraw, 'background.bmp', 800, 600);

FBotSurface := nil;
FBotSurface := DDLoadBitmap(FDirectDraw,
'images\bots\MonkeyBot\monkeybot.bmp', 0, 0);
DDSetColorKey(FBotSurface, RGB(0,0,0));

FMeatmanSurface := nil;
FMeatmanSurface := DDLoadBitmap(FDirectDraw,
'images\meatman\meatman.bmp', 0, 0);
DDSetColorKey(FMeatmanSurface, RGB(0,0,0));

FCursorSurface := nil;
FCursorSurface := DDLoadBitmap(FDirectDraw,
'cursor01.bmp', 0, 0);
DDSetColorKey(FCursorSurface, RGB(0,0,0));
ShowCursor(False);

PlayStrem('sounds\play.mp3');

while true do
begin
 if PeekMessage(msg, 0,0,0, pm_remove)= false then
  begin
   X := X+1;
     if X = 730 then
      begin
       X := X+(-1);
      end;
    if X-LastXState>10 then
     begin
      State := State+incparam;
       if State=10 then
        incparam := -1;
       if State=0 then
        incparam := 1;
        LastXState := X;
      end;
     SendMessage(Handle, wm_paint, 0, 0);
  end
 else
  begin
   translatemessage(msg);
   dispatchmessage(msg);
  end;
 end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
BASS_Stop;
BASS_StreamFree(result);
BASS_Free();

FBotSurface := nil;
FImageSurface := nil;
FBackgroundSurface := nil;
FPrimarySurface := nil;
FDirectDraw := nil;
ShowCursor(True);
Halt;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
ZeroMemory(@bltfx, SizeOf(BltFx));
BltFx.dwSize := SizeOf(BltFx);
BltFx.dwFillColor := 0;
FPrimarySurface.Blt(nil, nil, nil, DDBLT_COLORFILL or
 DDBLT_WAIT, @BltFx);

FBackgroundSurface.BltFast(0, 0, FImageSurface, nil, DDBLTFAST_WAIT);
FPrimarySurface.Flip(nil, DDFLIP_WAIT);

srcrect := Rect(0,0,70,70);
srcrect.Left := 0;
srcrect.Top := State*70;
srcrect.Right := 70;
srcrect.Bottom := State*70+70;
FPrimarySurface.BltFast(X, 10, FBotSurface, @srcrect,
DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);

meatmanrect := Rect(0,0,70,70);
meatmanrect.Left := 0;
meatmanrect.Top := State*70;
meatmanrect.Right := 70;
meatmanrect.Bottom := State*70+70;
FPrimarySurface.BltFast(X, 530, FMeatManSurface, @meatmanrect,
 DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);

FPrimarySurface.BltFast(MouseX, MouseY, FCursorSurface,
 nil, DDBLTFAST_WAIT or DDBLTFAST_SRCCOLORKEY);
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
 Shift: TShiftState);
begin
case chr(ord(Key)) of
 'W','Ц': Application.Terminate;
 'S','Ы': Application.Terminate;
 'D','А': Application.Terminate;
 'A','Ф': Application.Terminate;
end;

end;

procedure TForm1.ApplicationEvents1Restore(Sender: TObject);
begin
if HRet = DDERR_SURFACELOST then
 FPrimarySurface._Restore;
 FBackgroundSurface._Restore;
 FBotSurface._Restore;
 FMeatManSurface._Restore;
 FCursorSurface._Restore;
 FPrimarySurface.Blt(nil,nil,nil, DDBLT_COLORFILL or DDBLT_WAIT, @bltfx);
 FBackgroundSurface := DDLoadBitmap(FDirectDraw, 'background.bmp', 0, 0);

 FBotSurface := DDLoadBitmap(FDirectDraw,
  'images\bots\MonkeyBot\monkeybot.bmp', 0, 0);
 DDSetColorKey(FBotSurface, RGB(0,0,0));

 FMeatManSurface := DDLoadBitmap(FDirectDraw,
  'images\meatman\meatman.bmp', 0, 0);
 DDSetColorKey(FMeatmanSurface, RGB(0,0,0));

 FCursorSurface := DDLoadBitmap(FDirectDraw,
  'cursor.bmp', 0, 0);
 DDSetColorKey(FCursorSurface, RGB(0,0,0));
end;

procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
 Y: Integer);
begin
MouseX := X;
MouseY := Y;
FormPaint(nil);
end;

end.


NikeOLD   (2004-04-30 17:41:00) [8]

А где и как происходит обработка указателя мыши (получение координат курсора)?

Гони код - разберемся!


miek   (2004-04-29 18:43:00) [9]

Код рендеринга в студию!


Наверх

Титульная страница Поиск, карта сайта Написать письмо