Programm wie Space Invaders

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
navyseabear
Beiträge: 5
Registriert: So 21. Jan 2018, 09:27

Programm wie Space Invaders

Beitrag von navyseabear »

Moin moin,
ich möchte gerne ein Lernprogramm für Kinder schreiben, bei dem ich eine Linie benötige, welche ich von einem Objekt zu einem anderen Objekt zeichne. Die Objekte sind beweglich und ändern ihre Position ständig.
Das zeichnen der Linie ist ja soweit ganz einfach mit

Code: Alles auswählen

.Canvas.MoveTo(X,Y)
und

Code: Alles auswählen

.Canvas.LineTo(X,Y)
.
Wie aber kann ich diese Linie nun wieder löschen und zwar nur die Linie?
Ich habe im Hintergrund ein Bitmap und andere kleinere Grafiken welches für die Erklärung des Vorgangs wichtig sind. Dies sollte und muss auch erhalten bleiben.
Gibt es eine Möglichkeit das einfach und unkompliziert hin zu bekommen?
Wenn ich die alte Linie mit einer anderen Farbe überzeichne ist mein Hintergrund beschädigt. Ähnlich ist es wenn ich ein Rechteck über den gesamten Bereich zeichne.
Es muss doch eine einfache und schnelle Methode geben, da ich ja auch Dinge wie z.B. ein Label durch Änderung der Left und Top Werte einfach so über mein Bitmap schieben kann, ohne das der Hintergrund dabei beschädigt wird.

mfg
Tobias

Benutzeravatar
theo
Beiträge: 8406
Registriert: Mo 11. Sep 2006, 19:01

Re: Programm wie Space Invaders

Beitrag von theo »

Kopiere einfach immer alles neu auf den Bildschirm, auch den Hintergrund.
Das ist schnell genug.

Mathias
Beiträge: 5038
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Programm wie Space Invaders

Beitrag von Mathias »

Die einzige Lösung wird sein, im Repaint-Ereigniss als neu zu zeichnen.
Auf diese Art und Weise sind die meisten Programme aufgebaut.

Wen es waagrechte und senkrechte Linien sind, könntest du das ganze evtl. mit einer TShape umgehen.

So nebenbei kann man eine Linie mit einem Befehl zeichnem.

Code: Alles auswählen

Canvas.Line(x1, y1, x2, y2);


Ich habe im Hintergrund ein Bitmap und andere kleinere Grafiken welches für die Erklärung des Vorgangs wichtig sind.

Wie bringst du dies Bitmaps auf den Schirm ?

Es muss doch eine einfache und schnelle Methode geben, da ich ja auch Dinge wie z.B. ein Label durch Änderung der Left und Top Werte einfach so über mein Bitmap schieben kann,

ZB. ein Label, auch andere Komponenten, werden immer in einem Repaint-Ereigniss neu gezeichnet. ZB wen es vorher von einem anderen Fenster verdeckt war.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 628
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.7 FPC 3.04)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Programm wie Space Invaders

Beitrag von fliegermichl »

Hallo,
Es gibt zwei Möglichkeiten. Die erste ist einfach.

Code: Alles auswählen

 
procedure ZeichneLinie(x1, y1, x2, y2 : integer);
begin
 Canvas.Draw(0, 0, bmp);       // Überzeichnen mit dem Hintergrund (davon ausgehend, daß die Grafik in bmp so groß wie die zu bemalende Fläche ist)
 Canvas.Line(x1, y1, x2, y2);
end;
 


Für eine oder wenige Linien ist das absolut ausreichend. Wenn es aber viele Linien sind und evtl. deren Positionen zwischendurch ermittelt werden sollen usw. wird diese Art irgendwann ruckelig und der Anwender kann sehen, wie die Linien nacheinander gezeichnet werden. Dann kann man eine zweite Bitmap zu Hilfe nehmen und zunächst für den Anwender unsichtbar, da seine Linien rein zeichnen.
Wenn das erledigt ist, wird der Inhalt der Hilfsbitmap mit einem Kopiervorgang auf den Bildschirm gebracht.

Auch da kann man noch etwas optimieren, indem man anstelle von TCanvas.Draw die Systemfunktion BitBlt (aus LCLIntF) verwendet.

Code: Alles auswählen

 
procedure Zeichne1MioLinien(const a : array of TRect); // Die Linien werden immer von a.TopLeft nach a.BottomRight gezeichnet
var bmp2 : TBitmap;
     i : integer;
begin
 bmp2 := TBitmap.Create;
 try
   bmp2.width := bmp.Width;
   bmp2.Height := bmp.Height;
   BitBlt(bmp2.Canvas.Handle, 0, 0, bmp.width, bmp.Height, bmp.Canvas.Handle, 0, 0, SRCCOPY); // Zeichnet (zunächst unsichtbar) den Hintergrund aus bmp in bmp2
 
   // Jetzt werden die Linien in bmp2 gezeichnet. Das ist für den Anwender ebenfalls unsichtbar
   for i := Low(a) to High(a) do Canvas.Line(a[i].TopLeft, a[i].BottomRight);
 
   // Jetzt wird die fertige Grafik aus bmp2 auf einen Schlag auf den Bildschirm kopiert
 
  BitBlt(Canvas.Handle, 0, 0, bmp2.Width, bmp2.Height, bmp2.Canvas.Handle, 0, 0, SRCCOPY);
 finally
  bmp2.Free;
 end;
end;
 


Viele Grüße
Michael

kupferstecher
Beiträge: 273
Registriert: Do 17. Nov 2016, 11:52

Re: Programm wie Space Invaders

Beitrag von kupferstecher »

TBitmap kennt doch auch Transparenz, oder? Dann einfach den Hintergrund in eine Bitmap und darueber die Linien auf eine transparente Bitmap zeichnen.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 628
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Winux (L 2.0.7 FPC 3.04)
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Programm wie Space Invaders

Beitrag von fliegermichl »

kupferstecher hat geschrieben:TBitmap kennt doch auch Transparenz, oder? Dann einfach den Hintergrund in eine Bitmap und darueber die Linien auf eine transparente Bitmap zeichnen.


Kannst du das näher erläutern an einem Beispiel? Ich kann mir grad nicht so recht vorstellen was du meinst.

pluto
Lazarusforum e. V.
Beiträge: 7114
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Programm wie Space Invaders

Beitrag von pluto »

Ich habe sowas mal für ein Projekt gebraucht und habe nicht immer alles neu gezeichnet sondern nur das was sich geändert hat:
Ich hatte ein Buffer Bitmap.
Ich hatte Objekte/Klassen.

Und im Prinzip kann man jetzt folgendes machen:
1. Du Zeichnest, dann wird einfach zu erst an der "alten" Position der Entsprechende Teil von der Buffer Bitmap gezeichnet.
2. Nun Zeichnest du das "Eigentliche" Objekt.

Problem ist hier bei "nur", wenn sich die Objekte überlagern können, entstehen Grafikfehler....
Also habe ich als letzten Schritt einfach, alle Objekte die in der Nähe waren einfach auch neu gezeichnet....
Das klappte recht gut und ich muss nicht immer alles neu zeichnen sondern nur kleine Teile.
MFG
Michael Springwald

Mathias
Beiträge: 5038
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Programm wie Space Invaders

Beitrag von Mathias »

Wen man es ganz profesionel lösen will, dann wäre OpenGL für sowas gut geeignet.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

corpsman
Beiträge: 1118
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus SVN Trunk, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Programm wie Space Invaders

Beitrag von corpsman »

Ich habe zum "einfachen" Lernzweck mal Greenfoot nach Lazarus portiert (oder zumindes Teile)
Den DL gibt es hier: https://corpsman.de/index.php?doc=schule/greenfoot

das ganze nutzt OpenGL und die Original Javadokumentation ist echt gut. Evtl reicht dir das auch schon, ich meine da ist auch ein Space Invaders Sample mit dabei ;).
--
Just try it

navyseabear
Beiträge: 5
Registriert: So 21. Jan 2018, 09:27

Re: Programm wie Space Invaders

Beitrag von navyseabear »

Hallo,

ich habe nun ein wenig experimentiert und habe folgendes soweit geschafft.
Ich habe ein Form, auf das ich ein TImage mit Align als alClient gesetzt habe. Dieses lädt zu Programmbeginn ein Bitmap aus einer TImageList

Code: Alles auswählen

ImageList1.GetBitmap(0,ImageHintergrund.Picture.Bitmap);

Ein zweites TImage liegt über dem ersten und wird ebenfalls, hier nur mit Hilfe des Zufallsgenerators, mit einer kleinen Raketengrafik geladen.

Code: Alles auswählen

ImageList2.GetBitmap(Random(ImageList2.Count ),ImageRakete.Picture.Bitmap);

Die Raketengrafik bewegt sich nun mit Hilfe eines Timers über den Bildschirm.
Ich gebe hier zu beachten, dass es sich um ein Lernprogramm für Kinder handelt, bei dem es nicht unbedingt auf super tolle Animationen und dergleichen ankommt.
Leider bewegt sich mein RaketenImage nun extrem langsam über den Bildschirm. Lade ich hingegen das Hintergrundbild nicht ein, bzw. zeige es nicht an, "fliegt" meine Rakete in einem recht ordentlichem Tempo über den Bildschirm.
Wie aber bekomme ich eine flüssige Bewegung der Rakete hin, auch wenn ich ein Hintergrundbild geladen habe?

mfg
Tobias

Mathias
Beiträge: 5038
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Programm wie Space Invaders

Beitrag von Mathias »

Da kann ich nur OpenGL empfehlen.
Ein Hintergrundbild und ein paar Sprites sind einfach gemacht.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

navyseabear
Beiträge: 5
Registriert: So 21. Jan 2018, 09:27

Re: Programm wie Space Invaders

Beitrag von navyseabear »

Moin moin,

vielen Dank erst einmal für alle Ratschläge und Infos.
Leider bin ich aber immer noch nicht richtig weiter gekommen.
Ich habe versucht mich mit OpenGL zu beschäftigen, aber entweder bin ich zu blöd dazu oder ich kapiere es einfach nicht.
Ich verstehe einfach nicht wie ich
a) ein einfaches Hintergrundbild einlade und anzeige und
b) darauf ein Sprite erzeuge welches ich hin und her bewegen kann
OpenGL ist ja in erster Linie für 3D-Anwendungen gedacht, vielleicht sind mir deswegen die Beispiele die ich gefunden habe einfach zu komplex und und zu kompliziert.
Wenn OPenGL so einfach ist, wo kann ich den dann ein einfaches Beispiel für einen Hintergrund mit einem oder mehreren Sprites finden?

Mein klassischer Ansatz mit TImage funktioniert ganz gut, ist aber halt extrem langsam wenn ich mein zweites TImage auf dem ersten bewege. Solange nur ein einfacher Standardhintergrund da ist, bewegt es sich recht flott.

Brauch echt Hilfe im Moment, da ich wie man so schön sagt: "Lost in Space bin"

mfg
Tobias

Mathias
Beiträge: 5038
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Programm wie Space Invaders

Beitrag von Mathias »

Wenn OPenGL so einfach ist, wo kann ich den dann ein einfaches Beispiel für einen Hintergrund mit einem oder mehreren Sprites finden?

Ich habe da ein kleines Musterprogramm
http://mathias1000.bplaced.net/test/Spa ... ers.tar.gz

Von hier wird noch der Ordner Unit gebraucht.
Am besten dort die Pakage installieren.

https://github.com/sechshelme/Lazarus-O ... 3-Tutorial

Ich hoffe, das dir dies als Basis reicht.
Ansonsten weiter fragen.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Antworten