Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Flackern auf einer Map verhindern... (https://www.delphipraxis.net/46054-flackern-auf-einer-map-verhindern.html)

Master_RC 17. Mai 2005 15:51


Flackern auf einer Map verhindern...
 
hi leutz!

heute schon der 3. thread zu meinem RPG ;)

yo...
ganz schnell:
wie kann ich es verhindern, dass meine Map/Karte bei jedem Neuzeichnen flackert?
bzw... kann wer folgende funktion verbessern?
Delphi-Quellcode:
procedure MapRenew;
var aai,i,ii,iii: integer; MyRect,MyRect2: TRect; bitmap: TBitmap; ctype: string; center: TPoint;
begin
 if map[charx,chary].Begehbar = false then begin
  charx := map[0,0].startx;
  chary := map[0,0].starty;
  form1.Popup1.Title := 'ACHTUNG:';
  form1.Popup1.Text := 'Der Charakter war auf einem unzulässigen Feld! Er wurde zurückgesetzt!';
 end;
ctype := ini.ReadString('Char','type','');
MyRect2 := Rect(0,0,32,32);
if charx < 1 then charx := 1;
if chary < 1 then chary := 1;
character.mapx := charx;
character.mapy := chary;

form5.paintbox1.canvas.brush.style := bsclear;

center := Point(form5.Paintbox1.Width div 2-16,form5.Paintbox1.Height div 2-16);

for i := -2 to 2 do
  for ii := -2 to 2 do
    try
     MyRect := Rect(i*32+center.x,ii*32+center.y,i*32+center.x+32,ii*32+center.y+32);
     Bitmap:=TBitmap.Create;
      if (charx+i > 0) and (chary+ii > 0) then begin
      if FileExists('IMG/Map/'+map[charx+i,chary+ii].Textur) then begin
        Bitmap.LoadFromFile('IMG/Map/'+map[charx+i,chary+ii].Textur);
      end else Bitmap.LoadFromFile('IMG/Map/none.bmp');
      end else
        Bitmap.LoadFromFile('IMG/Map/none.bmp');
        form5.PaintBox1.Canvas.BrushCopy(MyRect,Bitmap,MyRect2,clfuchsia);
      if (charx+i > 0) and (chary+ii > 0) then begin
        if map[charx+i,chary+ii].Textur2 <> '' then begin
          Bitmap.LoadFromFile('IMG/Map/'+map[charx+i,chary+ii].Textur2);
          form5.PaintBox1.Canvas.BrushCopy(MyRect,Bitmap,MyRect2,clfuchsia);
        end;
      end;
    finally

    end;
MyRect := Rect(center.x,center.y,center.x+32,center.y+32);
 if fileexists('DATA/TEMPLATES/'+ctype+'/char_'+character.gender+'.bmp') then begin
   Bitmap.LoadFromFile('DATA/TEMPLATES/'+ctype+'/char_'+character.gender+'.bmp');
 end else begin
   Bitmap.LoadFromFile('IMG/Map/nochar.bmp');
 end;
form5.PaintBox1.Canvas.BrushCopy(MyRect,Bitmap,MyRect2,clfuchsia);
{for i := 0 to 1000 do begin
 if NPCs[i].name <> '' then begin
  Bitmap.LoadFromFile(NPCs[i].smallpic);
  //MyRect := Rect((NPCs[i].x+center.x)*32,(NPCs[i].y*+center.y)*32,(NPCs[i].x+center.x)*32+32,(NPCs[i].y+center.y)*32+32);
  MyRect := Rect(i*32+center.x,ii*32+center.y,i*32+center.x+32,ii*32+center.y+32);
  form5.PaintBox1.Canvas.BrushCopy(MyRect,Bitmap,MyRect2,clfuchsia);
 end;
end;}
for iii := 0 to 1000 do begin
 if NPCs[iii].name <> '' then begin
  for i := -2 to 2 do begin
   for ii := -2 to 2 do begin
    if NPCs[iii].x = charx + i then begin
     if NPCs[iii].y = chary + ii then begin
      Bitmap.LoadFromFile(NPCs[iii].smallpic);
      MyRect := Rect(i*32+center.x,ii*32+center.y,i*32+center.x+32,ii*32+center.y+32);
      form5.PaintBox1.Canvas.BrushCopy(MyRect,Bitmap,MyRect2,clfuchsia);
     end;
    end;
   end;
  end;
 end;
end;
viel spaß beim lesen ;)

Filou 17. Mai 2005 15:52

Re: Flackern auf einer Map verhindern...
 
Schon
Code:
doublebuffered:=true;
eingestellt?

Master_RC 17. Mai 2005 15:55

Re: Flackern auf einer Map verhindern...
 
ja, also meine paintbox1 liegt auf:

Form5 => Groupbox1 (oder 2) => pbox1

ich habs sowohl bei der form, als auch bei der groupbox angemacht => nix :(

Spessi 18. Mai 2005 02:24

Re: Flackern auf einer Map verhindern...
 
Also, ich habe es bei mir direkt ins OnCreate-Ereignis der Form geschrieben, bei mir flackert nichts.. Aber ich glaub da war noch was, was ich auch umgestellt habe, mir fällts aber im moment echt nich ein, ist ja auch schon spät :) Ich guck heut abend wenn ich aufwache nochmal, evtl. find ich was.

(Oder war es doch nur DoubleBuffered:=true? Naja, wie gesagt, ich guck dann nochmal)


mfg Spessi

Luckie 18. Mai 2005 02:48

Re: Flackern auf einer Map verhindern...
 
Zeichne alles auf ein Bitmap im Speicher und kopiere das dann mit BitBlt auf den Canvas der Paintbox.

Thebe 18. Mai 2005 07:44

Re: Flackern auf einer Map verhindern...
 
1. das TBitmap.Create VOR die zwei ineinander verschachtelten FOR Schleifen packen, das Bitmap wird immer wieder neu kreiert für jedes Map Tiles und das alte nicht freigegeben.

2. Ein Bitmap.Free am Ende der Procedure wäre auch nicht schlecht.

3. Du solltest die Bitmaps für jedes Tile Art im Speicher vorrätig lassen, die BMPs immer und immer wieder von der Platte auszulesen ist absoluter Käse, die Festplatte ist nicht ansatzweise so schnell wie der RAM Speicher.

4. Eine Map besteht eigentlich immer aus 3 Ebenen (Layer). Einmal der Map Untergrund der sich so schnell nicht ändern (sprich fast schon einmal zeichnen und gut is), dann der Items Layer der sich durch deine / NPC Interaktion ändern kann und letztendlich der Char Layer. Um bisschen Optimierung reinzukriegen, erstell eine Bitmap wo einmal (wenns gebraucht wird) die Map Tiles drauf gezeichnet werden und gut ist. Dann kannst Du deine Items und Chars über diesen Untergrund laufen lassen..


Ach ja, ich weiß Du wirst mich hassen, aber in deinem Interesse empfehle ich Dir: Lern ein bisschen OOP.

Delphi-Quellcode:
for iii := 0 to 1000 do begin
if NPCs[iii].name <> '' then begin
Vielleicht kannst Du so ein Zeug momentan noch machen, nur irgendwann wirste damit so richtig Probleme kriegen. Sieh es als Erfahrungs- und Weiterbildungschance an.

Master_RC 18. Mai 2005 09:07

Re: Flackern auf einer Map verhindern...
 
iss mir ja klar, dass es einige kritik gibt -> immerhin hab ich ja nach verbesserungen gesucht :)

also...
wie soll ich denn dann die karte aufbauen, wenn es denn nach OOP laufen soll?
bis jetzt isses "map: array[0..5000,0.5000] of TFeld" (oder so ähnlich)

gut...
wegen dem BitBlt:
Die Funktion hoffe ich steht in der Delphi-Hilfe :)
Und wie zeichne ich dann auf ein Bitmap im SPeicher?
einfach bitmap.create und dann per canvas genauso die bilder draufhaun wie bei der paintbox per canvas (hätt ich mir jetzt mal so vorgestellt :gruebel: )

und wie soll ich dann die ganzen bilder zwischenspeichern? :(

Thebe 18. Mai 2005 11:30

Re: Flackern auf einer Map verhindern...
 
Zitat:

also...
wie soll ich denn dann die karte aufbauen, wenn es denn nach OOP laufen soll?
bis jetzt isses "map: array[0..5000,0.5000] of TFeld" (oder so ähnlich)
Tut mir leid, aber die 2D Tile Matrix einer 2D Map ist das letzte was man OOP-mäßg machen kann. Wäre das eine 3D Map, wäre das schon wieder was anderes...

Anderes Beispiel: Charaktere...

Chars haben in den meisten RPGs Attribute wie Stärke, Intelligenz, Lebenspunkte, Mana, was weiß ich..
Diese 4 Beispiele wären innem Record einfach nur Variablen vom Typ Byte z.B. Nu haste ne Code Passage - meinetwegen im Programmcode für den Kampf, ein Char trifft den anderen mit nem Schwert - in der es heißt

Delphi-Quellcode:
if DerAndereCharWurdeGetroffen then
   DerAndereCharRecord.Lebenspunkte := DerAndereCharRecord.Lebenspunkte - 10;
Nu musst Du direkt danach darauf eingehen was dem anderen Char passiert. Stirbt er ? Kommt er in einen kritischen Bereich mit der Lebensenergie bei dem seine Stärke vllt halbiert wird ? Wenns Du es mit Records angehst, musst du bei JEDER Zuweisung einer Variablen selbstständig checken was im Anschluß darauf passiert. Mag bei dieser einen Passage schnuppe sein, weil das is dann ein Aufruf von einer Procedure hintendran mehr. Aber glaub mir, es wird nicht bei dieser einen Passage bleiben (Ich bin z.Zt. der Programmierteil von einem Ultima Online Freeshard (MMORPG), ich weiß wie dreckig anstrengend so ein Teil werden kann).

Nimm statt dessen lieber Klassen und statt Variablen Properties. Jedesmal wenn der Variable was zugewiesen wird, kannst Du in dem speziellen Fall drauf reagieren und musst das ganze nur einmal programmieren, sprich Ereignisorientiert programmieren, den Rest erledigt Delphi für Dich.

Nächstes Beispiel: Wie ich schon sagte, alles was Du an Bitmaps hast EINMAL einladen, dann immer aus diesen Bitmaps zeichnen. Bei ner Klasse kannst schon gleich im Konstruktor die Bitmap einladen, im Destruktur wird sie freigegeben. Zwischendurch kannst immer druff zugreifen und brauchst Dich sonst um nichts kümmern.

Nächstes Beispiel: Waffen, Items, Monster, alles Mögliche..
Man programmiert für die eine Grundgattung (meinetwegen Waffen) eine Basisklasse, sei es nun TBaseWeapon. Davon leitest Du die anderen Klassen ab, z.b. TBastardschwert. Wenn Du nun in der basisklasse das Grundverhalten von Waffen programmierst, wirkt sich das auf alle Nachfahren dieser Klasse aus, Du brauchst in deinem TBastardschwert nur vllt die Eigenschaften wie Schaden, Schadenstyp usw. ändern. Das wars.

Was aber nun, wenn Du mit deinen Records ein Schwert hättest, was ein komplett anderes Verhalten hat als z.b. so nen Standard Schwert. Lass es ein vergiftetes Schwert sein, oder eins was gelb leuchtet un den Gegner in Flammen steckt. Du musst beim Schadenscode überall abchecken, welches Schwert benutzt wird und darauf reagieren. Dadurch wird dieser Programmcode lang, kompliziert und unübersichtlich. Mit meiner Methode würdest einfach ein TFlammenschwert von TBaseWeapon ableiten und eine Methode überschreiben, die den Schaden zufügt.

Nächstes Beispiel: Interfaces
Ein Interface in einer Klasse zu implementieren bedeutet, man Klassen ansprechen, die nicht von einander abgeleitet sind, bzw. einen gleichen Vorfahren besitzen.
Bei Ultima Online (RunUO Server) gibbets ein Interface namens IEntity. Das beherbergt die Felder X, Y, Z, MapPlane (gibt verschiedene Maps dort). Dieses IEntity ist in der Basisklasse für Items und für Chars drinne. Ich könnte somit also einfach über dieses Interface gleichermaßen Items und Chars ansprechen, ohne mit der Wimper zu zucken was ich da nun eigentlich verschiebe. Mit Records musst Du entweder erstmal überladene Proceduren machen, die entweder Items oder Chars als Parameter annehmen ODER aber Du musst eine allgemeine Procedure machen und dann in dieser Procedure nachchcecken was Du eigentlich verschiebst und dann darauf reagieren.

Ich weiß Du siehst momentan nicht wirklich den Sinn dahinter, warum Du auf OOP umsteigen solltest und ich muss auch eingestehen, ich weiß noch nit wie fortgeschritten dein Spiel ist. Aber ich weiß GANZ GENAU, sobald das Ding an Komplexität zunimmt die über hin und her gehen und Chars anschnacken hinausgeht, wirst Du Dich vor lauter IF-Bedingungen nicht mehr retten können, solltest Du auf der Records-Schiene draufbleiben. Drum tu Dir selbst ein Gefallen, wechsel auf Klassen. Wenn erstmal das Spiel komplex ist, kannste das knicken, dann stampfst Du alles ein und fängst von vorne an weil Du kein Land mehr siehst.

- Thebe

Master_RC 18. Mai 2005 12:19

Re: Flackern auf einer Map verhindern...
 
vielen dank!! hat mir sehr geholfen! :top:

nur...
ich hab mit klassen sehr wenig erfahrung.. :(

was meien map anbelangt sollte sie so bleiebn, wenn ich richtig gelesen hab...

und das mit den if-gewurschtel ist schon passiert (noch blick ich noch durch! :D )

das mit den bitmaps würde ich mir dann so vorstellen, dass ich einen array mach und in den dann alle (bekannten) bilde reinlad, bzw. dann eben ausles. richtig so?

yo...

Thebe 18. Mai 2005 14:08

Re: Flackern auf einer Map verhindern...
 
in etwa
wenn Du mir noch sagst welche "Felder" in dem Record für deine Map und deine Chars drinne is kann ich Dir nen Beispiel schreiben wie man da sehr schön was draus mit ner Klasse machen kann..


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:10 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz