Entwickler-Ecke
Multimedia / Grafik - Einfache Methode Bewegung zu simulieren...
Mike_C - Sa 03.05.03 20:07
Titel: Einfache Methode Bewegung zu simulieren...
Hi
ich suche eine Möglichkeit auf einfachem weg eine bewegung zu simulieren.
Dazu folgende situation:
der spieler eines brettspiels (in meinem fall monopoly) hat die möglichkeit zu würfeln. abhängig von der würfelzahl, soll seine figur bewegt werden.
das spielfeld habe ich so auf die form gebracht:
ich habe eine TImagekomponente und habe dann über ein TBitmap eine grafik geladen
Quelltext
1: 2: 3: 4:
| bmp := TBitmap.Create; bmp.Loadfromfile(filename); image1.canvas.draw(0,0,bmp); bmp.free; |
das spart speicher....
zu meinem eigentlichen problem...
ich will die figur auf die gleiche speichersparende art "laden" und auf dem spielfeld plazieren. allerdings soll sie nicht auf die bitmap vom spielfeld gemalt werden (die bekommt man sonst nicht wieder runter), sondern so zu sagen eine ebene darüber.
ich hab keine ahnung, wie ich das machen kann. ich bräuchte eine möglichkeit, das ganze ohne eine zweite TImage-komponente zu lösen...
maximus - Mo 05.05.03 10:46
und was ist wenn dein spielfeld neugezeichnet werden muss...dann ist das bitmap nicht verfügbar, weil du es wieder freigegeben hast. Und fertig ist der salat...oder seh ich das falsch?
Mike_C - Mo 05.05.03 14:54
nicht, wenn ich den code in eine procedure Spieler.Draw packe und diese beim neuzeichnen aufrufe
tommie-lie - Mo 05.05.03 15:15
Ohne zweite TImage-Komponente wird das nicht gehen, denn ein Image hat nunmal nur ein Bitmap mit einem Canvas. Also könntest du mit manuellem Buffering arbeiten. Also erst alle anderen Sachen (Spielfelder, sondtige grafiken) und das dann in ein TBitmap im Hintergrund. Dann zeichnest du das Bitmap auf dein Image und zeichnest darüber die Spielfiguren. Beim nächsten Frame, also wenn sich die Figur einen Pixel weiterbewegt hat, zeichnest du wiede aus deinem Buffer (dem TBitmap) und darüber wieder deine Spielfigur, diesmal ein wenig woanders und immer so weiter.
Allerdings bringt deine Methode, Speicher zu sparen indem du das Bitmap jedesmal wieder freigibst, nichts, weil du durch das Laden wesentlich mehr Rechenzeit verbrätst, bei großen Bildern und langsamen Festplatten sogar mehr Leistung vebrauchst als die Speicherersparniss es ausgleichen würde. Im schlimmsten Fall (ich weiß nicht, was du vor und nach dem Laden machst) kann es angels gutem Speichermanager der heutigen Compiler (Borland oder MS, beide haben die gleichen Probleme) sogar zu einem erhöhten Speicherverbrauch kommen.
Es wäre also auf jeden Fall schneller, wenn du am Anfang einmal das Bitmap lädtst und dann immer wieder daraus zeichnest und am Ende wieder freigibst.
Mike_C - Mo 05.05.03 15:28
würde es so funktionieren:
ich nehme 2 bitmaps: die erste mit dem spielfeld und die zweite mit den anderen grafiken (figuren und so), dann definiere ich eine klasse TSpielfeld mit einer prozedur Draw, in der ich erst das spielfeld und dann die anderen grafiken zeichne und beide auf das canvas vom TImage lege?
an dieser stelle muss ich tommie wiedersprechen:
wenn ich mehrere instanzen von einem objekt erzeuge und mit ihnen arbeite, verbrauche ich auf jeden fall mehr speicher, als wenn ich die instanzen jedes mal wieder frei gebe! Grund: mit jeder operation in einer TBitmap-Instanz steigt der speicherverbrauch!!! wenn ich jedesmal eine grafik drüber male, wird der speicher, den ich vorher belegt habe nicht frei gegeben. was machen da rechner, die nicht so viel speicherkapzität habe? die haben glaub ich ein problem. und dieses problem dürfe größer sein, als die rechengeschwindigkeit, da ich ohne hin nicht vor habe, die figuren pixelweise zu bewegen! das ganze soll eher sprunghaft funktionieren!
Mike_C - Mo 05.05.03 15:53
ich hab's mal so versucht:
die Spielfeldklasse
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69:
| unit Spielfeld;
interface
uses Spieler, Windows, Classes, SysUtils, Graphics;
type TSpielfeld = class (TObject) protected Background, foreground: TBitmap; FCanvas: TCanvas;
FActPlayer: TSpieler; private
public constructor Create; virtual; destructor Destroy; override;
procedure Initialize; procedure SetActualPlayer(Player: TSpieler); procedure Draw; published property Canvas: TCanvas read FCanvas write FCanvas; end;
implementation
constructor TSpielfeld.Create; begin inherited; end;
destructor TSpielfeld.Destroy; begin background.Free; foreground.Free; inherited; end;
procedure TSpielfeld.Draw; begin Canvas.Draw(0,0,background); foreground.Canvas.draw(factplayer.Position.x,factplayer.position.y, factplayer.Bitmap); foreground.Transparent := true; foreground.Height := background.Height; foreground.Width := background.width; canvas.Draw(0,0,foreground); end;
procedure TSpielfeld.SetActualPlayer(Player: TSpieler); begin FActPlayer := Player; end;
procedure TSpielfeld.Initialize; begin Background := TBitmap.Create; Background.LoadFromFile('..\Graphic\Spielfeld.bmp');
Foreground := TBitmap.Create; FActPlayer := TSpieler.CreateColored('red'); end;
end. |
Die Spielerklasse:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46:
| unit Spieler;
interface
uses Windows, Graphics, Controls, ExtCtrls, Classes;
type TSpieler = class (TObject) protected FBMP: TBitmap; fPosition: TPoint; public constructor Create;virtual; constructor CreateColored(color: string); destructor Destroy; override; published property Bitmap: TBitmap read FBMP; property Position: TPoint read FPosition; end;
implementation
constructor TSpieler.Create; begin fbmp := TBitmap.Create; fPosition := Point(0,0); inherited; end;
constructor TSpieler.CreateColored(color: string); begin Create; fbmp.LoadFromFile('..\Graphic\man'+color+'.bmp'); fposition.x := 100; fposition.Y := 100; end;
destructor TSpieler.Destroy; begin fbmp.Free; inherited; end;
end. |
Das zeichnen:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| procedure TFormGameform.Button1Click(Sender: TObject); var Spielfeld : TSpielfeld; begin Spielfeld := TSpielfeld.Create; Spielfeld.Canvas := Image1.Canvas; Spielfeld.Initialize; Spielfeld.Draw; end; |
ich sehe aber nur die grafik vom spielfeld, nicht aber eine rote Figur. Kann mir jemand sagen, warum nicht?
maximus - Mo 05.05.03 16:30
Bei spielen hat man immer resourcen probleme...aber bei jedem frame alles neu zu laden ist gelinde gesagt grausam, derbst uneffizient und unprofessionell! -> bitte nicht persönlich nehmen, ich versuch dich nur davon abzuhalten einen fiesen architektonischen fehler zu machen :wink:
mimi - Mo 05.05.03 17:21
verwende DelphiX(DirecX) oder GLXTreen(OpenGl) damit ist das einfacher als mit Canvers:)
tommie-lie - Mo 05.05.03 17:51
| Mike_C hat folgendes geschrieben: |
an dieser stelle muss ich tommie wiedersprechen:
wenn ich mehrere instanzen von einem objekt erzeuge und mit ihnen arbeite, verbrauche ich auf jeden fall mehr speicher, als wenn ich die instanzen jedes mal wieder frei gebe! Grund: mit jeder operation in einer TBitmap-Instanz steigt der speicherverbrauch!!! wenn ich jedesmal eine grafik drüber male, wird der speicher, den ich vorher belegt habe nicht frei gegeben. was machen da rechner, die nicht so viel speicherkapzität habe? die haben glaub ich ein problem. und dieses problem dürfe größer sein, als die rechengeschwindigkeit, da ich ohne hin nicht vor habe, die figuren pixelweise zu bewegen! das ganze soll eher sprunghaft funktionieren! |
Mit Free wird aber nicht wirklich Speicher frei gegeben. Zumindest nicht für Windows. Der Speichermanager von Delphi holt den Speicher, und schaufelt da seine Daten aus der Klasse (TBitmap) rein. Beim .Free wird dann zwar der Speicher für andere Variablen des gleichen Prozesses frei gegeben, andere Programme können aber immer noch nicht auf den Speicher zugreifen. Das ist das gleiche Problem, das auftritt, wenn man Strings oder dynamische Arrays mehrmals in der Größe verändert (oder immer ein Zeichen dranhängt, das hatten wir hier irgendwann mal).
Außerdem sind die Pixel in einem Bitmap immer als Array gespeichert, dessen Dimensionen der Höhe und Breite entsprechen. Zeichnest du rein, werden die Werte im Array geändert, aber nicht die Größe des Arrays (das geschieht nur bei Größenänderungen). Ein weißes Bitmap braucht genausoviel Speicher, wie ein schwarzen oder ein rot-blau kariertes. Wenn du reinzeichnest, änderst du lediglich den Wert der im Array enthaltenen Integer-Werte.
Wenn du sie jedesmal freest und wieder createst, ist es Zufall, ob das alte "Speicherloch" noch frei ist. Wenn nicht, brauchst du mehr Speicher als wenn du das Bild im Speicher gelassen hättest.
Mike_C - Mo 05.05.03 17:51
problem: ich kann weder DelphiX noch OpenGL. Wie soll das also gehen?
mimi - Mo 05.05.03 18:12
lehren es, für DelphiX gibt es genügen tutors.....
(u.a eins von mir, hier im forum)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!