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

12.07.2011, 13:11

Nutze drei Kräfte:
* Gravitation
* Reibung
* Die Kraft deines Sprungs

Schon hast du realistische Bewegungen beinahe beliebiger Art.

Nutze drei Kräfte:
* Gravitation
* Reibung
* Die Kraft deines Sprungs

Schon hast du realistische Bewegungen beinahe beliebiger Art.


Die Kraft wäre also praktisch die Beschleunigung dann oder? Je nach dem ob ich renne oder stehe spring ich ja unterschiedlich weit^^ Reibung werde ich erstmal weglassen. Da es ja eine Art Super Mario werden soll wird diese kleine Einheit ja denke ich mal kaum auffallen. Habe jetzt als Membervariablen für den Spieler:

C-/C++-Quelltext

1
2
3
4
bool bJump;
float gravitation;
float beschleunigung;
float geschwindigkeit;


Jetzt muss ich nur noch schauen, wie ich die Werte initialisiere. Denke mal bei der Beschleunigung muss ich einfach nur messen ob gerannt wurde und wenn ja, wie lange schon. Dann kann ich diesen Bereich ja in 3 Teile zerlegen... 0 für stehen, erst kurz am laufen = 2 und endgeschw. dann 5 oder so. Die Gravitation wäre ja in diesem Falle meine ehemalige velocity, die mich dann ab einen bestimmten Zeitpunkt wieder nach unten zieht. Also bräuchte ich sobald ich alle Werte habe, eigendlich nur noch die Formel für den Wurf + den Freien Fall ...oder ist da jetzt noch irg ein Fehler drinn? ^^

Gruß
AK

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

12

12.07.2011, 13:19

Je nach dem ob ich renne oder stehe spring ich ja unterschiedlich weit^^ Reibung werde ich erstmal weglassen. Da es ja eine Art Super Mario werden soll wird diese kleine Einheit ja denke ich mal kaum auffallen.

Ohne Reibung würde sich Mario immer weiter bewegen, auch wenn man keine Taste drückt. Das wär nicht besonders schön ;)

Wenn du beim Sprung mit Konstanter beschleunigung arbeitest, springt Mario wie eine Rakete(steigt erst langsam und wird dann schneller). Du willst es vermutlich genau anders herum. Wie das funktioniert habe ich aber schon gepostet. Wieso ignorierst du die Erklärung?
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

13

12.07.2011, 13:47

Wieso ignorierst du die Erklärung?


Immer wenn ich es so versuche funktioniert es nicht. Habe die vCity auf 2000 gesezt im ctor weil das eigedlich einen schoenen Sprung ergab. der Code sieht so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Konstruktor von Spieler

Spieler::Spieler()
{
    // Alle Zeiger erstmal auf NULL initialisieren
    m_pSpriteSpieler = NULL;
    bJump = false;
    vCity = 2000.0f;
}


void Spieler::ProcessMoving()
{
    ... nach Links/Rechts laufen etc ....
   
    // Springen
    else if (g_pFramework->KeyDown(SDLK_SPACE) && m_yPos <= 415.0f)
    {
        m_yPos -= vCity * g_pTimer->GetElapsed();
        vCity -= 100.0f;
    }


Wenn ich das Programm so starte, und die Leertaste drücke, springt meine Figur genau einmal nach oben und landet wieder auf dem Boden. Danach jedoch kann ich die Leertaste nicht mehr betätigen. Und ich habe halt gedacht das liegt daran das ich die vCity wieder auf 2000 setzen muss:

Zitat

´Du kanns verticalVelocity in JEDEM Frame um einen bestimmten Wert erhöhen und ihn auf Null setzen, wenn er auf dem Boden steht.


aber auch das ändert nichts daran: Auf dem Boden steht meine figur ja wenn m_yPos auf 415.0 ist. Also hab ich die Abfrage hinzugefügt:

C-/C++-Quelltext

1
2
else if (m_yPos >= 415.0f)
    vCity = 2000.0f;



Aber auch das scheint nicht zu funktionieren.

Deshalb habe ich einen anderen Weg gesucht um den Sprung zu realisieren. Ansich ist der SPrung schon ganz gut....Aber leider kann man ihn nur einmal benutzen ^^

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

14

12.07.2011, 13:54

Achso. 2000 = 0?
Dann ist alles klar! :thumbsup:

edit:
Diese Zeile gehört nicht in den if-block:

C-/C++-Quelltext

1
m_yPos -= vCity * g_pTimer->GetElapsed();

Wo passiert das:

Zitat

verticalVelocity in JEDEM Frame um einen bestimmten Wert erhöhen

???

Manche Dinge funktionieren erst wenn du sie komplett implementiert hast. Stell dir vor du stellst dein Auto auf Gas um, modifizierst den Motor aber baust kein Gastank ein. Das kann nicht funktionieren!
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »NachoMan« (12.07.2011, 14:06)


15

12.07.2011, 14:04

Achso. 2000 = 0?
Dann ist alles klar! :thumbsup:


Aber vCity muss doch auf 2000. Das ist doch auch der Startwert. ?(

Setz ich vCity in der else if () auf 0 springt zudem mein Charakter garnicht mehr^^

Hab jetzt aber einfach mal den Startwert wieder mit auf 415.0 gesetzt, also:

C-/C++-Quelltext

1
2
3
4
5
else if (m_yPos >= 415.0)
{
   m_yPos = 415.0f;
   vCity = 2000.0f;
}


so funktionierts.... einigermaßen. Also hab dann jetzt immer noch das Problem das er, sobald ich die leertaste los lasse einfach in der Luft stehen bleibt^^

--> Wenn ich vCity auf 0 setze, springt er garnicht mehr...Verstehe das jetzt nich so genau warum du sagst ich muss das auf Null setzen^^

Gruß
AK

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

16

12.07.2011, 14:07

Aber vCity muss doch auf 2000. Das ist doch auch der Startwert. ?(

Ich sag dir aber, dass es falsch und unlogisch ist! Wie kommst du gerade auf 2000?

hab oben editiert.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

17

12.07.2011, 14:17

Aber vCity muss doch auf 2000. Das ist doch auch der Startwert. ?(

Ich sag dir aber, dass es falsch und unlogisch ist! Wie kommst du gerade auf 2000?

hab oben editiert.


Auf die 2000 kam ich durch probieren von verschiedenen Werten. Bei vCity 2000 springt er genau richtig hoch... bei = garnicht mehr....

Kann ungefär nachvollziehen warum

m_yPos -= vCity * g_pTimer->GetElapsed();

nicht in die if Bedingung darf...Aber weiss jetzt grad auch nicht so recht wo sie sonst hinsoll. Ich muss ja trotzdem irgendwie die Verbindung zur gedrückten Space-Taste haben.... ?(

*EDIT:

Hab ja extra die ProcessMoving-Funktion für alle Bewegungen...->

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
void Spieler::ProcessMoving()
{
    /* Diese Klasse steuert den Spieler
    ++++ Optionen für Steuerung:
            + Links, Rechts (Pfeiltasten links und rechts)
            + Springen      (Leertaste)
    ++++ */

    // Nach Links gehen

    if (g_pFramework->KeyDown(SDLK_LEFT))
    {
        m_xPos -= 100.0f * g_pTimer->GetElapsed();
        m_AnimPhase -= 10.0f * g_pTimer->GetElapsed();
    }
    // Nach Rechts
    else if (g_pFramework->KeyDown(SDLK_RIGHT))
    {
        m_xPos += 100.0f * g_pTimer->GetElapsed();
        m_AnimPhase += 8.0f * g_pTimer->GetElapsed();
    }


    // Springen
    else if (g_pFramework->KeyDown(SDLK_SPACE) && m_yPos <= 415.0f)
    {
        m_yPos -= vCity * g_pTimer->GetElapsed();
        vCity -= 100.0f;

    }

    else if (m_yPos >= 415.0)
    {
        m_yPos = 415.0f;
        vCity = 2000.0f;
    }


    // Spieler wurde nicht bewegt
    else
    {
        if (m_AnimPhase > 100.0f)
        {
            m_AnimPhase -= 60.0f *g_pTimer->GetElapsed();
        }
        if (m_AnimPhase < 0.0f)
        {
            m_AnimPhase += 60.0f * g_pTimer->GetElapsed();
        }
    }

}

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »AcidKiller« (12.07.2011, 14:24)


18

12.07.2011, 14:25

also wie groß vCity sein muss hängt davon ab wie schnell dein rechner ist, das ist an sich schonmal keine gute lösung.

der grund ist, dass du das mit der verstrichenen zeit multiplizierst. ist diese zu kurz (=schnellerer rechner) gibt es rundungsfehler und es kommt 0 raus.*

Ganz allgemein ist ein Sprung auch keine gleichm. Bewegung nach oben und danach eine gleichm. Bewegung nach unten, sondern eher eine Kurve wo die x-Achse die Zeit ist. Man hat da so verschieden Kräfte wie die Sprungkraft und die Gravitation die gegeneinander wirken. Wenn du einen Sprung haben willst der "richtig" aussieht solltest du dir das vielleicht nochmal angucken.

gruß

//edit:
*) d.h. es kommt 0 raus wenn m_yPos ein integer ist und die kommastellen abgeschnitten werden. ich mache sowas immer indem ich solange double nehme bis ich das am ende darstelle und das gerundete ergebnis nicht zurückschreibe.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »dennis-.-« (12.07.2011, 15:14)


19

12.07.2011, 14:33

also wie groß vCity sein muss hängt davon ab wie schnell dein rechner ist, das ist an sich schonmal keine gute lösung.

der grund ist, dass du das mit der verstrichenen zeit multiplizierst. ist diese zu kurz (=schnellerer rechner) gibt es rundungsfehler und es kommt 0 raus.

Ganz allgemein ist ein Sprung auch keine gleichm. Bewegung nach oben und danach eine gleichm. Bewegung nach unten, sondern eher eine Kurve wo die x-Achse die Zeit ist. Man hat da so verschieden Kräfte wie die Sprungkraft und die Gravitation die gegeneinander wirken. Wenn du einen Sprung haben willst der "richtig" aussieht solltest du dir das vielleicht nochmal angucken.

gruß


Ja perfekt wird dieser Sprung natürlich nicht. Aber es würd ja erstmal reichen wenn es überhaupt funktioniert^^ Werde daran später ja sowieso nochmal viel umschreiben müssen. Aber so Grundlegendes bleibt ja immer bestehen. Zum Beispiel würde mich jetzt halt noch interessieren waru meine Figur immer stehen bleibt, sobald ich SPace los lasse? Bzw. Wie kann man das verhindern? Ich will Space 1x drücken und dann soll der Sprung durchgeführt werden...

Kann man nict einfach sobald die SPACE Taste gedrückt wurde, bJump auf true setzen und diesen Wert immer der ProcessMoving übergeben bis die Figur wieder auf dem Boden ist und dann auf false setzn? So dürfte ja die Figur eigentlich nicht mehrin der Luft stehen bleiben^^

*EDIT: Bzw. man müsste doch irgendwie die SPACE-Taste freigeben und Sperren können....In etwa:

User drückt Leertaste (Space auf true und gesperrt) ...Figur in der Luft (SPACE gesperrt und auf true) Figur landet und hat wieder den Y-Ausgangswert(Space auf false und spieler kann erneut springen)... ?(

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »AcidKiller« (12.07.2011, 14:47)


NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

20

12.07.2011, 15:10

Kann ungefär nachvollziehen warum

m_yPos -= vCity * g_pTimer->GetElapsed();

nicht in die if Bedingung darf...Aber weiss jetzt grad auch nicht so recht wo sie sonst hinsoll. Ich muss ja trotzdem irgendwie die Verbindung zur gedrückten Space-Taste haben.... ?(

Nein musst du nicht denn...
Zum Beispiel würde mich jetzt halt noch interessieren waru meine Figur immer stehen bleibt, sobald ich SPace los lasse? Bzw. Wie kann man das verhindern? Ich will Space 1x drücken und dann soll der Sprung durchgeführt werden...


Du musst die Taste auch nicht blockieren wenn du es so machst wie ich es beschrieben habe. Das wird erst wichtig, wenn du nicht willst, dass der Spieler ununterbrochen auf und ab springt.
Dein Problem ist, dass du halb an deinem Lösungsversuch fest hältst und dann Teile von meinem Vorschlag ausprobierst. Das funktioniert natürlich nicht.
Du musst:
1. verticalVelocity in JEDEM Frame um, sagen wir mal 50*Frametime erhöhen. Den Wert kannst du später, je nach gewünschter Fallgeschwindigkeit anpassen. Das sorgt dafür, dass der Spieler im Freien fall immer schneller fällt. Bzw. beim Sprung langsamer steigt und wieder runter fällt.
2. Beim Tastendruck Prüfen ob der Spieler auf dem Boden steht und wenn ja verticalVelocity auf einen Negativen Wert SETZEN!
3. Bei Kontakt mit dem Boden verticalVelocity auf 0 setzen und den Spieler auf die höhe des Bodens stellen. Weil er sich ständig nach unten bewegt und er nicht durch den Boden fliegen soll ;)
4. verticalVelocity in jedem Frame verwenden. d.h. Position += verticalVelocity*Frametime. Wenn der Spieler gerade nicht Springt oder Fällt ist der Wert sowieso auf 0 und bewirkt nichts ;)

Das ist erstmal die einfachste Variante. Habe ja schon erwähnt, dass ein Jump'n'Run schwer ist...
@Dennis: Hier gehts nicht um Rundungsfehler sondern um die Logik. Selbst wenns keine Rundungsfehler gäbe würde der Code nicht funktionieren.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »NachoMan« (12.07.2011, 22:04)


Werbeanzeige