Scroll-Mechanismus oder wandernde Figur mit tCanvas.CopyRect
-
- Beiträge: 142
- Registriert: Sa 30. Jan 2010, 19:35
- OS, Lazarus, FPC: Linux64, Wiindows32, MacOS, Lazarus 1.8.2
- CPU-Target: xxBit
Scroll-Mechanismus oder wandernde Figur mit tCanvas.CopyRect
Ich möchte in meinem Canvas einen Scroll-Mechanismus einbauen oder, im Prinzip wäre das dieselbe Fragestellung, z. B. eine Figur über den Bildschirm wandern lassen. Also muss ich mit CopyRect einen Rectangle Canvas-Ausschnitt an einer separaten Stelle im Speicher abspeichern, den freiwerdenden Streifen konventionell neu zeichnen (ggfs. mit ClipRect, damit nur der obsolete Bereich gezeichnet wird) und den Bildschirmbereich an der anderen Stelle wieder zeichnen lassen, indem ich das gespeicherte Rectangle mit CopyRect an die neue Stelle kopiere.
Ich habe so etwas noch nicht gemacht, aber ich brauche wohl zwei CopyRect Aufrufe und einen Zwischenspeicher. Oder gibt es eine einfachere und schnellere Variante? Ich frage mich allerdiings, wo ich das zwischenspeichern soll. Es soll möglichst schnell gehen. Brauche ich ein Bitmap-Objekt oder einfach nur einen freien Speicherbereich, also einen Speicher im Heap? Wenn ich es direkt ohne Zwischenpuffer kopieren würde, hängt es davon ab, in welcher Reihenfolge der Pixel-Reihen und -Spalten der Kopiervorgang passiert, das ist wahrscheinlich zu riskant. Bei Computerspielen ist das ja ständig gefragt, also denke ich dass es eine elgante und sehr schnelle vorgefertigte Lösung geben sollte.
Ich habe so etwas noch nicht gemacht, aber ich brauche wohl zwei CopyRect Aufrufe und einen Zwischenspeicher. Oder gibt es eine einfachere und schnellere Variante? Ich frage mich allerdiings, wo ich das zwischenspeichern soll. Es soll möglichst schnell gehen. Brauche ich ein Bitmap-Objekt oder einfach nur einen freien Speicherbereich, also einen Speicher im Heap? Wenn ich es direkt ohne Zwischenpuffer kopieren würde, hängt es davon ab, in welcher Reihenfolge der Pixel-Reihen und -Spalten der Kopiervorgang passiert, das ist wahrscheinlich zu riskant. Bei Computerspielen ist das ja ständig gefragt, also denke ich dass es eine elgante und sehr schnelle vorgefertigte Lösung geben sollte.
-
- Beiträge: 6912
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Verstehe ich richtig, du willst Sprites darstellen ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
- af0815
- Lazarusforum e. V.
- Beiträge: 6771
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Im Lazarusfolder unter Examples sollte sich ein Spritdemo befinden. In Lazarus unter Tools->Example Projects zu finden.
- Dateianhänge
-
- Anmerkung 2020-04-05 150718.jpg (39.94 KiB) 5040 mal betrachtet
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
- Winni
- Beiträge: 1577
- Registriert: Mo 2. Mär 2009, 16:45
- OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
- CPU-Target: 64Bit
- Wohnort: Fast Dänemark
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Hi!
In den BGRAControls ist eine Komponente namens BGRASpriteAnimation.
Die BGRAControls kannst Du mit dem Online Package Manager runterladen.
Winni
In den BGRAControls ist eine Komponente namens BGRASpriteAnimation.
Die BGRAControls kannst Du mit dem Online Package Manager runterladen.
Winni
-
- Beiträge: 142
- Registriert: Sa 30. Jan 2010, 19:35
- OS, Lazarus, FPC: Linux64, Wiindows32, MacOS, Lazarus 1.8.2
- CPU-Target: xxBit
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Nein, eigentlich will ich in einem Texteditor das Scrollen geschwindigkeitsmäßig optimieren. Das ganze sollte in normalem Delphi-Code geschrieben sein, ohne Lazarus-spezifische Befehle, weil es auch in einer anderen Delphi-ähnlichen Entwicklungsumgebung (WDsibyl) laufen soll. Wenn man in einem Editor um eine Zeile hoch- bzw. runterscrollt, dann muss ja nur die unterste bzw. oberste Zeile neu geschrieben werden. Alle anderen Zeilen kann man als großes Rectangle vom vorherigen Zustand kopieren, was wesentlich schneller ist, als jedes Mal alle Zeilen neu zu schreiben. Es ist also eigentlich recht simpel: Altes rect in den Heap speichern, neues rect um eiine Zeilenhöhe versetzt neu zeichnen und die wirklich neue unterste bzw. oberste Zeile des Editors dann konventionell neu erzeugen. Das Beispiel mit dem Spiel habe ich nur zur Veständlichkeit gebracht. Ich brauche also die dargestellte "Zu-Fuß" Vorgehensweise mit direkten Canvas Befehlen, und vor allem die Frage, wo ich das zwischenspeichern soll.
- af0815
- Lazarusforum e. V.
- Beiträge: 6771
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Dann ist das Beispiel in Lazarus eher was. wobei die canvas implementation zwischen Lazarus und WDsibyl unterschiedlich sein kann. Ist oft auch bei Lazarus selbst in der Tiefe zwischen den Wigetsets nicht so einfach.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
- Winni
- Beiträge: 1577
- Registriert: Mo 2. Mär 2009, 16:45
- OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
- CPU-Target: 64Bit
- Wohnort: Fast Dänemark
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Hi!
Also im Prinzip so:
Platz für eine neue oberste Zeile machen:
Jetzt muss nur noch die oberste Zeile mit Textout geschrieben werden.
Winni
Also im Prinzip so:
Platz für eine neue oberste Zeile machen:
Code: Alles auswählen
.....
var FontHi : Integer;
bmp: TBitmap;
begin
FontHi := Memo1.Font.Height;
tmp := TBitMap.Create;
tmp.SetSize (Memo1.width, Memo1.height - FontHi;
tmp.Canvas.CopyRect (Rect (0,0,tmp.width,tmp.height), memo1.Canvas, Rect (0,0,tmp.width,tmp.height) );
Memo1.Canvas.CopyRect( Rect(0,FontHi,tmp.width,tmp.height+FontHi), tmp.canvas, Rect(0,0,tmp.width,tmp.height) );
tmp.free;
....
end;
Winni
-
- Beiträge: 142
- Registriert: Sa 30. Jan 2010, 19:35
- OS, Lazarus, FPC: Linux64, Wiindows32, MacOS, Lazarus 1.8.2
- CPU-Target: xxBit
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Ja, genau das war es was ich wissen wollte. Also ich brauche ein temporäres Bitmap-Objekt. Ich kann dann das Bitmap-Objekt auch stehenlassen und das SetSize nur machen, wenn sich etwas geändert hat. Weil das beim schnellen Scrollen ständig gebraucht wird, zählt jede Millisekunde und es schont dann den Heap-Speicher. Danke Winni !
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1639
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Für deinen Anwendungsfall reicht das. Wenn du aber wirklich eine Figur die nicht rechteckig ist über den Hintergrund schieben willst, brauchst du 3 Copyrect Befehle und 3 Bitmaps.
Die erste Bitmap ist deine Figur mit allen umliegenden Pixeln in weiß (Farbwert 255).
Die zweite ist exakt gleich, wobei alle Pixel deiner Figur schwarz sein müssen (Farbwert 0). Diese wird Maske genannt.
Die dritte Bitmap ist dein Hintergrund.
Der erste CopyRect Befehl zeichnet den Hintergrund auf die Paintbox.
Der zweite zeichnet die Maske (Bitmap 2) mit dem CopyMode SRCAND in die Paintbox und zuletzt die erste mit CopyMode MergePaint (OR Operation)
Ich hab mal eine kleine Demo gemacht. Anstatt da eine Hintergrund Grafik mit rein zu packen, generiere ich die im FormCreate, indem einfach Kreise reingemalt werden.
il ist eine ImageList in der meine Figur und die Maske sind. (Das bin ich mit meinem Hündchen
So schaut es dann aus:
Die erste Bitmap ist deine Figur mit allen umliegenden Pixeln in weiß (Farbwert 255).
Die zweite ist exakt gleich, wobei alle Pixel deiner Figur schwarz sein müssen (Farbwert 0). Diese wird Maske genannt.
Die dritte Bitmap ist dein Hintergrund.
Der erste CopyRect Befehl zeichnet den Hintergrund auf die Paintbox.
Der zweite zeichnet die Maske (Bitmap 2) mit dem CopyMode SRCAND in die Paintbox und zuletzt die erste mit CopyMode MergePaint (OR Operation)
Ich hab mal eine kleine Demo gemacht. Anstatt da eine Hintergrund Grafik mit rein zu packen, generiere ich die im FormCreate, indem einfach Kreise reingemalt werden.
il ist eine ImageList in der meine Figur und die Maske sind. (Das bin ich mit meinem Hündchen

Code: Alles auswählen
procedure TForm1.pbMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var bmp : TBitmap;
mask : TBitmap;
mw, mh : integer;
begin
bmp := TBitmap.Create;
mask := TBitmap.Create;
try
bmp.Assign(fBackGround);
bmp.canvas.CopyMode := SRCAND;
il.GetBitmap(1, mask); // Maske laden
mw := mask.Width;
mh := mask.Height;
bmp.Canvas.CopyRect(Rect(x, y, x+mw, y+mh), mask.canvas, Rect(0, 0, mw, mh));
il.GetBitmap(0, mask); // Figur laden
bmp.Canvas.CopyMode := MergePaint;
bmp.Canvas.CopyRect(Rect(x, y, x+mw, y+mh), mask.canvas, Rect(0, 0, mw, mh));
pb.canvas.copyrect(pb.clientrect, bmp.canvas, Rect(0, 0, bmp.width, bmp.height))
finally
mask.Free;
bmp.Free;
end;
end;
- Dateianhänge
-
- Figur
- yoshi_and_me.png (16.07 KiB) 4924 mal betrachtet
- kupferstecher
- Beiträge: 431
- Registriert: Do 17. Nov 2016, 11:52
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.Copy
Bist du dir da sicher? Beim Kopieren werden die kompletten Daten gelesen und wieder geschrieben, also doppelter Speicherzugriff. Da wird der Speicherzugriff schnell zum Flaschenhals. Anders sieht es vielleicht aus, wenn jede Zeile ein eigenes Control ist und verschoben wird, dann kann die Grafikkarte beim Verschieben unterstützen.Martin V hat geschrieben:Wenn man in einem Editor um eine Zeile hoch- bzw. runterscrollt, dann muss ja nur die unterste bzw. oberste Zeile neu geschrieben werden. Alle anderen Zeilen kann man als großes Rectangle vom vorherigen Zustand kopieren, was wesentlich schneller ist, als jedes Mal alle Zeilen neu zu schreiben.
-
- Beiträge: 142
- Registriert: Sa 30. Jan 2010, 19:35
- OS, Lazarus, FPC: Linux64, Wiindows32, MacOS, Lazarus 1.8.2
- CPU-Target: xxBit
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.CopyRect
Ich habe nun folgendes herausgefunden:
Zumindest bei WDsibyl wird auch ein darüberliegendes Fenster mitkopiert und es muss somit kontrolliert werden, dass das Fenster, wo schnell gescrollt werden soll, wirklich zuoberst liegt. Aus dem Bildschirm herausragen darf es auch nicht. In diesen Fällen funktioniert das Bildschirmspeicher-Kopieren nicht. In den meisten Fällen braucht man keinen Zwischenspeicher, aber es gibt Fälle, wo es doch nötig ist. Ich vermute, dass das bei Lazarus alles genauso ist.
Bei Lazarus benötigt man zur Kontrolle, ob das Fenster wirklich oben liegt (nicht nur bzgl. der App, sondern systemweit), ChangeBounds. Doch das ist in meiner älteren Lazarus Version 1.8.3 buggy, so dass ich die Routine zurückgestellt habe. (Ich habe mehrere Lazarus-Installationen auf mehreren Betriebssystemen und Computern, der Upgrade Aufwand ist bei mir hoch.)
Es gibt also doch einiges an Haken und Ösen. Der Geschwindigkeitseffekt ist nicht so groß wie ich erhoffte. Es ist schneller, aber nicht so viel schneller wie ich erwartete. Kupferstecher hat Recht, dass es nicht klar ist, dass es schneller ist. Das hängt vielleicht auch von Computer und Grafikkarte ab. Der Canvas-Speicher scheint nur dort zu existieren bzw. den richtigen Inhalt zu enthalten, wo es wirklich am Bildschirm auch abgebildet ist.
Zumindest bei WDsibyl wird auch ein darüberliegendes Fenster mitkopiert und es muss somit kontrolliert werden, dass das Fenster, wo schnell gescrollt werden soll, wirklich zuoberst liegt. Aus dem Bildschirm herausragen darf es auch nicht. In diesen Fällen funktioniert das Bildschirmspeicher-Kopieren nicht. In den meisten Fällen braucht man keinen Zwischenspeicher, aber es gibt Fälle, wo es doch nötig ist. Ich vermute, dass das bei Lazarus alles genauso ist.
Bei Lazarus benötigt man zur Kontrolle, ob das Fenster wirklich oben liegt (nicht nur bzgl. der App, sondern systemweit), ChangeBounds. Doch das ist in meiner älteren Lazarus Version 1.8.3 buggy, so dass ich die Routine zurückgestellt habe. (Ich habe mehrere Lazarus-Installationen auf mehreren Betriebssystemen und Computern, der Upgrade Aufwand ist bei mir hoch.)
Es gibt also doch einiges an Haken und Ösen. Der Geschwindigkeitseffekt ist nicht so groß wie ich erhoffte. Es ist schneller, aber nicht so viel schneller wie ich erwartete. Kupferstecher hat Recht, dass es nicht klar ist, dass es schneller ist. Das hängt vielleicht auch von Computer und Grafikkarte ab. Der Canvas-Speicher scheint nur dort zu existieren bzw. den richtigen Inhalt zu enthalten, wo es wirklich am Bildschirm auch abgebildet ist.
-
- Beiträge: 6912
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Scroll-Mechanismus oder wandernde Figur mit tCanvas.CopyRect
Wen du richtig Power willst, führt kein Weg an OpenGL vorbei. 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot