Delphi-PRAXiS
Seite 22 von 26   « Erste     12202122 2324     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   Andorra 2D [Ver. 0.4.5.1, 31.12.08] (https://www.delphipraxis.net/81314-andorra-2d-%5Bver-0-4-5-1-31-12-08%5D.html)

igel457 30. Dez 2008 13:24

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Liste der Anhänge anzeigen (Anzahl: 1)
Nachdem ich noch ein paar Probleme behoben habe, läuft jetzt auch die Videoplayer-Demo zum großen und ganzen untern Linux (aktuelle CVS-Version). Einzig der "Pause"-Knopf will noch nicht so, da TThread.Suspend unter Linux nicht implementiert ist. Als Beiweis habe ich einen kleinen Screenshot angehängt.

Es wird in den nächsten Tagen ein "neues" Release (sowas wie 0.4.6) geben, das einige kritische Probleme (wie zum Beispiel den Bug in der XML-Klasse) behebt.

Romi 30. Dez 2008 13:29

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Zitat:

Zitat von igel457
Es wird in den nächsten Tagen ein "neues" Release (sowas wie 0.4.6) geben, das einige kritische Probleme (wie zum Beispiel den Bug in der XML-Klasse) behebt.

Das ist schön zu hören. Was mich interessieren würde, was ist mit der Particle Engine los? Sind da einfach nur Änderungen vorgenommen worden und das Tutorial passt nicht mehr ganz darauf, oder wird da gerade gearbeitet und Sachen fehlen?

3_of_8 30. Dez 2008 13:30

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Gibt es denn keine andere Möglichkeit, den Thread anzuhalten? Ein Pause-Flag in die Klasse, das der Thread in jedem Schleifendurchlauf überprüft und nur dann weiter abspielt. wenn es False ist?

igel457 30. Dez 2008 13:40

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Zitat:

Zitat von Romi
Das ist schön zu hören. Was mich interessieren würde, was ist mit der Particle Engine los? Sind da einfach nur Änderungen vorgenommen worden und das Tutorial passt nicht mehr ganz darauf, oder wird da gerade gearbeitet und Sachen fehlen?

Ich schätze mal, dass das alles von dem Fehler in der XML-Bibliothek kommt. Ich konnte sonst noch keine Probleme mit der Partikelengine feststellen. Wenn du mal in die Demo "SimpleParticles" oder so ähnlich schaust, wirst du feststellen, dass ich auch dort die Eigenschaften des Partieklsystems verändere. Aber ich kümmere mich nochmal darum.

Zitat:

Zitat von 3_of_8
Gibt es denn keine andere Möglichkeit, den Thread anzuhalten? Ein Pause-Flag in die Klasse, das der Thread in jedem Schleifendurchlauf überprüft und nur dann weiter abspielt, wenn es False ist?

Genau das hatte ich vor. Das ist sowieso schöner, da das "Suspend" potenziell gefährlich ist.

Romi 30. Dez 2008 14:19

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Ich finds super, wie du dich um dein Projekt kümmerst. Kann man dir vllt. irgentwie helfen? Ich mache 2009 mein Abi in Englisch und Informatik, willst du vllt. die Tutorials übersetzt haben, oder sowas?

igel457 30. Dez 2008 14:52

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Das Suspend habe ich jetzt aus AdVideoTexture.pas entfernt, jetzt sollte das auch mit Linux funktionieren.

Das Particelsystem habe ich mir nochmal angeschaut, konnte aber keine Fehler entdecken.
Zitat:

Zitat von Romi
Kann man dir vllt. irgentwie helfen? Ich mache 2009 mein Abi in Englisch und Informatik, willst du vllt. die Tutorials übersetzt haben, oder sowas?

Danke für das Lob. Das Übersetzten der Tutorials wäre super! Das würde dem Projekt helfen. Wenn du damit Anfangen willst kannst du mir ja nochmal eine PN schicken oder mich im ICQ anschreiben. Die Tutorials sind übrigens in einfachem BB-Code geschrieben. Die aktuellen Tutorials gibt es auf dem Server zum herunterladen:
Z.B.: http://andorra.sourceforge.net/tutots/cvstutot1ger.bb

Ich selbst habe leider keine Zeit mich auch noch um das schreiben der Tutorials auf Englisch zu kümmern, von daher wäre das wirklich toll.

3_of_8 30. Dez 2008 15:29

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Mit den Übersetzungen hab ich auch irgendwann mal angefangen aber es dann wohl wieder vergessen... Seis drum, mir war sowieso grad langweilig, ich hab mal den verlinkten Text übersetzt, grobe Fehler dürften keine drin sein, ich habs dir mal per PN geschickt.

Im Übrigen fehlt in der deutschen Version (und daher auch in meiner Übersetzung, weil ich mir nicht sicher war, wie die Syntax für URLs ist) der Link zu TortoiseCVS.

Romi 30. Dez 2008 15:33

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Jo gut, mit dem war ich auch gerade fast fertig :-D

Wenn es okay für dich ist, werde ich das beste aus beiden Versionen nehmen.

Was mir auch aufgefallen ist, das neue ToroitseCVS sieht ganz anders aus als auf den Screenshots. Stört aber nicht wirklich, die Felder sind fast die gleichen.

Edit:
So, das wäre meine Version. Ich habe nur ein paar Dinge ausgetauscht, die sich für mich komisch angehört haben.
Zitat:

Checking out Andorra 2D with CVS

I thought having a short guidance for getting the latest version of Andorra2D would be a huge advantage, as it took me some time to figure it out. So here it is.

It's a precondition to have a CVS client which is able to fetch the files from the repository. I chose TortoiseCVS. It integrates into the Explorer's context menu and even allows creating a repository of your own. It can be found here.

After downloading and installing the application you should create an empty folder in which the files are to be stored. Open this folder and choose "checkout" in the context menu.

http://andorra.sourceforge.net/tutots/cvs1.png

Now the files for the repository are requested. These are shown in picture 2 using the example of Andorra. The username used is Anonymous and the password is empty. Thereby you only have read-only access. Only registered administrators of the project have writing privileges via SSH.

http://andorra.sourceforge.net/tutots/cvs2.png

Clicking OK starts the process. The minimal output is shown on the following picture.

http://andorra.sourceforge.net/tutots/cvs3.png

If files change now, they are shown in green colour with a U for update. That's it. If you want to bring Andorra up-to-date in the future, you only have to go to the directory and click "Update" or "Refresh CVS locally" in the context menu.

http://andorra.sourceforge.net/tutots/cvs4.png

I hope I was able to clarify some questions with this.

Greetings,
Codewalker (Thomas Hummes)
Translation by 3_of_8 (Manuel Eberl)

igel457 30. Dez 2008 16:51

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

Romi, kannst du mir den BB-Code von dem geposteten Tutorial schicken? Dann baue ich das sofort ein.

Um auf die anderen Tutorials zuzugreifen, einfach cvstut1ger.bb durch so etwas wie tut1ger.bb etc. ersetzten. Der Dateiname ist derselbe wie der im bb-Parameter des PHP-Scripts angegebene.

Bevor ich es vergesse, der Setup-Dialog läuft nun auch einwandfrei unter Linux. Hab davon auch noch einen Screenshot angehängt. Mit der aktuellen CVS-Version bin ich übrigens äußerst zufrieden: Hab das ganze einfach unter Linux als Annonymous ausgecheckt, AndorraOGL.lpi geöffnet, auf kompilieren geklickt, die erzeugte "AndorraOGLLaz.dll" zu "AndorraOGLLaz.so" umbenannt, VideoPlayer.lpi geöffnet, F9 gedrückt, fertig. Das ganze setzt natürlich voraus, dass Acinerella installiert ist. Auch der Pauseknopf funktioniert nun so, wie er soll.

3_of_8 30. Dez 2008 16:55

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Romi, könntest du mir bitte die "Dinge, die dir komisch vorgekommen sind" mitteilen? Ich arbeite immer daran, mein Englisch zu verbessern, und ich dachte zwar, dass ich keine Fehler drinhatte, aber ich kann mich natürlich auch irren.

Weil ich momentan zu viel Freizeit habe (bzw. keine Lust auf das, was ich eigentlich zu tun hätte), hab ich gleich noch das nächste übersetzt:

Andorra 2D tutorials
Part 2 - The first graphic


Introduction
In the last tutorial you have learned how to initialise Andorra 2D. The result was a black window. However, we could have achieved this with much less effort. Therefore we now continue with our sample programme - we load an image and display it.

The image list
What we need first of all is a so-called "ImageList", which conveniently stores all images that have been loaded into it.
Now we need a variable of the type "TAdImageList" which we call "AdImageList" and create in FormCreate. Note that the list may only be created after calling AdDraw.Initialize. So we continue writing below the line "Application.OnIdle := Idle":
Code:
AdImageList := TAdImageList.Create(AdDraw);
Now we want to add a image to the list. This is done by the following code:
Code:
with AdImageList.Add('image') do //A image called 'image' is added to the list.
begin
  Texture.LoadGraphicFromFile('texture.bmp'); //A image is loaded into the texture
end;
AdImageList.Restore; //To be explained later
The Imagelist's function "Add" adds a image of the type "TAdImage" with the corresponding name and returns it.

Why does this "TAdImage" now have a sub-object "Texture" again? Are an image and a texture not the same? As the following picture shows, this is not quite true in Andorra2D...
http://andorra.sourceforge.net/tutots/image.png
The image, the object we just added to the image list, that is, is merely some kind of base frame on which the texture is painted. So the "Image" or "Picture" is just a canvas whereas the texture is what is painted on it.

Now another uncertainty has to be clarified: The job of the procedure "Restore". When the image list's function "Restore" is being called, it just calls the "Restore" function of each image. Therefore the following code would do the same:
Code:
with AdImageList.Add('image') do //An image called 'image' is added to the list.
begin
  Texture.LoadGraphicFromFile('texture.bmp',false,clNone); //A texture is loaded into the image without transparency.
  Restore;
end;
However, this method is somewhat laborious when many entries are added to the image list.
Now it only has to be said what this "Restore" does. Let us remember the image mentioned earlier: The image is just the base frame on which the texture is painted. Now the base frame cannot know the size of the texture we loaded. Therefore the base frame is recreated with the appropriate size when the function "Restore" is called and according links are placed. When one forgets calling "Restore", an error message is the most likely result.


Loading the images
The texture provides the following procedure to load and save images:
Code:
procedure LoadFromStream(AStream:TStream);
procedure SaveToStream(AStream:TStream);
procedure SaveToFile(AFile:string);
procedure LoadFromFile(AFile:string);

procedure LoadGraphicFromFile(AFile:string;Transparent:boolean;TransparentColor:TColor);
procedure LoadFromGraphic(AGraphic:TGraphic);
Only the last two methods are relevant for loading graphics directly. The first few write the texture in a file format of Andorra 2D and are not suitable for loading "normal" graphic files.
"LoadFromGraphic" gets the transparency parameters directly from the loaded graphic. By default, Andorra 2D can load all standard graphics formats of the VCL - *.bmp (BItmap), *.dib (Device Independend Bitmap) and *.wmf (Windows Meta File) that is. To load other formats, appropriate loader libraries have to be added to the uses clause. These libraries add themselves to a list in "AdDraw" on initialisation. Andorra 2D can then load these formats and (if implemented accordingly) save them, too. To load PNG images, the unit "AdPNG" has to be added to the uses clause, for JPEG images the unit "AdJPEG". For loading the images, other libraries are needed in most cases. These have to be installed independently from Andorra 2D. For the PNG format the library "PNGDelphi" (http://pngdelphi.sourceforge.net/) is needed.

Rise the curtain
Now we are only a small step away from displaying our first image on the screen. The following line, which we add to the procedure "Idle" between "BeginScene" and "EndScene", does this.

Code:
AdImageList.Find('image').Draw(AdDraw,0,0,0);
Now what do these four parameters of the procedure "Draw" mean? Here AdDraw is the so-called "surface" which is the image is painted on. The next two parameters specify the position on the screen, at which the image is to be painted. The third parameters specifies the so-called "PatternIndex", which handles animations, of which more later.

Now there is not only the function "Draw" alone to draw images, this would be fairly little. The TAdImage object also provides these other procedures:
add
Code:
//Simplest method for drawing
procedure Draw(Dest:TAdDraw;X,Y,PatternIndex:integer);

//Draw an image stretched
procedure StretchDraw(Dest:TAdDraw;const DestRect:TAdRect;PatternIndex:integer);
//Draw an image stretched and with a certain alpha value (from 0 like fully transparent to 255 like completely opaque)
procedure DrawAlpha(Dest: TAdDraw; const DestRect: TAdRect; PatternIndex: Integer; Alpha: Integer);
//Draw an image stretched with additive colour blend and a certain alpha value (from 0 like fully transparent to 255 like completely opaque)
procedure DrawAdd(Dest: TAdDraw; const DestRect: TAdRect; PatternIndex: Integer; Alpha: Integer);
//Draw a stretched image completely black and with a certain alpha value (from 0 like fully transparent to 255 like completely opaque)
procedure DrawMask(Dest: TAdDraw; const DestRect: TAdRect; PatternIndex: Integer; Alpha: Integer);

//Draw an image rotated. Angle is a value from 0 to 360 degrees. CenterX and CenterY denote the centre of the rotation. The two values range from 0 to 1, so 0.5 and 0.5 are exactly the centre of an image.
procedure DrawRotate(Dest: TAdDraw; X, Y, Width, Height: Integer; PatternIndex: Integer; CenterX, CenterY: Double; Angle: Integer);
procedure DrawRotateAdd(Dest: TAdDraw; X, Y, Width, Height: Integer; PatternIndex: Integer; CenterX, CenterY: Double; Angle: Integer; Alpha: Integer);
procedure DrawRotateAlpha(Dest: TAdDraw; X, Y, Width, Height: Integer; PatternIndex: Integer; CenterX, CenterY: Double; Angle: Integer; Alpha: Integer);
procedure DrawRotateMask(Dest: TAdDraw; X, Y, Width, Height: Integer; PatternIndex: Integer; CenterX, CenterY: Double; Angle: Integer; Alpha: Integer);

//Similar to StretchBlt from the Windows GDI. Draws a certain part of the image magnified or downscaled.
procedure DrawEx(Dest:TAdDraw; SourceRect,DestRect:TAdRect;CenterX,CenterY:integer;Angle:Integer;Alpha:Integer;BlendMode:TAd2dBlendMode);
A more detailed description can be found in the documentation:
http://andorra.sourceforge.net/docs/...stomImage.html

You best try these methods on our sample image. However, I will explain some of them in the tutorials. As you might have noticed, Andorra 2D uses its own types such as "TAdRect", which are located in the unit "AdTypes". Therefore the VCL unit "Types" and "Windows" do not have to be used.


Fullscreen
Many games run fullscreen. You can also easily set it up in Andorra 2D. FOr this you only have to navigate to the "OnCreate" method of Form1. Add the following lines before "AdDraw.Initialize":
Code:
with AdDraw.Display do
begin
  Width := 800;
  Height := 600;
  BitDepth := ad32Bit; //The colour depth. The values "ad16Bit" and "ad32Bit" are allowed here.
  DisplayMode := dmFullscreen;
end;
Note that the graphic output of the AdDraw has to be on a TForm or the fullscreen display will not work.

And now your Andorra 2D application already runs fullscreen. However, you have to ensure that both your monitor and your graphics card support the specified resolution. There is a minor trick with which you can achieve fullscreen without having to change the resolution. Instead of the above lines just write:
Code:
BorderStyle := bsNone;
Top := 0;
Left := 0;
Width := Screen.Width;
Height := Screen.Height;
With this only the size of your form is changed.

Important: With the first method, it is tried to run the programme in a real overlay fullscreen mode. This means that the graphics output is a great deal faster because control elements of other applications are not drawn anymore. With the second method the window only covers all the others, so not as many FPS can be reached.

Movements and animations
You best delete all changes from the programme which you have made in this tutorial thus far.

Now we want to have an animated figure run across the screen. As soon as it has reached one edge of the screen, it should run back on an arbitrary Y position.
For this we first need the image of the animated figure - which looks like this:
http://andorra.sourceforge.net/tutots/pattern.png
As we see, this image is effectively constructed like a filmstrip. To show a part of the animated, only a part of the texture is drawn.
You might wonder why we don't have a separate image file for each step of the animation now, (also called frame or pattern) but this would simply be inefficient because it is better for the graphics card to manage one texture the size of 512x512 than many small ones the size of 128x128.

The image of the figure can be downloaded here. By the way, it originates from Reiner's Tilesets. You can find many figures, objects and a lot more for use in 2D games there.

First we have to load the image with the animations into the engine. This is done almost like we did before:
Code:
AdImageList := TAdImageList.Create(AdDraw);
with AdImageList.Add('figure') do
begin
  Texture.LoadGraphicFromFile('boy.bmp',true,clFuchsia); //This time the image is loaded transparently
  PatternWidth := 96;
  PatternHeight := 96;
end;
AdImageList.Restore;
With PatternWidth and PatternHeight the height and width of a frame are set, in our case to 96. By calling the "Restore" instruction, Andorra 2D creates some kind of map on which stores the number and position of each frame. In fact, Andorra counts from left to right and then from up to down. Also, the numbering starts from zero, as shown on the picture above.

If you now want to draw a single frame from the animation, the "PatternIndex" of the drawing function comes into play. Here you can simply specify the number of the frame and it is drawn.

But we wanted to have the figure run across the screen, so we take care of the animation first. For this we need a variable of the type Single or Double. You will see later why it cannot just be a simple Integer. So we add a variable "Pattern" to the variable declarations in the interface clause of the programme so that the line looks vaguely like this:
Code:
var
  Form1: TForm1;
  Pattern:single;
In "Idle" we now increment Pattern in each step and redraw the figure afterwards. We also have to check if the pattern exceeds the pattern number as the case may be and reset it to zero if it does.
Code:
Pattern := Pattern + 1;
if Pattern >= AdImageList.Items[0].PatternCount-1 then Pattern := 0;
AdImageList.Items[0].Draw(AdDraw,0,0,round(Pattern));
However, upon executing one can see that the animations happens far too fast. The rendering loop is executed up to 5000 times in a second and the pattern is therefore incremented by 5000. Of course, instead of +1 we could now write +0.001, for example, which would cause the animation to run more slowly. However, we then have to problem addressed in the first tutorial, the animation does not run at the same speed on every PC. To avoid this problem, there is another object in Andorra 2D: The so-called "TAdPerformanceCounter" which can be found in the unit "AdPerformanceCounter". So we declare a new variable of the type "TAdPerformanceCounter" called "AdPerCounter", create an instance of the class in "FormCreate" and free it again in FormDestroy as we have done it with all the other objects, too.
We now write "AdPerCounter.Calculate" fairly at the beginning of the "Idle" procedure. With this, the object calculates the lapse of time between procedure runs, apart from that the well-known FPS (frames per second), which you might know from some games and which are an importand performance indicator, are calculated. With the elapsed time in milliseconds, which is stored in the variable "AdPerCounter.TimeGap", we can now create an animation which runs at the same speed on almost all PCs in the world, like this:
Code:
AdPerCounter.Calculate;
Pattern := Pattern + 15 * (AdPerCounter.TimeGap / 1000);
15 is the number of frames per second with which the animation runs here. Upon executing the animation should now run nicely slowly and at an equal speed on every computer.

It was our goal to move the figure across the screen. But apart from being animated nicely now, it lacks movement. Now we first need a handful of new variables, which we declare near the others:
Code:
StartPt,EndPt:integer; //The animation's start and end pattern
Y,X:single; //The figures X and Y position
XSpeed:single; //The velocity in X direction
To move the figure we have to extend the "Draw" routine a bit.
Code:
AdImageList.Find('figure').Draw(AdDraw,round(X),round(Y),round(Pattern));
Now the figure is drawn at the position X and Y. To move it, we write the following above the drawing function:
Code:
X := X + XSpeed * (AdPerCounter.TimeGap / 1000);
Furthermore the animation should only range from "StartPt" to "EndPt", which is why we modify the if statement a bit:
Code:
if Pattern >= EndPt then Pattern := StartPt;
Now we just need a procedure to handle the figure's change of direction. We call it "SetLine", because the figure's Y position is also changed. "SetLine" should be declared within TForm1.
Code:
procedure TForm1.SetLine;
begin
  //Reverse the direction
  XSpeed := -XSpeed;
 
  if XSpeed > 0 then
  begin
    StartPt := 0;
    EndPt := 7;
    X := -96;
  end
  else
  begin
    StartPt := 8;
    EndPt := 15;
    X := ClientWidth+96;
  end;
 
  //Set the Y position
  Y := Random(ClientHeight-96);
end;
Apart from that we need the following line in the "Idle" procedure to call the procedure when the figure leaves the edge of the screen:
Code:
if ((X > ClientWidth) and (XSpeed > 0)) or
   ((X < -96) and (XSpeed < 0)) then SetLine;
Now we only have to set the XSpeed and call the procedure "SetLine" for the first time in "FormCreate":
Code:
XSpeed := -150;
SetLine;
And now our figure runs across the screen upon execution.

The source code
As always, the source code as a reference:

Code:
unit Main;

interface

uses
  Windows, Dialogs, SysUtils, Graphics, Classes, Forms, AdDraws, AdClasses, AdTypes,
  AdPerformanceCounter;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    AdDraw:TAdDraw;
    AdPerCounter:TAdPerformanceCounter;
    AdImageList:TAdImageList;
    procedure Idle(Sender:TObject;var Done:boolean);
    procedure SetLine;
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  Pattern:single;
  StartPt,EndPt:integer;
  Y,X:single;
  XSpeed:single;

implementation

{$R *.dfm}

procedure TForm1.SetLine;
begin
  XSpeed := -XSpeed;
  if XSpeed > 0 then
  begin
    StartPt := 0;
    EndPt := 7;
    X := -96;
  end
  else
  begin
    StartPt := 8;
    EndPt := 15;
    X := ClientWidth+96;
  end;
  Y := Random(ClientHeight-96);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  ReportMemoryLeaksOnShutdown := true;
  AdPerCounter := TPerformanceCounter.Create;

  AdDraw := TAdDraw.Create(self);
  AdDraw.DllName := 'AndorraDX93D.dll';

  if AdDraw.Initialize then
  begin
    Application.OnIdle := Idle;
    AdImageList := TAdImageList.Create(AdDraw);
    with AdImageList.Add('figure') do
    begin
      Texture.LoadGraphicFromFile('boy.bmp',true,clFuchsia);
      PatternWidth := 96;
      PatternHeight := 96;
    end;
    AdImageList.Restore;

    XSpeed := -150;

    Randomize;
    SetLine;
  end
  else
  begin
    ShowMessage('Error while initializing Andorra 2D. Try to use another display '+
                'mode or another video adapter.');
    Close;
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  AdImageList.Free;
  AdPerCounter.Free;
  AdDraw.Free;
end;

procedure TForm1.Idle(Sender: TObject; var Done: boolean);
begin
  if AdDraw.CanDraw then
  begin
    AdPerCounter.Calculate;
    Caption := 'FPS:'+inttostr(AdPerCounter.FPS);

    Pattern := Pattern + 15*AdPerCounter.TimeGap/1000;
    if Pattern >= EndPt then Pattern := StartPt;

    X := X + XSpeed*AdPerCounter.TimeGap/1000;
    if ((X > ClientWidth) and (XSpeed > 0)) or
       ((X < -96) and (XSpeed < 0)) then SetLine;


    AdDraw.ClearSurface(clBlack);
    AdDraw.BeginScene;

    AdImageList.Find('figure').Draw(AdDraw, round(X), round(Y), round(Pattern));
    AdDraw.EndScene;
    AdDraw.Flip;

    Done := false;
  end;
end;

end.
Conclusion
Now we already have created an animated figure, but the whole thing still was fairly pedestrian. Because of that we will take a look at the a solution integrated into Andorra 2D in the following tutorials: The so-called SpriteEngine. With its help one can programme all kinds of games without much effort.

Copyright and licence
(c) by Andreas Stöckel January 2007
Translation by 3_of_8 (Manuel Eberl)

Revision 2: October 2007
Revision 3: December 2007

The content of this tutorial is subject to the GNU Licence for free documentation.

Neutral General 30. Dez 2008 17:03

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Hi,

Grad nur 2 Sachen die mir in den ersten paar Zeilen deiner Übersetzung aufgefallen sind:

1.
Zitat:

we load an image and display it.
2.
Zitat:

Are an image and a texture not the same?
Bin mir da nicht sicher.. Es klingt komisch. Weiß aber auf Anhieb auch nichts Gutes.

igel457 30. Dez 2008 17:04

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Wie gesagt, es wäre super, wenn ihr den BB-Code anhängen könntet, damit ich davon was habe. Ich kann leider eure Posts nicht editieren und den BB-Code kopieren.

Aber schonmal Danke! :thumb:

Matze 30. Dez 2008 17:05

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
OT: Dann zitiere ihn doch. ;)

igel457 30. Dez 2008 17:22

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Zitat:

Zitat von Matze
OT: Dann zitiere ihn doch. ;)

Bestechende Antwort! Daran habe ich nicht gedacht. Die Tutorials sind hochgeladen und verlinkt.

Nochmal Danke!

3_of_8 30. Dez 2008 17:55

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Ich weiß, ich weiß... zu viel Freizeit...

Zitat:

Andorra 2D GUI
Part 1 - Using the GUI system


Introduction
http://andorra.sourceforge.net/tutots/guisample.jpg
Virtually all professional games do not use the standard components that Windows offers to build up the user interface. The GUI system should be adapted to the game after all - a simulation of the middle ages does certainly not benefit from higgledy-piggledy Windows XP buttons. Also, it is difficult to display the standard components in a hardware-accelerated way. To give you the possibility of creating consistent GUIs which are fully integrated into your game, Andorra 2D provides a fairly powerful and in most cases sufficient GUI system. This can easily be extended with self-made components and is also fully skinnable.
Please note: Writing such a GUI system is very time-consuming, which is why its development is currently suspended. If you have created new components on your own or wish to extend the system, please send me an e-mail.


Preparations
First you have to create a GUI in the supplied GUI editor, which works in a similar way to Delphi. In the process you should save each form as a separate GUI file. (*.axg, Andorra XML GUI)
Skins can also be created with the supplied skin editor which, however, is still somewhat complicated at the moment. Anyhow, the supplied skin file "sunna.axs" can be modified to achieve the same result.
Apart from that, an Andorra GUI needs a cursor definition file. For this, create an image list with the according cursors with the image list editor and write a simple XML file according to the following example, in which you refer to the individual entries:
Delphi-Quellcode:
<?xml version="1.0" encoding="iso-8859-1"?>
  <set>
    <images source="cursors.ail"/>
    <cursor name="default" src="default">
      <hotspot x="0" y="0"/>
    </cursor>
    <cursor name="wait" src="wait">
      <hotspot x="6" y="11"/>
      <anim start="0" stop="7" speed="25"/>
    </cursor>
    <cursor name="cross" src="cross">
      <hotspot x="8" y="8"/>
    </cursor>  
  </set>

Integration
To use the GUI in a programme now, we first need some units:
The base frame of all GUI components is located in "AdGUI" as well as the implementation of the cursors and the GUI manager. It is important to include the unit "AdComponents", if you use the supplied components. The reason for this is that with including the unit, the corresponding components are registered in the GUI system. If the file is not included, an error message is displayed because the specified components are not registered and therefore cannot be found.
First of all we need an instance of the class "TAdGUI", which takes care of loading, saving, skins and cursors automatically.
Delphi-Quellcode:
AdGUI := TAdGUI.Create(AdDraw); //Instantiating the class
AdGUI.Skin.LoadFromFile('sunna.axs'); //Loading the skin
AdGUI.Cursors.LoadFromFile('cursors.xml'); //Loading the cursor
AdGUI.LoadFromFile('gui.axg'); //Loading the GUI
Important: Commonly made mistakes
- Forgetting the unit "AdComponents"
- Forgetting to include a PNG loader (such as AdPNG, AdDevIL or AdFreeImage), because the standard skin "Sunna" uses the format PNG to save the data.

Of course, "AdGUI" has to be freed in the end. One only has to call the method
Delphi-Quellcode:
AdGUI.Update
in the game loop.
Technically, these steps should suffice to display the GUI. However, the emphasis lies on "display" - one can hit the mouse button as hard as one likes, nothing happens. Why would it? After all, mouse and keyboard events have to be passed on to the GUI system first. There are two possibilities for doing this. The first one is the easier one which should be enough in most cases.
We use the class "TAdGUIConnector" from the unit "AdGUIConnector". This loops the events of the AdDraw parent window system through the GUI system. For this, the following steps are necessary:
Delphi-Quellcode:
AdConnector := TAdGUIConnector.Create(AdGUI); //Creating the GUI connector
AdConnector.ConnectEventHandlers(AdDraw.Window); //Linking it to the parent window system
The GUI connector should also be freed upon terminating the programme.
But the GUI connector (still) has a few flaws: One can only link the events to a component of the class "TForm" - if the AdDraw is on a panel, the events have to be passed on manually.
However, this method is not that bad and also has another inherent advantage: Imagine a construction game, in which freely movable windows are on the screen. How can the game know if we clicked on the window or on the game field? Not a problem with the manual linking!
Delphi-Quellcode:
procedure Form1Click(Sender:TObject)
var
  p:TPoint;
begin
  GetCursorPos(p); //Read current cursor position
  p := ScreenToClient(p); //Convert to form-relative coordinates
  if not AdGUI.Click(p.X, p.Y) then //Execute event handling
  begin
   //The game field was clicked
  end;
end;
At this, the "Click" method of the GUI system is simply called, which recursively calls the click methods of all the other elements. When it is detected that the click was indeed on a control element, the "Click" method returns "true".
This works analogously with every other event handler.


Accessing control elements
Now it would be highly convenient if we could access the elements created in the editor in our programme somehow. In the editor, the elements are assigned a name which is stored in the property "Name" - just like in Delphi. The method "FindComponent" of TAdGUI returns the wanted element when given the corresponding name. To access component-specific properties, we only have to cast the result to the according component class.
Delphi-Quellcode:
TAdButton(AdGUI.FindComponent('AdButton1')).Caption := 'Hello!';

Control element events
Our GUI system is still fairly inanimate - we do not react to events such as clicks at all yet.
For that we can simply link procedures to events such as "OnClick". We have to create a procedure that has exactly the same parameters as the event procedure. These can be found out in the code completion. Please note that the declared procedure has to be part of a class. Example:
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    [...]
  private
    procedure AdButtonClick(Sender:TObject);
  public
    [...]
end;

[...]

procedure TForm1.AdButtonClick(Sender:TObject);
begin
  TAdButton(AdGUI.FindComponent('AdButton1')).Caption := 'You clicked me!!';
end;

procedure TForm1.FormCreate(Sender:TObject);
begin
  //Initialise Andorra 2D
  [...]
  //Load GUI
  [...]

  //Assign events
  TAdButton(AdGUI.FindComponent('AdButton1')).OnClick := AdButtonClick;
end;
By the way, this works the same way in the VCL.

Customised components
To create customised components, derive a class from "TAdComponent" and register it in the "initialization" clause of the unit. Along the lines of "Code is worth a thousand words" you best learn how this works by reading the unit "AdComponents". To use your creations in the editor, you have to include the corresponding class there, too.

Extend code with a loaded GUI
Calling "LoadFromFile" usually replaces the whole GUI - this can be avoided with the following code. Please note that you have to include the unit "AdSimpleXML" additionally.
Delphi-Quellcode:
procedure ExpandGUI(afile: string);
var
  elems:TAdSimpleXMLElems;
  xml:TAdSimpleXML;
  j:integer;
  cref:TPersistentClass;

  function SearchFirst(elem:TAdSimpleXMLElem):TAdSimpleXMLElems;
  var
    i:integer;
  begin
    result := nil;
    for i := 0 to elem.Items.Count - 1 do
    begin
      if elem.Items[i].Name <> 'TAdGUI' then
      begin
        result := elem.Items;
        exit;
      end
      else
      begin
        result := SearchFirst(elem.Items[i]);
        if result <> nil then
        begin
          exit;
        end;
      end;
    end;
  end;

begin
  xml := TAdSimpleXML.Create;
  xml.LoadFromFile(afile);
  elems := SearchFirst(xml.Root);
  if elems <> nil then
  begin
    for j := 0 to elems.Count - 1 do
    begin
      cref := GetClass(elems.Item[j].Name);
      if cref <> nil then
      begin
        with TAdComponent(TAdComponentClass(cref).Create(AdGUI)) do
        begin
          LoadFromXML(elems.Item[j]);
        end;
      end;
    end;
  end;
  xml.Free;
end;
Conclusion
This information should help you deal with the GUI system. It is most important to take a look at the properties of the components. Don't be afraid to take a look at the implementation of a component - then emerging questions usually sort themselves out. After all, this is fairly easy in Delphi but also in Lazarus: If you click on an identifier while pressing the CTRL key, you automatically navigate to its declaration.

Copyright and licence
(c) by Andreas Stöckel November 2007
Translation by 3_of_8 (Manuel Eberl)

The content of this tutorial is subject to the
GNU Licence for Free Documentation

Romi 30. Dez 2008 18:12

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Zitat:

Romi, könntest du mir bitte die "Dinge, die dir komisch vorgekommen sind" mitteilen? Ich arbeite immer daran, mein Englisch zu verbessern, und ich dachte zwar, dass ich keine Fehler drinhatte, aber ich kann mich natürlich auch irren.
Eigentlich musst du ja nur meinen mit deinem Text vergleichen, oder was genau meinst du? ;)

Zitat:

Weil ich momentan zu viel Freizeit habe (bzw. keine Lust auf das, was ich eigentlich zu tun hätte), hab ich gleich noch das nächste übersetzt:
Mist. Damit hatte ich auch schon angefangen (und war ca 50% fertig), und dann musste ich bis gerade weg. Wir sollten uns absprechen :-D

Hier noch ein paar Vorschläge:
Zitat:

What we need first of all is a so-called "ImageList"
First of all we need a so-called "ImageList"

Zitat:

and create in FormCreate.
and is created in FormCreate.

Zitat:

The Imagelist's function "Add" adds a image
an Image

Zitat:

Why does this "TAdImage" now have a sub-object "Texture" again?
Ich finde, den Satz kann man nicht direkt übersetzen. Mein Vorschlag:
What is the property "Texture" of "TAdImage"? An image and a texture are the same, aren't they?
The following picture will show you that they're not (at least for Andorra 2D):

Zitat:

The image, the object we just added to the image list, that is, is merely some kind of base frame on which the texture is painted.
The image (the object we just added to the image list) is merely some kind of base frame on which the texture is painted.

Zitat:

The job of the procedure "Restore". When the image list's function "Restore" is being called, it just calls the "restore" function of each image.
The assignment of the procedure "Restore". When the image list's function "Restore" is being called, it just calls the "restore" function of each of it's images.

Zitat:

However, this method is somewhat laborious when many entries are added to the image list.
But this method is a bit circumstantial when adding a lot of images to the list.

Zitat:

Now it only has to be said what this "Restore" does.
The last thing to address is what exactly this "restore"-funtcion does.

Zitat:

When one forgets calling "Restore", an error message is the most likely result.
If you forget to call the "restore"-function you will probably end with an error.

Zitat:

of the VCL - *.bmp (BItmap), *.dib (Device Independend Bitmap) and *.wmf (Windows Meta File) that is.
of the VCL - namely *.bmp (BItmap), *.dib (Device Independend Bitmap) and *.wmf (Windows Meta File).

Zitat:

These libraries add themselves to a list on initialisation.
This libraries will add themselves to a list in the unit AdDraw.

Zitat:

For loading the images, other libraries are needed mostly.
For loading the images, other libraries are needed.


So weit war ich.

3_of_8 30. Dez 2008 18:14

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Ich hab absichtlich das letzte genommen, weil ich vermutet habe, dass du mit dem nächsten weitermachst. :mrgreen:

Und, ja, ich habe verglichen, verstehe aber nicht so ganz, was daran seltsam klingt.

Romi 30. Dez 2008 18:29

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Zitat:

Zitat von 3_of_8
Ich hab absichtlich das letzte genommen, weil ich vermutet habe, dass du mit dem nächsten weitermachst. :mrgreen:

Und, ja, ich habe verglichen, verstehe aber nicht so ganz, was daran seltsam klingt.

Ich habe oben noch ein paar Dinge dazugeschrieben. Kannst du dir ja überlegen, ob du sie übernimmst ;)

Ich mache übrigens gerade das Tutorial zur Spriteengine. Also lass da die Finger von :-D

3_of_8 30. Dez 2008 20:18

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Zitat:

What we need first of all is a so-called "ImageList"
First of all we need a so-called "ImageList"
Geht beides.

Zitat:

and create in FormCreate.
and is created in FormCreate.
Der Rest des Satzes ist auch im Aktiv, Subjekt ist "we". Warum also hier Passiv?

Zitat:

The Imagelist's function "Add" adds a image
an Image
Schon gefixt, dank Neutral General

Zitat:

Why does this "TAdImage" now have a sub-object "Texture" again? [Are an image and a texture not the same? As the following picture shows, this is not quite true in Andorra2D...]
Ich finde, den Satz kann man nicht direkt übersetzen. Mein Vorschlag:
What is the property "Texture" of "TAdImage"? An image and a texture are the same, aren't they?
The following picture will show you that they're not (at least for Andorra 2D):
Nach Auskunft einer Engländerin versteht sie beides nicht wirklich, aber es sind keine Fehler drin.

Zitat:

The image, the object we just added to the image list, that is, is merely some kind of base frame on which the texture is painted.
The image (the object we just added to the image list) is merely some kind of base frame on which the texture is painted.
Also ob da jetzt ne Klammer is oder ein Einschub, das dürfte doch relativ egal sein.

Zitat:

The job of the procedure "Restore". When the image list's function "Restore" is being called, it just calls the "restore" function of each image.
The assignment of the procedure "Restore". When the image list's function "Restore" is being called, it just calls the "restore" function of each of it's images.
"assignment" klingt irgendwie mehr so nach "Mission, Auftrag".

Zitat:

However, this method is somewhat laborious when many entries are added to the image list.
But this method is a bit circumstantial when adding a lot of images to the list.
Wo ist das Problem mit "However", "laborious" und dem Rest der geänderten sachen?

Zitat:

Now it only has to be said what this "Restore" does.
The last thing to address is what exactly this "restore"-funtcion [sic!] does.
Korrektur: The last thing to address is what exactly this "Restore" function does.
("Restore" ist auch im Source großgeschrieben, IIRC, daher auch hier groß, weil Zitat, Bindestrich weg, ansonsten klingt das in der Tat besser als mein Satz)
Jop, übernehm ich in Korrektur.

Zitat:

When one forgets calling "Restore", an error message is the most likely result.
If you forget to call the "restore"-function you will probably end with an error.
Korrektur: [...]you will probably end up with an error.
Meine Variante ist deutlich förmlicher, ob das jetzt erwünscht ist oder nicht - keine Ahnung. Der Stil im deutschen Original schwankt ja sehr stark zwischen höflich-förmlich und kumpelhaft, und da ich recht nah am Original übersetzt habe, ist das jetzt hier wohl auch so.

Zitat:

of the VCL - *.bmp (BItmap), *.dib (Device Independend Bitmap) and *.wmf (Windows Meta File) that is.
of the VCL - namely *.bmp (BItmap), *.dib (Device Independend Bitmap) and *.wmf (Windows Meta File).
Das dürfte ziemlich äquivalent sein.

Zitat:

These libraries add themselves to a list on initialisation.
This libraries will add themselves to a list in the unit AdDraw.
Hoppala, das mit dem AdDraw habe ich tatsächlich übersehen, aber in deiner Version fehlt dafür das mit dem Programmstart.

Zitat:

For loading the images, other libraries are needed mostly.
For loading the images, other libraries are needed.
Meine Version klingt jetzt im Nachhinein doch etwas seltsam.

xZise 31. Dez 2008 02:05

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Ich habe mir noch nicht die neueste Version geholt, aber funktioniert es jetzt unter Delphi 2009, dass die Grafiken richtig im ImgEdit angezeigt werden?

Und unter welcher Lizenz steht Andorra 2D und der ImgEdit (ich habe mir daraus das Zeichnen der ListView geholt)?

MfG
xZise

Florian H 31. Dez 2008 02:15

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Zitat:

Zitat von xZise
Und unter welcher Lizenz steht Andorra 2D und der ImgEdit (ich habe mir daraus das Zeichnen der ListView geholt)?

Laut Webseite:
Zitat:

Andorra 2D is open source and licensed under the CPL. Because of incompatibility to the common open source license GPL you may also use Andorra 2D under the GPL or the LGPL.
CPL: http://www.opensource.org/licenses/cpl1.0.php
GPL: http://www.opensource.org/licenses/gpl-license.php
LGPL: http://www.opensource.org/licenses/lgpl-license.php

Such dir eine passende aus :stupid:

3_of_8 31. Dez 2008 10:47

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Hab das zweite Tutorial, das über die Anzeige von Bildern, nochmal leicht verbessert, basierend auf romis Vorschlägen.

igel457 31. Dez 2008 11:00

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Vielen Dank, ich aktualisiere das.

Könnte vielleicht nochmal jemand hierüber schauen:
Zitat:

Configuring Andorra 2D

Since version 0.4.5, the "src" directory contains a file named "andorra_conf.inc". This file contains all compiler switches available in Andorra 2D. This short article gives an overview over the meaning of those switches.

Using the "andorra_conf.inc"
The changes made in "src/andorra_conf.inc" are applied globally to all projects. If you don’t want this, delete the "andorra_conf.inc" from the "src" directory and create a copy for all your projects. Add this file to your project or add it to its search path. If you want to be sure whether your settings are actually used, you may activate the "TEST"-switch.

Available switches

DO_NOT_INCLUDE_STD_FORMATS
The VCL/LCL graphics format loaders, which are included by default, will be removed from your project, if you activate this switch. The unit "Graphics" will not be needed anymore, significantly decreasing the size of the executable. As a downside graphics formats like "BMP" etc. cannot be loaded anymore. To make this possible, other loaders have to be included. For example "AdBMP", "AdTGA", "AdPNG" (see below), "AdDevIL" (needs the "DevIL"-library) or "AdFreeImage" (needs the "FreeImage"-library).
Another disadvantage is that generating fonts will be disabled. To use fonts in your project, you have to generate the fonts in an external application, store them in a file and load them afterwards.

DO_NOT_INCLUDE_STD_WINDOWMGR
This switch deactivates loading the VCL/LCL window frameworks - Andorra 2D will not use the unit "Forms" anymore. Activate this compiler switch, if you are using other window frameworks like "AdGLFW", "AdSDL" or "AdWin32". If this compiler switch is activated, Andorra 2D cannot be integrated into an existing VCL/LCL application.

DO_NOT_USE_3DNOW
Deactivates the use of the 3DNow!-instruction set extension when running on AMD processors. This extension is available on AMD-Processors and increases the speed of matrix multiplication (which is used quite often in Andorra 2D). Activating the "DO_NOT_USE_ASM" switch includes this switch.

DO_NOT_USE_ASM
This switch removes any assembler code from Andorra 2D. Native pascal is used.

DO_NOT_USE_INTERNAL_PNG
The image loader unit "AdPNG" may use the external library "PNGImage" or an internal loader. The internal loader works in most cases, but still has some problems. This is why this switch is activated by default.

Copyright and license
(c) by Andreas Stöckel Dezember 2008
This tutorial is subject to the GNU Licence for Free Documentation

3_of_8 31. Dez 2008 11:19

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Ganz in Ordnung, ein paar Formulierungen klingen noch etwas holprig und ein paar mal häufen sich ein paar Wörter. Korrektur:
Zitat:

Configuring Andorra 2D

Since version 0.4.5 the "src" directory contains a file named "andorra_conf.inc", which contains all compiler switches available in Andorra 2D. This short article gives an overview over the meaning of those switches.

Using the "andorra_conf.inc"
The changes made in "src/andorra_conf.inc" are applied globally to all projects. If this is not desired, delete the "andorra_conf.inc" from the "src" directory and create a copy for all your projects. Add this file to your project or add it to its search path. If you want to be sure whether your settings are actually used, you can activate the "TEST"-switch.

Available switches

DO_NOT_INCLUDE_STD_FORMATS
The VCL/LCL graphics format loaders, which are included by default, will be removed from your project, if you activate this switch. The unit "Graphics" will not be needed anymore, which significantly decreases the size of the executable. As a downside, graphics formats like "BMP" etc. cannot be loaded anymore. To make this possible again, other loaders have to be included, such as "AdBMP", "AdTGA", "AdPNG" (see below), "AdDevIL" (requires the "DevIL"-library) or "AdFreeImage" (requires the "FreeImage"-library).
Another disadvantage is that generating fonts will be disabled. To use fonts in your project, you have to generate the fonts in an external application, store them in a file and load them afterwards.

DO_NOT_INCLUDE_STD_WINDOWMGR
This switch deactivates loading the VCL/LCL window frameworks - Andorra 2D will not use the unit "Forms" anymore. Activate this compiler switch if you are using other window frameworks such as "AdGLFW", "AdSDL" or "AdWin32". If this compiler switch is activated, Andorra 2D cannot be integrated into an existing VCL/LCL application.

DO_NOT_USE_3DNOW
Deactivates the use of the 3DNow! instruction set extension when running on AMD processors. This extension is available on AMD processors and increases the speed of matrix multiplication (which is used quite often in Andorra 2D). Activating the "DO_NOT_USE_ASM" switch includes this switch.

DO_NOT_USE_ASM
This switch removes any assembler code from Andorra 2D. Native pascal is used.

DO_NOT_USE_INTERNAL_PNG
The image loader unit "AdPNG" may use the external library "PNGImage" or an internal loader. The internal loader works in most cases, but still has some problems. This is why this switch is activated by default.

Copyright and license
(c) by Andreas Stöckel December 2008
This tutorial is subject to the GNU Licence for Free Documentation
Bei "create a copy for all your projects." war ich mir nicht ganz sicher - ist das jetzt eine Kopie für alle Projekte oder eine Kopie für jedes Projekt? Bei ersterem stimmt es so, bei letzterem wäre es "for each of your project" oder einfach "for each project".

igel457 31. Dez 2008 12:09

Re: Andorra 2D [Ver. 0.45, 24.12.08]
 
Danke, habe das abgeändert.

Romi 31. Dez 2008 15:08

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Hier die Spriteengine:
Ich wollte es noch vor Neujahr fertig haben, deshalb habe ich viel gestern Nacht gemacht. Wenn also jemand Fehler findet, dann sagt bescheidt ;)

Zitat:

Andorra 2D Tutorials
Teil 3 - The Spriteengine


Introduction
Introduction of the Introduction
Finally it's here: The (first) tutorial which will teach you how to use the Spriteengine. In this tutorial we will modify our project from the last tutorial.


What are sprites?
Sprites are objects which are (simply said) able to move independently from other objects (Check out the correspondingWikipedia Article for more information.).
In Andorra 2D, a sprite is an abstract object which is drawable, moveable and collideable. This actions are controlled by an surperior object (which actually is a sprite, too). Sprite do not have to be moveable - they can also be used to display the background.
And even more - you can write whole games using the Spriteengine.

Creating the SpriteEngine
We have used 4 units so far:
  • TAdDraw - The Andorra 2D core
  • TAdPerformanceCounter - Calculates the FPS and the "Timegap"
  • TAdImageList - Holds all the images
  • TAdImage - Manages and draws the images
In this tutorial you will learn how to use the object "TSpriteEngine". First of all, you should add the unit "AdSprites" to the uses-List of your program. Declare a new variable named "AdSpriteEngine" of the type "TSpriteEngine".
The following line of code - which should be inserted after the creation of your Imagelist - will create the SpriteEngine:
Delphi-Quellcode:
AdSpriteEngine := TSpriteEngine.Create(AdDraw);
As a matter of course you should free this object at the end of your program.

The family of sprites
Warning: If you do not know much about objectorientated programming yet, you should altercate with that first. Otherwise you may not understand everything.

As already mentioned above a sprite is not only used to draw a simple image. It is able to manage something much more abstract (the Spriteengine itself is a good example for that). Thats why there are multiple spriteclasses available. They all have something in common: They are derived from TSprite, the base-sprite-class.
  • TSprite
    • TImageSprite
      • TImageSpriteEx
    • TBackgroundSprite
    • TLightSprite
    • TParticleSprite
The baseclass is a "naked" sprite, which literally is not able to do anything but integrating itself into the Spriteengine. TImageSprite already is able to do anything we would want from a sprite: Drawing and animating. Again, TImageSpriteEx is capable of being drawn transparently and can be turned. TBackgroundSprite is (surprise!) to draw a background. TLight and TParticleSprite will be addressed later.

Go, Sprite, Go
We will now get the guy from our last tutorial running across the screen, but this time we'll use a sprite. So get your result from the last tutorial and get started!
We add the creation of the SpriteEngine and the TImageSprite with the name "figure" the initialisation routine:
Delphi-Quellcode:
.
.
AdImageList.Restore;

//create the SpriteEngine
AdSpriteEngine := TSpriteEngine.Create(nil);
AdSpriteEngine.Surface := AdDraw1;

//create TImageSprite
Figure := TImageSprite.Create(AdSpriteEngine);
with Figure do
begin
  //we'll go on here later on
end;
Do not free "Figure" at the end of your program - you would end in a mess of errors. The spriteengine frees the sprites automatically. If you want a Sprite to be free earlier you have to use it's dead routine.

We now have an "empty" sprite, without graphics or animation:
Delphi-Quellcode:
//assign a graphic to the sprite
Image := AdImageList.Find('figur');
//activate the animation
AnimActive := true;
//repeat the animation
AnimLoop := true;
//set the fps the animation should be played at
AnimSpeed := 15;
From the variables we used before (Pattern,StartPt,EndPt,Y,X,XSpeed) is only one left: XSpeed, because all the other ones are part of TImageSprite.


We will now modify the render routine:
Delphi-Quellcode:
if AdDraw.CanDraw then
begin
  AdPerCounter.Calculate;
   
  Figure.X := Figure.X + XSpeed*AdPerCounter.TimeGap/1000;
  if ((Figure.X > ClientWidth) and (XSpeed > 0)) or
     ((Figure.X < -96) and (XSpeed < 0)) then
  begin
    SetLine;
  end;


  AdDraw.ClearSurface(clBlack);
  AdDraw.BeginScene;

  //call all move-procedure of the engine
  AdSpriteEngine.Move(AdPerCounter.TimeGap / 1000);
  //draw all sprite
  AdSpriteEngine.Draw;
  //delete all sprites wich are marked as dead
  AdSpriteEngine.Dead;

  AdDraw1.EndScene;
  AdDraw1.Flip;

  Done := false;
end;
The following things have changed:
  • The part, which was responsible for the animation, has completly gone
  • Instead of modifying the value of the variable "X" directly, we now modify the X-Position
  • The drawing-routine has gone and is replaced by a routine in the spriteengine

We now have to modify the SetLine procedure a bit:
Delphi-Quellcode:
procedure TForm1.SetLine;
begin
  XSpeed := -XSpeed;
  if XSpeed > 0 then
  begin
    Figure.AnimStart := 0;
    Figure.AnimStop := 7;
    Figure.X := -96;
  end
  else
  begin
    Figure.AnimStart := 8;
    Figure.AnimStop := 15;
    Figure.X := ClientWidth+96;
  end;
  Figure.Y := Random(ClientHeight-96);
end;
The changes made in this part should be clearly understandable.

And now our figure runs across the screen.

Our own spriteclass
Looking at the solution we have so far we have to admit that it is more or less suboptimal. Wouldn't it be better to have a Spriteclass that does all the movement for us? It would be no problem to have several figures moving independently from each other.

Actually this is possible - thats what the spriteengine is for.
So lets declare a class which is derived from TImageSprite or TImageSpriteEx (just as you like). The declaration should take place above the one of TForm1.
Delphi-Quellcode:
type
  TFigure = class(TImageSprite)
    private
    protected
      procedure DoMove(TimeGap:double);override;
    public
      XSpeed:integer;
      constructor Create(AParent:TSprite);override;
      procedure SetLine;
  end;
DoMove, DoDraw...
Lets have a look at what we have so far:
The "public"-part now has a variable named "XSpeed" - which is the same as our previously globally declared "XSpeed" (which should be deleted by the way...).
The procedure SetLine hat now become part of our sprite, too. Again theres an overwritten constructor.
Now we have nearly everthing which belongs to our figure stored in its' own class. But where is the code that cares about the movement? That's what we have "DoMove" for. Andorra 2D provides a set of those "Do"-Methods:
Delphi-Quellcode:
//this is where the movement takes place
procedure DoMove(TimeGap:double);
//this is where we store our code for collisions (later)
procedure DoCollision(Sprite:TSprite; var Done:boolean);
//this is where we the drawing is done (even later ;) )
procedure DoDraw;
Now we have the base frame of a new class called "TFigure". Thats why the variable "Figure" can now be of the type "TFigure".
The only thing left is the implementaion:
Delphi-Quellcode:
{ TFigure }

constructor TFigure.Create(AParent: TSprite);
begin
  inherited;
  //Start at (0;0)
  X := 0;
  Y := 0;
 
  //Set XSpeed to -150
  XSpeed := -150;
end;

procedure TFigure.DoMove(TimeGap: double);
begin
  inherited;

  //the part from the render-procedure
  X := X + XSpeed*TimeGap;
  if ((X > Engine.SurfaceRect.Right) and (XSpeed > 0)) or
     ((X < -96) and (XSpeed < 0)) then
  begin
    SetLine;
  end;
end;

procedure TFigure.SetLine;
begin
  //moves the figure to a new layer
  XSpeed := -XSpeed;
  if XSpeed > 0 then
  begin
    AnimStart := 0;
    AnimStop := 7;
    X := -96;
  end
  else
  begin
    AnimStart := 8;
    AnimStop := 15;
    X := Engine.SurfaceRect.Right+96;
  end;
  Y := Random(Engine.SurfaceRect.Right-96);
end;
We have to change the code in FormCreate to correspond to our new changes. The following Code has to be replaced:
Delphi-Quellcode:
Figure := TImageSprite.Create(AdSpriteEngine);
.
.
Delphi-Quellcode:
Figure := TFigure.Create(AdSpriteEngine);
with Figure do
begin
  Image := AdImageList1.Find('figure');
  AnimActive := true;
  AnimLoop := true;
  AnimSpeed := 15;
  XSpeed := -150;
  SetLine;
end;
Marathon
Lets have more than one figure running across the screen. Delete the declaration of Figure and replace it by the following code:
Delphi-Quellcode:
for i := 0 to 5 do
begin
  with TFigure.Create(AdSpriteEngine) do
  begin
    Image := AdImageList1.Find('figure');
    AnimActive := true;
    AnimLoop := true;
    AnimSpeed := 15;
    XSpeed := -(random(100)+50);
    SetLine;
  end;
end;
Yet six manikin with different speeds run across the screen.

The whole sourcecode is available at:hier.

Homework
You did it until here. But now I'm having a few assignments for you:
  • It is possible that some Figures are displayed over another one although it should be behind it. Remove this error! Hint: The class TSprite has a variable "Z" which is to define its position according to the background.
  • All figures look the same. Include a few more graphics!

If you have any questions, feel free to contact me at:E-Mail.

Conclusion
You're now able to deal with the spriteengine. The next tutorial will deal with an old DelphiX-demo, in which you move as a ball through a world peopled with other balls. Certainly, we will "upgrade" it a bit.
The last thing I wanted to notice is that I didn't invent the spriteengine. It's a reproduction of the spriteengine of DelphiX - although it has been enhanced.


Copyright und Lizenz
(c) by Andreas Stöckel März 2007

Revision 2: Oktober 2007

This tutorial is licenced under the GNU Free Documentation License

igel457 31. Dez 2008 15:27

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
@Romi: Vielen Dank, ich baue das ein.

Übrigens: Ich habe das versprochene Bugfixrelease 0.4.5.1 hochgeladen.

Die wichtigste Änderung ist, dass die XML-Bibliothek nun keine Dateien mehr unbenutzbar macht.

Romi 31. Dez 2008 15:37

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Zitat:

Zitat von igel457
Übrigens: Ich habe das versprochene Bugfixrelease 0.4.5.1 hochgeladen.

Die wichtigste Änderung ist, dass die XML-Bibliothek nun keine Dateien mehr unbenutzbar macht.

Also ich habe die jetzt getestet. Und irgentwie hat das DefaultParticle immer noch keine "LifeTime" Eigenschaft, obwohl das im Tutorial ausdrücklich erwähnt wird.

Oder bin ich einfach nur blind? :-D

igel457 31. Dez 2008 15:40

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Hast du DefaultParticle auch entsprechend gecastet? Schau dir mal die SimpleParticle Demo an. Standardmäßig ist default Partikel vom Typ "TAdStdParticle":
Delphi-Quellcode:
with partengine.DefaultParticle as TAdStdParticle do
  LifeTime := 0.5;

3_of_8 31. Dez 2008 16:40

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Romi: sprite engine, nicht Spriteengine, außerdem hast du vergessen, "hier" zu übersetzen und auch steht da noch "Copyright und Lizenz" ganz unten. Genauer hab ichs mir jetzt ned durchgesehen.

xZise 1. Jan 2009 14:30

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Neben den ganzen Übersetzungen habe ich die Unit AdSprites erweitert. Und zwar ist es ja nicht sinnvoll in einer Engine nach Sprites zu suchen, sondern direkt in der Liste (so kann diese Funktionalität auch in Abkömmlingen verwendet werden). Deshalb habe ich der Klasse TSpriteList "GetSpritesAt" verpasst:
Delphi-Quellcode:
procedure TSpriteList.GetSpritesAt(ASpriteList: TSpriteList; const AX,
  AY: Integer; const ASpriteClass: TSpriteClass);
var
  i : Integer;
  Rect : TAdRect;
begin
  if Assigned(ASpriteList) then
  begin
    ASpriteList.Clear; // Standard ?
    for i := 0 to Count - 1 do
    begin
      Rect := Items[i].BoundsRect;
      if (AX >= Rect.Left) and (AX <= Rect.Right) and
         (AY >= Rect.Top) and (AY <= Rect.Bottom) and
         (Items[i] is ASpriteClass) then
      begin
        ASpriteList.Add(Items[i]);
      end;
    end;
  end;
end;
Und dann das in der Engine dahingehend abgeändert, dass es wie ".Clear" bei einer ListView arbeitet indem es einfach das der Liste aufruft:
Delphi-Quellcode:
procedure TSprite.GetSpritesAt(const AX, AY: Integer; ASprites: TSpriteList;
  AClass: TSpriteClass);
begin
  Items.GetSpritesAt(ASprites, AX, AY, AClass);
end;
Da die andere Methode diese Aufruft muss diese nicht geändert werden.

MfG
xZise

PS: Diese Funktion basiert noch auf 0.4.5 (ich hoffe da gabs keine Änderung die dies nicht möglich machen).
PPS: Danke für die Lizenzinformationen.

igel457 1. Jan 2009 14:41

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Ähm... Das hast du mir doch schonmal geschickt, und ich habe es schon längst eingebaut. Das ist schon in dem 0.4.5.1 Release.

xZise 1. Jan 2009 14:45

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Ehm nein ^^ Davor war es eine Funktion der Klasse TSprite jetzt ist es eine der Klasse TSpriteList und TSprite ruft die der TSpriteList auf ;)

MfG
xZise

inherited 1. Jan 2009 18:29

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Es ist die Frage ob man wirklich auf Assigned prüfen sollte am Anfang. Wenn man eine nicht valide Liste übergibt würde ich erwartten, dass eine Exception geschmissen wird und nicht einfach nur nichts passiert.

xZise 1. Jan 2009 21:28

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Hmm stimmt, das wäre tatsächlich besser und nachher hilfreicher. Kann Igel ja ändern ;)

Und in welchen Format speichert AdBitmap.SaveToFile die Datei ab? Ich wollte nämlich mal gucken woran es liegt, das unter Delphi 2009 der ImageListEditor nicht funktioniert (also die Vorschau anzeige in der ListView nicht mit Transparenzen umgehen kann). Kann es sein, dass es sich um ein von dir entwickeltes Format handelt? Wie kann ich das Umstellen?

Zu der Änderung im obigen Sourcecode: Statt Items.Count wird nur Count aufgerufen. Außerdem ist zu beachten, dass einige Parameter umbenannt wurden ;)

Und eine Frage zur Lizenz: Ist es mir dann auch möglich das Programm unter BY-NC-SA zu stellen? (Ich habe Sourcecodeteile aus deinem ImageEditor verwendet).

MfG
xZise

Florian H 1. Jan 2009 23:35

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Aloha igel,

ich wollte jetzt eigentlich mal das TAdTextureSurface benutzen, um statische Dinge nicht in jedem Zeichenschritt zeichnen zu müssen ... allerdings gibt es ein Problem: Das Ganze funktioniert nur mit dem OpenGL-Plugin.

Wenn ich das DirectX-Plugin verwende, sehe ich im AdDraw nicht, was ich aufs TextureSurface und anschließend von diesem auf das Addraw gezeichnet habe. Mit dem OpenGL-Plugin funktioniert es jedoch.

Habe heute auf die aktuelle Andorra-Version aktualisiert (das Komplett-Paket, kein CVS) und natürlich auch die aktuellen DLLs in das Programmverzeichnis gepackt.

Edit: Aber ansonsten ein dickes Danke für das Feature, hat mir beim performanceschwachen OpenGL einen dicken Geschwindigkeitsboost gebracht, da bei Drawball ja sehr viele Einzelelemente gemalt werden, das kann ich mir jetzt auf einfache und schnelle Weise sparen. Früher wäre das relativ doof und umständlich gewesen.

Edit2: Wenn ich das Fenster vom einen Monitor auf den anderen verschiebe, vergisst das TextureSurface seinen Inhalt und ich muss ihn neuzeichnen. Ist das normal, wegen unterschiedlicher Ausgabedevices? Dann müsste ich mir wohl einen Code suchen, der das erkennt.

xZise 2. Jan 2009 00:23

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Ich habe übrigens ein Speicherleck in AdDraws.pas gefunden (Z. 2601 - 2608 in Version 0.4.5.1):
Delphi-Quellcode:
procedure TAdTexture.SaveToFile(AFile: string);
var
  ms:TMemoryStream;
begin
  ms := TMemoryStream.Create;
  SaveToStream(ms);
  ms.SaveToFile(AFile);
end;
Du gibst den MemoryStream nie frei!

Die Methode (Z. 2610 - 2619) procedure TAdTexture.LoadFromFile(AFile: string);) darunter hat nebenbei auch keinen Ressourcenschutzblock . Beabsichtigt?

Übrigens geht deine Dokumentation im Internet nicht :( Oder weiß jemand, wie ich den Inhalt eines AdImages in einen PNG Datei speichere?

MfG
xZise

Romi 2. Jan 2009 02:03

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Zitat:

Zitat von igel457
Hast du DefaultParticle auch entsprechend gecastet? Schau dir mal die SimpleParticle Demo an. Standardmäßig ist default Partikel vom Typ "TAdStdParticle":
Delphi-Quellcode:
with partengine.DefaultParticle as TAdStdParticle do
  LifeTime := 0.5;

Jip, damit gehts!

igel457 2. Jan 2009 10:12

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Hallo,

@xZise
Deinen Sourcecode baue ich bei Gelegenheit ein. AdBitmap.SaveToFile schreibt die Daten (wie im zweiten Tutorial beschrieben) in ein Andorra internes Format. Zu den eigentlichen Bilddaten kommen Informationen über das Texturobjekt (Breite, Höhe, Bittiefe) hinzu. Das Memoryleak behebe ich, Ressourcenschutzblöcke füge ich hinzu. Die Dokumentation habe ich jetzt endlich erfolgreich über SSH entpackt. Wenn du ein Andorra-Bild in ein anderes Grafikobjekt speichern willst, kannst du die Funktion "SaveToGraphic" verwenden.

@Florian
Wenn das Surfaceobjekt mit OpenGL funktioniert, sollte es eigentlich erst recht mit DirectX gehen. Hast du mal die Surface-Demo ausprobiert? Bei dem Problem mit den zwei Monitoren kann ich leider nicht helfen, da ich nur einen Monitor habe.

Florian H 2. Jan 2009 10:19

Re: Andorra 2D [Ver. 0.4.5.1, 31.12.08]
 
Zitat:

Zitat von igel457
@Florian
Wenn das Surfaceobjekt mit OpenGL funktioniert, sollte es eigentlich erst recht mit DirectX gehen. Hast du mal die Surface-Demo ausprobiert?

Die kriege ich leider nicht zum Laufen, die beendet sich direkt wieder. Kann aber auch daran liegen, dass ich erst in ein paar Units rumpfuschen muss, um die Delphi6-inkompatiblen Sachen zu ändern ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:28 Uhr.
Seite 22 von 26   « Erste     12202122 2324     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz