Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Hintergrundbild erstellen (https://www.delphipraxis.net/166434-hintergrundbild-erstellen.html)

VkPenguin 13. Feb 2012 16:09

Hintergrundbild erstellen
 
Hallo,

nachdem ich nun gelernt habe, Bilder usw. zu verwenden zeichne ich in meinem Programm munter alles was ich brauche. Nun würde ich aber gerne ein Hintergrundbild einfügen, dass die gesamte Zeit konstant dort angezeigt wird, wo grade nichts anderes dargestellt wird, ich bräuchte also eine Art eben. Habe dazu schon einige Themen und Beispiele gefunden, die aber alle deutlich komplexere Ansprüche an ihre Ebenen haben (z.B. diese Seite zu Sprites).

Wenn ich das Bild zuerst zeichne werden die anderen Bilder ja einfach darübergezeichnet, was meinem Ziel im Prinzip schon nahekommt; nur bewegen sich meine Bilder ja.
Momentan mache ich das so, dass ich das alte Bild mit Schwarz (der aktuellen Hintergrundfarbe) übermale und es neu an die aktuelle Position zeichne - das geht natürlich nicht, wenn ich ein Bild im Hintergrund habe.
Ich wüsste also gern, ob den Hintergrund als eine Art Konstante festlegen kann, die sich nicht übermalen lässt..

Geht soetwas oder muss ich doch den umständlichen Weg über Sprites gehen?

Vielen Dank für Eure Tipps!

Sir Rufo 13. Feb 2012 16:15

AW: Hintergrundbild erstellen
 
Nun ja, du malst auf einer Leinwand und pinselst dann etwas darüber. Somit ist das Bild darunter nicht mehr vorhanden.

Du musst also dieses Hintergrundbild immer wieder malen und dann den Rest darüber.

VkPenguin 13. Feb 2012 16:19

AW: Hintergrundbild erstellen
 
Ja, nur dann müsste ich erstens einen beträchtlichen Teil des Programms umschreiben (Im Moment zeichne ich nicht "zentral", sondern immer dann, wenn es benötigt wird. Wenn ich aber jedesmal davor das Hintergrundobjekt zeichne, wäre alles andere ja weg) - und vor allem: Das Hintergrundbild hat dem Bildschirm entsprechend die Auflösung 1920x1080. Wenn ich das für ca 30 FPS also 30 mal pro Sekunde neu zeichnen lasse ist das doch extrem Ressourcen-fressend oder nicht?

freeway 13. Feb 2012 17:27

AW: Hintergrundbild erstellen
 
Leg 2 Images übereinander
lad dein Bild in das untere und mach das oberste Transparent

Popov 14. Feb 2012 02:14

AW: Hintergrundbild erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Paar Punkte wenn du selbst so etwas wie ein Bild zeichnest:

Zuerst in Create DoubleBuffer auf True setzten, gegen Flackern.

Wenn du direkt auf der Canvas des Formulars oder PaintBox zeichnest:
Du mußt auf OnFormPaint reagieren, d. h. die wird ausgeführt wenn dein Formular ganz, aber auch nur in Teilen neu gezeichnet wird.

Das Arbeiten mit mehreren Images führt zum flackern. Images sind keine Sprites.

Das Einfachste (nicht das Beste) ist mit einer temporären Bitmap zu arbeiten. Du zeichnest zuerst alles auf der Bitmap und dann, wenn alles fertig ist, das Ergebnis auf das Formular. Wenn das nur etwas Einfaches ist, dann reicht es. Wenn du dein Ergebnis z. B. 10 mal in der Sekunde zeichnest, dann kommen die Probleme. Das Ergebnis flackert und, ja nach Bildgröße kommt das Programm mit dem Zeichnen nicht nach.

Etwas besser, aber aufwendiger ist, du erstellst eine Art Clipping-Map. Das habe ich mal gemacht, ist aber schon Jahre her, so dass ich die Details auch nicht weiter weiß. Die Clipping-Map (ich nenne das mal so) ist eine Art Lochmaske die du beim Zeichnen erstellst. Beispiel, du hast ein 50 Pixel großen Ball der sich sich bewegt. Beim letzten Bild war der an der Position 100x100, jetzt ist er an 120x100. Du vermerkst die Umrisse des alten Balles an der Position 100x100 und des neuen Balles an Position 120x100. Parallel dazu zeichnest du den Hintergrund an der alten Position neu und den Ball auf der neuen Position, auf der temporären Bitmap. Wenn das Ergebnis fertig ist, legst du die Clipping-Map über das Formular und zeichnest die temporäre Bitmap.

Welchen Vorteil bringt es, wenn hier mehr gezeichnet wird? Erstens brauchst du nur das neu zeichnen was geändert wurde und Zweites zeichnet das System später nichts außerhalb der "Löcher". Das hat Folgen: Erstens ist es schneller, da nur in den Clipping Bereich gezeichnet wird und Zweitens, noch wichtiger, es flackert weniger.

Leider hatte ich nicht genug Zeit das weiter zu verfolgen, aber auf Canvas ein Game zaubern ist möglich.

Als Anhang eine kleine Demo. Auf einem Formular befinden sich an die 100 Rechtecke, auf 100 Ebenen, paar davon bewegen sich zwischen den Ebenen. Es sieht nicht spektakulär aus, ist aber nach dem oberen Muster mit Clipping-Bereichen gemacht worden. Leider habe ich nur die Exe, finde auf die Schnelle den Code nicht.

VkPenguin 14. Feb 2012 20:01

AW: Hintergrundbild erstellen
 
Danke für Eure Hilfe!
@ Popov: Deine erste Variante verstehe ich zwar, sie funktioniert für mich nur leider nicht. Die zweite Variante hört sich da schon wesentlich vielversprechender an, aber da komme ich wiederum leider nicht ganz mit :( Kennst du vielleicht ein Tutorial, oder weißt du wo ich den Code zu der Demo finde, sodass ich mir da ein paar Techniken abgucken kann? Alternativ wäre es auch nett, wenn du einen etwas ... offizielleren Namen dafür kennst, unter deinem konnte ich bisher nämlich leider nichts wirklich passendes finden..

Popov 14. Feb 2012 23:08

AW: Hintergrundbild erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich gucke die Tage ob ich das in den Archiven finde. Ansonsten heißt das Schlagwort Api und Clipping. Soweit ich weiß liefert Delphi da nichts, so daß man die Api bemühen muß. Es gibt da paar Clipping Funktionen mit denen ich experimentiert haben. Ist aber, wie gesagt, schon lange her. Ansonsten im Internet nach Komponenten suchen die das irgendwie erledigen. Ist auch nicht einfach.

Aber, so habe ich gerade festgestellt, die Welt dreht sich weiter. Was vor 10 Jahren mit Delphi 3 noch stark ruckelte, klappt mit den heutigen Computern (obwohl meiner ist auch schon fünf Jahre alt) auch ohne Tricks relativ gut. Ich hab unten ein kleines Demo programmiert. Dieses mal einfach über eine temporärer Bitmap und Canvas 500 Objekte die sich bewegen. Es geht flüssig.

Achso: die Ellipse im Hintergrund soll der Ersatz-Hintergrund sein. Hier bewegen sich also Objekte über einen Hintergrund.

VkPenguin 15. Feb 2012 18:32

AW: Hintergrundbild erstellen
 
Habe die einfache Variante mal getestet, obwohl ich einen Relativ guten PC hab wird das Spiel dadurch aber ruckelig - auch wenn es grundsätzlich funktioniert. Selbst wenn ich die Gegner-Raumschiffe nicht nach dem Prinzip "eins löschen, neue malen, nächstes" abarbeite, sondern alle lösche und dann neuzeichne ist schon ein bisschen Flackern zu sehen - ganz im Gegensatz zu deinen Demos.

Werde dann wohl die komplexere Variante benötigen, schaue mich in nächster Zeit mal nach den Schlüsselwörtern um, wäre aber dennoch lieb von Dir, wenn Du mir den Quellcode geben würdest, falls Du ihn findest :-)

Popov 15. Feb 2012 19:06

AW: Hintergrundbild erstellen
 
Hast du DoubleBuffer auf True gesetzt?

//Edit:

Tipp: wenn dir die einfache Canvas Art nicht ausreicht, weil dein Spiel komplexer ist und du deshalb tiefer in die Materie einsteigen willst, dann erfinde nicht das Rad neu, sondern mach es gleich richtig. Warum die Api studieren und Tage oder Wochen mit der Entwicklung einer Engine vergeuden, mach es gleich richtig, nimm dir einer von den zahlreichen kostenlosen Engines für Delphi und investiere die Kraft da. Die bieten alles was man für ein Spiel braucht. Denn irgendwann kommst du auch mit der "Lochmaske" nicht klar. Das ist möglich, aber auch nicht das Wahre.

//Edit2:

Zufällig habe ich letzte Woche auf YouTube etwas zu 3D Spiele Programmierung mit Delphi entdeckt. Ich habe es mir nicht angeguckt, bis auf die ersten drei Minuten, also kann ich die Qualität der Videos nicht beurteilen, aber die Reihe scheint paar Stunden zu laufen und sich mit Delphi und Spielen zu beschäftigen.

Ach ja, der Link: http://www.youtube.com/watch?v=yotbaJaurPA

VkPenguin 15. Feb 2012 23:02

AW: Hintergrundbild erstellen
 
@ Popov:
Ja, DoubleBuffer war True, so kompliziert ist mein Spiel aber (Finde ich) garnicht.. bisher zumindest :-) Nach den Videos auf Youtube werd ich mal suchen, das Problem an Delphi-Erweiterungen wie DelphiX ist aber, dass ich nichts nehmen kann, was zusätzlich installiert werden muss, da ich in meiner Schule keine Rechte dazu hab. Wenn schon müsste es also "out of the Box" funktionieren - und da hab ich noch nichts gefunden. Trotzdem aber Dankschöne für die Tipps!

DeddyH 16. Feb 2012 07:31

AW: Hintergrundbild erstellen
 
Auch wenn es jetzt zu funktionieren scheint, möchte ich doch einmal spezielle Engines wie Andorra 2D in den Raum werfen.

VkPenguin 16. Feb 2012 22:17

AW: Hintergrundbild erstellen
 
Wie kommst du darauf, dass es funktioniert :?:

Habe schon ein paar Sachen selbst versucht und will - wenn ich mal Zeit dazu habe - nochmal Google bemühen. Bisher bin ich noch nicht weitergekommen, habe mich nur nicht gemeldet, weil ich keine spezifische Frage hab und "hilfe!" ja nicht wirklich weiterhilft ;-)

Andorra hatte ich vor einiger Zeit schonmal im Auge, das erschien mir damals aber als zuviel Aufwand für das kleine Programm.. Jetzt ist es vielleicht nötig, ich befürchte nur, dass es sich nicht mit mSuM verträgt wie die meisten schönen Delphi-Techniken.

Vielleicht findet Popov ja auch noch was im Archiv, dann kann ich es mir da anschauen, an Codebeispielen konnte ich bisher immer am besten lernen :)

Popov 17. Feb 2012 00:04

AW: Hintergrundbild erstellen
 
Auch wenn ich es finden würde, es waren nur Experimente, keine Engine. Also erhoffe dir nicht zu viel. Ansonsten die Api nach Clip, Rect und Rgn durchsuchen. Vor allem die Bereiche Kombinieren.

DeddyH 17. Feb 2012 07:41

AW: Hintergrundbild erstellen
 
Oder mit einer Maske arbeiten und so das Vordergrundbild "ausstanzen". Vielleicht bringt das hier Licht ins Dunkel: http://www.hitekdev.com/delphi/BITMAPANIMATION.html

VkPenguin 17. Feb 2012 12:23

AW: Hintergrundbild erstellen
 
Hi, danke für die Tipps. Ich verstehe die Texte zu den gesuchten Begriffen zwar noch nicht so ganz, da komme ich aber vielleicht noch hinter. Was mir gerade einfiel (wahrscheinlich funktioniert cliping auch so in der Art): Wenn ich wüsste, wie ich den Teil des Bildschirms, auf den das neue Bild gezeichnet werden soll, scanne, in ein Bild speichere und nachher zum übermalen lade müsste es doch gehen oder? Wobei ich irgendwie befürchte, dass es dann immernoch ruckeln wird, immerhin sind das ja auch unglaublich viele Berechnungen, die pro Sekunde gemacht werden müssten. Meint ihr, so könnte es funktionieren? Wenn ja, kann ich dann vielleicht
Delphi-Quellcode:
Bild.LoadFromClipboardFormat
nehmen?

Popov 17. Feb 2012 19:40

AW: Hintergrundbild erstellen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Als ich DeddyHs Link oben gelesen habe, ist mir noch eine andere Methode eingefallen mit der ich auch leicht experimentiert habe. Sie ist ein Zwischending zwischen dem was ich bereits oben beschrieben habe, also alles zuerst auf eine temporäre Bitmap zeichnen und dann das gesamte Ergebnis auf die Leinwand zeichnen, und eine Lochmaske aus Regionen, was etwas komplexer wäre.

Hier ein Beispiel mit den Hausmitteln von Delphi, anhand eines Balls der sich über einen Hintergrund bewegt. Beim zeichnen wird der alte Bereich vom letzten Schritt als Rect-Bereich gespeichert, der neue Bereich, auch als Rect-Bereich. Dann wird der kleinste gemeinsamer Rect-Bereich berechnet. Alles was gezeichnet wird, wird auf diesem gemeinsamen Bereich auf der Temporärbitmap gezeichnet. Dann wird das Ergebnis übertragen. Der Vorteil hier, es wird nur das gezeichnet was sich verändert hat. Allerdings wird hier grob gearbeitet, d. h. die kleinste gemeinsame Fläche, aber auf dieser eben alles.

Auch wenn das nicht die versprochene Lochmaske ist, so ist es das Prinzip. Zerst den alten Bereich reparieren, dann das Neue zeichnen, Ergebnis übertragen.

Delphi-Quellcode:
    //das Alte merken
    RecAlt := Rect(x, y, x+Bmp.Width, y+Bmp.Height);

    ...

    //das Neue berechnen
    RecNeu := Rect(x, y, x+Bmp.Width, y+Bmp.Height);
    //kleinste gemeinsame Fläche ermitteln
    UnionRect(RecZusammen, RecAlt, RecNeu); //!Bool Funktion, Abfrage?
    //auf Temporärgrafik arbeiten
    TBmp.Canvas.CopyRect(RecZusammen, HBmp.Canvas, RecZusammen);
    TBmp.Canvas.Draw(x, y, Bmp);
    //Ergebnis übertragen
    Canvas.CopyRect(RecZusammen, TBmp.Canvas, RecZusammen);
Das ist auch eine Antwort auf deine Frage, Vergiss das Scannen und die Zwischenablage. Warum Zwischenablage wenn du das, was du kopieren möchtest, in einer Variable speichern kannst. Und warum den alten Bereich scannen, nimm doch gleich die Quelle.

VkPenguin 18. Feb 2012 20:20

AW: Hintergrundbild erstellen
 
Hmm, vielen lieben Dank für Deine Mühe, aber irgendwie komme ich mir gerade schrecklich Dumm vor. Verstehe ich das richtig (Auf mein Problem übertragen):

- RecAlt ist die vohrige Position des Gegners bzw. der Rahmen darum (dafür müsste ich doch zuvor einmal den Gegner erst zeichnen oder nicht?)
- RecNeu ist die neue Position
- RecZusammen ist die Mischung aus RecNeu und dem Hintergrund (Aber wie funktioniert das Mischen? Woher weiß das Programm denn was wohin soll? Die Transparenzoptionen gehen doch im BMP-Format verloren, oder nicht? Deswegen benutzt ich ja PNG mit Transparenz)
- x ist die X-Position des Gegners
- Y " " Y- " " "
- BMP ist das Bild des Gegners (ist bei mir PNGImage, das macht aber nichts, oder?)
- TBMP ist das temporäre BMP
- HBMP ist das Hintergrundbild

Und ich müsste das ganze dann also mit *Pseudocode*
Delphi-Quellcode:
For I:=1 to Gegneranzahl Do
Begin
Altes merken
Neue Position berechnen
"verschieben"
End;
machen..? Das kann so doch nicht funktionieren ?! Bin ratlos :(

Popov 18. Feb 2012 21:31

AW: Hintergrundbild erstellen
 
Ich glaube PNG ist ganz schlecht für ein Spiel bei dem es um Geschwinigkeit geht, dann egal welches Format man auch Windows anbietet, wenn es auf den Bildschirm kommt, ist es eine Bitmap. D. h. wenn man PNG nutzt, wird sie intern konvertiert. Sind es viele Grafiken, wird viel konvertiert. Und wenn man man 60 Durchläufe pro Sekunde hat, und hier bin ich mir nicht sicher ob das intern nur ein mal konvertiert wird oder bei jedem Aufruf, dann ist es viel Rechenarbeit.

Dabei geht es doch einfach, denn Bmp beherrscht auch die Transparenz. Einfach die transparente Farbe wählen, Transparent auf True setzten und gut ist es. Für ein Spiel ist Bmp immer vorzuziehen.

Nun zu deiner Frage: das was ich dir angeboten habe ist nicht die versprochene Lochmaske. Ich finde die alten Daten nicht mehr. Also habe ich so eine Art Lochmaske light programmiert.

Hier arbeite ich mit Rect-"Regionen" (keinen Windows-Rgn-Regionen). Noch bevor die neue Position berechnet und gezeichnet wird, wird aus den alten Werten, also die alte Region in der sich der Ball zuletzt befand, die Rect-Region als RecAlt gespeichert. Dann folgen die Berechnungen und ich berechne die Position in die gleich gezeichnet wird. Das ist die RecNeu. Nun berechne ich aus den beiden Werten den kleinsten gemeinsamen Rect-Rechteck. Nun wird per CopyRect der Hintergrund an der Stelle gezeichnet, also nicht der ganze Hintergrund, sondern nur das Rechteck. Dann wird der Ball in das Rechteck gezeichnet. Jetzt übertrage ich das Rechteck, wieder über CopyRect auf die entgültige Leinwand.

TmpBitmap dient hier nur zum arbeiten. Ich zeichne alles zuerst TmpBitmap und übertrage den kleinen Teil der geändert wurde auf die entgültige Leinwand.

Wieso der Umstand? Wenn ich zwei Bilder auf die gleiche Stelle (Hintergrund und Ball) nacheinander direkt auf die endgültige Leinwand zeichne, dann merkt man das durch flackern. Es wird zuerst das eine Bild gezeichnet und gleich danach das zweite. Auch wenn das schnell geht, man erkennt es. Also wird beides zuerst auf eine TmpBitmap gezeichnet und nur ein Bild wird kopiert.

Als du paar Posts weiter oben geschrieben hast, dass es immer noch flackert, da habe ich ein Test gemacht. Zuletzt habe ich 2000 Objekte über eine TmpBitmap gezeichnet, geflackert hat es nicht. Das Ganze ist in die Knie gegangen, so dass zuletzt die Leinwand nur noch zwei Bilder pro Sekunde erneuert wurde, also es ruckelte, aber geflackert hat es nicht.

Nun zum Nachteil der oberen Methode. Sie arbeitet immer mir dem kleinsten gemeinsamen Rechteck. Wenn aber auf dem ganzen Bildschirm sich Raumschiffe befinden dann wird schnell die ganze Leinwand zum Rechteck. Dann kann man sich auch das Berechnen sparen. Um die TmpBitmap kommst du aber nicht drumherum.

VkPenguin 18. Feb 2012 21:52

AW: Hintergrundbild erstellen
 
Zunächst nocheinmal vielen Dank, dass du soviel Geduld mit mir hast, soetwas trifft man selten... Gebe mir auch Mühe ;-)

Also eins nach dem anderen: Wenn das so ist, ist BMP natürlich besser, das ist einleuchtend. Aber wenn ich mein *.png-Bild als .bmp speichern will bekomme ich die Warnmeldung: "Beim Speichern geht die Transparenz verloren. Fortfahren?", deshalb bin ich bisher davor zurückgeschreckt. Und wenn ich einfach Transparent:=True sage, woher will die Bitmap dann wissen, welcher Bereich Transparent war, wenn eben das doch verlorengegangen ist? Und - entschuldige die wahrscheinlich Dumme Frage, aber wieso soll ich eine Farbe für etwas Transparentes auswählen? Ich meine, es soll doch durchsichtig sein...?!

Popov 18. Feb 2012 22:59

AW: Hintergrundbild erstellen
 
Bei der Bitmap funktioniert es mit der Transparenz so: du mußt eine Farbe opfern, die wird dann durchsichtig dargestellt. In der Praxis wird in der Regel clFuchsia genommen, man kann aber beliebige Farbe nehmen. Eingestellt wird die Farbe über
Delphi-Quellcode:
Bitmap.TransparentColor := ...
, dann noch
Delphi-Quellcode:
Bitmap.Transparent := True
setzen.

Diese Methode ist vorzuziehen, denn hier hast du die Kontrolle über die Transparente Farbe. Wenn ich mir unsicher bin welche Farbe es ist, dann mache ich es so:
Delphi-Quellcode:
Bitmap.TransparentColor := Bitmap.Canvas.Pixels[0, 0];
. Hier wird erste Farbe oben links genommen. Das ist aber fast das Gleiche wie
Delphi-Quellcode:
Bitmap.TransparentMode := tmAuto
. Hier erkennt das System die Farbe automatisch in dem es die Pixelfarbe unten links als transparent annimmt. Wenn du also mit TransparentMode und tmAuto arbeitest, brauchst du keine Farbe zuweisen. Prüfe aber ob die Farbe korrekt erkannt wurde.

VkPenguin 18. Feb 2012 23:19

AW: Hintergrundbild erstellen
 
So, habe mal mit der Umstellung auf Bitmaps angefangen, es gibt da aber ein Problem: Das Programm läuft tatsächlich deutlich flüssiger und ohne flackern, aber nur solange ich
Delphi-Quellcode:
// MobPIC.TransparentColor:=MobPiC.Canvas.Pixels[0,0];
//MobPIC.Transparent:=True;
die "//" Zeichen stehen lasse. Wenn ich den Transparenzmodus aktiviere fallen die FPS von über 60 auf 0.5. Weißt Du, woran das liegen könnte?

*Edit* Die Darstellung ist dann aber übrigens richtig, also es ist nur das Gegnerraumschiff sichtbar, der Rest des Rechtecks ist schwarz, wie es erstmal sein soll.
*Edit2* Um genau zu sein ist es die
Delphi-Quellcode:
//MobPIC.Transparent:=True;
Zeile, die den Unterschied ausmacht, egal, was mit der anderen ist

Popov 18. Feb 2012 23:42

AW: Hintergrundbild erstellen
 
Nun, mit Transparenz ist mehr zu rechnen. Ohne wird zeilenweise kopiert, bei Transparenz muß, auch wenn das nicht viel Leistung in Anspruch nimmt, jeder Pixel überprüft werden.

Aber ich kann mir das kaum vorstellen. Ich habe gerade 500 teil-transparente Objekte getestet, da bin ich auf 21 FPS runter und es ruckelt. Bei 300 Objekten bin ich über 30 und es läuft flüssig. Die Geschwindigkeit ist zwar runter, aber es ist flüssig.

Wie viel Raumschilfe hast du denn?

VkPenguin 18. Feb 2012 23:51

AW: Hintergrundbild erstellen
 
Nie mehr als 50, allerdings ist die Auflösung auch recht hoch. Im Spiel sind sie nicht mehr als höchstens 100*100px, das Originalbild, dass mit stretchdraw runtergerechnet wird ist aber 900*750px. Ich wollte das einfach mal testen und dann soweit wie nötig runterrechnen, es klappte aber sofort, also hab ich's so gelassen. Denkst Du, nun liegt es doch daran?

Popov 18. Feb 2012 23:54

AW: Hintergrundbild erstellen
 
Moment, stretchdraw?

Weißt du vieviel Rechenleistung draufgeht wenn du das Bild 60 mal pro Sekunde verkleinerst?

VkPenguin 18. Feb 2012 23:55

AW: Hintergrundbild erstellen
 
Ja, aber je nach Level gibt es unterschiedlich große Gegner... Soll ich lieber für jede Sorte ein eigenes Ressourcenbild machen?

Popov 19. Feb 2012 00:01

AW: Hintergrundbild erstellen
 
Vor dem Start des Levels kannst du so viel runter stretchen wie du willst, aber im Spiel solltest du mit festen Größen arbeiten. Auch wenn das bedeutet, das du für 10 Größen eines Raumschiffs 10 Bitmaps nutzt.

Das ist nun mal so, die Canvas wurde nicht zum spielen entwickelt.

VkPenguin 19. Feb 2012 00:03

AW: Hintergrundbild erstellen
 
Hm, okay. Kann ich denn einer Bitmap sagen, sie soll das Bild einmal stretchen, sich dann merken und immer wieder zeichnen? Oder muss ich wirklich alle Bilder vor Programmstart erstellen?

Popov 19. Feb 2012 00:16

AW: Hintergrundbild erstellen
 
Du kannst es machen wie du willst, aber es kostet nun mal Rechenzeit bei jeder Bewegung erst die Größe zu ändern.
Wobei ein kleiner Tipp, damit du nicht mit zig Bitmaps jonglieren mußt:

Delphi-Quellcode:
var
  _bmp_klein: TBitmap;
  _bmp_normal: TBitmap;
  _bmp_gross: TBitmap;

procedure TForm1.FormCreate(Sender: TObject);
begin
  _bmp_klein := TBitmap.Create;
  _bmp_normal:= TBitmap.Create;
  _bmp_gross := TBitmap.Create;
  //freigeben nicht vergessen

  _bmp_klein ...zuweisen...
  _bmp_normal ...zuweisen...
  _bmp_gross ...zuweisen...
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  bmp_zum_arbeiten: TBitmap;
begin
  bmp_zum_arbeiten := _bmp_klein;

  bmp_zum_arbeiten ...mach was...

  bmp_zum_arbeiten := _bmp_normal;

  bmp_zum_arbeiten ...mach was...
end;
Das klappt. Du mußt die Bitmap nicht umkopieren, du kopiert einfach deren Adresse und arbeitest immer mit der gleichen Bitmap. Nur bei Größenänderung kopierst du die Adresse einer anderen Bitmap.

VkPenguin 19. Feb 2012 00:19

AW: Hintergrundbild erstellen
 
Das ist geschickt, aber es wird ne weile dauern, das alles umzubauen.. Melde mich dann morgen nocheinmal :-)

VkPenguin 19. Feb 2012 01:44

AW: Hintergrundbild erstellen
 
So, die Anzeigen laufen jetzt über Bitmaps. Es läuft, wenn man alle Transparenzen aktiviert, schon etwas langsam, aber es geht.

Was mir gerade einfiel:
Zitat:

Du mußt auf OnFormPaint reagieren, d. h. die wird ausgeführt wenn dein Formular ganz, aber auch nur in Teilen neu gezeichnet wird.
Kannst du das vielleicht ein bisschen erläutern?


... jetzt müsste ich nurnoch den Teil mit den Rechtecken verstehen, dann wär alles so, wie ich es gerne hätte :-)

Wie lade ich denn einen Bildschirmausschnitt in die Bitmap? ist das der Teil mit "CopyRect..."?

Popov 19. Feb 2012 01:57

AW: Hintergrundbild erstellen
 
Zitat:

Zitat von VkPenguin (Beitrag 1151819)
So, die Anzeigen laufen jetzt über Bitmaps. Es läuft, wenn man alle Transparenzen aktiviert, schon etwas langsam, aber es geht.

Man kann immer noch eine Kleinigkeit opftimieren.

Zitat:

Was mir gerade einfiel:
Zitat:

Du mußt auf OnFormPaint reagieren, d. h. die wird ausgeführt wenn dein Formular ganz, aber auch nur in Teilen neu gezeichnet wird.
Kannst du das vielleicht ein bisschen erläutern?
Das hängt davon ab wo du zeichnest. In eine TImage, dann brauchst du es nicht. Direkt auf das Canvas des Formular, dann wird löscht jedes Fenster das sich drüber legt die Zeichenfläche (Canvas). Aber das Formular erkennt, dass da eine gelöschte Fläche ist und füllt OnFormPaint aus. Natürlich weiß da Formular nicht was da hin soll, es ruft nur OnFormPaint auf. Du kannst dort ein mal das komplette Bild zeichnen und gut ist es. Wenn es wieder nötig wird, ruft das Formular wieder OnFormPaint auf.


Zitat:

... jetzt müsste ich nurnoch den Teil mit den Rechtecken verstehen, dann wär alles so, wie ich es gerne hätte :-)

Wie lade ich denn einen Bildschirmausschnitt in die Bitmap? ist das der Teil mit "CopyRect..."?
Ja.

VkPenguin 19. Feb 2012 11:10

AW: Hintergrundbild erstellen
 
Es hat zwar noch ein ganzes Weilchen gedauert, habe jetzt aber endlich die CopyRect Funktion und den Rest verstanden, denke ich. Ich kann es zwar so noch nicht in meinem Hauptprogramm testen, aber ich denke, es würde funktionieren. Das Problem ist das erste mal:
Meine Gegner werden mit
Delphi-Quellcode:
x:=Random(50)+1;
For I:=1 To X Do
Begin
*erstelleGegner*
End;
erstellt, die Bewegung erfolgt in einer anderen Procedur etwa so:

Delphi-Quellcode:
For I:=1 Gegneranzahl DO
Begin
Gegner[I].lösche;
Gegner[I].PosX:=Gegner[I].PosX+Gegner[I].Geschwindigkeit;
Gegner[I].zeichne;
Wenn ich in die Bewegungsprocedur deinen Vorschlag einfüge sollte es ja gehen. Aber wie komme ich entweder beim ersten Durchgang an das GegnerBild oder, wenn ich es zuerst auf die Form zeichne, an den Ursprünglichen Inhalt des Fensters, also an den Hintergrund? Das einzige, was mir einfiel ist, das nötige im Record jedes Gegners zu speichern, und bei der Erstellung einzutragen, das erscheint mir aber ziemlich umständlich.. Geht das nicht besser? :?:

Popov 19. Feb 2012 11:41

AW: Hintergrundbild erstellen
 
Du kopierst nichts zurück aus der Form Canvas. Die Form Canvas ist ist das endgültige Bild das permanent angepasst/verändert wird. Die Änderungen speisen sich immer aus dem Original. Der Hintergrund ist entweder immer fest, ist am einfachsten, dann hast du aber einen Hintergrund de sich nicht bewegt, oder flexibel, also einen beweglichen Hintergrund, z. B. ein Planet im Hintergrund der auf die Cursor-Tasten rauf und runter reagiert, dann ist der sichtbarer Hintergrund immer ein kleiner Ausschnitt eines großen Hintergrundbildes der mit CopyRect aus dem großen Bild kopiert wird. Soll das Bild scrollen, d. h. nach Linksbewegung, verschwindet der Planet rechts und kommt irgendwann wieder links wieder, muß ein Bild zusammengesetzt werden. Hört sich aber wilder an als es ist.

VkPenguin 19. Feb 2012 11:48

AW: Hintergrundbild erstellen
 
Ahh! Okay ;-)

Hab mir nochmal dein Ballprojekt angesehen, verstehen kann ich's aber leider immernoch nicht so ganz..Man kopiert aus dem Originalbild, das kommt jetzt auch meiner Ursprünglichen Vorstellung entgegen. Aber wie? In Deiner uMain wird doch RectNeu auch nur als
Delphi-Quellcode:
RecNeu := Rect(x, y, x+Bmp.Width, y+Bmp.Height);
deklariert. Wo sagst du denn Delphi, dass du nicht den Bereich auf dem Bildschirm, sondern im Originalbild meinst? Es scheint ja in deinem Programm zu funktionieren, aber ich kapiers trotzdem nicht :(

Popov 19. Feb 2012 12:20

AW: Hintergrundbild erstellen
 
Ok, es gibt drei Bereiche. Der eine Bereich der repariert werden muß, der Bereich in dem etwas passiert, z. B. Ball taucht hier auf, und der gemeinsamer Bereich.

Den alten Rect-Bereich berechne ich nur, damit ich weiß wo etwas repariert werden muß. Da befindet sich noch das alte Ball Bild und das soll weg. Ich hab ja die Möglichkeit den kompletten Hintergrund zu zeichnen oder nur das zu übermalen was stört. Ich überzeichne also nur den Unterschied zum Original. Ich stelle somit im Tempbild das Originalbild wieder her. Nur mache ich es nicht in dem ich das komplette Originalbild in das TempBild zeichne, sondern ich flicke den Unterschied, ich mache also nur den Ball weg. Dazu muß ich zuerst wissen welchen Bereich ich reparieren muß. Das berechne ich aus den alten X/Y Koordinaten, plus Breite und Höhe des Ball-Bildes. Das Bild ist ja 72 Pixel breit und hoch, plus X und Y ergibt das einen bestimmten Rechteckbereich auf der Canvas. Das ist der Bereich der repariert werden muß.

Als nächstes berechne ich den Rect-Bereich in den gleich gezeichnet wird. Um den Ball zu zeichnen brauche ich den Rect-Bereich nicht. Das mache ich einfach mit Draw(X, Y, ...). Den Rect-Bereich brauche ich für was anderes.

Habe ich jetzt den alten Temp-Hintergrund-Bereich aus dem Originalbild repariert, in dem ich über CopyRect den den Teilbereich aus dem Originalbild auf das Tempbild kopiert habe, und dann den Ball mit Draw(X, Y, ...) auf das Tempbild gezeichnet habe, muß ich beide Bereiche auf die Canvas kopieren. Das mache ich in dem ich einen dritten Rect-Bereich aus den beiden berechne. Das ist der gemeinsame Rect-Bereich. Nun übertrage ich aus dem Tempbild den gemeinsamen Rect-Bereich auf die Canvas. Somit habe ich mit einem Kopiervorgang die alte Stelle repariert und die neue gezeichnet.

Beim nächsten Bild fängt alles von vorne an.

Du mußt dir das so vorstellen, das Tempbild entspricht zu 100% dem Bild auf der Canvas. Nur ich zeichne nicht immer das komplette Bild, was zeit kosten würde, sondern nur den nötigen Bereich.

VkPenguin 19. Feb 2012 12:54

AW: Hintergrundbild erstellen
 
Hm, ich dachte, ich hätte es jetzt endlich verstanden, dem ist aber offensichtlich nicht so. Das habe ich als Versuch gemacht:
Delphi-Quellcode:
 Recalt:=rect(Kidat[I].PosX,Kidat[I].PosY,Kidat[I].PosX+Kidat[I].Groesse,Kidat[I].PosY+Kidat[I].Groesse);
  Recneu:=rect(Kidat[I].PosX,Kidat[I].PosY+Kidat[I].Geschwindigkeit,
  Kidat[I].PosX+Kidat[I].Groesse,Kidat[I].PosY+Kidat[I].Groesse+Kidat[I].Geschwindigkeit);
  UnionRect(RecZusammen, RecAlt, RecNeu);
  Tmpbmp.Width:=Kidat[I].Groesse;
  Tmpbmp.Height:=Kidat[I].Groesse*2;
  TmpBmp.Canvas.CopyRect(RecZusammen, HintergrundPIC.Canvas, RecZusammen);
  TmpBmp.Canvas.Draw(0, 0, RaumschiffMobPIC[1]);
  Screen.ActiveForm.Canvas.Draw(Kidat[I].PosX,Kidat[I].PosY, TmpBmp);
Wenn ich Höhe und Breite der Bitmap nicht einstelle sehe ich garnichts, wenn doch wird das Raumschiff vor weißem Hintergrund gezeichnet, der nach und nach das komplette Hintergrundbild übermalt.. Was mach ich nur falsch? :oops:

Popov 19. Feb 2012 13:23

AW: Hintergrundbild erstellen
 
Tmpbmp ist die Kopie der Canvas, bzw. andersherum. Wieso änderst du die Größe beim Durchlauf.

VkPenguin 19. Feb 2012 13:52

AW: Hintergrundbild erstellen
 
meinst Du
Delphi-Quellcode:
Tmpbmp.Width:=Kidat[I].Groesse; Tmpbmp.Height:=Kidat[I].Groesse*2;
? Nunja, wie gesagt, wenn ich es nicht mache sehe ich garnichts, es scheint mir, als würde er dann einfach 0,0 als Größe wählen.

Popov 19. Feb 2012 14:38

AW: Hintergrundbild erstellen
 
Wenn du über eine TempBitmap arbeitest, dann sollte sie die Größe der Ausgabe haben.

VkPenguin 19. Feb 2012 14:41

AW: Hintergrundbild erstellen
 
Aber wenn ich es weglasse sind die Schiffe unsichbar.. Was ist denn an meinem Code falsch?


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:38 Uhr.
Seite 1 von 2  1 2      

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