Je viens de commencer la SFML et comme premier jeu j'aimerais faire un bête jeu de plateforme, mais je ne comprends pas comment réussir à faire des sauts réalistes. J'ai à peu près réussi à faire une "gravité" en appliquant toute les millisecondes une valeur (-10) sur mon personnage en Y, mais pour les saut je n'y arrive pas et sur internet je ne trouve rien d'expliquant cela vraiment clairement... quelqu'un pourrait m'aider ? :P
Mon code :
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include <cstdlib>
#include <thread>
#include <SFML/System/Time.hpp>
using namespace sf;
std::string jeu("[FlappyDoc] ");
std::string nameGame("Jeu");
int l(1920), h(1080); //Dimension par défaut de la fenêtre (l = Largeur, h = 1080)
int jmpH(h / 2);
int cy((h/2)-50), cx((l/2)-50);
int var(0), i, j(+10);
#pragma region variables
sf::RenderWindow w;
sf::Event e;
sf::CircleShape cercle;
sf::CircleShape bullet;
sf::RectangleShape rect;
sf::Clock cl;
sf::Time el1 = cl.getElapsedTime();
#pragma endregion variables
void collision() {
if (cercle.getGlobalBounds().intersects(rect.getGlobalBounds())) {
cercle.move(0, -1);
var = 1;
}
}
void g() {
cl = cl;
if(el1.asMilliseconds() == 0 && var == 0) {
cercle.move(0, +20);
cl.restart();
}
}
void player() {
if (Keyboard::isKeyPressed(Keyboard::Up) && var == 1) {
cercle.move(0, -10);
var = 0;
}
if (Keyboard::isKeyPressed(Keyboard::Down) && var != 1) {
cercle.move(0, +10);
}
if (Keyboard::isKeyPressed(Keyboard::Left)) {
cercle.move(-10, 0);
}
if (Keyboard::isKeyPressed(Keyboard::Right)) {
cercle.move(Vector2f(10, 0));
}
if (Keyboard::isKeyPressed(Keyboard::RControl)) {
w.draw(bullet);
bullet.move(+10, 0);
}
}
int main(){
std::cout << jeu << "Le jeu se lance bien !" << std::endl;
w.create(VideoMode(l, h), nameGame);
w.setFramerateLimit(60);
//Modifier position fenêtre
//window.setPosition(Vector2i(X, Y));
cercle.setFillColor(Color::Green);
cercle.setRadius(50.f);
cercle.setPosition(cx, cy);
cercle.setOutlineColor(Color::Red);
cercle.setOutlineThickness(10.f);
bullet.setFillColor(Color::White);
bullet.setRadius(3.f);
bullet.setPosition(cercle.getPosition());
rect.setFillColor(Color::White);
rect.setSize(Vector2f(l, 100));
rect.setPosition(0, h - 100);
while (w.isOpen()) {
while (w.pollEvent(e)) { //Place la suite en priorité sur l'event Queue
if (e.type == e.KeyPressed && e.key.code == Keyboard::Escape){
w.close();
}
else if (e.type == e.Closed) {
w.close();
}
}
g();
collision();
player();
w.draw(cercle);
w.draw(rect);
w.display();
w.clear();
}
return 0;
}
Malheureusement, si tu veux que ce soit "réaliste", il faut que tu fasse appliquer les règles de la physique "élémentaire". Plus tu t'éloigneras de ces règles, moins le rendu que tu obtiendra sur ton écran correspondra à ce que tu verrais si quelqu'un sautait à coté de toi
Tu peux simplifier ta logique au point de n'avoir que des sortes de triangle isocèles plus ou moins hauts, plus ou moins larges, voire, des "demis cercles" sous des formes proches de
* *** ******
*** *** *** **** ****
** ** *** *** **** *****
* * ou *** *** ou encore **** ****
mais tu ne dois alors pas t'attendre à ce que cela fasse "réaliste".
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
Malheureusement, si tu veux que ce soit "réaliste", il faut que tu fasse appliquer les règles de la physique "élémentaire". Plus tu t'éloigneras de ces règles, moins le rendu que tu obtiendra sur ton écran correspondra à ce que tu verrais si quelqu'un sautait à coté de toi
Tu peux simplifier ta logique au point de n'avoir que des sortes de triangle isocèles plus ou moins hauts, plus ou moins larges, voire, des "demis cercles" sous des formes proches de
* *** ******
*** *** *** **** ****
** ** *** *** **** *****
* * ou *** *** ou encore **** ****
mais tu ne dois alors pas t'attendre à ce que cela fasse "réaliste".
Hmmm, mais dans un Mario par exemple.. c'est pas "réaliste" mais la courbe est assez juste, enfin jouable quoi.
Mais il n'y a pas de fonction qui fait ça ? Une fonction qui permettrait juste que quand un appuie sur un bouton, le personnage saut de x et la courbe se calculerait en fonction des déplacements latéraux du joueurs... ?
En général, c'est simplifié (mais ça revient au même)
Dans la structure du sprite tu as :
x,y : position sprite : vx,vy = vecteur vitesse. status (au sol, en saut)
A chaque frame, tu déplaces le sprite ainsi :
x+=vx ; y+=vy
Si tu as le statut au sol, et que tu appuies sur le saut, alors le status devient "en saut" et vy prend une valeur négative forte.
et a chaque frame, tu augmentes vy d'une constante... au bout de quelques frames, il devient positif et donc le sprite part dans l'autre sens (redescente du saut).
La première chose que tu dois faire, c'est chronométrer tes frames (cela permettra de t'assurer que ton jeu tourne de la même façon sur n'importe quel PC). Tu peux utiliser une sf::Clock (ou std::chrono) pour cela.
Ensuite, il faut que tu définisse une constante pour la gravité, exprimée en pixel/seconde^2, soit la vitesse que gagnera ton joueur à chaque seconde. Cette vitesse sera donc exprimée en pixels.
Puis, à chaque frame, tu devras mettre à jour la position y de ton joueur, en fonction du temps écoulé depuis la dernière frame et de la vitesse de ton joueur.
Tu dois donc également stocker la vitesse verticale de ton joueur.
Tu auras donc besoin de deux formules :
Gain de vitesse = Accélération * Temps écoulé
Déplacement = Vitesse * Temps écoulé
Et dans ton code ça donnera quelque chose comme ça :
velocity += GRAVITY * elapsedTime;
position += velocity * elapsedTime;
(Tu pourras remplacer la vitesse, la gravité et la position par des vecteurs)
Voilà, j’espère t'avoir aidé !
N'hésite pas à poser plus de questions si tu n'a pas compris quelque chose
La première chose que tu dois faire, c'est chronométrer tes frames (cela permettra de t'assurer que ton jeu tourne de la même façon sur n'importe quel PC). Tu peux utiliser une sf::Clock (ou std::chrono) pour cela.
Ensuite, il faut que tu définisse une constante pour la gravité, exprimée en pixel/seconde^2, soit la vitesse que gagnera ton joueur à chaque seconde. Cette vitesse sera donc exprimée en pixels.
Puis, à chaque frame, tu devras mettre à jour la position y de ton joueur, en fonction du temps écoulé depuis la dernière frame et de la vitesse de ton joueur.
Tu dois donc également stocker la vitesse verticale de ton joueur.
Tu auras donc besoin de deux formules :
Gain de vitesse = Accélération * Temps écoulé
Déplacement = Vitesse * Temps écoulé
Et dans ton code ça donnera quelque chose comme ça :
velocity += GRAVITY * elapsedTime;
position += velocity * elapsedTime;
(Tu pourras remplacer la vitesse, la gravité et la position par des vecteurs)
Voilà, j’espère t'avoir aidé !
N'hésite pas à poser plus de questions si tu n'a pas compris quelque chose
Fvirtman a écrit:
Salut,
En général, c'est simplifié (mais ça revient au même)
Dans la structure du sprite tu as :
x,y : position sprite : vx,vy = vecteur vitesse. status (au sol, en saut)
A chaque frame, tu déplaces le sprite ainsi :
x+=vx ; y+=vy
Si tu as le statut au sol, et que tu appuies sur le saut, alors le status devient "en saut" et vy prend une valeur négative forte.
et a chaque frame, tu augmentes vy d'une constante... au bout de quelques frames, il devient positif et donc le sprite part dans l'autre sens (redescente du saut).
Merci énormément ! ça confirme ce que j'étais entrain de faire !! Merciiii !!
[SFML]Faire des sauts réalistes.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html