| Autor |
Beitrag |
Daether
      
Beiträge: 21
|
Verfasst: Do 18.08.05 13:17
Moin,
habe bie meinem Spiel ein paar fortschirtte gemacht, dank eurer Hilfe. Nun brauche ich wieder eure Hilfe.
Wie kann ich das Drawgrid dazu bringen, die gezeichnetetn Bitmaps nicht selbst wieder zu übermalen.
Ich weiß, dass man das Ereigniss onDrawCell nehmen muss und habe folgendes eingefügt:
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure TFormSpielfeld.DrawGridSpielfeldDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); begin DrawGridSpielFeld.refresh; end; |
desweiteren, lasse ich so die Bilder malen:
Delphi-Quelltext 1:
| FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(i*35,j*35,Bitmap); |
Wie kriege ich das Drawgrid dazu nicht in eine Endloschleife zu verfallen (wie momentan) und wie kriege ich es dazu die Bitmaps stehen zu lassen?
|
|
SMO
      
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Do 18.08.05 15:21
Wenn ein DrawGrid gezeichnet wird, dann ruft es für jede einzelne Zelle einmal OnDrawCell auf (natürlich nicht jedesmal für alle Zellen, sondern nur für diejenigen, die auch tatsächlich neu gezeichnet werden müssen). Du musst den Inhalt einer Zelle also im OnDrawCell Ereignis zeichnen, nicht vorher und nicht nachher!
Dein jetziger OnDrawCell-Code DrawGridSpielFeld.refresh; ist Quatsch, denn Refresh veranlasst, dass das DrawGrid sofort neu gezeichnet wird, was zur Folge hat, dass wieder OnDrawCell aufgerufen wird... daher die Endlosschleife.
|
|
Daether 
      
Beiträge: 21
|
Verfasst: Do 18.08.05 16:51
ist diese Prozedur denn jetzt richtig?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| procedure TFormSpielfeld.DrawGridSpielfeldDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var i,j: integer; Bitmap: TBitmap; begin Bitmap:= TBitmap.Create; for i:=0 to strtoint(FormStartbedingungen.EditBreite.text)-1 do begin for j:=0 to strtoint(FormStartbedingungen.EditHoehe.Text)-1 do begin if Spiel.Spielfeld[i,j].Planet.Name ='Planetwueste' then begin Bitmap.LoadFromFile('PlanetWueste.bmp'); FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(i*34,j*34,Bitmap); end else begin Bitmap.LoadFromFile('All.bmp'); FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(i*34,j*34,Bitmap); end; end; end; end; |
Denn das Problem dabei ist, dass ich an die 100x100 Felder habe und sobald ich nur eines anklicke alle anderen neu gezeichnet werden.
|
|
SMO
      
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Do 18.08.05 17:06
Nein, nicht ganz richtig. Du zeichnest jetzt in OnDrawCell mit den beiden Schleifen ALLE Zellen. Du sollst aber nur EINE Zelle zeichnen, nämlich genau diejenige, die durch die Parameter ACol, ARow und Rect angegeben wird. Außerdem vergisst du, das Bitmap mit Bitmap.Free wieder freizugeben, das ist nicht gut. Besonders effizient ist dein Vorgehen auch nicht, aber bevor man das optimiert, solltest du erstmal die Funktionsweise des DrawGrids verstanden haben.
|
|
Daether 
      
Beiträge: 21
|
Verfasst: Do 18.08.05 20:01
Ich glaube ich verstehe was du meinst. Habe die Prozedur nun umgeschrieben und habe das Problem nichtmehr, ich kann einzelne Bilder anklicken und auch Markierungen ziehen, ohne das ein Problem auftritt.
Anbie mal mein Code:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TFormSpielfeld.DrawGridSpielfeldDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var i,j: integer; Bitmap: TBitmap; begin Bitmap:= TBitmap.Create; if Spiel.Spielfeld[Acol,Arow].Planet.Name ='Planetwueste' then begin Bitmap.LoadFromFile('PlanetWueste.bmp'); FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(ACol*34,ARow*34,Bitmap); end else begin Bitmap.LoadFromFile('All.bmp'); FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(ACol*34,ARow*34,Bitmap); end; Bitmap.free; |
Ich habe das Bitmap nun frei gegeben und ich könnte (muss später) das ganze umstellen und anstatt mit if/then, case/of benutzten.
Danke schonmal für die Hilfe!
Aber ich habe jetzt ein ähnlich neues Problem. Wie kann ich die Bilder zeichnen und "verschieben", wenn ich die Scrollleisste eines Drawgrids benutze? Denn immer wenn ich die Scrollleisten bewege zeichnen sich die Bilder nicht neu, da ich ja onDrawCell so eingestellt habe, das die markierte Zelle gemalt wird.
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Do 18.08.05 20:21
Daether hat folgendes geschrieben: |
Aber ich habe jetzt ein ähnlich neues Problem. Wie kann ich die Bilder zeichnen und "verschieben", wenn ich die Scrollleisste eines Drawgrids benutze? Denn immer wenn ich die Scrollleisten bewege zeichnen sich die Bilder nicht neu, da ich ja onDrawCell so eingestellt habe, das die markierte Zelle gemalt wird. |
wo hast du denn die Abfrage, das du nur die markierte Zelle zeichnest? Du fragst den State doch gar nicht ab.
Aber die Funktionsweise von drawcell hast du auch nicht verstanden und es gibt hier im Fourm auch genügend CodeBeispiele, wirklich. Dein Problem beim scrollen rührt denke ich mal hiervon:
Delphi-Quelltext 1:
| FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(ACol*34,ARow*34,Bitmap); |
richtig wäre:
Delphi-Quelltext 1:
| FormSpielfeld.DrawGridSpielfeld.Canvas.Draw(rect.left,rect.top,Bitmap); |
rect ist die zu zeichnende Zelle, es ist nicht notwendig, das selber auzurechnen.
und zur Effizienz:
Wenn du jedesmal bei ondrawcell die Bitmap erstellst, ist das ein Performancekiller. In diesem Fall ist eine globalere Veriable besser angebracht und die Bitmap wird 1x erstellt und freigegeben, aber auch das brauchst du nicht, s.u..
Desweitern wird sich das loadfromfile auch nicht grad gut machen. Jedesmal, wenn die Zelle neu gezeichnet wird (Scrollen, Selektionsänderung, ...), lädst du das Bitmap von der Platte. Außerdem beuntzt Du nur relative Pfade und die werden dich irgendwann sicher vor Probelem stellen.
Erstell dir besser eine Liste/Array/Imagelist, wo du deine Bilder am Programmstart reinlädst. Bei Ondrawcell zeichnest du dann das entsprechende Bild aus der Liste und lädst es nicht erst von der Platte.
Mfg Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
SMO
      
Beiträge: 120
Erhaltene Danke: 18
D2005 Personal
|
Verfasst: Do 18.08.05 20:28
Jepp, wie Keldorn bereits geschrieben hat, dein Problem beim Scrollen kommt daher, dass du versuchst, die Canvas-Position der Zellen selbst auszurechnen anstatt den Rect Parameter dafür zu verwenden.
Statt Canvas.Draw kannst du übrigens auch Canvas.StretchDraw benutzen, dann wird dein Bitmap auf Zellengröße skaliert, falls es kleiner oder größer ist:
Delphi-Quelltext 1:
| DrawGridSpielfeld.Canvas.StretchDraw(Rect, Bitmap); |
|
|
Daether 
      
Beiträge: 21
|
Verfasst: Do 18.08.05 20:43
Danke für eure Hilfe.
Wenn wir schon dabei sind und ihr noch Zeit habt  :
Ich werde es mal mit dem "BilderArray" versuchen.
Mal ne Frage Dazu, wie mache ich das mit Bitmap create und free?
Das ist meine momentane Struktur die in einer einzelnen UnitFunktionen ist: Delphi-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:
| type TBild = record Name : string; Bitmap : TBitmap; end; TBilder = array of TBild; TPlanet = record Name : string; end; TSchiff = record Name : String; end; TFeld = record Planet : TPlanet; Schiffe : array of TSchiff; end; TSpielfeld = record Spielfeld : array of array of TFeld; end; TSpiel = class private public procedure Neuesspiel(Breite,Hoehe : integer); end;
var Spiel : TSpielfeld; Spielfunktionen : TSpiel; |
So könnte ich ja den Array (dynamisch) mit einer procedur füllen und alle Bilder in die "Bitmap"-Variablen reinladen. Muss ich die dann alle noch vorher createn? Wenn ja, wie lege ich fest wann sie auf free gesetzt werden?
|
|
|