AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Geschwindigkeit bei bewegten Objekten
Thema durchsuchen
Ansicht
Themen-Optionen

Geschwindigkeit bei bewegten Objekten

Ein Thema von Antigo · begonnen am 8. Aug 2006 · letzter Beitrag vom 8. Aug 2006
Antwort Antwort
Seite 1 von 2  1 2      
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#1

Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 11:32
Hi,
Ich habe jetzt schon des öfteren kleine Spiele programmiert, aber ich hatte jedesmal Probleme wenn es darum ging verschiedene Geschwindigkeiten darzustellen. Jetzt habe ich wieder das Problem.

Ich habe ein relativ simples Programm:
Es gibt einen Ball, und diesem kann man mit einer bestimmten Kraft in eine beliebige Richtung "werfen". Mithilfe von Vektoren kann ich den Einfluss der Gravitation und des Windes beobachten. Soweit ist das kein Problem. Aber jetzt geht es darum einen Geschwindigkeits Faktor einzubauen. Hier hab ich jetzt einfach die Länge (oder den Betrag) des Vektors genommen, und ihn auf die Anzahl der Pixel übertragen, die sich der Ball in diesem Timer durchlauf bewegt. Funktionieren tut das ohne Frage, nur es gibt 2 Nachteile:
1. Es sieht doof aus ^^. Der Ball macht einfach zu große Sprünge (10-30 Pixel)
2. Kollisionsabfrage wird schwierig, da der Ball nicht genau auf Objekte trifft, sondern quasi direkt in sie hinein, da die Sprünge eben so groß sind.

Eine andere Möglichkeit wäre, die Zeit zwisachen den Timer Aufrufen dynamisch an die Geschwindigkeit anzupassen. Aber hier gibt es dann schnell eine untere Grenze, und es ist stark von der Belastung des PC`s abhängig wie schnell sich der Ball bewegt.


Hat vielleicht jemand eine Idee wie man soetwas elegant lösen könnte?


Vielen Dank im vorraus
Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
TheAn00bis

Registriert seit: 7. Jun 2004
386 Beiträge
 
#2

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 11:48
Wo mit bewegst du denn das Objekt? Über einen einfachen Timer?

Ich denke du solltest einfach das Timer-Intervall erhöhen, so dass kleinere Bewegungen pro Intervall ausreichen.

Ich habe für sowas immer das OnIdle benutzt; es wird so oft wie es dem Rechner möglich ist ausgeführt. Dann kannst du die Koordinaten des Objektes in kleinen Schritten vergrößern oder verkleinern und das ganze sollte flüßig laufen.


Also statt OnTimer (oder was auch immer du verwendet hast):

Application.OnIdle := procedure1; in das OnCreate und dann den zu wiederholenden Code in eine Methode mit Namen 'procedure1'.

Auf DelphiGL.com gibt es einen Bomberman Tutorial, dort steht etwas über 'Timebased Movement', dass du dir mal durchlesen solltest. Der Nachteil vom OnIdle ist nämlich, dass es von der Rechenleistung abhängt, wie oft es ausgeführt wird und das Programm dann auf schnellen Rechner möglicherweise zu schnell ausgeführt wird. Dort ist beschrieben, wie du das umgehen kannst.
  Mit Zitat antworten Zitat
Cöster

Registriert seit: 6. Jun 2006
589 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 11:57
Hi!
Ich würde das timer-Intervall nicht ändern, sondern immer bei 13 ms lassen (ca. 75 Hz). Dann kann man große Sprünge auch nicht wahrnehmen, wenn es sie denn geben sollte.
Zur Kollisionsabfrage:
Deine OnTimer-Procedure sieht wahrscheinlich ungefähr so aus:
Delphi-Quellcode:
Ball.Left := Ball.Left + Vektor;
Kollisionsabfrage;
wobei der Vektor dann die die Geschwindigkeit ist. Dabei fliegt der Ball aber, wie bereits von dir erwähnt evtl. direkt ins Objekt hinein. Mach's doch stattdessen so:
Delphi-Quellcode:
For i := 1 to Vektor do begin
  Ball.Left := Ball Left + 1;
  Kollisionsabfrage;
  If Kollision then Break;
end;
Dann fliegt der Ball nämlich nur so lange, bis es eine Kollision gibt.
  Mit Zitat antworten Zitat
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#4

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 12:03
danke euch beiden. Dieses Time Based Movement habe ich mir mal angeschaut. Scheint vielversprechend. Auch das OnIdle Event kannte ich noch nicht. Danke

Zur Kollisionsabfrage: gute Idee. Ich denke mal so wirds klappen, danke
Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
Benutzerbild von JasonDX
JasonDX
(CodeLib-Manager)

Registriert seit: 5. Aug 2004
Ort: München
1.062 Beiträge
 
#5

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 12:15
Hallo Antigo

Welchen Typ haben deine Vektorenelemtene? Ganzzahl? Dann war das die falsche Wahl. Wenn du Gleitkommazahlen fuer die Vektoren nimmst, dann sollte es eigentlich keine Schwierigkeiten bezueglich Genauigkeiten geben.
Was die Kollisionserkennung betrifft: Ich wuerde in folgender Reihenfolge vorgehen:
  1. Neue Position des Objektes berechnen
  2. Pruefen, ob es dort zu einer Kollision kommt (ob sich die Richtungsvektoren der 2 Objekte schneiden / auf einen gewissen abstand naehern)
  3. Wenn ja, dann:
    1. Pruefen, wo die wirkliche Kollision zustande kam (d.h. den Schnittpunkt der Richtungsvektoren)
    2. Das Objekt auf diesen Punkt setzen, bzw. bereits den Austrittsvektor berechnen und es dementsprechend vom anderen Objekt "abprallen" lassen.

greetz
Mike
Mike
Passion is no replacement for reason
  Mit Zitat antworten Zitat
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#6

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 12:41
Ähm meine Vektorelemente sind in der Tat Integer. Und es funktioniert auch nicht so wie es soll, da er durch Rundungen so wie es aussieht einfach immer einen Pixel vorgeht. Jedenfalls ist es so, das der Ball sich anders verhält wenn ich das Timer Interval ändere, und genau das sollte beim Timebased Movement ja nicht der Fall sein.

Optimal wäre es wohl wenn ich die komplette Flugbahn des Balles schon kennen würde und dann beim Timer durchlauf nur gucken müsste in welchem Zeitindex ich mich befinde und die dazugehörige Position raussuchen würde. Dann würde das Timer Intervall wirklich keinen EInfluss mehr haben, und es sollte auch nicht mehr ruckeln, aber ich weiss nicht wie ich das bewerkstelligen sollte...

Zurück zum vektor inwiefern würden Gleitkommazahlen da helfen?


Zur Kollisionsabfrage: DIe Möglichkeit, wäre quasi andersrum. Ist vielleicht ressourcenschonender, weil man nicht immer in Einzelschritten vorgeht. Naja mal sehen, erstmal muss der Ball vernünftig fliegen

Vielen dank schonmal
Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
Benutzerbild von JasonDX
JasonDX
(CodeLib-Manager)

Registriert seit: 5. Aug 2004
Ort: München
1.062 Beiträge
 
#7

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 12:55
Zitat von Antigo:
Optimal wäre es wohl wenn ich die komplette Flugbahn des Balles schon kennen würde und dann beim Timer durchlauf nur gucken müsste in welchem Zeitindex ich mich befinde und die dazugehörige Position raussuchen würde. Dann würde das Timer Intervall wirklich keinen EInfluss mehr haben, und es sollte auch nicht mehr ruckeln, aber ich weiss nicht wie ich das bewerkstelligen sollte...
Das sollte eigentlich schon Moeglich sein. Wenn ich das richtig Interpretiert habe, so hast dus mit einem Schiefen Wurf zu tun, der sich natuerlich berechnen laesst. Wenn du die Bewegung zweier Objekte in Funktionen fassen kannst, so ist es natuerlich moeglich, zu jedem beliebigen Zeitpunkt vorauszusagen, ob, und wenn wo die beiden Objekte kollidieren werden.

Zitat von Antigo:
Zurück zum vektor inwiefern würden Gleitkommazahlen da helfen?
Nehmen wir an, du willst dein Objekt mit 5Pixel/Sekunde bewegen. Du hast eine Framerate von 20FpS. Dann bewegst du dein Objekt pro Frame um 0.25 Pixel. In Integern ausgedrueckt: um 0 Pixel. Wenn du also Integer verwendest, steht dein Objekt bei dieser Geschwindigkeit nach 1 Sekunde immernoch am selben Fleck wie davor, obwohl es sich eigentlich um 5 Pixel bewegen haette sollen.
Bei der Verwendung von Floats wuerde es nach 1 Sekunde an der richtigen Stelle befinden, naemlich 5 Pixel weiter

greetz
Mike
Mike
Passion is no replacement for reason
  Mit Zitat antworten Zitat
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#8

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 13:44
Zitat:
Das sollte eigentlich schon Moeglich sein. Wenn ich das richtig Interpretiert habe, so hast dus mit einem Schiefen Wurf zu tun, der sich natuerlich berechnen laesst. Wenn du die Bewegung zweier Objekte in Funktionen fassen kannst, so ist es natuerlich moeglich, zu jedem beliebigen Zeitpunkt vorauszusagen, ob, und wenn wo die beiden Objekte kollidieren werden.
Naja es ist ja schon dadurch das ich eine WIndkomponente eingebaut habe, kein standard schräger Wurf wie man ihn aus dem Mathe Unterricht kennt Ausserdem möchte ich den Ball später auch noch gegen andere Gegenstände prallen lassen. Trotzdem könnte ich natürlich im ersten Schritt alles Berechnen und dann mit zweiten Schritt ausgeben, aber ich weiss nicht ob das so sinnvoll wäre.

Zitat:
Nehmen wir an, du willst dein Objekt mit 5Pixel/Sekunde bewegen. Du hast eine Framerate von 20FpS. Dann bewegst du dein Objekt pro Frame um 0.25 Pixel. In Integern ausgedrueckt: um 0 Pixel. Wenn du also Integer verwendest, steht dein Objekt bei dieser Geschwindigkeit nach 1 Sekunde immernoch am selben Fleck wie davor, obwohl es sich eigentlich um 5 Pixel bewegen haette sollen.
Bei der Verwendung von Floats wuerde es nach 1 Sekunde an der richtigen Stelle befinden, naemlich 5 Pixel weiter
Hmm dann müsste ich aber auch die X / Y Koordinaten des Balles in float ausdrücken. Sonst kann ich schlecht um 0.25 Pixel weitergehen. Ich werd das mal versuchen und berichten obs klappt.

danke nochmal
Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
Antigo

Registriert seit: 14. Mär 2005
274 Beiträge
 
#9

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 14:07
ok es kann gar nicht funktionieren mit diesem Time Based Movement :/

Ich habe es so geregelt, dass bei jedem mal, wenn der Ball bewegt wird, seine Flugbahn direkt mit der Gravitation und dem Wind verrechnet wird:
Delphi-Quellcode:
var
  Gravitation,Wind:TVektor;
  Ball: TBall;
...
...
procedure TForm1.Timer1Timer(Sender: TObject);
  ...
  Ball.vektor.addieren(Gravitation);
  Ball.vektor.addieren(wind);
  ...
  //Time Based Movement
  time:=gettickcount()-timestamp;
  ball.bewegen((5*ball.vektor.gibLaenge/10)*time/1000);
Jetzt ist es natürlich so, dass die Flugbahn anders verläuft, wenn der Vektor des Balles öfters mit den beiden anderen verrechnet wird. Deshalb ist es immer noch so das der Ball bei Timer Intervall 1 anders fliegt als bei Timer Intervall 50

Vielleicht hat ja jemand einen Ansatz wie man das lösen kann. Ich hab schon an sowas gedacht:
Delphi-Quellcode:
if ball.x mod 1 = 0 then begin
  Ball.vektor.addieren(Gravitation);
  Ball.vektor.addieren(wind);
  end;
Also das nur bei jedem vollen Pixel die Flugbahn verändert wird, aber das haut auch nicht hin. Denn bei Timer Intervall 50 können ja auch mehrere Pixel gegangen worden sein, und trotzdem nur eine einzige Flugbahn anpasung vorgenommen worden sein.


Ich hoffe da blickt jetzt noch jemand durch
Michael
"How should I know if it works? That's what beta testers are for. I only coded it."
  Mit Zitat antworten Zitat
Benutzerbild von JasonDX
JasonDX
(CodeLib-Manager)

Registriert seit: 5. Aug 2004
Ort: München
1.062 Beiträge
 
#10

Re: Geschwindigkeit bei bewegten Objekten

  Alt 8. Aug 2006, 14:55
Zitat von Antigo:
Naja es ist ja schon dadurch das ich eine WIndkomponente eingebaut habe, kein standard schräger Wurf wie man ihn aus dem Mathe Unterricht kennt
Den Windfaktor kann man natuerlich miteinbeziehen: Ich schaetze mal, dass der Wind-Vektor ca. so aussieht: (x, y, 0), sprich der Wind die Kugel nicht nach unten drueckt. Das vereinfacht das insofern, dass nur die Funktion x(t) veraendert werden muss. xy(t) ist dann nicht mehr nur
Code:
v0 * t * cos(b)
sondern es muss auch der Wind noch miteinbezogen werden:
Code:
xy(t) = v0 * t * cos(b) + vw * t * c
      = t * (v0 * cos(b) + vw * c)
wobei vw der Vektor des Windes ist und c ein Faktor, mit dem die Kraft des Windes an dem Objekt wirkt. (Siehe dazu Luftwiderstand)
Zitat von Antigo:
Ausserdem möchte ich den Ball später auch noch gegen andere Gegenstände prallen lassen. Trotzdem könnte ich natürlich im ersten Schritt alles Berechnen und dann mit zweiten Schritt ausgeben, aber ich weiss nicht ob das so sinnvoll wäre.
Wenn die Flugbahnen konstant bleiben, d.h. nicht zwischendurch durch aeussere Einwirkungen (benutzer ect.) veraendert werden, dann rentiert sich das vorberechnen von Kollisionspunkten. Dann musst du naemlich nur bei Flugbahnveraenderungen (Kollisionen) die Kollisionen neu berechnen. Wenn du dies bei jedem Frame machst, bremst das normalerweise ziemlich, vor allem da eine Kollisionserkennung bei sich bewegenden Objekten nicht sonderlich schnell ist. Bei einer Einfachen Implementierung bringt das eine Laufzeit von O(n * n). Zwar kann man das ganze beschleunigen (Quad-/Octrees ect.), das bringt aber einen weitaus hoeheren Implementierungsaufwand mit sich.

Zitat von Antigo:
Zitat:
Nehmen wir an, du willst dein Objekt mit 5Pixel/Sekunde bewegen. Du hast eine Framerate von 20FpS. Dann bewegst du dein Objekt pro Frame um 0.25 Pixel. In Integern ausgedrueckt: um 0 Pixel. Wenn du also Integer verwendest, steht dein Objekt bei dieser Geschwindigkeit nach 1 Sekunde immernoch am selben Fleck wie davor, obwohl es sich eigentlich um 5 Pixel bewegen haette sollen.
Bei der Verwendung von Floats wuerde es nach 1 Sekunde an der richtigen Stelle befinden, naemlich 5 Pixel weiter
Hmm dann müsste ich aber auch die X / Y Koordinaten des Balles in float ausdrücken. Sonst kann ich schlecht um 0.25 Pixel weitergehen. Ich werd das mal versuchen und berichten obs klappt.
Nein, die Pixel koennen Ints bleiben. Hier ein vergleich:
Code:
Schritt Position/Pixel (float)     Position/Pixel (int)
1        0    / 0                    0 / 0                          (+0.25)
2        0.25 / 0                    0 / 0                          (+0.25)
3        0.50 / 0                    0 / 0                          (+0.25)
....
6        1.25 / 1                    0 / 0                          (+0.25)
7        1.50 / 1                    0 / 0                          (+0.25)
....
9        2.00 / 2                    0 / 0                          (+0.25)
10       2.25 / 2                    0 / 0                          (+0.25)
ect.
So sieht das aus im Vergleich, wenn du einmal Position und Pixel als Integer speicherst, und einmal, wenn du Position als floats und Pixel als integers speicherst.

Zitat von Antigo:
ok es kann gar nicht funktionieren mit diesem Time Based Movement :/
Hier mal ein kleines Beispiel:
Delphi-Quellcode:
var
  LastTick: Integer;
//...
procedure TForm1.OnTimer(Sender: TObject);
var
  CurrentTick, dt: Integer;
begin
  CurrentTick := GetTickCount();
  dt := CurrentTick - LastTick; //dt = Delta T, die Zeitdifferenz zwischen dem letzten Tick und dem derzeitigen
  //hier dann dein Verarbeitungscode
  LastTick := CurrentTick;
end;
dt ist die wichtige Variable. Diese gibt dir in Millisekunden an, wieviel Zeit seit dem letzten Tick vergangen ist. Wie du sie anwendest: hier mal ein kleines Beispiel:
Delphi-Quellcode:
procedure PhysicTick(dt: real); //dt, aber in Sekunden! (angenehmer fuer physische Berechnungen)
var
  Speed, Position: TVektor; //Geschwindigkeits- und Positionsvektoren
begin
  Position := Position + (Speed * dt);
end;

procedure OnTimer(...)
begin
  //hier dann dein Verarbeitungscode
  PhysicTick(dt / 1000); //division durch tausend, um von Millisekunden auf Sekunden umzurechnen.
end;
Damit sollte das Timebased Movement korrekt implementiert sein.
Code is allerdings im Kopf entstanden, also koennten kleinere Fehlerchen dabeisein

greetz
Mike
Mike
Passion is no replacement for reason
  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 17:25 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