Autor Beitrag
somebody
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 167
Erhaltene Danke: 2



BeitragVerfasst: Fr 29.02.08 16:27 
Hallo Leute, ich habe mich gerade mal an einem 3D Spiel versucht. Mit einige Tutorials ging das dann auch schon ganz gut. Es soll eine Art eigener Ego shooter werden. Die Welt erscheint auch schon so, wie sie soll. Und der Gegner erscheint auch und er kann auch laufen.

ausblenden volle Höhe 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:
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:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
unit G4DGame3;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  // Genesis_for_Delphi-Units
  G4D_Genesis, G4D_BaseType, G4D_XForm3D, G4D_Vec3D, G4D_geTypes, G4D_Vfile,
  G4DDriver, G4DFigur;

type
  TForm1 = class(TForm)
    procedure FormCreate (Sender: TObject);
    procedure FormActivate (Sender: TObject);
    procedure FormDestroy (Sender: TObject);
    procedure FormClick (Sender: TObject);
  private
    { Private-Deklarationen }
    Engine    : pgeEngine;      // 3D-Engine
    World     : pgeWorld;       // World/Level
    Camera    : pgeCamera;      // Kamera/Betrachter
    Driver    : pgeDriver;      // Grafiktreiber
    DMode     : pgeDriver_Mode; // Grafikmodus
    XForm     : geXForm3D;      // Matrix für Welt->Betrachter
    isRunning : Boolean;        // Schalter für Spiel (ein/aus)
    CW8087    : DWord;          // FPU-Kontrollwert
    ViewVector: geVec3D;        // aktuelle Betrachterposition
    LookVector: geVec3D;        // neue Betrachterposition
    TurnVector: geVec3D;        // Drehwinkel
    MinVector : geVec3D;        // min. Kollisionsgrenze
    MaxVector : geVec3D;        // max. Kollisionsgrenze
    procedure ExitError (Txt: String);
    procedure CreateGame;
    procedure RunGame;
    procedure FreeGame;
    procedure GetInput;
    procedure GetMousePos;
    function  Collision: Boolean;
    procedure SetFigure;
  public
    { Public-Deklarationen }
  end;

const
  Pfad      = '.\';
  ACT_Datei = 'G4DFigur.act';
  BSP_Datei = 'genvs2.bsp';
  GVersion  = 'G4DPlay3';
  OK        = GE_TRUE;       // Kontrollwert für Engine-Methoden
  MaxWidth  = 640;           // Max. Screenbreite
  MaxHeight = 480;           // Max. Screenhöhe
  MCW_EM    = DWORD($133f);  // für evtl. Division-durch-Null-Fehler

var
  Form1     : TForm1;     // Spiel-"Unterlage"
  Figur     : TFigur;     // Figur (Gegner?)
  GHandle   : HWnd;       // Handle des Formulars
  GInstance : LongInt;    // Handle der Applikation

implementation

  {$R *.DFM}

procedure TForm1.ExitError (Txt: String);
begin
  // Fehlermeldung anzeigen, Programm abbrechen
  ShowMessage (Txt); halt;
end;

procedure TForm1.CreateGame;
var
  WorldScreen: geRect;    // Anzeigefläche
  WorldName:   String;    // Name der BSP-Datei (Welt/Level)
  WorldFile:   pgeVFile;  // BSP-Datei (Welt/Level)
begin
  // Anzeigefläche festlegen
  with WorldScreen do
  begin
    Left := 0; Right  := MaxWidth  - 1;
    Top  := 0; Bottom := MaxHeight - 1;
  end;
  // Koordinaten-Matrix setzen
  geXForm3D_SetIdentity (@XForm);
  // Kamera initialisieren
  Camera:= geCamera_Create (2.0, @WorldScreen);
  if Camera = nil then
    ExitError('Kamera kann nicht installiert werden!');
  // BSP-Datei laden
  WorldName := Pfad + BSP_Datei;
  WorldFile := geVFile_OpenNewSystem (nil,
    GE_VFILE_TYPE_DOS, PChar(WorldName), nil, GE_VFILE_OPEN_READONLY);
  // Wenn Datei ok, Welt/Level erzeugen
  if WorldFile <> nil then
  begin
    World := geWorld_Create(WorldFile);
    geVFile_Close(WorldFile);
  end;
  if World = nil then
    ExitError ('Welt/Level lässt sich nicht erzeugen!');
  // Welt/Level mit 3D-Engine verknüpfen
  if geEngine_AddWorld(Engine, World) <> OK then
    ExitError ('Welt/Level lässt sich nicht einbinden!');
  // Betrachterposition "nullen"
  geVec3d_Set (@ViewVector, 0.0, 0.0, 0.0);
  LookVector := ViewVector;
  geVec3d_Set (@TurnVector, 0.0, 0.0, 0.0);
  geVec3d_Set (@MinVector,-20.0,-20.0,-20.0);
  geVec3d_Set (@MaxVector, 20.0, 20.0, 20.0);
  // Figur erzeugen und positionieren
  Figur := TFigur.Create (World, Pfad + ACT_Datei);
  SetFigure;
end;

procedure TForm1.RunGame;
begin
  // Spielmodus auf "Laufen" einstellen
  isRunning := true;
  // Solange Spiel "läuft"
  while isRunning do
  begin
    // ggf. auf Ereignisse reagieren (z.B. Tastatur/Maus)
    Application.ProcessMessages;
    // Tasten und Maus abfragen
    GetInput;
    GetMousePos;
    // Koordinaten und Winkel ausrichten
    geXForm3D_SetIdentity (@XForm);
    geXForm3D_RotateX (@XForm, TurnVector.x);
    geXForm3D_RotateY (@XForm, TurnVector.y);
    geXForm3D_RotateZ (@XForm, TurnVector.z);
    geXForm3D_Translate
      (@XForm, ViewVector.x, ViewVector.y, ViewVector.z);
    geCamera_SetWorldSpaceXForm (Camera, @XForm);
    // Rendering starten
    if geEngine_BeginFrame(Engine, Camera, GE_TRUE) <> OK then
      ExitError ('BeginFrame gescheitert!');
    // Figur mit Bewegung rendern
    Figur.Render (GetTickCount);  
    // Welt/Level rendern und darstellen
    if geEngine_RenderWorld (Engine, World, Camera, 0.0) <> OK then
      ExitError ('Rendering gescheitert!');
    // Rendering beenden
    if geEngine_EndFrame(Engine) <> OK then
      ExitError ('EndFrame gescheitert!');
  end;
end;

procedure TForm1.FreeGame;
begin
  // Figurdaten freigeben
  Figur.Free;
  // Kamera, Welt und Engine freigeben
  if Camera <> nil then geCamera_Destroy (@Camera);
  if World  <> nil then geWorld_Free (World);
  if Engine <> nil then geEngine_Free (Engine);
  // Zeiger "nullen"
  Camera := nil; World := nil; Engine := nil;
end;

procedure TForm1.GetInput;
const xDiff=4.0; yDiff=2.0; zDiff=6.0;
begin
  // Links-Rechts-Bewegung
  if GetAsyncKeystate(VK_LEFT) < 0 then
  begin
    LookVector.x := ViewVector.x - xDiff * cos(TurnVector.y);
    LookVector.z := ViewVector.z + xDiff * sin(TurnVector.y);
  end;
  if GetAsyncKeystate(VK_RIGHT) < 0 then
  begin
    LookVector.x := ViewVector.x + xDiff * cos(TurnVector.y);
    LookVector.z := ViewVector.z - xDiff * sin(TurnVector.y);
  end;
  // Vor-Zurück-Bewegung
  if GetAsyncKeystate(VK_UP) < 0 then
  begin
    LookVector.x := ViewVector.x - zDiff * sin(TurnVector.y);
    LookVector.z := ViewVector.z - zDiff * cos(TurnVector.y);
  end;
  if GetAsyncKeystate(VK_DOWN) < 0 then
  begin
    LookVector.x := ViewVector.x + zDiff * sin(TurnVector.y);
    LookVector.z := ViewVector.z + zDiff * cos(TurnVector.y);
  end;
  // Rauf-Runter-Bewegung
  if GetAsyncKeystate(VK_PRIOR) < 0 then
    LookVector.y := ViewVector.y + yDiff;
  if GetAsyncKeystate(VK_NEXT)  < 0 then
    LookVector.y := ViewVector.y - yDiff;
  // Ende mit Esc
  if GetAsyncKeystate(VK_ESCAPE) < 0 then isRunning := false;
  // Neue View-Werte nur, wenn keine Kollision
  if not Collision then ViewVector := LookVector;
end;

procedure TForm1.GetMousePos;
const xDiff=0.05; yDiff=0.03;
var xMouse, yMouse: Integer; MousePos: TPoint;
begin
  GetCursorPos (MousePos);
  xMouse := (MousePos.x - Screen.Width  div 2);
  yMouse := (MousePos.y - Screen.Height div 2);
  // Drehen links/rechts
  if xMouse < 0 then TurnVector.y := TurnVector.y + xDiff;
  if xMouse > 0 then TurnVector.y := TurnVector.y - xDiff;
  // Schauen rauf/runter
  if yMouse < 0 then
    if TurnVector.x <  1 then TurnVector.x := TurnVector.x + yDiff;
  if yMouse > 0 then
    if TurnVector.x > -1 then TurnVector.x := TurnVector.x - yDiff;
  SetCursorpos (Screen.Width div 2, Screen.Height div 2);
end;

function TForm1.Collision: Boolean;
var KontaktInfo: GE_Collision;
begin
  Result := Boolean(geWorld_Collision (World, @MinVector, @MaxVector,
    @LookVector, @ViewVector, GE_CONTENTS_SOLID_CLIP, GE_COLLIDE_ALL,
    0, nil, nil, @KontaktInfo));
end;

// für jede ACT-Datei neu anpassen!!!
procedure TForm1.SetFigure;
begin
  // Figur skalieren und ausrichten
  Figur.SetScale (1.5, 1.5, 1.5);
  // "Körpermaße" setzen
  Figur.SetRange (-50,0,-50, 50,150,50);
  // Geschwindigkeit festlegen, Bewegung einschalten
  Figur.SetMotion (2.0, 'Walk', true);
  // y-Wert anpassen, Abstand zum Betrachter lassen
  Figur.SetPosition (ViewVector.x, ViewVector.y, ViewVector.z-300);
end;

procedure TForm1.FormCreate(Sender: TObject);
var AppDir: String;
begin
  // Wert von ControlWord speichern, Division durch Null "ausschalten"
  CW8087 := Default8087CW;
  Set8087CW(MCW_EM);
  // Handle/Instanz von Formular/Applikation für 3D-Engine festlegen
  GHandle   := Self.Handle;
  GInstance := hInstance;
  // Pfad der Applikation ermitteln
  AppDir := ExtractFilePath (Application.Exename);
  // 3D-Engine initialisieren
  Engine := geEngine_CreateWithVersion
    (GHandle, GVersion, PChar(AppDir), GE_VERSION);
  if Engine = nil then
    ExitError ('3D-Engine kann nicht gestartet werden!');
  // Treiber auswählen (Methode aus Unit G4DDriver)
  SetDriver (GInstance, GHandle, Engine, Driver, DMode);
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  // Grafiktreiber/modus überprüfen
  if (Driver = nil) or (DMode = nil) then
    ExitError ('Kein Grafiktreiber/modus ausgewählt!');
  // Grafiktreiber/modus initialisieren
  if geEngine_SetDriverAndMode(Engine, Driver, DMode) <> OK then
    ExitError ('Grafikinitialisierung fehlgeschlagen!');
  // Anzeigedaten für Engine ausschalten
  geEngine_EnableFrameRateCounter(Engine, GE_FALSE);
  // Mauszeiger als kleines Fadenkreuz
  Cursor := crCross;
  // Spiel initialisieren
  CreateGame;
  // Wiederholungs-Schleife für Spielverlauf
  RunGame;
  // Formular (bei Spielende) schließen
  Close;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // Spiel "freigeben"
  FreeGame;
  // Alten FPU-Kontrollwert wiederherstellen
  Set8087CW (CW8087);
end;

procedure TForm1.FormClick(Sender: TObject);
begin
  isRunning := false;
end;

end.


So, bis jetzt habe ich es so gemahct, dass wenn manaufs Formular klickt, dass sich das Programm dann beendet. So, jetzt wollte ich machen, das man den Gegner auch abschießen kann, nur wie geht das? Könntet ihr mir da vielleicht helfen?
j.klugmann
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 29.05.08 18:17 
ich würde das Buch mal weiterlesen.
Webo
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 577
Erhaltene Danke: 14

Win 7, Debian
C# (Visual Studio 2013), PHP, C, C++ (Eclipse, KDevelop)
BeitragVerfasst: Do 29.05.08 18:46 
Ist der einzig vernüntige Tipp. Man wär hier sonst ewig am tippen um dir das zu erklären ...

Gruß

Webo
Yogu
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2598
Erhaltene Danke: 156

Ubuntu 13.04, Win 7
C# (VS 2013)
BeitragVerfasst: Do 29.05.08 19:32 
Hallo,

user profile iconsomebody hat folgendes geschrieben:
Es soll eine Art eigener Ego shooter werden.

Da hast du ja genau das richtige Buch erwischt. Nach dem letzen Kapitel hast du ein Third Person Egoshooter. Sogar mit Licht und Sound. Das ist das einzige, was ich an dem Werk von Hans Georg Schumann zu meckern habe.

user profile iconj.klugmann hat folgendes geschrieben:
ich würde das Buch mal weiterlesen.

Das ist ein Tipp, den du dir merken kannst. In Kurzform: Quelle lesen -> versuchen, zu verstehen -> evtl. Fragen hier stellen.

Ich hoffe, das kommt jetzt nicht falsch an. Ich will dich nicht anmeckern, sondern lediglich darauf hinweisen, wie man hier vielleicht nervige Antworten (so wie diese hier auch ;)) vermeiden kann.

Natürlich bist du hier trotzdem willkommen. :D

Grüße,
Yogu