| Autor |
Beitrag |
MaxMüller123
Hält's aus hier
Beiträge: 6
|
Verfasst: 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:
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..100] of tshape; sh2: array[1..100] of tshape; sh3: array[1..100] of tshape; sh4: array[1..100] of tshape; sh5: array[1..100] of 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 AXMD: Quote- durch Delphi-Tags ersetzt
|
|
jaenicke
      
Beiträge: 19336
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 04.01.09 21:46
|
|
MaxMüller123 
Hält's aus hier
Beiträge: 6
|
Verfasst: 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  .
Danke nochmal -schonmal,
Mfg Martin
|
|
jaenicke
      
Beiträge: 19336
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mi 07.01.09 03:29
Wie wäre es zum Beispiel so? 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[216, 18+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(0, 0, 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 
Hält's aus hier
Beiträge: 6
|
Verfasst: 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
      
Beiträge: 19336
Erhaltene Danke: 1751
W11 x64 (Chrome, Edge)
Delphi 12 Pro, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
Hält's aus hier
Beiträge: 6
|
Verfasst: 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:
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 Narses: Quote- durch Delphi-Tags ersetzt
|
|
IceBube
      
Beiträge: 231
|
Verfasst: 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
Delphi-Quelltext 1: 2: 3: 4:
| public DeinBild1 : TBitmap |
Danach musst du deine TBitmap's erstellen und die Bilder laden
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
Delphi-Quelltext 1: 2:
| TImage1.Picture.Bitmap := DeinBild1; |
Hoffe das war die eine Hilfe
lg
|
|
MaxMüller123 
Hält's aus hier
Beiträge: 6
|
Verfasst: 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 
Hält's aus hier
Beiträge: 6
|
Verfasst: 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
|
|
|