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

Luca

Treue Seele

  • »Luca« ist der Autor dieses Themas

Beiträge: 188

Wohnort: Braunschweig

  • Private Nachricht senden

1

25.04.2012, 21:58

Bewegung flüssiger machen

Hallo,

Ich habe mit sfml ein Programm geschrieben, mit dem ich ein schwarzes Rechteck auf dem Bildschirm mit den Pfeiltasten bewegen kann. Allerdings ruckelt die Bewegung sehr stark. Ich kann beispielsweise auch nicht diagonal gehen, wenn ich 'oben' und 'unten' gleichzeitig gedrückt halte.

Was ich brauche ist nur ein kleiner Vorschlag, wie ich die Bewegung flüssiger bekomme. Ich dachte an eine art Schleife. Zurzeit besteht die Bewegung des Sprites nur aus: ändere Y um 5 bzw. ändere X um 5.

Ich bin dankbar für jeden Tipp.
Gruß,
Lardos

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

25.04.2012, 22:00

Gib dem Objekt eine Geschwindigkeit.
Wenn du eine Taste zum Bewegen drückst, beeinflusst du die Geschwindigkeit.
In jedem Frame bewegst du das Objekt entsprechend der Geschwindigkeit weiter und reduzierst die Geschwindigkeit, indem du sie mit einem Faktor < 1 multiplizierst (damit es anhält, sobald du keine Taste mehr drückst).
Die Geschwindigkeit hat natürlich zwei Komponenten: x und y.

3

25.04.2012, 22:04

Warum sollte es sich diagonal bewegen, wenn du 'oben' und 'unten' gleichzeitig drückst!?

Luca

Treue Seele

  • »Luca« ist der Autor dieses Themas

Beiträge: 188

Wohnort: Braunschweig

  • Private Nachricht senden

4

25.04.2012, 22:06

Ah, super Idee! Vielen Dank!

Edit: Ich meine natürlich oben und rechts... Sorry ^^

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

5

25.04.2012, 22:28

Weil du es vermutlich nicht eingebaut hast. Du hast vermutlich so etwas wie if(taste_oben_gedrückt)else if(taste_rechts_gedrückt) etc. Das else if lässt dann halt nur eine der Möglichkeiten zu. Da gibt es ja mehrere Möglichkeiten. Du könntest überlegen ob du irgendwie 2 Tasten gleichzeitig abfragen kannst. Ansonsten kannst du gucken ob du das else unbedingt brauchst für das was du willst.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

FSA

Community-Fossil

  • Private Nachricht senden

6

26.04.2012, 21:34

Damit die Geschwindikeit beim Seitwärtslaufen nicht schenller wird, gibt es eine Rechnung die ich mal rauskrame ;) Ich habe die irgendwann mal geschrieben. Wenn du sie brauchst :)

Zitat

Der RCCSWU (RandomCamelCaseSomtimesWithUndersquare) Stil bricht auch mal mit den veraltet strukturierten Denkmustern und erlaubt dem Entwickler seine Kreativität zu entfalten.

7

26.04.2012, 21:58

Du kannst in Sfml einfach die Keyboard Klasse benutzen und mit der isKeyPressed Funktion die Tasten abfragen. Wenn du dich dann diagonal bewegen möchtest kannst du einfach das benutzen.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Update(){

// Oben/Unten prüfen
if(sf::Keyboard.isKeyPressed(sf::Keyboard::Key::Up)){
// nach oben bewegen
}else if(sf::Keyboard.isKeyPressed(sf::Keyboard::Key::Down)){
// nach unten bewegen
}

// Links/Rechts prüfen
if(sf::Keyboard.isKeyPressed(sf::Keyboard::Key::Left)){
// nach links bewegen
}else if(sf::Keyboard.isKeyPressed(sf::Keyboard::Key::Right)){
// nach rechtsbewegen
}
}


Wenn die Geschwindigkeit diagonal nicht schneller sein soll als horizontal/vertikal musst du nur deinen Bewegungsvektor normaliesieren. Normaliesieren bedeutet das du die Figur im relativen Bezug zur gesamten Bewegung versetzt.

Beispiel:
x= 5,y= 10, maximale Geschwindigkeit = 5px/sekunde

ohne normaliesieren:
Zurückgelegter Weg = wurzel aus(x²+y²) (Pythagoras :D ) = ca. 7,07px

mit normaliesieren:
Vektorlänge = x + y = 15

Relatives x = x / Vektorlänge = 1/3
Relatives y = y / Vektorlänge = 2/3

Bewegung in x Richtung = Relatives x * maximale Geschwindigkeit = ca. 1,67
Bewegung in y Richtung = Relatives y * maximale Geschwindigkeit = ca. 3,33

Zurückgelegter Weg = 1,67 + 3,33 = 5px
greate minds discuss ideas;
average minds discuss events;
small minds discuss people.

Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

8

26.04.2012, 21:58

Da so schwierig ist diese Rechnung nicht;) Stell dir ein Dreieck vor. Du hast die Seiten A, B und C. C ist die Hypotenuse. A ist die Seite die parallel zu deiner X-Achse liegt, B liegt parallel zu deiner Y-Achse. C ist die Richtung in die du dich bewegen willst, wenn die 2 Tasten gedrückt werden. Du weißt wie lang C ist, da du dich ja mit einer bestimmten Geschwindigkeit bewegst. Du musst also nur wissen um wie viele Einheiten du auf der X und der Y-Achse bewegen musst, um dich um die Geschwindigkeit zu bewegen. Du musst also A und B bestimmen. Da die Bewegung ja genau Diagonal ist, müssen A und B gleich groß sein. Jetzt denk mal an Pythagoras. Du hast die länge der Seite C und weißt, dass A und B gleich groß sind. Um es einfacher zu machen kannst du in der Formel das B durch ein A austauschen. Dann wird es vielleicht klarer. Jetzt stellst du das ganze nach A um und weißt wie du dir die Geschwindigkeit ausrechnen kannst. Das ist dann die Geschwindigkeit auf sowohl der X als auch der Y Achse. Mal es dir zur Not einfach mal auf.

edit: War ich mal wieder zu langsam.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Luca

Treue Seele

  • »Luca« ist der Autor dieses Themas

Beiträge: 188

Wohnort: Braunschweig

  • Private Nachricht senden

9

27.04.2012, 20:43

So, danke nochmal für die Antworten. Lasse mir jetzt in meinem Programm die Frames per second anzeigen. Jetzt frage ich mich wie ich nun dem Sprite die Anweisung gebe, den Wert Geschwindigkeit PRO FRAME zu gehen. Hier ist mein Code (damit ihr mal seht wie das aussieht).

Leider gibt mir getElapsedTime() nicht die Zeit seit dem letzten Frame zurück, sondern die Zeit, die seit dem letztem restart() verstrichen ist. Jetzt habe ich zwar die FPS aber weiß nicht, wie ich die Steps pro Frame mache. In der SFML 2.0 Documentation habe ich auch nichts gefunden, was mir helfen könnte.

Gruß,
Luca

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// Erstes Projekt mit sfml 2.0
// Ein Image bewegen
#include <string>
#include <sstream>
#include <SFML\Graphics.hpp>
#include <SFML\Window.hpp>
#include <SFML\System.hpp>
#include <SFML\System\Vector2.hpp>
#include <iostream>

using namespace std;

// FPS initialisieren
sf::Time Time;
sf::Clock elapsed;

// IntToString - Funktion
string IntToString(int d)
{
    stringstream ss;
    ss << d;
    return ss.str();
}

// Get framerate - Funktion
string FrameRate()
{
    static int frameCounter = 0;
    static int fps = 0;
    frameCounter++;
    Time = elapsed.getElapsedTime();
    if(Time.asMilliseconds() > 999)
    {
        fps = frameCounter;
        frameCounter = 0;
        elapsed.restart();
    }

    return IntToString(fps);
}

// Hauptprogramm
//
int main()
{
    // Videomode
    sf::VideoMode VMode(800, 600, 32);
    sf::RenderWindow Window(VMode, "sfml 2.0 - moving image");
    
    // Texture Laden
    sf::Texture Texture;
    if(!Texture.loadFromFile("player.png"))
    {
        return 1;
    }

    // Sprite initialisieren
    sf::Sprite Sprite;
    Sprite.setTexture(Texture);

    sf::Vector2f vec = Sprite.getPosition();
    vec.x;
    vec.y;

    // FPS Text erstellen
    sf::Text FPS("0", sf::Font::getDefaultFont(), 25);

    // Geschwindigkeit initialisieren
    float Yspeed = 5.0f;
    float Xspeed = 5.0f;
        
    // Gameloop
    while(Window.isOpen())
    {
        sf::Event Event;
        while(Window.pollEvent(Event))
        {
            switch(Event.type)
            {
                case sf::Event::Closed:
                    std::cout << "The window was closed." << std::endl;
                    Window.close();
                    break;

                case sf::Event::KeyPressed:
                    // Bewegung
                    break;

                default:
                    break;
            }
        }

        // running fps
        FPS.setString(FrameRate());
        Window.clear(sf::Color(255, 255, 255));
        Window.draw(FPS);
        Window.draw(Sprite);
        Window.display();
    }

    return 0;
}

10

27.04.2012, 21:05

Ich hab zwar nur SFML 1.6, aber da geht das so:
float elapsedTime = window.GetFrameTime();
Das ist die Zeit für das letzte Frame, also die Zeit die vergangen ist, seit dem letzen Rendern, sprich window.Display();

Werbeanzeige