Da DelphiX eine sehr bekannte und bliebte Komponenten samlung
für 2D Spiele geworden ist, hier mal mein "Tutorial-Projekt".
Es gibt verschiende Thmen jedes Thema ist in unter thmen unterteilet.
Inhaltverzeichnis
- Einführung
Was muss/sollte ich wissen bevor ich DelphiX downloade ?
Wo gibt es DelphiX zum Downloaden ?
Wie installiere ich es, richtig ?
- Erstes DelphiX Projekt
DXDraw
DXImageList
DXTimer
- Erstes Beispiel Sokubahn(Zusammenfassung)
Speichern und verwalten von Objekten ?
Verschieben von Objekten
der PatternIndex
- Verschiende Techniken
Scrollen
Minikarte
Levelformat
Drehen von Objekten
Einführung
Es wird kein DelphiX wissen vorrausgesetzt, aber Delphi solltes du schon können z.b.
was Schleifen oder IF anweisungen sind ebenfalls sollte bekanntt sein was Array sind
(da ist ein sehr wichtiger bestanteil jeder(Fast) anwendung von delphiX sein wird).
Ich werde nicht jede Komponenten beschreiben, es ist ja klar was die
DXTimer oder die DXImageList machen......
Da DelphiX nicht mehr weiter Entwicklet wird verwende ich unDelphiX
turbo.gamedev.net/undelphix.asp
das ist der nach fogler von delphiX das ist gleich für die neusten Delphi versionen ausgelegt.
Das Zip Archiv muss entpacken werden( verzeichnis nach wahl) und dieses verzeichnis muss in
Delphi unter dem Menupunkt: "Tools" und auf der Registerkarte "Bibliothek" bei "Bibliothekpfad"
eingetragen werden damit findet Delphi auch die komponenten
Erstes DelphiX Projekt
Jetzt beginen wir mit dem ersten delphiX Projekt:
Als allererstes werden drei Komponenten von DelphiX auf das Form gepackt:
DXDraw, DXTimer, DXImageList
Jetzt wird die DXImageList mit der DXDraw Komponenten verknüpft und zwar mit der Eigenschaft:
DXImageList1.DXDraw:=DXDraw1(geht auch im OI).
Nun muss der Intervall von der DXTimer Komponenten auf 0 gestellt werden.
In normalen Delphi anwendungen ist ja 1 das schnellste bei DelphiX ist 0 das schnellste(jede ms wird
ein Ereignis ausgelöst: das DXTimer Ereignis).
Damit wir nun auch was auf dem Bildschrim sehen müssen wir auch etwas code schreiben.
Du wälst jetzt die DXTimer komponenten aus und dort fügst du ein ereignis hinzu,
OI:ereignise, onTimer(Letztes ereignis). Anschließend wird der Code Editor geöffnet und folgede zeilen werden geschriben:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer); begin DXDraw1.Surface.Fill(0); DXImageList1.Items[0].Draw(DXDraw1.Surface,0,0,0); DXDraw1.flip end; |
Damit die DXImageListe auch was zeichnen kann muss sie Bilder haben. Bilder werden so hinzugefügt:
Im OI auf Items klicken auf das Dialog was kommt auf das + Symbol klicken und ein Bild duswählen.
Zur Parameter erlärung von der DXImageList:
Items[index].Draw(Dest: TDirectDrawSurface; X, Y,PatternIndex: Integer)
Es gibt auch nach indexOf bei Items dort kannst du einen Namen eingeben das hat den vorteil,
wenn sich die liste verändern musst du nicht alles nach bessern.
Dest: damit DelphiX weißt auf welchen Surface gezeichnet werden soll
X,Y: Die position auf der DXDraw Komponente es geht Oben Linx los
PatternIndex: du verwendes eine Grafik mit mehren gleichgroßen Bildern auch Tiles gennant.
Das geht aber nur wenn du vohrer in der DXImageList unter items die PatternWith und PatternHeight
mit werden fütterst.
Damit die ImageList auch mit jpeg arbeiten kann(wie im beispiel) muss der uses die unit Jpeg hinzugefügt werden.
Zur der Flip Funktion: es wird ein Bild in einen Backpuffer geschriben und mit der Flip Funktion auf
den Fornbuffer gezeichnet(jetzt sehen wir das Bild) so wird der Flimmer effegt vermiden der da ist
wenn nicht DoubleBuffered auf True steht.
So damit währe die erste DelphiX Anwendung zu ende jetzt solltes du ein bild sehen.
Erstes Beispiel Sokubahn(Zusammenfassung)
So damit wir das Spiel Sokubahn auch Schreiben können müssen wir und darüber gedanken machen
wie wir die Objekte auf der Karte verwalten die beste und einfachste möglichkeit ist ein 2D Array
da Sokubahn ja nur gleichgroße Objkekte verwendet.
Jetzt muss eine großer der Tiles und der Karter ausgewählt werden.
Ich nehme mal 640 X 480 Pixl(Standart größe vom kleinen Spielen).
Damit wir ein Raster enhalten sollten wir ein gerade Zahl nehmen z.b. 20:
640 div 20 = 32-1(weil die Array fangen ja bei 0 an)
480 div 20 = 24-1
Dies ergbnis Speichern wir in den Konstanten Variablen
MapX = 31
MapY = 23
MapS = 20 // Raster größe
So jetzt fängt das eigentliche Spiele Programieren an. Es geht damit los die Grafiken zusammen zustellen
die man benötigt und wie sollen sie verwaltet werden ?
Ich mache das einfach so:
bei meinen Projekten gibt es im verzeichnis: Image eine datei namens image.txt
dort stehen alle Image drinen die gebraucht weren die Datei ist so aufgebaut:
background.bmp; Verzeichnis namen(muss sich im gleichen verzeichnis befinden wie die datei)
0,0; Die Pattern Größe
B; Der Alias(jedes Item kann ein Namen haben)
clNone Trantzparent Farbe
das ganze sieht jetzt so aus
background.bmp;0,0;B;clNone
Ich habe ein kleines tools geschrieben was diese Dateien erstellen kann.
Jetzt muss dieses Datei geladen werden: DelphiX hat zwar sein eigens Grafik archiv format
nur da ist der Nachteil das dies Dateien immer neu erstellt werden müssen sobalt sich eine Datei ändern
das ist in meinem Format nicht der fall nur du musst es selbst laden d.h. die funktion dafür schreiben.
Wir werden eine Unit erstellen um nützliche funktionen abzuspeichern die nennen wir dann: DX_Tools
So könnte die Funktion aussehem zum laded der Grafiken aussehen damit diese unit auch funktioniert musst du noch folgende
funktion als erstes hinzufügen(die werde ich nicht beschreiben, da sie nichts mit delphiX zu tuen hat).
Ich hoffe du weißst wie man Units erstellt und Funktionen hinzufügt, weil dies werde ich nicht erklären.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54:
| function GetToken(aString: String; SepChar: Char; TokenNum: Byte):String; var Token : String; StrLen : Byte; TNum : Byte; TEnd : Byte;
begin StrLen := Length(aString); TNum := 1; TEnd := StrLen; while ((TNum <= TokenNum) and (TEnd <> 0)) do begin TEnd := Pos(SepChar,aString); if TEnd <> 0 then begin Token := Copy(aString,1,TEnd-1); Delete(aString,1,TEnd); Inc(TNum); end else Token := aString; end;
if TNum >= TokenNum then Result := Token else begin Result := Format('Fehler: Tokennummer (%s) ist größer als token !',[aString]); MessageBox(0,pchar(Result),nil,MB_OK or MB_ICONEXCLAMATION); end; end;
procedure LoadImageToListe(FileName:TFileName; DXImageList:TDXImageList); var i:integer; bilder:TStringList; str:String; begin bilder:=TStringList.create; bilder.LoadFromFile(FileName);
for i:=0 to bilder.count-1 do begin DXImageList.Items.Add; with DXImageList.Items[i] do begin Picture.LoadFromFile(ImageDir + GetToken(Bilder.Strings[i],';',1)); str:=GetToken(bilder.strings[i],';',2);
PatternHeight:=StrToInt(GetToken( str,',',1));; PatternWidth:=StrToInt(GetToken( str,',',2));;
Name:=GetToken(bilder.Strings[i],';',3); Transparent:=True; TransparentColor:=StringToColor(GetToken(bilder.Strings[i],';',4) );
end; end; end; |
Die Funktion sollte verstäntlich sein. Die Kommt nun in die DX_Tools.pas rein. So jetzt geht es weiter, erstelle
ein Verzeichnis Image da drint erstellt du die Dateien
Delphi-Quelltext
1: 2: 3: 4:
| steine.bmp(40 X 20 also zwei Bilder) ziele.bmp(20 X 20 also zwei Bilder) kasten.bmp(20 X 20 also zwei Bilder) ziele.bmp(20 X 20 also zwei Bilder) |
und jetzt erstellt du eine Datei names image.txt und schreibst dort folgendes rein:
Delphi-Quelltext
1: 2: 3: 4:
| steine.bmp;20,20;S;clNone player.bmp;20,20;p;clNone kasten.bmp;20,20;k;clNone ziele.bmp;20,20;z;clNone |
damit wir auch was sehen werden wir das erste Projekt neu abspeichern und zwar unter Kap2. Wir löschen das
Image aus der DXimageList(Items\ - Symbole und auf OK) und fügen beim erstellen das Formlaures die funktion
LoadImageToList, die sieht dann so aus:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TForm1.FormCreate(Sender: TObject); begin LoadImageToListe(GetExeDir + '\Image\image.txt',GetExeDir + '\Image\',DXImageList1); end; |
Complier jetzt mal dein Projekt und Starte es wenn alles gut geht dürftes du jetzt nichts sehen
Jetzt kommt der eignentliche teiel, das Zeichnen von mehren grafiken:
Du füghst ein 2D Array hinzu bei den goblaen variabeln
Map:array[0..MapX,0..MapY] of Integer;
zur bessern übersicht erstellen wir unter const(muss noch hinzugefügt werden über den Typs) die variabeln:
// Wenn die index stimmem kannst du sie so übernehmen ansonst musst du sie anpassen
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| const MapX = 31; MapY = 23; MapS = 20; None = -1; Stein = 0; Kasten = 2; Ziel = 3;
Lings = -1; Rechts = +1; Oben = -1; Unten = +1; |
jetzt fügst du folgende sachen unter private der Forms class hinzu:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| Map:array[0..MapX, 0..MapY] of TMap;
Player:TPlayer;
c:string;
procedure ClearMap;
procedure CreateMap;
procedure AddMapRand;
procedure MovePlayer(x,y:Integer);
procedure CreateObj(x,y,typ,tex:Integer); |
und so sehen die "sachen" mit leben gefühlt aus
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152:
| procedure TForm1.CreateObj(x,y,typ,tex:Integer); begin Map[x,y].Typ1:=Typ; Map[x,y].Tex1:=Tex; if typ = Stein then Map[x,y].frei:=False; end;
procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer); var x,y:Integer; begin DXDraw1.Surface.Fill(0); for x:=0 to MapX do begin for y:=0 to MapY do begin if Map[x,y].Typ1 <> None then DXImageList1.Items[Map[x,y].typ1].Draw(DXDraw1.Surface,x*MapS,y*MapS,Map[x,y].tex1); end; end;
DXImageList1.Items[1].Draw(DXDraw1.Surface,player.x*MapS,player.y*MapS,player.Tex);
DXDraw1.flip end; procedure TForm1.MovePlayer(x,y:Integer); var px,py:Integer; begin px:=player.x+x; py:=player.y+y; if Map[px,py].frei = True then begin if Map[px,py].typ1 = Kasten then begin if Map[px+x,py+y].frei = True then begin Map[px+x,py+y].Typ2:=Map[px+x,py+y].Typ1; Map[px+x,py+y].Tex2:=Map[px+x,py+y].Tex1;
Map[px+x,py+y].Typ1:=Map[px,py].Typ1; Map[px+x,py+y].Tex1:=Map[px,py].Tex1;
if Map[px,py].Typ2 = Ziel then begin Map[px,py].Typ1:=Map[px,py].Typ2; Map[px,py].Tex1:=Map[px,py].Tex2; end else begin Map[px,py].Typ1:=None; Map[px,py].Tex1:=0; end;
Map[px,py].frei:=True; Player.x:=px; Player.y:=py;
end; end else begin Player.x:=px; Player.y:=py; end; end; Form1.Caption:=c +' ' + IntToStr(px) + '\' + IntToStr(py);
end;
procedure TForm1.AddMapRand; var x,y:Integer; begin Randomize; for x:=0 to MapX do CreateObj(x,0,stein,0);
for x:=0 to MapX do CreateObj(x,MapY,stein,0);
for y:=0 to Mapy do CreateObj(0,y,stein,0);
for y:=0 to MapY do CreateObj(Mapx,y,stein,0); end;
procedure TForm1.CreateMap; var x,y:Integer; begin AddMapRand; for x:=5 to 20 do CreateObj(x,5,stein,1); for x:=5 to 20 do CreateObj(x,20,stein,1);
for y:=5 to 20 do CreateObj(20,y,stein,1);
CreateObj(10,11,Kasten,0); CreateObj(11,11,Kasten,0); CreateObj(10,12,Kasten,0);
CreateObj(28,5,Ziel,0); CreateObj(27,20,Ziel,0); CreateObj(22,12,Ziel,0);
Player.x:=2; Player.y:=12; Player.Tex:=0; end;
procedure TForm1.ClearMap; var x,y:Integer; begin for x:=0 to MapX do begin for y:=0 to MapY do begin map[x,y].Typ1:=None; map[x,y].Typ2:=None; map[x,y].Tex1:=None; map[x,y].Tex2:=None; map[x,y].Frei:=True; end; end; end;
procedure TForm1.FormCreate(Sender: TObject); begin c:='Erste DelphiX anwendung'; LoadImageToListe(GetExeDir + 'Image\image.txt',GetExeDir + '\Image\',DXImageList1); ClearMap; CreateMap; end; |
Wenn du alles richtig gemacht hast soltles du eine Karte sehen mit einem Rand und einem C in etwa sollte es so aussehen
(habe wie gesagt leider keinen Server so muss ich es halt mit assci zeichen da stellen)
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7:
| ------------------ - z - - ------ - - .. - z - - . - - - ------ z - ------------------ |
Ich hoffe das wahr verständlich.
Vorschläge, Verbesserungs wünsche und sowas in der art sind erwünscht(bitte nicht über die rechtschreibung reden nur einfach
wenn nötig fehler melden dann kann ich sie beheben)
dieses Totur habe ich in zwei Tagen erstellt wobei ich heute den meisten Teil geschrieben habe ich hoffe es hilft jemmanden weiter