Autor Beitrag
MaxMüller123
Hält's aus hier
Beiträge: 6



BeitragVerfasst: So 04.01.09 20:55 
Hi,
ein Kumpel und ich programmiern für die Schule ein kleines Spiel. Hierfür bräuchte ich die Animation eines Flußes in 2d.
Trotz mittlerweilen schon ein paar Jahren Info bin ich nun wirklich nicht so der Pro, von daher bitte Rücksicht nehmen sollte die Frage etwas bescheuert klingen.
Die Flußanmation soll nicht sehr aufwendig sein und vertikal verlaufen.
In der Schule hatten wir mal ne Sinuskurve, diese wollte ich nun verwenden, indem ich mehrere Sinuskruven eng nebeneinander ablaufen lasse ( Farbe: Blau --> Fluss )
Der Quelltext sieht so aus:

ausblenden volle Höhe 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:
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:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
...
var sh1: array[1..100of tshape;
    sh2: array[1..100of tshape;
    sh3: array[1..100of tshape;
    sh4: array[1..100of tshape;
    sh5: array[1..100of tshape;
    zeit:integer=0;
    start:boolean=false;
    interferenz:boolean=false;
    Amplitude, Frequenz: integer;
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var   i: integer;
begin
For i:= 1 To 100 Do begin
sh1[i]:=tshape.create(form1);
sh1[i].parent:=form1;
sh1[i].Width:=15;
sh1[i].Height:=15;
sh1[i].Shape:=stRoundSquare;
sh1[i].Brush.color:=clblue;
sh1[i].Pen.color:=clblue;
sh1[i].Top:=216;
sh1[i].Left:=18+i*5;
end;

For i:= 1 To 100 Do begin
sh2[i]:=tshape.create(form1);
sh2[i].parent:=form1;
sh2[i].Width:=15;
sh2[i].Height:=15;
sh2[i].Shape:=stRoundSquare;
sh2[i].Brush.color:=clblue;
sh2[i].Pen.color:=clblue;
sh2[i].Top:=216;
sh2[i].Left:=18+i*5;
end;

For i:= 1 To 100 Do begin
sh3[i]:=tshape.create(form1);
sh3[i].parent:=form1;
sh3[i].Width:=15;
sh3[i].Height:=15;
sh3[i].Shape:=stRoundSquare;
sh3[i].Brush.color:=clblue;
sh3[i].Pen.color:=clblue;
sh3[i].Top:=216;
sh3[i].Left:=18+i*5;
end;

For i:= 1 To 100 Do begin
sh4[i]:=tshape.create(form1);
sh4[i].parent:=form1;
sh4[i].Width:=15;
sh4[i].Height:=15;
sh4[i].Shape:=stRoundSquare;
sh4[i].Brush.color:=clblue;
sh4[i].Pen.color:=clblue;
sh4[i].Top:=216;
sh4[i].Left:=18+i*5;
end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var   i: integer;
begin

Amplitude:=StrToInt(EAmplitude.Text);
Frequenz:=StrToInt(EFrequenz.Text);
inc(zeit);

For i:= 1 To 100 Do begin
sh1[i].Top:=220+round(Amplitude*sin((2*pi/Frequenz)*(zeit-sh1[i].Left/5)));
end;

For i:= 1 To 100 Do begin
sh2[i].Top:=235+round(Amplitude*sin((2*pi/Frequenz)*(zeit-sh2[i].Left/5)));
end;

For i:= 1 To 100 Do begin
sh3[i].Top:=250+round(Amplitude*sin((2*pi/Frequenz)*(zeit-sh3[i].Left/5)));
end;

For i:= 1 To 100 Do begin
sh4[i].Top:=265+round(Amplitude*sin((2*pi/Frequenz)*(zeit-sh4[i].Left/5)));
end;
...


Nun 2 Fragen hierzu:
1. Wie bekomme ich diese Sinuskurven in die vertikale ( wenn möglich biite auf einfachen Niveau erklärt ;-D ) ??

2. Bei der Animation entsteht ein Flackern, wie lässt sich dieses ausschalten?

Danke schonmal, hoffe euch nicht mit meinem Text erschlagen zu haben,
Mfg Martin

PS: Falls jemand noch eine andere Methode zur Animation des Flußes einffällt, die nicht allzu kompliziert ist, nur her damit ...

Moderiert von user profile iconAXMD: Quote- durch Delphi-Tags ersetzt
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 04.01.09 21:46 
user profile iconMaxMüller123 hat folgendes geschrieben Zum zitierten Posting springen:
1. Wie bekomme ich diese Sinuskurven in die vertikale ( wenn möglich biite auf einfachen Niveau erklärt ;-D ) ??
Top und Left umgekehrt verwenden? Wenn ihr verstanden habt was da passiert, dann sollte da eigentlich klar sein.

user profile iconMaxMüller123 hat folgendes geschrieben Zum zitierten Posting springen:
2. Bei der Animation entsteht ein Flackern, wie lässt sich dieses ausschalten?
Mit derart vielen Shapes sei froh, dass das überhaupt läuft. :lol:
Aber DoubleBuffered auf True setzen könnte evtl. helfen.

user profile iconMaxMüller123 hat folgendes geschrieben Zum zitierten Posting springen:
PS: Falls jemand noch eine andere Methode zur Animation des Flußes einffällt, die nicht allzu kompliziert ist, nur her damit ...
Selbst zeichnen, z.B. in ein TImage oder eine TPaintBox.
MaxMüller123 Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Mi 07.01.09 02:57 
Hi,
erstmal danke für deine Hilfe!!
Der Fluss ist mittlerweile zwar nicht ganz vertikal, aber ich hab ihn soweit drehen können, durch ein ausprobieren und dem vertauschen der top, left-pos, dass es passt. Das Flimmern ist auch ganz weg.
Das Problem immoment ist jedoch, dass der Fluss, wohl aufgrund der vielen Shapes, den CPU so belastet, dass z.B. das Boot, welches über dem Fluss soll, sich nur ruckhaft bewegt.
Gibt es eine Möglichkeit diesen krassen Leistungsanspruch zu reduzieren oder ist das, vorrausgesetzt man verwendet die Shape-Version, nicht möglich?
Du sprachtest ja auch von der Möglichkeit den Fluss selbst zu zeichnen, mit 'TImage' oder 'TPaintBox', könntest du das bzw. alle anderen die das lesen ;-D, nocheinmal genauer erläutern ( hab bisher nie damit gearbeitet ), wäre auch ein bewegter Fluß mit dieser Methode möglich?
Sollte jemand hierfür ein geeigntes Tutorial kennen oder sonst irgendetwas mit dem man einen 'lebendigen' Fluss mit Delphi erschaffen kann ----> BITTE POSTEN :wink:.
Danke nochmal -schonmal,
Mfg Martin
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mi 07.01.09 03:29 
Wie wäre es zum Beispiel so?
ausblenden volle Höhe 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:
28:
29:
30:
31:
32:
33:
34:
35:
36:
var
  Form1: TForm1;
  zeit: Integer = 0;
  start: Boolean = false;
  interferenz: Boolean = false;
  Amplitude, Frequenz: Integer;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 1 to 100 do
    Canvas.Pixels[21618+i*5] := clBlue;
end;

procedure TForm1.tmrAnimateTimer(Sender: TObject);
var
  i: Integer;
begin
  Amplitude := StrToInt(EAmplitude.Text);
  Frequenz := StrToInt(EFrequenz.Text);
  Inc(zeit);
  Canvas.Rectangle(00, Width, Height);

  for i:= 1 to 100 do
  begin
    Canvas.Pixels[220+round(Amplitude*sin((2*pi/Frequenz)*(zeit-18+i*5/5))), 18+i*5] := clBlue;
    Canvas.Pixels[235+round(Amplitude*sin((2*pi/Frequenz)*(zeit-18+i*5/5))), 18+i*5] := clBlue;
    Canvas.Pixels[250+round(Amplitude*sin((2*pi/Frequenz)*(zeit-18+i*5/5))), 18+i*5] := clBlue;
    Canvas.Pixels[265+round(Amplitude*sin((2*pi/Frequenz)*(zeit-18+i*5/5))), 18+i*5] := clBlue;
  end;
end;
Natürlich kannst du dort auch stattdessen Kreise zeichnen statt nur ein Pixel zu färben. ;-)

Und wenn du noch eine TPaintbox mit Hintergrundbitmap und DoubleBuffered := True benutzt, dann flackert es auch weniger.
MaxMüller123 Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Sa 10.01.09 01:48 
Hi,
danke nochmals für deine schnelle und kompetente Hilfe jedesmal, hab erstmal einige zeit gebraucht um hinter deinen Lösungsansatz mit dem Färben der Pixel zu kommen. ALlerdings tritt bei dieser Variante das Problem auf, dass das Rectangle, welches die "alten Pixel" immer wieder löscht bzw. übermalt, dann auch die Shapes des Bootes welchen den dargestellten Fluss runterfährt, überzeichnet.
Das Verwenden der TPaintbox bzw. OffscreenBitmap ist mir noch immer etwas schleierhaft (geflackert hatte es jedoch auch vorher nicht, da ich "DoubleBuffered" schon auf true hatte).

Letzendlich habe ich nun einfach die Anzahl der Shapes, die ich in meinen Lösungsansatz benutzt habe, stark reduziert und die Breite der überiggebliebenen erhöht, damit geht es auch und die CPU Auslastung ist annehmbar. Das Thema "Fluss" ist somit nun erstmal abgehakt.

Mein nächtes Problem ist, dass ich eine Figur ( Schaf ), welches ich als TImage eingebunden haben gerne bewegen lassen würde. Das klappt über
'Image.left:= Image.left + 1; '
im Timer auch gut. Um die Bewegung flüssiger erscheinen zu lassen habe ich jetzt noch ein weiteres Bild, indem das Schaf die Beine zusammenklappt.
Meine Frage nun: Wie ist es möglich in einem Image Feld mit leichter Zeitverzögerung ( also noch gut sichtbar ), immer abwechselnd zwei verschiedene Bilder zu laden.
Ich habe auch schon eine ImageList erstellt, die Bilder hier sind aber irgendwie winzig und wie ich sie zum austauschen bringe weiß ich auch nicht (über die ImageList). Gibt es hierfür einen möglichst gut nachvollziehbaren Lösungsweg?
Im weiteren Bezug hierzu noch, ist es möglich das Schaf irgendwie transparent bzw. ausgeschnitten darzustellen?

Danke wirklich für die Mühe, das hier zu lesen ;-D.
Mfg Martin
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19335
Erhaltene Danke: 1751

W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 10.01.09 01:52 
Mehrere visuelle Komponenten zu bewegen ist keine gute Möglichkeit. Wenn man selbst die Elemente an die richtige Stelle zeichnet, dann kann man auch flüssige Bewegungen gut hinbekommen. Visuelle Komponenten wie TImage sind dafür einfach nicht gedacht.

Wenn du wirklich in ein TImage mehrere Bilder abwechselnd laden willst, dann ist es wohl am besten diese in globale TBitmaps zu laden und dann daraus ins TImage zu laden. Dann sollte sich das Flackern in Grenzen halten.
MaxMüller123 Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: Sa 10.01.09 02:15 
Was meinst du mit "Elemente selbst zeichnen"? Soll ich das Schaf sozusagen von Hand bzw. mit Shapes zeichnen und dann laufen lassen?

Viel wichtiger aber immoment für mich: Wie würde der Quelltext für das abwechselnde Laden der TBitmaps in das TImage aussehen?
Ich füg ma kurz den Quelltext aus dem Timer hinzu wie er bisher aussieht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TForm1.TimerSchafLangTimer(Sender: TObject);
begin
Image14.Picture.LoadfromFile(ExtractFilePath(ParamStr(0)) + 'Schaf-lang.bmp');
Image14.Left:=Image14.left +1;
if Image14.left > 290 then TimerSchafLang.Enabled:=false;
end;

Könnte ich hier direkt das Laden des anderen Bildes mit einbauen, egal ob über eine globale TBitmap oder direkt...?
Danke,
Mfg Martin

Moderiert von user profile iconNarses: Quote- durch Delphi-Tags ersetzt
IceBube
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 231



BeitragVerfasst: Sa 10.01.09 12:43 
Meinst du wie du das TBitmap in das TImage bekommst?

Zuvor musst du globale Variabeln des Types TBitmap machen...klar

ausblenden Delphi-Quelltext
1:
2:
3:
4:
{...}
public
  DeinBild1 : TBitmap
{...}


Danach musst du deine TBitmap's erstellen und die Bilder laden

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure ...FormCreate...
begin
 DeinBild1 := TBitmap.create;
 DeinBild1.LoadFromFile(FileName);
end;


So hast du das gemacht (die Bilder hineingeladen)...
dann die Bilder in das Image übergeben, dies würd so ausschauen

ausblenden Delphi-Quelltext
1:
2:
TImage1.Picture.Bitmap := DeinBild1;
//in Deinem Fall Image14....


Hoffe das war die eine Hilfe ;)

lg
MaxMüller123 Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: So 11.01.09 16:35 
Hi,
danke für deine Hilfe, das einbinden klappt auch wunderbar, meine eigentlich Frage ist aber wie ich die Bitmaps in dem Image schnell austauschen kann.
Im Endeffekt soll die Laufbewegung eines Schafes dargestellt werden, hierfür hab ich nun zwei Bilder, eins wo das Schaf die Beine ausgestreckt hat und eins wo es sie zusammenzieht. Wie kann ich nun diese Bilder in dem Image immer schnell austauschen?????
Mfg Martin
MaxMüller123 Threadstarter
Hält's aus hier
Beiträge: 6



BeitragVerfasst: So 11.01.09 17:27 
Hi,
die letzte Frage hat sich eben gerade von selbst beantwortet, ich nehm einfach eine Boolean variable für den Austausch.

Mfg Martin