![]() |
kleines Spiel auf dem Form "rendern"
Hallo miteinander,
Ich hatte gestern Abend spontan den Einfall mal ein kleines Jump 'n' Run-Spiel zu basteln. Ich habe noch ein paar alte Sprites auf dem PC liegen gehabt welche alle im PNG Format vorliegen und zusammen geradeeinmal 50KB groß sind. Der Plan war diese später über das RC File direkt in die EXE zu binden. Ich hatte das ganze zuerst auf einem leeren Form (mit Doublebuffer), einer TImage und dem OnKeyDown-Event vesucht. Mit einem Timer und einer Case-Of Schleife habe ich dann die Animationen nachgeschoben. Das ganze hat zwar funktioniert, aber so richtig Toll war das natürlich nicht. Ein alter Beitrag von dem User dominikkv hat mich dann auf die richtige Spur gebracht. Das Programm läuft zwar jetzt viel flüssiger aber die Optimallösung ist das natürlich auch nicht. Bei der Bewegung fängt das Image natürlich trotz DoubleBuffer an ein wenig zu flackern. In der Theory wollte ich das Problem später über eine Paintbox mit Stream lösen. Das Problem hierbei ist jedoch das ich scheinbar meine PNG Datein nicht ohne weiteres auf diese Weise einlesen kann. Diese ganze Timer Geschichte ist allerdings auch nicht unbedingt das gelbe vom Ei da die Animationen nicht nur ein paar MS nachhängen wenn ich eine Taste drücke sondern sich auch teilweise Überlappen wenn ich z.b. W und D gleichzeitig drücke (Hab leider noch nicht so recht raus gefunden wie ich das am besten umgehe). Kann man eigentlich direkt die Grafiken im Speicher behalten? Dieses ständige LoadFromFile ist sicherlich auch nicht unbedingt sehr Ressourcenfreundlich. (Achja, gehört zwar nicht unbedingt zu der eigentlichen Frage, aber hat jemand eine Idee wie man das Problem mit dem Springen lösen könnte? Ich dachte zuerst den Timer mit Case-Of durchlaufen zu lassen und dann immer das Top um 10 hochzuzählen bis die Maximalhöhe erreicht ist und dann danach wieder um 10 pro Durchlauf abzusenken bis man auf ein Hindernis trifft (Wand, Boden, Kiste etc.). Wollte das erst mit einer permanenten Gravity machen aber ich hab noch nicht so richtig raus gefunden wie das Funktioniert:-D). Ich hatte im Internet auch schonmal nach einigen Engines geschaut und dabei GLScene und Andorra2D gefunden. Bei beiden bin ich bereits an der Installation gescheitert:cry: Ich poste hier mal einen Auszug aus dem Code wie ich ihn mir bisher zusammengesetzt habe: Der Code selbst Funktioniert wenn auch ein wenig Suboptimal.
Delphi-Quellcode:
const
Speed = 3; AnimSpeed = 175; Pfad = '.\Debug\Win32\Graphic'; procedure TForm1.FormCreate(Sender: TObject); begin TMoveR := TTimer.Create(self); TMoveR.Interval := AnimSpeed; TMoveR.OnTimer := TMoveREvent; TMoveR.Enabled := false; TMoveL := TTimer.Create(self); TMoveL.Interval := AnimSpeed; TMoveL.OnTimer := TMoveLEvent; TMoveL.Enabled := false; TMoveJ := TTimer.Create(self); TMoveJ.Interval := AnimSpeed; TMoveJ.OnTimer := TMoveJEvent; TMoveJ.Enabled := false; TMoveD := TTimer.Create(self); TMoveD.Interval := AnimSpeed; TMoveD.OnTimer := TMoveDEvent; TMoveD.Enabled := false; end; procedure TForm1.TMoveREvent(Sender: TObject); begin Case MoveR of 0: Player1.Picture.LoadFromFile(Pfad+'move1R.png'); 1: Player1.Picture.LoadFromFile(Pfad+'move2R.png'); 2: Player1.Picture.LoadFromFile(Pfad+'move3R.png'); 3: Player1.Picture.LoadFromFile(Pfad+'move2R.png'); end; MoveR := MoveR+1; if MoveR > 3 then MoveR := 0; TMoveR.Enabled := False; end; procedure TForm1.TMoveLEvent(Sender: TObject); begin Case MoveL of 0: Player1.Picture.LoadFromFile(Pfad+'move1L.png'); 1: Player1.Picture.LoadFromFile(Pfad+'move2L.png'); 2: Player1.Picture.LoadFromFile(Pfad+'move3L.png'); 3: Player1.Picture.LoadFromFile(Pfad+'move2L.png'); end; MoveL := MoveL+1; if MoveL > 3 then MoveL := 0; TMoveL.Enabled := False; end; procedure TForm1.TMoveJEvent(Sender: TObject); begin Player1.Picture.LoadFromFile(Pfad+'jump.png'); TMoveJ.Enabled := False; end; procedure TForm1.TMoveDEvent(Sender: TObject); begin if Direction = 0 then Player1.Picture.LoadFromFile(Pfad+'duckR.png') Else Player1.Picture.LoadFromFile(Pfad+'duckL.png'); TMoveD.Enabled := False; end; procedure TForm1.Timer1Timer(Sender: TObject); var SpeedX, SpeedY: Integer; begin Caption := TimeToStr(Time); SpeedX := 0; SpeedY := 0; if GetAsyncKeyState(VkKeyScan('d')) <> 0 then begin TMoveR.Enabled := True; Inc(SpeedX, Speed); Direction := 0; end; if GetAsyncKeyState(VkKeyScan('a')) <> 0 then begin TMoveL.Enabled := True; Dec(SpeedX, Speed); Direction := 1; end; if GetAsyncKeyState(VkKeyScan('s')) <> 0 then begin TMoveD.Enabled := true; //Inc(SpeedY, Speed); end; if GetAsyncKeyState(VkKeyScan('w')) <> 0 then begin TMoveJ.Enabled := true; Dec(SpeedY, Speed); end; Player1.Left := Player1.Left + SpeedX; Player1.Top := Player1.Top + SpeedY; If (GetAsyncKeyState(VkKeyScan('w')) = 0) AND (GetAsyncKeyState(VkKeyScan('a')) = 0) AND (GetAsyncKeyState(VkKeyScan('s')) = 0) AND (GetAsyncKeyState(VkKeyScan('d')) = 0) then begin If Direction = 0 then Player1.Picture.LoadFromFile(Pfad+'standR.png') Else Player1.Picture.LoadFromFile(Pfad+'standL.png'); end; end; end. MoveR = Rechts bewegen MoveL = Links bewegen MoveJ = Springen MoveD = Ducken Wie würdet Ihr das Problem lösen? Habt Ihr vielleicht eine Idee für mich?:-D |
AW: kleines Spiel auf dem Form "rendern"
Als erstes würde ich die Sprites alle während des Designs in eine ImageList laden. Damit sind die schon mal gleich mit in der Exe und das zeitraubende LoadFromFile fällt weg. Du musst dir nur die Indizes der einzelnen Bilder in der Imagelist irgendwo merken (z.B. als Konstanten).
Wenn du dann das Sprite wechseln willst, geht das einfach über
Delphi-Quellcode:
Player1.Picture.Bitmap := nil;
ImageList1.GetBitmap(<hier der Index>, Player1.Picture.Bitmap); |
AW: kleines Spiel auf dem Form "rendern"
Aber wenn ich das ganze in eine ImageList laden möchte, dann müssten die Sprites im BMP Format vorliegen oder irre ich mich da?
Delphi-Quellcode:
var
Frame1 : TBitmap; begin Frame1 := TBitmap.Create; Frame1.LoadFromFile(Pfad+'standR.png'); ImageList1.Add(Frame1,nil); |
AW: kleines Spiel auf dem Form "rendern"
Es mußt ja keine ImageList sein, wobei du dafür das Bild natürlich vorher auch umwandeln könntest.
Wie wäre es mit mehreren TPngImage-Instanzen? PS: Daß man eine PNG-Datei nicht direkt in ein TBitmap (BMP) laden kann, sollte schon klar sein. Relative Pfade sind eh keine gute Lösung. Wobei sich hier gut machen würde, wenn die Bilder in die Resourcen verschoben werden. Aber zumindestens die Idee die Bilder schon bei Programmstart zu laden und dann nut noch zuzuweisen, ist nicht zu unterschätzen. Warum erstellst du die Timer eigentlich dynmaisch, wo man das auch die DFM-Loader machen lassen könnte. |
AW: kleines Spiel auf dem Form "rendern"
Ich bin gerade über die PngComponents-Komponente auf der DN Seite gestoßen. Bin gerade dabei zu testen in wie weit das Funktioniert:-D
Ich wollte das ganze bei PNG belassen da jedes Sprite nur 1KB groß ist und keinen Qualitätsverlust aufweist. Das ich die Timer dynamisch erstelle hat eigentlich keinen besonderen Grund, ich mag es einfach nicht so mir das Form mit Icons vollzumüllen. Die Pfade sind in erster Linie nur eine temporäre Lösung. Die möchte ich gern später aus der EXE selbst lesen. |
AW: kleines Spiel auf dem Form "rendern"
Zitat:
Alternativ geht natürlich auch eine ![]() Für die Darstellung am Bildschirm wird das PNG sowieso in sowas wie eine Bitmap umgewandelt. EDIT: die PngComponents hast du ja schon gefunden. |
AW: kleines Spiel auf dem Form "rendern"
Ich habe für die PNG Komponente jetzt alle Bilder auf eine identische Größe gebracht. Danach konnte ich alle Problemlos laden. Jetzt habe ich allerdings ein Problem mit der Transparenz des Bildes. DrawingStyle steht auf dsTransparent jedoch ist der Hintergrund des Bildes weiß.
Das wechseln der Bilder zur Laufzeit klappt übrigens Perfekt:-D Kann die PngImageList eigentlich auch Bilder horizontal drehen? Dann könnte ich mir die Hälfte der aktuellen Bilder sparen:wink: |
AW: kleines Spiel auf dem Form "rendern"
Zitat:
Zitat:
|
AW: kleines Spiel auf dem Form "rendern"
Ich habe vor einigen Stunden das ganze mit den verschiedenen Farbtiefen bereits probiert. Leider brachte das keinen Erfolg.
Testweise habe ich die Bilder in BMP konvertiert und die Transparenz zu clLime (0,255,0) gemacht. Die AutoTransparenz von der TImage funktioniert aber nur in 60-70% der Fälle und selbst wenn ich eine Fixe Farbe angebe tritt das Problem auf das er statt Grün einfach Schwarz nimmt. Irgentwas mache ich noch falsch glaube ich |
AW: kleines Spiel auf dem Form "rendern"
Zitat:
Normalerweise ist OpenGL natürlich für 3D Anwendungen gedacht, aber auch 2D Spiele/Programme kann man damit gut programmieren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:32 Uhr. |
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