Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

11

26.10.2015, 17:40

Hi,

da du per PN nach einer Möglichkeit gefragt hast, die Steuerung "weicher" zu gestalten, hier eine Art, das zu programmierern. Ich schreibe das hier öffentlch, weil es vermutlich auch noch andere interessiert.

Prinzipiell hat das Spielerschiff drei physikalische Größen, die direkt mit der Trajektorie zusammenhängen: Die Position r, die Geschwindigkeit v und die Beschleunigung a. Alle drei Größen sind Vektoren, d.h. sie haben eine x und y Komponente.

Bis jetzt sieht dein Code vermutlich so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
void update (void)
{
  // ....
  if (key.left)
  {
    ship.r.x -= 5 * dT;
  }
  else if (key.right)
  {
    ship.r.x += 5 * dT;
  }
}


Das ganze könntest du wie folgt umbauen, sodass nicht mehr die direkte Position geändert wird, sondern eine Beschleunigung wirkt (normal verwende ich natürlich englische Kommentare)

C-/C++-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
void update (void)
{
  // ....
  ship.a.x = 0  // Beschleunigung auf null setzen, falls nichts gedrückt wird.
  float accel = 5;
  if (key.left)
  {
    ship.a.x = - accel;
  }
  else if (key.right)
  {
    ship.a.x =  accel;
  }
  ship.v.x = ship.v.x + (ship.a.x * dT);  // Beschleunigung ist die Änderung der Geschwindigkeit
  ship.r.x = ship.r.x + (ship.v.x * dT);  // Geschwindigkeit ist die Änderung der Position

  // bis jetzt würde das Schiff einfach weiter gleiten, deshalb muss die Geschwindigkeit in jedem Frame reduziert werden.
  float k = 0.95;
  ship.v.x *= k;

  // Außerdem sollte man noch eine Maximalgeschwindigkeit angeben, da die Geschwindigkeit sonst zu groß werden kann.
  float maxvel = 100;
  if (ship.v.x > maxvel)
  {
    ship.v.x = maxvel;
  }
  if (ship.v.x < -maxvel)
  {
    ship.v.x = -maxvel;
  }
}


Das gleiche dann natürlich noch für die y Komponente. dT bezeichnet hier die Zeit, zwischen dem letzten und dem aktuellen Frame und stellt eine glatte Bewegung auch bei schwankender Framerate sicher. Die hier angegebenen Werte (accel, k, maxvel) sind reine Beispielwerte, die ich nicht getestet habe. Hier musst du selber mal ein wenig herumprobieren und experimentieren, welche Werte passen.

Je größer du accel wählst, desto schneller beschleunigt das Schiff. je kleiner, desto langsamer. Je kleiner du k wählst, desto schneller bremst das Schiff ab. Je größer, desto mehr "rutschst" du, quasi wie auf Eis. k sollte nicht größer als 1 sein (warum?). je größer maxvel ist, desto schneller bewegt sich das Schiff, je kleiner, desto langsamer.

Ich hoffe, damit konnte ich deine Fragen beantworten.

So Far...
Laguna
Portfolio runvs.io | Gamejolt | itch.io | PEWN | Twitter

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

12

26.10.2015, 19:46

Ich hoffe, damit konnte ich deine Fragen beantworten.

Ja danke für die Antwort :D

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

13

27.10.2015, 13:21

Heute habe ich mal den Code (versucht) zu implementieren. Aktuell sieht das so bei mir aus:

class Player::Update(Game &game)

C-/C++-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
// ...

    a.x = 0;    // Beschleunigung auf NULL setzen, falls nichts gedrückt wird.
    float accel = 5;

    if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
    {
        a.x = -accel;
    }
    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
    {
        a.x = accel;
    }
    v.x = v.x + (a.x * dT);  // Beschleunigung ist die Änderung der Geschwindigkeit
    r.x = r.x + (v.x * dT);  // Geschwindigkeit ist die Änderung der Position

    // bis jetzt würde das Schiff einfach weiter gleiten,
    // deshalb muss die Geschwindigkeit in jedem Frame reduziert werden.
    float k = 0.95;
    v.x *= k;

    // Außerdem sollte man noch eine Maximalgeschwindigkeit angeben,
    // da die Geschwindigkeit sonst zu groß werden kann.
    float maxvel = 100;
    if (v.x > maxvel)
    {
        v.x = maxvel;
    }
    if (v.x < -maxvel)
    {
        v.x = -maxvel;
    }

// ...


Nun bekomme ich diese Fehler:

1) Binärer Operator "+": Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ "float" akzeptiert (oder keine geeignete Konvertierung möglich)
2) Binärer Operator "+": Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ "float" akzeptiert (oder keine geeignete Konvertierung möglich)

Beide Fehler verveisen auf die Zeilen 14 und 15. Leider hat mich auch Google im Stich gelassen. Habt ihr eine Idee?

Danke :)

14

29.10.2015, 15:12

Bin kein C++ Experte, versuche es aber trotzdem mal

C-/C++-Quelltext

1
(a.x * dT) 


könnte sein das das zu double konvertiert wird, entweder weil dT double ist oder damit durch die Multiplikation kein Overflow ausgelöst wird.
Der + Operator würde dann versuchen float + double zu berechnen, was er nicht kann.

Teste mal (a.x * dT) nach float zu casten. Wenn das ganze dann funktioniert, solltest du prüfen ob der cast immer gut geht, oder ob du mit dem double außerhalb des float-Wertebereiches liegen kannst...
Empires in Space
MMO 4X, Rundenbasiert
HTML5/TypeScript/Javascript/CSS/C#/SQL

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

15

29.10.2015, 15:57

Beide Fehler verveisen auf die Zeilen 14 und 15. Leider hat mich auch Google im Stich gelassen. Habt ihr eine Idee?
Wenn Du uns verraten würdest welchen Datentype dT eigentlich hat, könnte man Dir sicherlich helfen.

Der + Operator würde dann versuchen float + double zu berechnen, was er nicht kann.
Doch, kann er. Ergebnis ist double.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

16

29.10.2015, 16:00

Doch, kann er. Ergebnis ist double.

Wenn a.x teil eines sf::Vector2f ist bin ich mir nicht sicher ober das implizit nach double casten wiklich funktioniert.
Edit: die Rechnung a.x * dT dürfte Funktionieren und ist dann ein double ausdruck der das eigentlich Problem verursacht.

Wahrscheinlich ist es aber die Addition (v.x+ (a.x *dT) also float + double) und nicht die Multiplikation.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Koschi« (29.10.2015, 16:12)


BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

17

29.10.2015, 16:25

Egal ob Addition oder Multiplikation. Aus float+double oder float*double wird double. Ohne zu wissen welchen Typ dT hat, raten wir hier sinnlos rum.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

18

29.10.2015, 17:06

Ohne zu wissen welchen Typ dT hat

dT = sf::Time

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

19

29.10.2015, 17:11

Das ist natürlich dann Unsinn. Du willst da einen float oder double haben. Zum Glück bietet sf::Time das an.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

20

29.10.2015, 17:13

Ja, dann ist kein Wunder das es nicht geht.

Das ist das gleich für den Compiler wie 10 Häuser + 3 Äpfel = ???

Schau dir mal sf::Time und dann kommst du hoffentlich selber drauf was da schief läuft.
Wer aufhört besser werden zu wollen hört auf gut zu sein!

aktuelles Projekt:Rickety Racquet

Werbeanzeige