CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[SFML]Déplacer un sprite

iostream
iostream
Niveau 4
04 août 2009 à 20:43:10

Bonjour, pour m'entrainer j'ai décidé de dev ... un pong :) , original je sais ... j'ai un petit soucis, certainement très simple a régler.
J'ai un classe Moteur2d avec dedans une fonction deplacerBarre qui devrait logiquement déplacer la barre du pong mais ca ne fonctionne pas. Le code si dessous :) !

main.cpp

  1. include <SFML/System.hpp>
  2. include <SFML/Window.hpp>
  3. include <SFML/Graphics.hpp>
  4. include <iostream>
  5. include <string>
  6. include "Moteur2d.h"

const int SCREEN_WIDTH = 600;
const int SCREEN_HEIGHT = 400;
const int COLOR_DEPH = 32;

int main(int argc, char** argv)
{

sf::RenderWindow App(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, COLOR_DEPH), "SFML Test !!");
float ElapsedTime = App.GetFrameTime();

bool Running = true;
while (Running)
{
Moteur2d moteur(App);
Moteur2d moteur(App);
moteur.loadSprite("barre.png");
// moteur.loadSprite("balle.png");
moteur.afficherSprites(App);

sf::Event Event;
while (App.GetEvent(Event))
{
if((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Down))
{
moteur.deplacerBarre(App,ElapsedTime);
}

}

App.Display();
}

return EXIT_SUCCESS;
}

Moteur2d.h

  1. ifndef DEF_MOTEUR2D
  2. define DEF_MOTEUR2D
  1. include <string>
  2. include <iostream>
  3. include <SFML/System.hpp>
  4. include <SFML/Window.hpp>
  5. include <SFML/Graphics.hpp>
  6. include <vector>

class Moteur2d
{

public :
Moteur2d(sf::RenderWindow &win);
void loadSprite(std::string nomSprite);
void resizeSprite(float newLargeur, float newLongueur);
void afficherSprites(sf::RenderWindow &win);
void deplacerBarre(sf::RenderWindow &win, float currentTime);

private :
std::vector<sf::Image> imagesToLoad;
std::vector<sf::Sprite> sprites;
int i;
// float ElapsedTime;

};

  1. endif

Et enfin, Moteur2d.cpp

  1. include "Moteur2d.h"

Moteur2d::Moteur2d(sf::RenderWindow &win)
{

i = 0;

}

void Moteur2d::loadSprite(std::string nomSprite)
{

imagesToLoad.resize(i+1);
sprites.resize(i+1);
imagesToLoad[i].LoadFromFile(nomSprite);
sprites[i].SetImage(imagesToLoad[i]);

i++;

}
void Moteur2d::resizeSprite(float newLargeur, float newLongueur)
{

sprites[i-1].Resize(newLargeur,newLongueur);

}
void Moteur2d::afficherSprites(sf::RenderWindow &win)
{

for(unsigned int k = 0; k < sprites.size();k++)
{
win.Draw(sprites[k]);
}

}

void Moteur2d::deplacerBarre(sf::RenderWindow &win, float currentTime)
{
//currentTime = win.GetFrameTime();

//sprites[0].Move(0,-100 * currentTime);
sprites[0].SetPosition(200,-300);
win.Draw(sprites[0]);

}

Voilà, j'imagine aussi que mon code est catastrophique :-d mais c'est pas grave, merci de votre aide !

dnob700
dnob700
Niveau 10
04 août 2009 à 21:18:23

Si l'erreur n'est pas grossière (en tout cas elle ne m'a pas sauté au yeux) c'est très difficile de déboguer un tel programme sans l'exécuter. Donc il faut que tu apprenne à le faire toi même.

Là par exemple tu peut commencer à mettre des printf par exemple dans la boucle "while (App.GetEvent(Event))" avant et à l'intérieur du "if" pour voir si l'événement se déclenche. Si c'est le cas tu pourra alors regarder ce qui ne vas pas dans ta fonction de déplacement, sinon tu vas essayer de comprendre pourquoi ton test ne vas pas. Mais en tout cas, tu auras progressé.

godrik
godrik
Niveau 30
04 août 2009 à 22:12:55

En version lisible, ca donne ca: http://pastebin.com/m359dab60

godrik
godrik
Niveau 30
04 août 2009 à 22:16:06

apres avoir lu le code, je pense que le probleme vient de la variable ElapsedTime qui n'a pas la bonne valeur.
La fonction 'float sf::Window::GetFrameTime () const' renvoie le temps ecoule depuis la derniere frame, comme tu ne l'appelle qu'une seule fois juste apres la creation de la fenetre, j'imagine que sa valeure est 0.

sinon dnob++

Paulop
Paulop
Niveau 12
04 août 2009 à 22:28:25

Tu devrais utiliser pastebin la prochaine fois ^^

Bon déjà dans le main :

Moteur2d moteur(App);
Moteur2d moteur(App);

Et dans Moteur2D, tu fais Window.Draw dans deux méthodes différentes

C'est étrange :)

Ensuite, je pense que tu t'embêtes avec ta classe Moteur2D, elle ne fait qu'intermédiaire entre ton Main et ta classe Sprite.

Je pense que tu peux la transformer pour avoir les rôles suivant :

Encapsuler ta fenêtre et l'initialiser(Méthode Init)
Update les évènements (Méthode Update) -> Je te conseille de renvoyer tous les évènements claviers et souris vers une autre classe.
Afficher (Méthode Display ou Draw pour afficher tout, DrawSprite pour faire une liste des sprites à afficher)

Tu pourras aussi garder ta liste d'images dans la classe, ce n'est pas trop gênant, et donc rajouter une méthode pour les charger à partir d'une String. (ça te permettra de coder une "cache" pour ne pas charger deux images identiques)

Ensuite dans tes autres classes, tu vas par exemple à partir de la méthode Draw de la classe Jeu faire : Moteur.DrawSprite(raquette).
Une référence vers ton sprite de raquette sera copié dans une liste dans Moteur2D, et affiché en temps voulu dans la méthode Draw.

Je sais pas si j'ai été clair là :/
Au pire pose des questions :)

En faisant déjà ça tu auras réduit ton code, et ça te permettra de mieux voir.

Paulop
Paulop
Niveau 12
04 août 2009 à 22:30:36

Ah et puisque je viens de m'en appercevoir, utilise plutôt les méthodes push_back et insert que resize pour tes std::vector (voir la doc)

iostream
iostream
Niveau 4
04 août 2009 à 22:40:42

Merci, je penserais à utiliser pastebin la prochaine fois :) je ne connaissais pas ce site ! Concernant les deux

Moteur2d moteur(App);

Dans mon code ils n'y sont pas, j'ai fait une bête faute de frappe et comme jv.com a du mal a coder la fonction éditer (remarque, quand elle sortira elle devra etre sacrément au point la bestiole depuis le temps) bah ..

Pour la classe, j'avais pas pensé a tout ça et en fait je voulais créé un moteur 2d qui puisse (après de nombreuse modification j'en suis conscient) servir de base pour d'autre jeux à venir et pour un pong c'est vrai que j'ai pas voulu faire trop de classe, afficher une barre, une balle et bouger la barre et la balle en gérant les collisions,normalement, ca devrait pas être trop difficile !

Hum, t'as été moyen clair la ^^ mais je vais essayer de bien décortiquer ça, faire comme dnob a dit.

@godrik : Nan dans mon code, j'ai mis en commentaire la ligne ou je me servais de GetElapsedTime, en fait en appuyant sur la flèche du bas ca devrait changer la position de mon sprite

sprites[0].SetPosition(200,-300);

Mais nan, rien ... ça compile bien mais je vais rajouter des if partout pour tester tout et on verra bien, merci :) !

godrik
godrik
Niveau 30
04 août 2009 à 22:47:55

Si tu ne nous donnes pas le code exacte que tu utilises comment veux tu qu'on t'aide ? :)

iostream
iostream
Niveau 4
04 août 2009 à 22:51:20

C'est le code exact :-) !

Regarde,

void Moteur2d::deplacerBarre(sf::RenderWindow &win, float currentTime)
{
//currentTime = win.GetFrameTime();
//sprites[0].Move(0,-100 * currentTime);
sprites[0].SetPosition(200,-300);
win.Draw(sprites[0]);

}

Les deux lignes utilisant le temps sont commenté et la seule qui devrait marcher c'est celle qui change la position mais je sais pas, en plus y'a pas de méthode update dans la classe RenderWindow de la sfml c'est étrange ... enfin, je me lance dans le débuggage :) si vous avez d'autre idée hésitez pas !

Paulop
Paulop
Niveau 12
04 août 2009 à 22:51:32

Pour résumer, chaque classe droit répondre à un problème.

Donc dans l'idéal tu auras une classe gérant les graphismes, une gérant le clavier et la souris (Input), une gérant le fonctionnel du jeu. Après tu peux avoir une autre granularité, par exemple, une classe qui gère la raquette, une qui gère la balle...

Ta classe Moteur2D devrais donc seulement faire de l'affichage.

Dans l'idéal, tu lui dis quoi afficher, ce n'est pas elle qui le décide.

D'ou le fait de lui donner les adresses des sprites à afficher plutôt que de lui faire stocker tous les sprites.

Je te conseillais en gros donc de faire une méthode appellée depuis ta classe "Jeu" ou ce que tu veux :
DrawSprite ( Sprite& sprite)
{
listeDeSprites.push_back(sprite);
}

Puis une autre appelée dans le main.cpp à chaque tour de boucle :
Draw ()
{
pour chaque sprites de la liste de sprites
{
Windows.Draw(listeDeSprites[i]);
}
listeDeSprites.clear()
}

Paulop
Paulop
Niveau 12
04 août 2009 à 22:53:19

Double poste pour ton autre question :p

Ouais en fait ton seul GetFrameTime est tout en haut du main, il n'est pas dans le update, donc forcemment il est jamais mit à jour, il faut que tu le déplace dans le while(1)

Et c'est normal que RenderWindow n'ait pas de Update, puisqu'il n'a rien à updater :-p

iostream
iostream
Niveau 4
04 août 2009 à 23:02:21

Je vois ce que tu veut dire :) j'ai une question donc parceque je maitrise encore mal ce concept ...

Un moteur 2d est censé gérer quoi ? Si j'ai bien saisi, l'affichage de tout élément graphique du jeu mais il ne doit en aucun cas les stocker ou faire des opérations dessus ? En fait tout ça est réservé à d'autre classe comme Input pour gérer clavier souris, Jeu pour gérer les sprite en mémoire etc .. ?

Pourl'histoire d'update, oui c'est vrai ca s'update tout seul ... donc si je demande seulement de bouger le sprite avec ca :

sprites[0].Move(0,-100 * currentTime);

j'ai pas besoin de mettre un

win.Draw(sprite[0]);

? il devrait s'update seul, nan ^^ ?

Paulop
Paulop
Niveau 12
04 août 2009 à 23:10:06

Le moteur il va simplement rendre à l'écran ce que tu lui envoies.

Dans un monde idéal, tu créeras des entités (une classe balle par exemple) qui contiendront un sprite (avec l'image de la balle, une position du sprite etc...)

Dans ta classe jeu, tu diras que tu veux afficher ton entité à l'écran, tu appelleras la méthode Draw de ton entité. Celle-ci, a toutes les données nécessaire à l'affichage de la balle, elle n'a plus qu'a l'envoyer au moteur2D pour qu'il le restitue à l'écran.

C'est comme si tu voulais un dessin, tu sais exactement ce que tu veux, tu l'as dans la tête, tu vas voir un dessinateur, et tu lui dis : je veux ça, lui il s'exécute.

Tu ne dois mettre qu'un win.Draw dans ton cas, tu gardes celui dans afficherSprites et tu enlèves l'autre.

Et il faut que tu passes :
float ElapsedTime = App.GetFrameTime(); (ligne 16) dans le while(IsRunning) (ligne 22)

iostream
iostream
Niveau 4
04 août 2009 à 23:11:22

Après un control de ma boucle d'évenement :

sf::Event Event;
while (App.GetEvent(Event))
{

//test de la boucle
if(!App.GetEvent(Event))
std::cerr << "Event marche pas !" << std::endl;
if((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Down))
{
moteur.deplacerBarre(App,ElapsedTime);
}

}

Et bah ... la boucle d'évenement ne marche pas ! a moins que je me sois trompé dans mon if de test :gni:

Paulop
Paulop
Niveau 12
04 août 2009 à 23:13:33

C'est normal, il faut que tu mettes ton std::cerr dans le second if et que tu supprimes le premier qui ne sert à rien (si on est dans la boucle while, c'est parce que la condition est déjà vérifiée donc inutile de la vérifier une seconde fois)

iostream
iostream
Niveau 4
04 août 2009 à 23:15:38

Oui je viens d'y penser, c'est très con -_- desfois je réfléchis pas

mis dans la deuxième ca me sors la même erreur, bon je vais réfléchir un peu, j'aimerais bien régler ce problème avant de recoder toute mes classes ...

Paulop
Paulop
Niveau 12
04 août 2009 à 23:17:19

Si cela affiche "Event marche pas !" alors c'est que ça fonctionne correctement justement :)

iostream
iostream
Niveau 4
04 août 2009 à 23:18:57

Ah bah ... ça vient de ma méthode alors, mais je vois pas trop, une simple fonction de déplacement de sprite, peut etre que quand je met

sprites[0].SetPosition(200,-300);

ca envoi une copie de sprite et ducoup, ca modifie pas la position, nan ? a part ça, je vois mal ou j'ai fait une erreur, c'est une méthode basique de chez basique ...

iostream
iostream
Niveau 4
04 août 2009 à 23:32:02

y'a une évolution, déjà les coordonné été mauvaise, c'est pas le système x,y qu'on n'ous apprend a l'école j'avais pas fait gaffe, mais ca règle pas, j'ai changé les coordonnées, ca s'affiche pas, si je met un

win.Draw(sprites[0]);

ca me change la position ... en gardant l'ancienne aussi ducoup je retravaille la méthode, je vais y arriver !

Paulop
Paulop
Niveau 12
04 août 2009 à 23:38:22

http://pastebin.com/m2d0e6f01

Voila une version corrigée, compare chaque point pour bien comprendre ce qui n'allait pas :)

Sous forums
  • Aide à l'achat Mac
  • Création de Jeux
  • Linux
  • Création de sites web
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment