tappytux: Large graphics rework, changes TFPRasterImage into TLazIntfImage to store sprites to increase the speed in Linux and Mac OS X

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2148 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2011-11-16 07:44:39 +00:00
parent d07426651b
commit 5e35b522d3
5 changed files with 144 additions and 86 deletions

View File

@ -1,7 +1,7 @@
object formTappyTuxGame: TformTappyTuxGame
Left = 599
Left = 388
Height = 425
Top = 312
Top = 172
Width = 621
Caption = 'Tappy Tux'
ClientHeight = 425
@ -21,7 +21,7 @@ object formTappyTuxGame: TformTappyTuxGame
end
object Answer: TEdit
Left = 104
Height = 23
Height = 22
Top = 392
Width = 514
OnKeyPress = AnswerKeyPress
@ -83,7 +83,7 @@ object formTappyTuxGame: TformTappyTuxGame
end
object Level: TEdit
Left = 8
Height = 23
Height = 22
Top = 64
Width = 76
ReadOnly = True
@ -91,7 +91,7 @@ object formTappyTuxGame: TformTappyTuxGame
end
object Score: TEdit
Left = 8
Height = 23
Height = 22
Top = 152
Width = 76
ReadOnly = True
@ -99,7 +99,7 @@ object formTappyTuxGame: TformTappyTuxGame
end
object Lives: TEdit
Left = 8
Height = 23
Height = 22
Top = 232
Width = 76
ReadOnly = True

View File

@ -98,10 +98,9 @@ begin
snowmanWrong.StartPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanWrong.EndPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanWrong.Position := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanWrong.Bitmap := TPortableNetworkGraphic.Create;
snowmanWrong.LoadImageFromPng(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanwrong.png');
snowmanWrong.caption:= 'Oh-oh!';
snowmanWrong.value:= '0';
snowmanWrong.Bitmap.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanwrong.png');
vTappyTuxDrawer.AddAnimation(snowmanWrong);
vTappyTuxDrawer.RemoveAnimation(i);
i := i -1;
@ -184,17 +183,13 @@ begin
lTuxAnimation.IsInfinite := True;
lTuxAnimation.StartPoint := Point(250, 328);
lTuxAnimation.EndPoint := lTuxAnimation.StartPoint;
SetLength(lTuxAnimation.Bitmaps, 6);
lTuxAnimation.Bitmaps[0] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[0].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_1.png');
lTuxAnimation.Bitmaps[1] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[1].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_2.png');
lTuxAnimation.Bitmaps[2] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[2].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_3.png');
lTuxAnimation.Bitmaps[3] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[3].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_4.png');
lTuxAnimation.Bitmaps[4] := lTuxAnimation.Bitmaps[2];
lTuxAnimation.Bitmaps[5] := lTuxAnimation.Bitmaps[1];
SetLength(lTuxAnimation.Images, 6);
lTuxAnimation.LoadImageFromPng(0, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_1.png');
lTuxAnimation.LoadImageFromPng(1, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_2.png');
lTuxAnimation.LoadImageFromPng(2, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_3.png');
lTuxAnimation.LoadImageFromPng(3, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_4.png');
lTuxAnimation.LoadImageFromPng(4, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_3.png');
lTuxAnimation.LoadImageFromPng(5, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_2.png');
vTappyTuxDrawer.AddAnimation(lTuxAnimation);
for i:= 1 to 5 do
@ -274,9 +269,8 @@ begin
snowmanAnimation.StartPoint := Point(xAux, 5);
snowmanAnimation.EndPoint := Point(xAux, 100);
snowmanAnimation.IsInfinite:= false;
snowmanAnimation.Bitmap := TPortableNetworkGraphic.Create;
snowmanAnimation.LoadImageFromPng(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowman.png');
//snowmanAnimation.caption:= gameQuestionList[random(gameQuestionList.Count - 1)];
snowmanAnimation.Bitmap.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowman.png');
questionType[1] := random(3);
@ -332,10 +326,9 @@ begin
snowmanRight.StartPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanRight.EndPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanRight.Position := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanRight.Bitmap := TPortableNetworkGraphic.Create;
snowmanRight.caption:= 'OK!';
snowmanRight.value:= '0';
snowmanRight.Bitmap.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanright.png');
snowmanRight.LoadImageFromPng(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanright.png');
vTappyTuxDrawer.AddAnimation(snowmanRight);
vTappyTuxDrawer.RemoveAnimation(i);
i := i - 1;

View File

@ -7,7 +7,7 @@ interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, fpSound,
// LCL
ExtCtrls,
ExtCtrls, IntfGraphics,
// TappyTux
tappyconfig, tappydrawer, tappymodules;
@ -99,10 +99,9 @@ begin
snowmanWrong.StartPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanWrong.EndPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanWrong.Position := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanWrong.Bitmap := TPortableNetworkGraphic.Create;
snowmanWrong.caption:= 'Oh-oh!';
snowmanWrong.value:= '0';
snowmanWrong.Bitmap.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanwrong.png');
snowmanWrong.LoadImageFromPng(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanwrong.png');
vTappyTuxDrawer.AddAnimation(snowmanWrong);
vTappyTuxDrawer.RemoveAnimation(i);
i := i -1;
@ -157,7 +156,6 @@ procedure TTappyWords.StartNewGame(SndFX: Integer; Music: Integer; Level: Intege
var
i: Integer;
lTuxAnimation: TTappySpriteAnimation;
begin
count := 5;
timerWords.Enabled := True;
@ -174,8 +172,8 @@ begin
if QuestionList < 0 then QuestionList := 0;
gameQuestionList := TStringList.Create;
//gameQuestionList.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images'+PathDelim+'modules'+PathDelim+'tappywords'+PathDelim+'0.txt');
gameQuestionList.LoadFromFile('C:/'+IntToStr(QuestionList)+'.txt');
gameQuestionList.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images'+PathDelim+'modules'+PathDelim+'tappywords'+PathDelim+'0.txt');
//gameQuestionList.LoadFromFile('C:/'+IntToStr(QuestionList)+'.txt');
formTappyTuxGame.Answer.ReadOnly := false;
formTappyTuxGame.GameOver.Visible := false;
@ -190,17 +188,13 @@ begin
lTuxAnimation.IsInfinite := True;
lTuxAnimation.StartPoint := Point(250, 328);
lTuxAnimation.EndPoint := lTuxAnimation.StartPoint;
SetLength(lTuxAnimation.Bitmaps, 6);
lTuxAnimation.Bitmaps[0] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[0].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_1.png');
lTuxAnimation.Bitmaps[1] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[1].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_2.png');
lTuxAnimation.Bitmaps[2] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[2].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_3.png');
lTuxAnimation.Bitmaps[3] := TPortableNetworkGraphic.Create;
lTuxAnimation.Bitmaps[3].LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_4.png');
lTuxAnimation.Bitmaps[4] := lTuxAnimation.Bitmaps[2];
lTuxAnimation.Bitmaps[5] := lTuxAnimation.Bitmaps[1];
SetLength(lTuxAnimation.Images, 6);
lTuxAnimation.LoadImageFromPng(0, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_1.png');
lTuxAnimation.LoadImageFromPng(1, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_2.png');
lTuxAnimation.LoadImageFromPng(2, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_3.png');
lTuxAnimation.LoadImageFromPng(3, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_4.png');
lTuxAnimation.LoadImageFromPng(4, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_3.png');
lTuxAnimation.LoadImageFromPng(5, vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'tux_2.png');
vTappyTuxDrawer.AddAnimation(lTuxAnimation);
//Sound Creation
@ -227,7 +221,6 @@ var
heightAux: array [0..4] of integer;
existenceAux: array [0..4] of boolean;
snowmanAnimation: TFallingText;
begin
for i:= 0 to 4 do
@ -288,9 +281,8 @@ begin
snowmanAnimation.StartPoint := Point(xAux, 5);
snowmanAnimation.EndPoint := Point(xAux, 100);
snowmanAnimation.IsInfinite:= false;
snowmanAnimation.Bitmap := TPortableNetworkGraphic.Create;
snowmanAnimation.LoadImageFromPng(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowman.png');
snowmanAnimation.caption:= gameQuestionList[random(gameQuestionList.Count - 1)];
snowmanAnimation.Bitmap.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowman.png');
vTappyTuxDrawer.AddAnimation(snowmanAnimation);
end;
@ -300,7 +292,6 @@ var
i: Integer;
j: Integer;
snowmanRight: TFallingText;
begin
i:= 0;
j:= vTappyTuxDrawer.GetAnimationCount - 1;
@ -319,10 +310,9 @@ begin
snowmanRight.StartPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanRight.EndPoint := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanRight.Position := vTappyTuxDrawer.GetAnimation(i).Position;
snowmanRight.Bitmap := TPortableNetworkGraphic.Create;
snowmanRight.LoadImageFromPng(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanright.png');
snowmanRight.caption:= 'OK!';
snowmanRight.value:= '0';
snowmanRight.Bitmap.LoadFromFile(vTappyTuxConfig.GetResourcesDir() + 'images' + PathDelim + 'sprites' + PathDelim + 'snowmanright.png');
vTappyTuxDrawer.AddAnimation(snowmanRight);
vTappyTuxDrawer.RemoveAnimation(i);
i := i - 1;

View File

@ -6,7 +6,7 @@ interface
uses
Classes, SysUtils, Controls, Graphics, LCLType, IntfGraphics, fpimage,
Math,
Math, LCLIntf,
tappyconfig, tappymodules;
type
@ -14,6 +14,7 @@ type
{ TTappyTuxAnimation }
TTappyTuxAnimation = class
public
StartPoint, EndPoint: TPoint;
Position: TPoint;
CurrentStep: Integer;
@ -32,20 +33,22 @@ type
TTappySpriteAnimation = class(TTappyTuxAnimation)
public
//StartPoint, EndPoint: TPoint; override;
Bitmaps: array of TFPImageBitmap;
Images: array of TLazIntfImage;
destructor Destroy; override;
procedure DrawToIntfImg(AIntfImage: TLazIntfImage); override;
procedure ExecuteFinal; override;
procedure LoadImageFromPng(AIndex: Integer; APath: string);
end;
{ TFallingText }
TFallingText = class(TTappyTuxAnimation)
public
//StartPoint, EndPoint: TPoint; override;
Bitmap: TFPImageBitmap;
Image: TLazIntfImage;
destructor Destroy; override;
procedure DrawToIntfImg(AIntfImage: TLazIntfImage); override;
procedure DrawToCanvas(ACanvas: TCanvas); override;
procedure ExecuteFinal; override;
procedure LoadImageFromPng(APath: string);
end;
{ TTappyTuxDrawer }
@ -62,7 +65,7 @@ type
procedure DrawToCanvas(ACanvas: TCanvas);
class procedure DrawImageWithTransparentColor(
ADest: TLazIntfImage; const ADestX, ADestY: Integer; AColor: TFPColor;
AImage: TFPImageBitmap);
AImage: TLazIntfImage);
class function DateTimeToMilliseconds(aDateTime: TDateTime): Int64;
//function GetImage(ATile: TChessTile): TPortableNetworkGraphic;
procedure HandleMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
@ -85,17 +88,26 @@ implementation
{ TTappySpriteAnimation }
destructor TTappySpriteAnimation.Destroy;
var
i: Integer;
begin
{ for i := 0 to Length(Images)-1 do
if Assigned(Images[i]) then Images[i].Free;}
inherited Destroy;
end;
procedure TTappySpriteAnimation.DrawToIntfImg(AIntfImage: TLazIntfImage);
var
lNumBitmaps, lCurBmpIndex: Integer;
begin
lNumBitmaps := Length(Bitmaps);
lNumBitmaps := Length(Images);
if lNumBitmaps = 0 then Exit;
lCurBmpIndex := CurrentStep mod lNumBitmaps;
TTappyTuxDrawer.DrawImageWithTransparentColor(AIntfImage,
Position.X, Position.Y, colFuchsia, Bitmaps[lCurBmpIndex]);
Position.X, Position.Y, colFuchsia, Images[lCurBmpIndex]);
end;
procedure TTappySpriteAnimation.ExecuteFinal;
@ -103,12 +115,32 @@ begin
inherited ExecuteFinal;
end;
procedure TTappySpriteAnimation.LoadImageFromPng(AIndex: Integer; APath: string);
var
lBitmap: TPortableNetworkGraphic;
begin
lBitmap := TPortableNetworkGraphic.Create;
try
lBitmap.LoadFromFile(APath);
Images[AIndex] := TLazIntfImage.Create(0, 0);
Images[AIndex].LoadFromBitmap(lBitmap.Handle, 0);
finally
lBitmap.Free;
end;
end;
{TFallingText}
destructor TFallingText.Destroy;
begin
if Assigned(Image) then Image.Free;
inherited Destroy;
end;
procedure TFallingText.DrawToIntfImg(AIntfImage: TLazIntfImage);
begin
TTappyTuxDrawer.DrawImageWithTransparentColor(AIntfImage,
Position.X, Position.Y, colFuchsia, Bitmap);
Position.X, Position.Y, colFuchsia, Image);
end;
procedure TFallingText.DrawToCanvas(ACanvas: TCanvas);
@ -122,6 +154,20 @@ begin
inherited ExecuteFinal;
end;
procedure TFallingText.LoadImageFromPng(APath: string);
var
lBitmap: TPortableNetworkGraphic;
begin
lBitmap := TPortableNetworkGraphic.Create;
try
lBitmap.LoadFromFile(APath);
Image := TLazIntfImage.Create(0, 0);
Image.LoadFromBitmap(lBitmap.Handle, 0);
finally
lBitmap.Free;
end;
end;
{ TTappyTuxAnimation }
@ -208,7 +254,7 @@ var
X, Y: integer;
i: Integer;
lAnimation: TTappyTuxAnimation;
lStartTime, lTimeDiff: TDateTime;
lStartTime, lAnimTime, lTimeDiff: TDateTime;
begin
{$IFDEF TAPPY_PROFILER}
lStartTime := Now;
@ -224,7 +270,14 @@ begin
begin
lAnimation := TTappyTuxAnimation(FAnimationList.Items[i]);
lAnimation.CalculatePosition();
{$IFDEF TAPPY_PROFILER}
lAnimTime := Now;
{$ENDIF}
lAnimation.DrawToIntfImg(lIntfImage);
{$IFDEF TAPPY_PROFILER}
lTimeDiff := Now - lAnimTime;
WriteLn(Format('[TTappyTuxDrawer.DrawToCanvas] %s %d DrawToIntfImage Performance: %7d ms', [lAnimation.ClassName, i, DateTimeToMilliseconds(lTimeDiff)]));
{$ENDIF}
end;
lTmpBmp.LoadFromIntfImage(lIntfImage);
@ -234,9 +287,7 @@ begin
// Now TCanvas drawings
// -------------------------
// Now the module should draw itself
// Draw all animations via TLazIntfImage
// Second pass of animation drawings, now draw via TCanvas for using fonts
for i := 0 to FAnimationList.Count - 1 do
begin
lAnimation := TTappyTuxAnimation(FAnimationList.Items[i]);
@ -249,22 +300,17 @@ begin
end;
{$IFDEF TAPPY_PROFILER}
lTimeDiff := Now - lStartTime;
// DebugLn(Format('[TwebLobbyServer.DataModuleRequest] END RequestClass=%s Performance: %7d ms', [Msg.ClassName, DateTimeToMilliseconds(lTimeDiff)]));
WriteLn(Format('[TTappyTuxDrawer.DrawToCanvas] Performance: %7d ms', [DateTimeToMilliseconds(lTimeDiff)]));
{$ENDIF}
end;
class procedure TTappyTuxDrawer.DrawImageWithTransparentColor(ADest: TLazIntfImage;
const ADestX, ADestY: Integer; AColor: TFPColor; AImage: TFPImageBitmap);
const ADestX, ADestY: Integer; AColor: TFPColor; AImage: TLazIntfImage);
var
x, y, CurX, CurY: Integer;
IntfImage: TLazIntfImage;
lDrawWidth, lDrawHeight: Integer;
CurColor: TFPColor;
begin
IntfImage := TLazIntfImage.Create(0,0);
try
IntfImage.LoadFromBitmap(AImage.Handle, AImage.MaskHandle);
// Take care not to draw outside the destination area
lDrawWidth := Min(ADest.Width - ADestX, AImage.Width);
lDrawHeight := Min(ADest.Height - ADestY, AImage.Height);
@ -278,16 +324,12 @@ begin
// Never draw outside the destination
if (CurX < 0) or (CurY < 0) then Continue;
CurColor := AImage.Canvas.Colors[x, y]; // Good for debugging
if ((CurColor.Green div $FF) <> (AColor.Green div $FF)) or
((CurColor.Red div $FF) <> (AColor.Red div $FF)) or
((CurColor.Blue div $FF) <> (AColor.Blue div $FF)) then
ADest.Colors[CurX, CurY] := IntfImage.Colors[x, y];
CurColor := AImage.Colors[x, y];
if (AColor.Green <> CurColor.Green) or (AColor.Red <> CurColor.Red)
or (AColor.Blue <> CurColor.Blue) then
ADest.Colors[CurX, CurY] := CurColor;
end;
end;
finally
IntfImage.Free;
end;
end;
class function TTappyTuxDrawer.DateTimeToMilliseconds(aDateTime: TDateTime

View File

@ -16,8 +16,38 @@
<VersionInfo>
<StringTable ProductVersion=""/>
</VersionInfo>
<BuildModes Count="1">
<BuildModes Count="2">
<Item1 Name="Default" Default="True"/>
<Item2 Name="Profiler On">
<CompilerOptions>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="tappytux"/>
</Target>
<SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf2"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
<Other>
<CompilerMessages>
<UseMsgFile Value="True"/>
</CompilerMessages>
<CustomOptions Value="-dTAPPY_PROFILER"/>
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
</Item2>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
@ -97,7 +127,7 @@
</Units>
</ProjectOptions>
<CompilerOptions>
<Version Value="10"/>
<Version Value="11"/>
<PathDelim Value="\"/>
<Target>
<Filename Value="tappytux"/>
@ -107,6 +137,9 @@
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths>
<Linking>
<Debugging>
<DebugInfoType Value="dsDwarf2"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>