Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Do Jul 10, 2025 17:38

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Sa Dez 02, 2006 17:46 
Offline
DGL Member
Benutzeravatar

Registriert: Do Aug 25, 2005 16:00
Beiträge: 189
Programmiersprache: Java, C#
Hi!
Also, folgendes Problem: Ich kann zwar ohne Probleme 2D Animationen abspielen und meine Spielfigur übers Spielfeld bewegen. Was ich aber nicht kann ist das ganze in gutes OOP zu pressen (wahrscheinlich mangelnde Übung :x ). Seth' SourceCodes haben mir zwar weiter geholfen, aber ich habe an einigen Stellen immer noch Probleme.

Zuerst mal mein derzeitiger Code:
Code:
  1.  
  2. type
  3.  
  4.   TFACE_POSITION = (
  5.    FACE_DOWN,
  6.    FACE_RIGHT,
  7.    FACE_UP,
  8.    FACE_LEFT
  9.   );
  10.  
  11.   TTexCoords = record
  12.    U, V: Integer;
  13.   end;
  14.  
  15.   TPosition = record
  16.    X, Y: Extended;
  17.   end;
  18.  
  19.   TAnimation = record
  20.     AnimStart: Integer;     //dort wird Animation gestartet
  21.     AnimCount: Integer;     //Max. Zahl an Animationsstufen
  22.  
  23.     Position : Single;      //Die derzeitige Position der Animation
  24.     Duration : Integer;     //Die Dauer in ms
  25.     Coords   : TTexCoords;  //Die Texturkoordinaten
  26.   end;
  27.  
  28.   TAnimationHandler = class
  29.     Animations    : Array of TAnimation;
  30.     AnimationName : TStringList;
  31.  
  32.     constructor Create;
  33.     destructor Destroy ; override;
  34.     function GetTexCoords(Animation: String; FACE: TFace_Position) : TTexCoords;
  35.     procedure AddAnimation(Name: String; Start, End, pDuration: Integer);
  36.   end;
  37.  
  38.  
  39.  
  40.   TPlayer = class
  41.     Textures   : TStringList;
  42.     Animation     : TAnimationHandler;
  43.     Pos           : TPosition;
  44.     TexCoords     : TTexCoords;
  45.     Face          : TFace_Position;
  46.     State         : String;
  47.  
  48.     constructor Create;
  49.     destructor Destroy; override;
  50.     procedure Render;
  51.   end;
  52.  
  53.  
  54.  
  55. constructor TAnimationHandler.Create;
  56. begin
  57.  AnimationName := TStringList.Create;
  58. end;
  59.  
  60. destructor TAnimationHandler.Destroy;
  61. begin
  62.  AnimationName.Free;
  63. end;
  64.  
  65. function TAnimationHandler.GetTexCoords(Animation: String; FACE: TFace_Position) : TTexCoords;
  66. var
  67.  i: Integer;
  68. begin
  69.  i := AnimationName.IndexOf(Animation);
  70.  
  71.   case FACE of
  72.    FACE_UP    : Animations[i].Coords.V := 0;
  73.    FACE_RIGHT : Animations[i].Coords.V := 1;
  74.    FACE_DOWN  : Animations[i].Coords.V := 2;
  75.    FACE_LEFT  : Animations[i].Coords.V := 3;
  76.   end;
  77.  
  78.  Animations[i].Position := Animations[i].Position + 1000 * Speedfactor;
  79.  
  80.  if Animations[i].Position >= (Animations[i].Duration / Animations[i].AnimCount) then
  81.  begin
  82.   Animations[i].Position := 0;
  83.   inc(Animations[i].Coords.U);
  84.  
  85.   if Animations[i].Coords.U > Animations[i].AnimCount then
  86.    Animations[i].Coords.U := Animations[i].AnimStart;
  87.  end;
  88.  
  89.  result := Animations[i].Coords;
  90. end;
  91.  
  92.  
  93. procedure TAnimationHandler.AddAnimation(pName: String; pStart, pEnd, pDuration: Integer);
  94. begin
  95.  SetLength(Animations, (Length(Animations)+1));
  96.  Animations[High(Animations)].AnimStart := pStart;
  97.  Animations[High(Animations)].AnimCount := pEnd;
  98.  Animations[High(Animations)].Duration := pDuration;
  99.  
  100.  AnimationName.Add(pName);
  101. end;
  102.  
  103.  
  104.  
  105. //Player
  106.  
  107. constructor TPlayer.Create;
  108. begin
  109.  TextureName := TStringList.Create;
  110.  State := 'Stand';
  111.  
  112.  SetLength(Textures, 1);
  113.  Textures[0] := TglBitmap2D.Create;
  114.  Textures[0].LoadFromFile('D:\Internet Downloads\Delphi Downloads\hero_mod.bmp');
  115.  Textures[0].AddAlphaFromColorKey(41, 156, 0, 60);
  116.  Textures[0].GenTexture();
  117.  
  118.  TextureName.Add('hero_mod');
  119.  Animation := TAnimationHandler.Create;
  120.  Animation.AddAnimation('Walk', 0, 2, 5000);
  121.  Animation.AddAnimation('Stand', 1, 1, 1000);
  122.  Face := FACE_DOWN;
  123.  TexCoords := Animation.GetTexCoords(State, Face);
  124.  
  125.  Pos.X := 160;
  126.  Pos.Y := 120;
  127.  
  128. end;
  129.  
  130. destructor TPlayer.Destroy;
  131. begin
  132.  Animation.Destroy;
  133.  Texturs.Free;
  134. end;
  135.  
  136. procedure TPlayer.Render;
  137. begin
  138.  glPushMatrix;
  139.  glTranslatef(Pos.X, Pos.Y, -1);
  140.  TexCoords := Animation.GetTexCoords(State, Face);
  141.  glColor3f(1, 1, 1);
  142.  Player.Bind();                                                    //derzeit gibts nur eine Textur, später ruf ich die Textur über einen
  143.  glBegin(GL_QUADS);                                         //TexturManager auf
  144.   glTexCoord2f(TexCoords.U/12, (TexCoords.V+1)/8); glVertex3f(-16, -16, 0);            //das ganze erstmal
  145.   glTexCoord2f((TexCoords.U+1)/12, (TexCoords.V+1)/8); glVertex3f(16, -16, 0);      //nur für eine bestimmte Textur
  146.   glTexCoord2f((TexCoords.U+1)/12, TexCoords.V/8); glVertex3f(16, 16, 0);             //wird später noch erweitert
  147.   glTexCoord2f(TexCoords.U/12, TexCoords.V/8); glVertex3f(-16, 16, 0);
  148.  glEnd;
  149.  glPopMatrix;
  150. end;
  151.  
  152.  
  153.  


Änderungen im Status der Figur entstehen dann so:
Code:
  1.  
  2.  
  3. procedure TForm1.KeyStrokes;
  4. begin
  5.  if GetASyncKeyState(VK_DOWN) and GetASyncKeyState(VK_RIGHT) < 0 then
  6.  begin
  7.   Player.State := 'Walk';
  8.   Player.Face := FACE_DOWN;
  9.   Player.Pos.Y := Player.Pos.Y - 2 * Speedfactor;
  10.   Player.Pos.X := Player.Pos.X + 2 * Speedfactor;
  11.  end
  12.  else
  13.   if GetASyncKeyState(VK_DOWN) and GetASyncKeyState(VK_LEFT) < 0 then
  14.   begin
  15.    Player.State := 'Walk';
  16.    Player.Face := FACE_DOWN;
  17.    Player.Pos.Y := Player.Pos.Y - 2 * Speedfactor;
  18.    Player.Pos.X := Player.Pos.X - 2 * Speedfactor;
  19.   end
  20.   else
  21.    if GetASyncKeyState(VK_UP) and GetASyncKeyState(VK_RIGHT) < 0 then
  22.    begin
  23.     Player.State := 'Walk';
  24.     Player.Face := FACE_UP;
  25.     Player.Pos.Y := Player.Pos.Y + 2 * Speedfactor;
  26.     Player.Pos.X := Player.Pos.X + 2 * Speedfactor;
  27.    end
  28.    else
  29.    if GetASyncKeyState(VK_UP) and GetASyncKeyState(VK_LEFT) < 0 then
  30.    begin
  31.     Player.State := 'Walk';
  32.     Player.Face := FACE_UP;
  33.     Player.Pos.Y := Player.Pos.Y + 2 * Speedfactor;
  34.     Player.Pos.X := Player.Pos.X - 2 * Speedfactor;
  35.    end
  36.    else
  37.     if GetASyncKeyState(VK_DOWN) < 0 then
  38.     begin
  39.      Player.State := 'Walk';
  40.      Player.Face := FACE_DOWN;
  41.      Player.Pos.Y := Player.Pos.Y - 2 * Speedfactor;
  42.     end
  43.     else
  44.      if GetASyncKeyState(VK_RIGHT) < 0 then
  45.      begin
  46.       Player.State := 'Walk';
  47.       Player.Face := FACE_RIGHT;
  48.       Player.Pos.X := Player.Pos.X + 2 * Speedfactor;
  49.     end
  50.     else
  51.      if GetASyncKeyState(VK_UP) < 0 then
  52.      begin
  53.       Player.State := 'Walk';
  54.       Player.Face := FACE_UP;
  55.       Player.Pos.Y := Player.Pos.Y + 2 * Speedfactor;
  56.      end
  57.      else
  58.       if GetASyncKeyState(VK_LEFT) < 0 then
  59.       begin
  60.        Player.State := 'Walk';
  61.        Player.Face := FACE_LEFT;
  62.        Player.Pos.X := Player.Pos.X - 2 * Speedfactor;
  63.       end
  64.       else
  65.        Player.State := 'Stand';
  66. end;
  67.  


Das gefällt mir nicht wirklich und ist schätze ich auch mal nicht wirklich elegant. Ich wüsste aber nicht wie ich das ganze anders machen sollte.
Dazu kommt noch eine weitere Einschränkung - Derzeit ist es so das wenn man gehen will man eine Pfeiltaste drückt. Die "Stehen" Animation wird einfach unterbrochen, eine neue Animation angezeigt. Genauso läufts beim Laufen. Wenn man die Pfeiltaste loslässt wird das ganze einfach unterbrochen egal an welcher Stelle der Animation man gerade ist. Das ist beim Laufen und Stehen auch gut so, nur beim Schlagen usw. darf das nicht gehen. Meine Idee wäre ein Boolean à la "Finished" einzuführen um zu testen ob die animation fertig ist - aber mir fällt eigentlich keine gute Möglichkeit ein wann und wo ich das abfragen könnte.


Also, Anregungen, Verbesserungsvorschläge und vernichtende Kritik sehr erwünscht ;)


Die Texturen die die Animationen enthalten sehen btw. so aus: Bild

cya,
Deathball


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Dez 03, 2006 01:09 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jun 24, 2003 19:09
Beiträge: 732
Ohne jetzt groß auf das Problem mit dem wechsel zwischen den Animationen einzugehen was ganz allgemeines zum Code.


Code:
  1. Animations    : Array of TAnimation;
  2. AnimationName : TStringList;

Sowas ist meiner Meinung nach verdammt ungünstig. Sollten aufgrund irgendeines Fehlers mal beide Listen nicht mehr "synchron" sein bricht dir alles zusammen. Auch die Handhabung davon macht sich denke ich relativ schlecht (was wenn du mal eine einzelne Animation raus löschen willst?)
Mein Tipp ist da die Klasse TObjectList (Achtung, es muß eine extra Unit eingebuden werden, siehe Delphi Hilfe). Eine TObjectList ist praktisch wie eine TStringList nur das .Items vom Typ TObject ist. D.h. du kannst beliebige Klassen als Items rein schmeißen. Mag auf den ersten Blick wie ein Array sein, aber es hat den Vorteil das du Exchance,Delete,Remove,Extract,Insert,IndexOf funktionen direkt von der TObjectList Klasse hast. Du müßtest TAnimation einfach als Klasse definieren und Animations in TObjectList ändern. Dann kannst du das AnimationName : TStringList komplett knicken. Natürlich noch den Namen der Animation als neue Eigenschaft in die Klasse.
Für deine TAnimationHandler Klasse kannst du dir dann einfach eine GetItem funktion bauen,
in etwa so:
Code:
  1. function TAnimationHandler.GetItem(pName : String) : TAnimation;
  2. var
  3.   n : integer;
  4.   item : TAnimation;
  5. begin
  6.   for n := 0 to Animations.Count - 1 do
  7.   begin
  8.     item := TAnimation(Animations.Items[n]);
  9.     if item.Name = pName then
  10.     begin
  11.       result := item;
  12.       exit;
  13.     end;
  14.   end;
  15.  
  16.   result := nil;
  17. end;
  18.  

Insgesammt ist es Geschmackssache, aber gerade wenn der Code größer wird es meiner Erfahrung nach besser gleich alles über Klassen und TObjectList zu machen. Das ewige rum gespiele mit Records und Arrays ist bei mir immer viel zu Fehleranfällig ;)
Aber nochma gesagt, alles Geschmackssache - es gibt ja auch durchaus noch Leute die ernsthaft noch mit "MyClass.next" Pointer Listen arbeiten :roll:



der "procedure TForm1.KeyStrokes;" ließe sich bestimmt auch ist ne lustige Liste verpacken.
Sowas wie "KeyStrokes.AddEvent(Key1, Key2 : integer; pNewState : String; pFace : TFace; XMod, YMod : integer);" (oder die Tasten gleich als array bzw. Liste)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Dez 03, 2006 10:26 
Offline
DGL Member

Registriert: Di Jun 06, 2006 09:59
Beiträge: 474
Wieso nimmst du den Namen der Animation nicht einfach in deinen TAnimation-Record auf?

Zitat:
es gibt ja auch durchaus noch Leute die ernsthaft noch mit "MyClass.next" Pointer Listen arbeiten

Wenn es sich anbieten, warum nicht? in meinem aktuellen Projekt verwende ich durchaus doppelt verlinkte Listen, da dabei der verwaltungsoverhead sehr gering ist, und sie für meine Zwecke Optimal geeignet sind. Übrigens bietet auch schon TStringlist das verlinken von Objekten an, TObjectlist übernimmt aber zusätzlich noch die Verwaltun (also freigabe/erstellen), zumindest wenn mich mein Gedächtnis nicht im Stich lässt-


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Dez 03, 2006 10:56 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Ich weiss ja nicht ob es allg. bekannt ist, aber man kann bei TStringList auch mit .AddObject(S: String; AObject: TObject) ein Objekt adden welches man dann über .Objects[Index: Integer] bekommt und welches immer zu dem entsprechenden String zugeordnet ist.

Gruß Lord Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Dez 03, 2006 17:11 
Offline
DGL Member
Benutzeravatar

Registriert: Do Aug 25, 2005 16:00
Beiträge: 189
Programmiersprache: Java, C#
Billi Berserker hat geschrieben:
Mein Tipp ist da die Klasse TObjectList (Achtung, es muß eine extra Unit eingebuden werden, siehe Delphi Hilfe). Eine TObjectList ist praktisch wie eine TStringList nur das .Items vom Typ TObject ist. D.h. du kannst beliebige Klassen als Items rein schmeißen. Mag auf den ersten Blick wie ein Array sein, aber es hat den Vorteil das du Exchance,Delete,Remove,Extract,Insert,IndexOf funktionen direkt von der TObjectList Klasse hast.

Thx. Für den Tipp. Dann müsste die Funktion "GetTexCoords" ja so oder so ähnlich aussehen (habs jetzt zugegebenermaßen nit ausprobiert):
Code:
  1.  
  2. function TAnimationHandler.GetTexCoords(Animation: TAnimation; FACE: TFACE_POSITION) : TTexCoords;
  3. begin
  4.   case FACE of
  5.    FACE_UP    : Animation.Coords.V := 0;
  6.    FACE_RIGHT : Animation.Coords.V := 1;
  7.    FACE_DOWN  : Animation.Coords.V := 2;
  8.    FACE_LEFT  : Animation.Coords.V := 3;
  9.   end;
  10.  
  11.   Animation.Position := Animation.Position + 1000 * Speedfactor;
  12.   if Animation.Position >= (Animation.Duration / Animation.AnimCount) then
  13.   begin
  14.    Animation.Position := 0;
  15.    inc(Animation.Coords.U);
  16.  
  17.    if Animation.Coords.U > Animation.AnimCount then
  18.     Animation.Coords.U := Animation.AnimStart;
  19.   end;
  20.  
  21.   result := Animation.Coords;
  22. end;
  23.  


Oder hab ich da was falsch verstanden? Naja, das ganze gefällt mir persönlich nit so \";)\" . Was aber weg kommt ist die TStringList. Ich werd Name in den Record mit aufnehmen (wie The-Winner meinte) und mir meine Prozedur zum löschen einer einzelnen Animation selbst schreiben.

Allerdings kannte ich die Klasse noch gar nit und ich glaub ich hab schon ne andere Verwendung dafür gefunden \":)\"


Zitat:
der "procedure TForm1.KeyStrokes;" ließe sich bestimmt auch ist ne lustige Liste verpacken.
Sowas wie "KeyStrokes.AddEvent(Key1, Key2 : integer; pNewState : String; pFace : TFace; XMod, YMod : integer);" (oder die Tasten gleich als array bzw. Liste)


Hab jetzt meinen Code folgendermaßen abgeändert:
Code:
  1.  
  2. procedure TForm1.KeyStrokes;
  3. var
  4.  i: Integer;
  5. begin
  6.  for i := 0 to 255 do
  7.   if GetASyncKeyState(i) and $8000 = $8000 then Keys[i] := TRUE
  8.   else Keys[i] := FALSE;
  9. end;
  10.  


Keys ist ein Array[0..255] of Boolean. Falls ein Menü oder so dazu kommen sollte ist das ganze wirklich besser als meine Lösung. Hab mir bisher aber noch keine Gedanken über eine neue Prozedur bei der Player Klasse gemacht, die das ganze dann abfragt. Werd ich wahrscheinlich morgen nach der Mathe Kursarbeit machen.


Seht den Post hier aba bitte nicht als Aufforderung an aufzuhören zu posten :wink: Will immer noch andere Möglichkeiten wissen :D


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 5 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 15 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 14 Queries | GZIP : On ]