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 ). Seth' SourceCodes haben mir zwar weiter geholfen, aber ich habe an einigen Stellen immer noch Probleme.
Zuerst mal mein derzeitiger Code:
Code:
type
TFACE_POSITION =(
FACE_DOWN,
FACE_RIGHT,
FACE_UP,
FACE_LEFT
);
TTexCoords =record
U, V:Integer;
end;
TPosition =record
X, Y:Extended;
end;
TAnimation =record
AnimStart:Integer;//dort wird Animation gestartet
AnimCount:Integer;//Max. Zahl an Animationsstufen
Position :Single;//Die derzeitige Position der Animation
Duration :Integer;//Die Dauer in ms
Coords : TTexCoords;//Die Texturkoordinaten
end;
TAnimationHandler =class
Animations :Arrayof TAnimation;
AnimationName : TStringList;
constructor Create;
destructor Destroy ;override;
function GetTexCoords(Animation:String; FACE: TFace_Position): TTexCoords;
if GetASyncKeyState(VK_DOWN)and GetASyncKeyState(VK_RIGHT) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_DOWN;
Player.Pos.Y:= Player.Pos.Y-2* Speedfactor;
Player.Pos.X:= Player.Pos.X+2* Speedfactor;
end
else
if GetASyncKeyState(VK_DOWN)and GetASyncKeyState(VK_LEFT) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_DOWN;
Player.Pos.Y:= Player.Pos.Y-2* Speedfactor;
Player.Pos.X:= Player.Pos.X-2* Speedfactor;
end
else
if GetASyncKeyState(VK_UP)and GetASyncKeyState(VK_RIGHT) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_UP;
Player.Pos.Y:= Player.Pos.Y+2* Speedfactor;
Player.Pos.X:= Player.Pos.X+2* Speedfactor;
end
else
if GetASyncKeyState(VK_UP)and GetASyncKeyState(VK_LEFT) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_UP;
Player.Pos.Y:= Player.Pos.Y+2* Speedfactor;
Player.Pos.X:= Player.Pos.X-2* Speedfactor;
end
else
if GetASyncKeyState(VK_DOWN) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_DOWN;
Player.Pos.Y:= Player.Pos.Y-2* Speedfactor;
end
else
if GetASyncKeyState(VK_RIGHT) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_RIGHT;
Player.Pos.X:= Player.Pos.X+2* Speedfactor;
end
else
if GetASyncKeyState(VK_UP) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_UP;
Player.Pos.Y:= Player.Pos.Y+2* Speedfactor;
end
else
if GetASyncKeyState(VK_LEFT) < 0then
begin
Player.State:='Walk';
Player.Face:= FACE_LEFT;
Player.Pos.X:= Player.Pos.X-2* Speedfactor;
end
else
Player.State:='Stand';
end;
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:
Ohne jetzt groß auf das Problem mit dem wechsel zwischen den Animationen einzugehen was ganz allgemeines zum Code.
Code:
Animations : Array of TAnimation;
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:
function TAnimationHandler.GetItem(pName : String) : TAnimation;
var
n : integer;
item : TAnimation;
begin
for n := 0 to Animations.Count - 1 do
begin
item := TAnimation(Animations.Items[n]);
if item.Name = pName then
begin
result := item;
exit;
end;
end;
result := nil;
end;
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
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)
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-
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 network • my 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
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:
function TAnimationHandler.GetTexCoords(Animation: TAnimation; FACE: TFACE_POSITION): TTexCoords;
if Animation.Position >=(Animation.Duration/ Animation.AnimCount)then
begin
Animation.Position:=0;
inc(Animation.Coords.U);
if Animation.Coords.U > Animation.AnimCountthen
Animation.Coords.U:= Animation.AnimStart;
end;
result := Animation.Coords;
end;
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:
procedure TForm1.KeyStrokes;
var
i:Integer;
begin
for i :=0to255do
if GetASyncKeyState(i)and$8000=$8000then Keys[i]:=TRUE
else Keys[i]:=FALSE;
end;
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 Will immer noch andere Möglichkeiten wissen
Mitglieder in diesem Forum: Majestic-12 [Bot] und 8 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.