![]() |
"Ruckeln" bei bewegten Shapes abstellen
Hallo,
ich hab mal mein erstes kleines Spiel programmiert: Pong Kennt wahrscheinlich jeder: **********___ ***o *************___ *Nicht beachten, statt Leerzeichen... Zwei Paddel und ein Ball der immer hin und her geht, solange er auf die Paddel trifft. Das untere Paddel wird durch die Mausbewegung gesteuert. Die Ballbewegung wird durch einen Timer mit 10 als Einstellung gesteuert. Wenn er auf eine Wand trifft wird die Richtung umgekehrt, wenn er auf ein Paddel trifft auch. Das Gegnerische Paddel wird ebenfalls durch einen Timer gesteuert, jedoch mit einer anderen Einstellung: 15 So ist das Paddel etwas langsamer und trifft nicht jeden Ball. Wenn der Ball weiter rechts ist, so wird die Mitte pro Intervall an die Mitte des Balles angeglichen. Also das Spiel läuft auch und funtkioniert richtig schön - fast. Wenn das gegnerische Paddel recht nah an der Leftposition des Balles ist, dann ruckelt das Spiel total stark. Am Anfang überhaupt nicht, wenn das Paddel noch weiter weg ist (s.o.) *******___ ********o **___ Hier ruckelt es dann ziemlich stark... Habe DoubleBuffered=True, hilft aber auch nur solange, bis das Paddel nahe des Balles ist. Kann ich das noch etwas flüssiger machen (Ohne Canvas und andere veränderbare Elemente)? :glaskugel: Liebe Grüße! |
Re: "Ruckeln" bei bewegten Shapes abstellen
Erstmal: Timer mit 10/15 kann man vergessen
intern arbeitet dein Windows mit einem Zeitfenster von 16ms für deine Timer und dazu kommt noch, daß Windows kein Echtzeitsystem ist und man also über solche "normalen" Timer eh nicht mit solchen kleinen Zeiteinheiten rechnen sollte. So, was nun das Ruckeln angeht: Entweder liegen da grad irgendwelche andere Komponenten im Weg und behindern das Zeichnen etwas (können auch Paddel und Ball gegenseitig sein) Oder du hast z.B. ein Problem bei deinen Berechnung. DoubleBuffered bringt hier auch nichts, da dieses gegen ein Flackern hilft, welches durch ungünstige Zeichenoperationen entstehen kann. Also gegen ein Ruckeln hilft das nichts. Was nun eine Lösung angeht: Das ist für uns auch eine unbeantwortbare :glaskugel: , da wir ja nicht wissen was du wie gelöst hast. PS: sowas kannst du mit den [code]-Tags lösen
Code:
| ___ |
| | | | | o | | | | | | | | ___ | | ___ | | | | | | o | | | | | | | | ___ | |
Re: "Ruckeln" bei bewegten Shapes abstellen
Liste der Anhänge anzeigen (Anzahl: 1)
Ok, danke.
Delphi-Quellcode:
Das ist jetzt der Code, der für den Ball zuständig ist.
procedure TPong.BewegungstimerTimer(Sender: TObject);
begin if Ball.Left>=Pong.Width then vLR:=2; if Ball.Left<=0 then vLR:=1; if vLR=1 then Ball.left:=Ball.Left+5 else Ball.Left:=Ball.Left-5; if vOU=1 then Ball.Top:=Ball.Top+2 else Ball.Top:=Ball.Top-2; if Ball.Top=680 then begin if Paddel.left<Ball.left+10 then if Paddel.Left+150>Ball.Left+10 then vOU:=2; end; if Ball.Top=30 then begin if Gegner.left<Ball.left+10 then if Gegner.Left+150>Ball.Left+10 then vOU:=1; end; end; Ist der Timer...
Delphi-Quellcode:
Das ist der Timer, der das automatische Paddel angleicht.
procedure TPong.ReaktionstimerTimer(Sender: TObject);
begin if Ball.Left+10-75<Gegner.Left then Gegner.Left:=Gegner.Left-5; if Ball.Left+10-75>Gegner.Left then Gegner.Left:=Gegner.Left+5 end; ____________________________ Im Weg liegen die nicht, ist auch bei einer Anordnug wie auf dem kleinen Bildchen. Ball auf Formularhöhe/2, die beiden Paddel unten und oben... Berechnungen sind oben. Geht bestimmt auch viel einfacher, aber für den Anfang wollt ich das so lassen... LG ____________________________ Zum Echtzeitsystem: Das ist mir schon klar, aber das Verhältnis stimmt. Ob 15 dann eigentlicht 18 oder 10 ist, ist eher nebensächlich... Edit: Ich hab gerade herausgefunden, dass es verstärkt ruckelt, wenn das Paddel bewegt wird... Also bei MouseMove |
Re: "Ruckeln" bei bewegten Shapes abstellen
Liste der Anhänge anzeigen (Anzahl: 1)
also bei mir ruckelt nichts :gruebel:
OK, abgesehn davon, daß die Darstellung der Shapes auf meinem alten TFT etwas langsam ist ... bzw. mein Monitor ist es auch noch. Was du aber beachten solltest, bei deinen Abfragen: die rechte Kante des Balls ist z.B. nicht Ball.Left es ist Ball.Left+Ball.Width und das Selbe gild für die Unterkanten der Objekte. und bei deinen Vergleichen speziell das prallen gegen die Rechte Fensterkante und die unterkanten von Ball und Paddeln ist also falsch und die prallen erstmal voll ineinander. genauso ist das Fenster (der sichtbare Bereich) nicht Width breit, sondern ClientWidth Width ist die ganze Breite des Fensters, samt der Rahmen auch hier ist dein Ball erstmal rechts aus dem Fenster, bevor er zurückkam. |
Re: "Ruckeln" bei bewegten Shapes abstellen
Darum
Ball.Left+10 Das ist die width des Balles durch 2. Wenn ich es mit Tastatursteuerung mache, ruckelt auch nichts... Das mit CLientWidth war sehr hilfreich! Jetzt hat sich noch ein Problem aufgetan:
Delphi-Quellcode:
Wenn geprüft wird, ob das Paddel getroffen wurde, passiert alles mögliche... Der Ball springt von einem Ort zum anderen, ich bekomme Punkte, wenn der Gegner trifft und der Ball prallt auf Höhe des Gegners ab, obwohl dieser gar nicht trifft...
procedure TPong.BewegungstimerTimer(Sender: TObject);
begin if Ball.Left+20>=Pong.CLientWidth then vLR:=2; if Ball.Left<=0 then vLR:=1; if vLR=1 then Ball.left:=Ball.Left+5 else Ball.Left:=Ball.Left-5; if vOU=1 then Ball.Top:=Ball.Top+2 else Ball.Top:=Ball.Top-2; if Ball.Top=40 then begin Reaktionstimer.Enabled:=False;//Edit Gegnerpruefen; Reaktionstimer.Enabled:=True;//Edit exit; end; if Ball.top=680 then begin Reaktionstimer.Enabled:=False;//Edit Paddelpruefen; Reaktionstimer.Enabled:=True;//Edit exit; end; end; procedure TPong.Gegnerpruefen; begin if Gegner.left<Ball.left+10 then if Gegner.Left+150>Ball.Left+10 then begin vOU:=1; exit; end else begin vpunkte:=vpunkte+1; Punkte.Caption:=('Punkte: '+inttostr(vPunkte)); delay(3000); Ball.Top:=Pong.Height-300; vOU:=1; end; end; procedure TPong.Paddelpruefen; begin if Paddel.left<Ball.left+10 then if Paddel.Left+150>Ball.Left+10 then begin vOU:=2; exit; end else begin vOU:=2; vpunkte:=0; Punkte.Caption:=('Punkte: '+inttostr(vPunkte)); delay(3000); Ball.Top:=Pong.Height-300; exit; end; end; Findet jemand den Fehler? Ich habs noch kein zweites Mal durchgesehen und auch nur so kurz runtergeschrieben, aber ich denke, da ist eigentlich alles richtig... Vielleicht hängt das am zweiten Timer, dass während der Prozedur ein Wert geändert wird... Ich deaktivier den während der Prozedur mal... Edit: Daran hat's gelegen... Hab oben mal die Änderung eingetragen. |
Re: "Ruckeln" bei bewegten Shapes abstellen
Normaler Weise ist immer nur eine Timerprozedur aktiv.
Es laufen also "nie" zwei dieser Prozeduren gleichzeitig, weswegen ein Deaktivieren da eigentlich nicht viel dran ändern würde. (das "nie" natürlich nicht bei Umgehen/Änderung der Nachrichtenbehandlung) Aber dieses Delay verarbeitet, wärend des Wartens, die Windows-Nachrichten und würde demnach auch innerhalb dieses Befehls andere Dinge, wie ander oder die selbe Timer-Prozedur erneut zu starten. Blöd nur, daß du danach erst Dinge, wie Ball.Top und vOU änderst. Also (A) würde durch Delay nicht die Bearbeitung angehalten und (B) werden diese Werte erst später geändert, das Programm läuft wärenddessen weiter und im Nachhinein ändert sich das also erst. Das Ergebnis von A und B ist dein schönes Rumgespringe :zwinker: |
Re: "Ruckeln" bei bewegten Shapes abstellen
Die Timer laufen meines Wissens nach parallel...
Mit dem deaktivieren hats geklappt. Ich verwende jetzt Sleep statt Delay... Sieht auch nett aus :wink: Danke für die Hilfe! |
Re: "Ruckeln" bei bewegten Shapes abstellen
Zitat:
Delphi-Quellcode:
Ausgabe mit Sleep:
procedure Delay(Milliseconds: Integer);
var Tick: DWord; Event: THandle; begin Event := CreateEvent(nil, False, False, nil); try Tick := GetTickCount + DWord(Milliseconds); while (Milliseconds > 0) and (MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do begin Application.ProcessMessages; if Application.Terminated then Exit; Milliseconds := Tick - GetTickcount; end; finally CloseHandle(Event); end; end; procedure TForm1.FormCreate(Sender: TObject); begin Timer1.Interval := 100; Timer2.Interval := 1000; end; procedure TForm1.Timer1Timer(Sender: TObject); begin Memo1.Text := Memo1.Text + '*'; end; procedure TForm1.Timer2Timer(Sender: TObject); begin Memo1.Text := Memo1.Text + 's'; Sleep(900); Memo1.Text := Memo1.Text + 'e'; end; procedure TForm1.Button1Click(Sender: TObject); begin Timer1.Enabled := not Timer1.Enabled; Timer2.Enabled := not Timer2.Enabled; end; die Timer1Proc arbeitet nicht, wärend Timer2Proc aktiv ist = sequentiell
Code:
Ausgabe mit Delay:
*********se**se**se**se**se**se*se
hier ist zwar auch noch alles "sequentiell", außer das Delay (oder besser gesagt Application.ProcessMessages) hier zwischendurch mal die Anfragen abarbeitet. Wenn etwas wärend wärend Delay länger braucht, dann wird Delay/Timer2Timer auch länger brauchen, bis dieses feritg ist ... eben, da alles nur sequentiell abgearbeitet wird. (paralell geht mit Threads)
Code:
das sind übriges Beides die Ergebnisse von je 7 Sekunden
*********s********e*s********e*s********e*s********e*s********e*s*********es*********e
|
Re: "Ruckeln" bei bewegten Shapes abstellen
Hm, nagut... Versteh ich zwar nicht komplett aber grob schon.
Jetzt noch zur Steuerung: Ich hab das mit OnKeyPress gemacht. Wie kann ich vom Programm her die Wiederholung des Signals ändern? Also wenn man eine Taste gedrückt hält, ist der zeitliche Abstand von der ersten Wiederholung ja länger, prinzipiell so:
Code:
Aber ich möchte, dass das so aussähe:
a*****a*a*a*a*a*a* ...
Code:
Kann ich das vom Programm aus steuern?
a*a*a*a*a*a*a* ...
Das Paddel soll ohne große Zeitverzögerung reagieren können. |
Re: "Ruckeln" bei bewegten Shapes abstellen
Ähm Leute... Ich würde mal spontan sagen:
Zitat:
Wir haben doch schon oft im Forum stehen gehabt, dass es nicht die richtige Wahl ist die Komponentan auf der Forum zu verschieben. Dafür gibt es Canvas (was nun wirklich nicht so schwer ist) oder so tolle Dinge wie OpenGL und DirectX (was jetzt schon etwas oversized ist). ;-) Liebe Grüße, Valle |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:47 Uhr. |
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 by Thomas Breitkreuz