Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Déplacement de sprite avec la souris [SFML 2.0][Résolu]  (Lu 9265 fois)

0 Membres et 1 Invité sur ce sujet

DrPapino

  • Newbie
  • *
  • Messages: 34
    • Voir le profil
Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« le: Février 27, 2013, 08:41:32 pm »
Bonjour à tous :)

Alors voilà, je me suis mis en tête de déplacer un sprite à l'écran par un clic de la souris. Je m'explique : quand le programme se lance, le sprite est affiché en haut à gauche de l'écran ( ça lui apprendra ! ) puis quand on clique sur la souris, le sprite se déplace gaiement, d'un mouvement simple et allègre, vers l'endroit où on a cliqué.

J'utilise pour ça 3 vecteurs.
Le premier, pour la position du sprite ( on l'appelle position )
Le deuxième, pour enregistrer la position de la souris lorsqu'on a cliqué ( on l'appelle destination )
Le troisième vecteur représente quant lui le trajet à parcourir ( destination - position, qu'on appelle… vecteur. Oui, je suis pas trop inspiré là )

Il s'agit ensuite de placer notre sprite en ( destination - (1-t)vecteur )

t varie entre [0 ; 1], il est en fait le rapport du temps passé depuis le début du mouvement sur le temps total du mouvement ( calculé par le désormais célèbre v.d ). Mais jugez plutôt :


#include <SFML/Graphics.hpp>
#include <math.h>
#include <time.h>
#include <iostream>

int main ()
{
    bool moving(0);
    float a(0);
    float v(0.01);// vitesse de déplacement ( en inverse )
    float distance;
   
    sf::RenderWindow window(sf::VideoMode(800, 600), "Deplacer une ellipse");
   
    sf::Texture perso;
   
    perso.loadFromFile("/Users/blablabla/image.png");
   
    sf::Sprite mysprite(perso);
   
   
    sf::Vector2f position(0,0);
   
    sf::Vector2f vecteur(0,0);
   
    sf::Vector2f destination(0,0);

    sf::Clock clock;

   
   

    window.clear();
   
    mysprite.setPosition(position);

    window.draw(mysprite);

    window.display();
   
   
   
    while (window.isOpen())
    {
        sf::Event event;
       
        while (window.pollEvent(event))
        {
                if ((event.type == sf::Event::Closed) || (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape))
                {      
                window.close();
            }
           
            if ((event.type == sf::Event::MouseButtonPressed) && (event.mouseButton.button == sf::Mouse::Left))
            {
                destination.x=event.mouseButton.x;
               
                destination.y=event.mouseButton.y;

                vecteur=destination-position;
               
                moving = true;
               
                clock.restart();
               
                distance=(vecteur.x > vecteur.y ) ? vecteur.x : vecteur.y ;
            }
        }
       
       
        if (moving==true)
        {
            sf::Time elapsed = clock.getElapsedTime();
           
            a=elapsed.asSeconds();
           
            mysprite.setPosition(destination-vecteur*(1-(a/(v*distance))));
           
            position.x=(destination.x-vecteur.x*(1-(a/(v*distance))));
            position.y=(destination.y-vecteur.y*(1-(a/(v*distance))));
               
           
           
           
            if (a/(v*distance)>1)
            {
                moving=false;
                position=destination;
            }
             
           
           
        }
     
       
        window.clear();
       
        window.draw(mysprite);
       
        window.display();
       
       
    }
        return EXIT_SUCCESS;
}

Voilà voilà... " Mais ton code est parfait ", me diriez vous, et vous n'auriez pas tort ( j'espère que vous avez saisi mon humour glacé et raffiné ), quoiqu'un peu quand même.. En fait, des fois mon sprite se trompe de direction : au lieu d'aller en haut à gauche, comme je le lui dis avec la souris, ce petit rigolo part en bas à droite. Curieux, n'est ce pas ! Auriez vous une solution ?

Autre fait amusant, et pas des moindres : parfois, mon sprite va trop vite. Je pensais pourtant avoir calculé son déplacement par rapport au temps, et non par rapport aux caprices de framerate de mon ordinateur, mais il faut croire que j'ai du me planter quelque part.

Enfin voilà, si une bonne âme passe par là et qu'elle a la solution à tous mes problèmes ce serait super sympa de laisser une petite réponse !

Merci.

Bonne journée, ou bonne soirée, et joyeux noël  ;D

Mr Pchoun.
« Modifié: Février 28, 2013, 12:33:55 am par MrPchoun »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Déplacement de sprite avec la souris [SFML 2.0]
« Réponse #1 le: Février 27, 2013, 08:54:21 pm »
Ca me paraît un poil plus alambiqué que ce qu'il faudrait faire.

#include <SFML/Graphics.hpp>
#include <cmath>

const float speed = 100;

float length(sf::Vector2f v)
{
    return std::sqrt(v.x * v.x + v.y * v.y);
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(800, 600), "Follow me");

    sf::Vector2f target;
    sf::Vector2f velocity;
    bool moving = false;

    sf::CircleShape shape(10);
    shape.setFillColor(sf::Color::White);
    shape.setOrigin(5, 5);

    sf::Clock clock;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
            else if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left)
            {
                sf::Vector2i cursor(event.mouseButton.x, event.mouseButton.y);
                target = window.mapPixelToCoords(cursor);
                velocity = target - shape.getPosition();
                velocity = velocity / length(velocity) * speed;

                moving = true;
                clock.restart();
            }
        }

        if (moving)
        {
            sf::Time elapsed = clock.restart();
            shape.move(velocity * elapsed.asSeconds());

            if (length(target - shape.getPosition()) < 5)
                moving = false;
        }

        window.clear();
        window.draw(shape);
        window.display();
    }

    return 0;
}
 
« Modifié: Février 27, 2013, 08:56:39 pm par Laurent »
Laurent Gomila - SFML developer

DrPapino

  • Newbie
  • *
  • Messages: 34
    • Voir le profil
Re : Déplacement de sprite avec la souris [SFML 2.0]
« Réponse #2 le: Février 27, 2013, 10:24:00 pm »
C'est fou ça... Merci Laurent, c'est super, ça maaaarche :) Je crois avoir compris ton code, sauf deux ou trois trucs, je m'en vais replancher tout ça. Enfin c'est vrai que le tiens est beaucoup plus lisible pour le coup.

Merci encore !

Mr Pchoun.

PS : Comment fait-on pour mettre le sujet en "résolu" ?  ;D

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Déplacement de sprite avec la souris [SFML 2.0]
« Réponse #3 le: Février 27, 2013, 10:37:43 pm »
Citer
Je crois avoir compris ton code, sauf deux ou trois trucs, je m'en vais replancher tout ça
N'hésite pas à demander si tu as besoin.

Citer
Comment fait-on pour mettre le sujet en "résolu" ?
Tu peux éditer le titre pour ajouter quelque chose si tu y tiens, mais il n'y a pas d'obligation.
Laurent Gomila - SFML developer

mccusti

  • Invité
Re : Déplacement de sprite avec la souris [SFML 2.0]
« Réponse #4 le: Février 27, 2013, 11:00:12 pm »
Si je peux me permettre... Ce qui était foireux dans ton code c'est la ligne
distance=(vecteur.x > vecteur.y ) ? vecteur.x : vecteur.y ;
Avec ça tu te retrouves facilement à manipuler des distances négatives, d'où le programme qui fera n'importe quoi  ;)

DrPapino

  • Newbie
  • *
  • Messages: 34
    • Voir le profil
Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #5 le: Février 27, 2013, 11:23:26 pm »
Ah ben maintenant que tu le dis, c'est vrai que des abs() auraient pas fait de mal.

[...]

Je viens de tester là, effectivement, c'est les distances négatives qui ne faisaient pas bon ménage. Mais j'ai toujours ce problème de variations de vitesse, je pense que mon clock.restart() était au mauvais endroit. M'enfin toute façon, le code de Laurent est mieux  ;D

Mr Pchoun

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #6 le: Février 28, 2013, 07:52:34 am »
Pourquoi est-ce que tu prends une seule composante du vecteur, et non sa vraie longueur ?
Laurent Gomila - SFML developer

DrPapino

  • Newbie
  • *
  • Messages: 34
    • Voir le profil
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #7 le: Février 28, 2013, 01:39:45 pm »
Dans l'idéal, j'aurais voulu que ma vitesse soit exprimée en pixels/secondes. Si on admet que mon sprite peut se déplacer en diagonale ( c'est à dire sauter une ligne ET une colonne ) et pas forcément qu'avec des pas sur le côté ( sauter une colonne ) ou dans la hauteur (sauter une ligne), le nombre de pas à faire ne peut plus être calculé par Pythagore, mais par ce petit bout de ligne :

distance=( abs(vecteur.x) > abs(vecteur.y) ) ? abs(vecteur.x) : abs(vecteur.y) ; ( que j'ai corrigé, dit dit en passant )

Après, je suis effectivement parti du principe que le sprite PEUT se déplacer en diagonale, mais je pense que j'ai juste, non ? Ce qui est sûr, c'est que si je rajoute Pythagore à mon algo mon sprite se déplace beaucoup moins vite et s'arrête parfois un peu trop tard.

Mr Pchoun

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #8 le: Février 28, 2013, 01:52:34 pm »
A mon avis ça n'a aucun impact, il faut donc bien prendre la distance réelle (la longueur du vecteur). Après tout, tu déplaces ton sprite dans un monde 2D dont les coordonnées sont continues et quelconques. Le mapping vers des pixels n'est fait que lorsque la carte graphique rasterize ton sprite, donc ça n'a absolument rien à voir.

En d'autres termes, si ton sprite se déplace de 1 unité en diagonale, il va se retrouver aux coordonnées (0.707, 0.707) -- donc il aura bien avancé de 1 unité -- et non magiquement en (1, 1), car quand tu le déplaces il n'y a que des formules mathématiques en jeu, aucune notion de pixel.

Après j'ai peut-être mal compris ce que tu voulais dire ;D
Laurent Gomila - SFML developer

DrPapino

  • Newbie
  • *
  • Messages: 34
    • Voir le profil
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #9 le: Février 28, 2013, 02:18:04 pm »
Non non tu as bien compris, et tu as même su y répondre ! En effet, j'étais dans l'optique de me rapprocher le plus possible d'un univers "pixélisé", et c'est pour ça que j'avais fait mon calcul de cette manière.

Enfin.. ne vas pas demander pourquoi, dans ce cas, je n'ai pratiquement déclaré que des float et des sf::vector2f .. C'était au cas où ;D Par contre, qu'est ce qu'une rasterization ? J'ai cherché sur le net, j'ai pas trop compris.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #10 le: Février 28, 2013, 02:27:19 pm »
La rasterization est la transformation d'une image quelconque en une image faite de pixels. C'est l'étape durant laquelle la carte graphique va prendre ton sprite, qui est un rectangle dont les coordonnées sont des nombres réels, et le convertir en la zone de pixels qu'il va occuper à l'écran.

Par exemple :
Laurent Gomila - SFML developer

dorgon

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #11 le: Avril 05, 2014, 08:24:39 pm »
Bonjour,
Donc moi aussi j'ai besoin de déplacer un sprite avec la souris. En fait, je voudrais un peu modifier votre fonction, Laurent, mais j'ai juste besoin d'une petite explication, par rapport au vecteur vélocity et à quoi il sert.
Merci d'avance :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #12 le: Avril 05, 2014, 10:26:33 pm »
Le vecteur "velocity" est le vecteur vitesse. Qu'est-ce que tu veux savoir au juste ?
Laurent Gomila - SFML developer

dorgon

  • Newbie
  • *
  • Messages: 6
    • Voir le profil
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #13 le: Avril 08, 2014, 06:28:09 pm »
Salut,
Ce que je voudrais savoir, enfin ce à quoi je réfléchis, c'est comment faire pour que "shape" bouge tout le temps à la même vitesse, et non ne mette à chaque fois environ deux secondes pour passer à ,'importe quel point de l'écran.
En réfléchissant je me suis demander si je pouvais passer par un vecteur d'angle 45° et d'adapter les mouvements qui ne seront plus en ligne droite (quand x ou y sera égale à x ou y de la cible) mais j'ai un peu de mal à mettre ne place la fonction,
Merci d'avoir répondu aussi vite je n'avais pas vu x)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32504
    • Voir le profil
    • SFML's website
    • E-mail
Re : Déplacement de sprite avec la souris [SFML 2.0][Résolu]
« Réponse #14 le: Avril 08, 2014, 07:12:05 pm »
Justement avec un vecteur vitesse ton objet se déplacera toujours avec la même vitesse. Donc s'il va plus près il mettra moins de temps.

C'est vraiment vague ta description du problème, est-ce que ce ne serait pas mieux d'essayer de faire quelque chose et puis de revenir avec du concret ?
Laurent Gomila - SFML developer