AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi kleines Spiel auf dem Form "rendern"
Thema durchsuchen
Ansicht
Themen-Optionen

kleines Spiel auf dem Form "rendern"

Ein Thema von Plastewolf · begonnen am 6. Apr 2014 · letzter Beitrag vom 25. Apr 2014
Antwort Antwort
Seite 1 von 2  1 2      
Plastewolf
(Gast)

n/a Beiträge
 
#1

kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 12:49
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).

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


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?

Geändert von Plastewolf ( 6. Apr 2014 um 12:51 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.014 Beiträge
 
Delphi 12 Athens
 
#2

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 13:20
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);
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#3

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 13:38
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);
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.149 Beiträge
 
Delphi 12 Athens
 
#4

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 13:46
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#5

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 14:03
Ich bin gerade über die PngComponents-Komponente auf der DN Seite gestoßen. Bin gerade dabei zu testen in wie weit das Funktioniert

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.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.014 Beiträge
 
Delphi 12 Athens
 
#6

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 14:06
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?
Wenn du das so machst, ja. Aktuelle Delphi-Versionen erlauben aber auch das Laden von PNGs in eine ImageList innerhalb der IDE (dehalb auch mein Hinweis "während des Designs"!).

Alternativ geht natürlich auch eine PngImageList (Png-Support scheint ja vorhanden zu sein) oder das Umwandeln eines TPngImage in eine Bitmap.

Für die Darstellung am Bildschirm wird das PNG sowieso in sowas wie eine Bitmap umgewandelt.

EDIT: die PngComponents hast du ja schon gefunden.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#7

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 14:38
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

Kann die PngImageList eigentlich auch Bilder horizontal drehen? Dann könnte ich mir die Hälfte der aktuellen Bilder sparen
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.014 Beiträge
 
Delphi 12 Athens
 
#8

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 18:18
Jetzt habe ich allerdings ein Problem mit der Transparenz des Bildes. DrawingStyle steht auf dsTransparent jedoch ist der Hintergrund des Bildes weiß.
ColorDepth sollte auf cd32Bit stehen, DrawingStyle sollte dann auch mit dsNormal funktionieren.

Kann die PngImageList eigentlich auch Bilder horizontal drehen? Dann könnte ich mir die Hälfte der aktuellen Bilder sparen
Meinst du horizontal spiegeln? Das ist standardmäßig wohl nicht verfügbar. Aus Performancegründen würde ich das auch nicht bei jedem Bildwechsel machen lassen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Plastewolf
(Gast)

n/a Beiträge
 
#9

AW: kleines Spiel auf dem Form "rendern"

  Alt 6. Apr 2014, 20:13
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
  Mit Zitat antworten Zitat
Astobix

Registriert seit: 26. Dez 2012
26 Beiträge
 
Delphi 6 Personal
 
#10

AW: kleines Spiel auf dem Form "rendern"

  Alt 11. Apr 2014, 12:36
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
Anstatt GLScene kannst du auch "normales" OpenGL benutzen. Da hast du eben keinen Baukasten dabei wie mit GLScene, allerdings kannst du damit mehr machen, wenn du dich einmal eingearbeitet hast. Die "Installation" von OpenGL könnte kaum einfacher sein und es gibt eine tolle OpenGL Community für Delphi.

Normalerweise ist OpenGL natürlich für 3D Anwendungen gedacht, aber auch 2D Spiele/Programme kann man damit gut programmieren.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz