AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

"Ruckeln" bei bewegten Shapes abstellen

Ein Thema von Delphi-Narr · begonnen am 20. Okt 2009 · letzter Beitrag vom 21. Dez 2010
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Delphi-Narr
Delphi-Narr

Registriert seit: 29. Aug 2009
Ort: Duisburg
437 Beiträge
 
Delphi 2007 Professional
 
#1

"Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 15:02
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)?




Liebe Grüße!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#2

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 15:21
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 ,
da wir ja nicht wissen was du wie gelöst hast.



PS: sowas kannst du mit den [code]-Tags lösen
Code:
|          ___     |
|                  |
|                  |
|   o             |
|                  |
|                  |
|                  |
|             ___  |



|       ___        |
|                  |
|                  |
|        o        |
|                  |
|                  |
|                  |
|  ___             |
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Delphi-Narr
Delphi-Narr

Registriert seit: 29. Aug 2009
Ort: Duisburg
437 Beiträge
 
Delphi 2007 Professional
 
#3

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 15:32
Ok, danke.

Delphi-Quellcode:
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;
Das ist jetzt der Code, der für den Ball zuständig ist.
Ist der Timer...


Delphi-Quellcode:
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;
Das ist der Timer, der das automatische Paddel angleicht.

____________________________

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
Miniaturansicht angehängter Grafiken
pong_361.jpg  
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#4

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 18:20
also bei mir ruckelt nichts

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.
Angehängte Dateien
Dateityp: 7z test_187.7z (1,7 KB, 7x aufgerufen)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Delphi-Narr
Delphi-Narr

Registriert seit: 29. Aug 2009
Ort: Duisburg
437 Beiträge
 
Delphi 2007 Professional
 
#5

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 18:33
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:
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;
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...
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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#6

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 18:41
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
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Delphi-Narr
Delphi-Narr

Registriert seit: 29. Aug 2009
Ort: Duisburg
437 Beiträge
 
Delphi 2007 Professional
 
#7

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 18:45
Die Timer laufen meines Wissens nach parallel...
Mit dem deaktivieren hats geklappt. Ich verwende jetzt Sleep statt Delay... Sieht auch nett aus

Danke für die Hilfe!
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#8

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 19:18
Zitat von Delphi-Narr:
Die Timer laufen meines Wissens nach parallel...
Die Timer laufen vielleicht paralell, aber Ereignis-Prozeduren laufen sequentiell


Delphi-Quellcode:
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;
Ausgabe mit Sleep:
die Timer1Proc arbeitet nicht, wärend Timer2Proc aktiv ist = sequentiell
Code:
*********se**se**se**se**se**se*se
Ausgabe mit Delay:
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:
*********s********e*s********e*s********e*s********e*s********e*s*********es*********e
das sind übriges Beides die Ergebnisse von je 7 Sekunden
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Delphi-Narr
Delphi-Narr

Registriert seit: 29. Aug 2009
Ort: Duisburg
437 Beiträge
 
Delphi 2007 Professional
 
#9

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 19:32
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:
a*****a*a*a*a*a*a* ...
Aber ich möchte, dass das so aussähe:
Code:
a*a*a*a*a*a*a* ...
Kann ich das vom Programm aus steuern?
Das Paddel soll ohne große Zeitverzögerung reagieren können.
  Mit Zitat antworten Zitat
Benutzerbild von Valle
Valle

Registriert seit: 26. Dez 2005
Ort: Karlsruhe
1.223 Beiträge
 
#10

Re: "Ruckeln" bei bewegten Shapes abstellen

  Alt 20. Okt 2009, 19:38
Ähm Leute... Ich würde mal spontan sagen:

Zitat von Delphi-Narr:
Kann ich das noch etwas flüssiger machen (Ohne Canvas und andere veränderbare Elemente)?
Nein.

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
Valentin Voigt
BOFH excuse #423: „It's not RFC-822 compliant.“
Mein total langweiliger Blog
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz