Entwickler-Ecke

Multimedia / Grafik - [Delphi] 2D-Landschaft Schwerkraft


95CAHEK95 - Fr 07.09.12 12:14
Titel: [Delphi] 2D-Landschaft Schwerkraft
Hi Leute,

ich hoffe ich bin hier ihm richtigem Forum.

Ihr kennt doch bestimmt alle diese Spiel, wo 2 Panzer sich gegenseitig beschießen.
Ich habe so was ähnliches nach programmiert, doch komme jetzt bei einer Sache nicht wirklich weiter.
Und zwar will es so machen, dass die losen Pixel nach der Explosion runter fallen.

Hier ist meine Procedure dafür:


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 TForm1.Test ();
VAR
   I, J, T: Integer;
   PFarbe: TColor;
BEGIN
     FOR T := 1 TO 5 DO //T steht für dich Anzahl der Schichten die runterfallen 
     FOR I := ExKoord.X - 20 TO  ExKoord.X + 20 DO // Bei den ExKoord.X und Y wird eine Ellipse gezeichnet
         FOR J := 1 TO ExKoord.Y + 20 DO
         BEGIN (* FOR J *)
              IF Landschaft.Canvas.Pixels [I, J] <> ClWhite
                 THEN
                     BEGIN (* IF <> ClWhite *)
                          PFarbe := Landschaft.Canvas.Pixels [I, J];
                          IF Landschaft.Canvas.Pixels [I, J + 1] = ClWhite
                             THEN
                                 BEGIN (* IF = ClWhite *)
                                 Landschaft.Canvas.Pixels [I, J] := ClWhite;

                                 Landschaft.Canvas.Pixels [I, J + 1] := ClRed;
                                 END(* IF = ClWhite *)
                     END(* IF <> ClWhite *)
         END(* FOR J *)
END;


Die Prozedur funktioniert auch, doch mein Problem ist das wenn man t vergrößert fängt das Spiel an zu laggen.

Hat wer eine bessere Lösung für mein Problem?

Würde mich über jeden Tipp freuen.

Moderiert von user profile iconMartok: Delphi-Tags hinzugefügt


Mathematiker - Fr 07.09.12 23:11

Hallo,
user profile icon95CAHEK95 hat folgendes geschrieben Zum zitierten Posting springen:
Die Prozedur funktioniert auch, doch mein Problem ist das wenn man t vergrößert fängt das Spiel an zu laggen.

Nach Stupipedia gilt:
Zitat:
Menschen, die älter sind als 4000 Jahre kennen das Wort "Laggen" nicht, wohl aber die Bedeutung, welche uns als soviel wie "Hängen" überliefert ist.

Ich bin noch nicht ganz 4000 Jahre, aber fast, und vermute, dass Du verlangsamen/verzögern meinst?
Aus Deinem Text entnehme ich, dass Du für jedes T (41 x ExKoord.Y + 20) Punkte abfragst und eventuell änderst. Wie groß wird denn ExKoord.Y? Sollte es mehrere Hundert Pixel umfassen, ist die Verzögerung so kaum vermeidbar.
Ein einfacher Vorschlag: In einem Feld die Position der dargestellten Pixel merken und nur deren Position ändern. Das Abfragen des ganzen Darstellungsbereichs kostet Zeit.
Aber so nebenbei: 2 Panzer ( :puke: ), die aufeinander schießen?! :?!?:
Wer will denn solchen Schrott sehen?
Beste Grüße
Mathematiker


Boldar - Sa 08.09.12 19:45

user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:

Aber so nebenbei: 2 Panzer ( :puke: ), die aufeinander schießen?! :?!?:
Wer will denn solchen Schrott sehen?
Beste Grüße
Mathematiker


naja, andere sind vielleicht von ständig neuen kontextlosen Mathematikfragen genervt. So doch jedem das Seine.


Mathematiker - Sa 08.09.12 22:10

user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
naja, andere sind vielleicht von ständig neuen kontextlosen Mathematikfragen genervt. So doch jedem das Seine.

Dass Du Mathematik kontextlos findest, naja, ist lustig und ich kann damit leben. Das hilft aber 95CAHEK95 nicht weiter. Ich habe es wenigstens versucht.

Aber "Jedem das Seine"?? Ein paar Links für Deine Weiterbildung:
http://www.hollbeck.net/2012/07/jedem-das-seine/
http://www.spiegel.de/schulspiegel/wissen/nazi-slogan-cdu-stoppt-kampagne-jedem-das-seine-a-612757.html
http://www.sopos.org/aufsaetze/3c7d45aeb2e57/1.phtml
Solltest Du meinen "Jeder soll das programmieren, was er gern möchte!", dann sag es auch und ich stimme Dir zu! Aber nicht so!
Mathematiker


95CAHEK95 - So 09.09.12 14:22

ExKoord gibt die Koordinaten des Einschlages an. Also wenn das Geschoss vom Panzer die Landschaft trifft.
Und dann wird ein Ellipse, mit (ExKoord.X - 20, ExKoord.Y -20, ExKoord.X + 20, ExKoord.Y +20) an dieser Stelle, gezeichnet.

Könntest du dein Vorschlag mir bitte nochmal genauer erklären?
Verstehe nicht wie ich das anstellen soll.

Und unser Lehrer will es sehen ;)


Mathematiker - So 09.09.12 14:38

user profile icon95CAHEK95 hat folgendes geschrieben Zum zitierten Posting springen:
ExKoord gibt die Koordinaten des Einschlages an. Also wenn das Geschoss vom Panzer die Landschaft trifft.
Und dann wird ein Ellipse, mit (ExKoord.X - 20, ExKoord.Y -20, ExKoord.X + 20, ExKoord.Y +20) an dieser Stelle, gezeichnet.
Könntest du dein Vorschlag mir bitte nochmal genauer erklären?

Nehmen wir an, dass Du 20 oder mehr Pixel verschieben möchtest. Dann wähle ich ein

Delphi-Quelltext
1:
var punkte : array[1..20of tpoint;                    

In diesem speicherst Du die Anfangswerte (irgendetwas in Deiner Ellipse) Deiner Pixel, z.B.

Delphi-Quelltext
1:
2:
3:
4:
for i:=1 to 20 do begin
  punkte[i].x:=exkoord.x-20 +irgendetwas;
  punkte[i].y:=exkoord.y-20 +irgendetwas;
end;

In einer Schleife (besser einem Timer) wird dann nur an den Stellen [punkte[i].x,punkte[i].y] die Hintergrundfarbe gesetzt, die y-Koordinate erhöht und am neuen Punkt die gewünschte Farbe gesetzt; bis zum Erreichen des Bodens.
Schön ist das nicht, aber wirksam. Da Du nur eine begrenzte Anzahl Punkte betrachtest, dürfte es schneller gehen, als die ganze Fläche zu testen.
user profile icon95CAHEK95 hat folgendes geschrieben Zum zitierten Posting springen:
Und unser Lehrer will es sehen ;)

Aber hallo! Dein Lehrer will eine Explosion nach einem Panzerbeschuss als Programm sehen? Was ist denn das für eine Schule? :hair:

Beste Grüße
Mathematiker


Martok - So 09.09.12 15:02

user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
user profile icon95CAHEK95 hat folgendes geschrieben Zum zitierten Posting springen:
Und unser Lehrer will es sehen ;)

Aber hallo! Dein Lehrer will eine Explosion nach einem Panzerbeschuss als Programm sehen? Was ist denn das für eine Schule? :hair:
Vermutlich eine, in der Informatiklehrer schonmal irgendwann in ihrem Leben einen Computer benutzt haben (wow, sowas gibts? :shock:) und deswegen das gute alte Scorched Tanks [http://www.youtube.com/watch?v=P-9O1TOSfCM] vom Amiga kennen. Für die Jüngeren unter uns: Worms.


Grundsätzlich solltest du (user profile icon95CAHEK95) auf Canvas.Pixels[] verzichten (das ist furchtbar langsam). Sinnvoller ist es, die Landschaft in einem TBitmap zu halten und nach den Berechnungen per Canvas.Draw auf die Ausgabe-Fläche zu malen.
TBitmap hat nämlich die Eigenschaft Suche in: Delphi-Forum SCANLINE, mit der du vieeel schneller auf Pixeldaten zugreifen kannst. 4000 Pixel (in deinem Beispiel) zu bearbeiten sollte damit nicht allzu lange dauern.


Mathematiker - So 09.09.12 15:53

Hallo Martok,
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Vermutlich eine, in der Informatiklehrer schonmal irgendwann in ihrem Leben einen Computer benutzt haben (wow, sowas gibts? :shock:) und deswegen das gute alte Scorched Tanks [http://www.youtube.com/watch?v=P-9O1TOSfCM] vom Amiga kennen.

Schlechte Erfahrungen mit Informatiklehrern gemacht? :wink:

user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
Grundsätzlich solltest du (user profile icon95CAHEK95) auf Canvas.Pixels[] verzichten (das ist furchtbar langsam). Sinnvoller ist es, die Landschaft in einem TBitmap zu halten und nach den Berechnungen per Canvas.Draw auf die Ausgabe-Fläche zu malen.
TBitmap hat nämlich die Eigenschaft Suche in: Delphi-Forum SCANLINE, mit der du vieeel schneller auf Pixeldaten zugreifen kannst. 4000 Pixel (in deinem Beispiel) zu bearbeiten sollte damit nicht allzu lange dauern.

Ich stimme Dir voll zu, vermute aber, dass 95CAHEK95 nun gar nicht mehr weiß, was er jetzt machen soll. Vielleicht kann er Deinem Link etwas entnehmen. Bleibt aber immer noch das Problem, wie er an das Bitmap kommt. Aber da gibt es ja http://www.entwickler-ecke.de/viewtopic.php?t=97312&highlight=bitmap+verwenden

Beste Grüße
Mathematiker


95CAHEK95 - So 09.09.12 18:07

Danke für eure Tipps :)

Doch leider komm ich irgendwie mit Scanline nicht klar :(
Die Landschaft habe ich als eine BitMap gemacht. Und die RGB - Werte der Pixel auszulesen,
habe ich auch geschaft. Doch wie kann ich jetzt nur bestimmte Pixel weiss anmalen?
Also die sozusagen fallen zulassen :?: :?:


Martok - So 09.09.12 19:17

user profile icon95CAHEK95 hat folgendes geschrieben Zum zitierten Posting springen:
Und die RGB - Werte der Pixel auszulesen,
habe ich auch geschaft. Doch wie kann ich jetzt nur bestimmte Pixel weiss anmalen?
Gebauso, wie du sie ausgelesen hast, nur andersrum. Der Einfachheit halber setze ich immer am Anfang das PixelFormat des Bitmaps auf pf32bit, also:

Delphi-Quelltext
1:
2:
3:
var Landschaft: TBitmap;
//...
Landschaft.PixelFormat:= pf32bit;

Das führt dazu, dass die Werte im passenden Format im Speicher liegen und wir uns nicht weiter drum kümmern müssen, das umzurechnen.


Wenn du jetzt den Pixel an (X, Y) bearbeiten willst, könntest du das so tun:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
var SLine: PCardinal;
//...

//Zeile holen, SLine Zeigt dann auf das erste Pixel der Zeile.
SLine:= Landschaft.ScanLine[Y];
//zum Pixel "spulen", d.h. "verschiebe SLine X-mal weiter"
inc(SLine, X);

//SLine ist ein Zeiger, d.h. es enthält nicht den Wert selber, sondern die Stelle im Speicher
//an der sich der (Farb)Wert befindet.
//Wir wollen aber den Wert erhalten/bearbeiten, müssen den Zeiger "de-referenzieren". Das macht der ^ -Operator.
if SLine^ = clWhite then
  SLine^:= clBlack;


Der Einfachheit halber könntest du das auch in 2 Hilfsfunktionen verpacken:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
function GetPixel(Bitmap: TBitmap; X, Y: integer): TColor;
var SLine: PCardinal;
begin
  SLine:= Bitmap.ScanLine[Y];
  inc(SLine, X);
  Result:= SLine^;
end;

procedure SetPixel(Bitmap: TBitmap; X, Y: integer; Color: TColor);
var SLine: PCardinal;
begin
  SLine:= Bitmap.ScanLine[Y];
  inc(SLine, X);
  SLine^:= Color;
end;

Die könntest du dann in deiner ursprünglichen Funktion statt den Zugriffen/Zuweisungen an Pixels verwenden und erstmal sehen, ob das vielleicht schon schnell genug ist.

Delphi-Quelltext
1:
IF GetPixel(Landschaft, I, J) <> ClWhite then //...