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

Auteur Sujet: Collision Tilemap  (Lu 29402 fois)

0 Membres et 2 Invités sur ce sujet

spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #15 le: Mai 10, 2014, 07:48:38 pm »
Re, oui je sais disant que ça fait une petite heure que je re-travaille dessus et j'ai changer le 450 et 430,
Vuc mes lignes de codes ne sont pas vraiment juste ;D

wala le prinsipe que j'aimerai faire:   
1) loader un carrer(qui serras pour ce test un mur)
2) luis inscrire la position du millieu ect..
//juste que la aucun problème  :)

3)si mon personnage fait une collision(de nimporte quelle côté) alors le personnage est bloqué
en gros comme quand tu fonce dans un mur & tu ne le traverse pas...

Comment dois-je faire cela en ligne de code ???



A aussi pour les test je les avait utilisé ce matin pour justement blocké le bord de la fenêtre afin que mon perso ne puisse en sortir...



spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #16 le: Mai 10, 2014, 07:53:18 pm »
A j'oubliais, j'ai regarder aussi http://fr.openclassrooms.com/informatique/cours/theorie-des-collisions denouveau le problème comme je te le dis en haut c'est q'après j'ai stricktement aucune idée pour faire blocké le personnage... 

car envoyé un true si le perso a 0 vie ont l'amène jute a "mort" donc c'est plus simple...

kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Collision Tilemap
« Réponse #17 le: Mai 10, 2014, 08:14:36 pm »
Bonjour,
Pour "bloquer" ton personnage, tu peux le repositionner à la limite de obstacle lorsqu'il y a une collision.
Pour savoir où est cette limite, tu peux utiliser la direction dans laquelle se déplace le personnage pour savoir de quel coté il vient et en déduire de quel coté de l'obstacle il doit être repositionné. Après, il faut utiliser les tailles de l'obstacle et du personnage.

Voilà un exemple simplifié. (Il faudrait aussi tenir compte de l'origine des objets, comme tu utilises des objets dérivant de sf::Transformable)
Je ne sais pas comment est structuré ton programme et si c'est directement applicable mais j'espère que ça te donnera des idées.

if(collision(joueur, obstacle))
{
    switch(joueur.direction)
    {
        case UP: // le joueur vient d'en bas
            joueur.y = obstacle.y + obstacle.h; // on le place en bas de l'obstacle
            break;
        case DOWN:
            joueur.y = obstacle.y - joueur.h;
            break;
        case LEFT:
            joueur.x = obstacle.x + obstacle.w;
            break;
        case RIGHT:
            joueur.x = obstacle.x - joueur.w;
            break;
    }
}

spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #18 le: Mai 10, 2014, 08:22:05 pm »
Salut
Citer
Pour "bloquer" ton personnage, tu peux le repositionner à la limite de obstacle lorsqu'il y a une collision.
Pour savoir où est cette limite, tu peux utiliser la direction dans laquelle se déplace le personnage pour savoir de quel coté il vient et en déduire de quel coté de l'obstacle il doit être repositionné. Après, il faut utiliser les tailles de l'obstacle et du personnage.
oui cela je le savais deja  :D

merci beaucoup pour tes lignes de codes je vais de ce pas les essayer et en redire des nouvelles ;)

spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #19 le: Mai 10, 2014, 08:58:01 pm »
Salut merci pour ta ligne de code, mais je pense que tu n'as pas compris ma question(dsl si je l'ai mal posée)

voici toutes mes lignes de code (simplifiée)

main.cpp

Citer
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
#include "Shape.h"

sf::RenderWindow window;
sf::RectangleShape rect;
int speed = 2;
sf::Vector2i positionSouris;
sf::Texture perso;
sf::Sprite sprite_perso;

enum Dir{ Down, Left, Right, Up };
sf::Vector2i anim(1, Down);
bool updateFPS = true;
int blockSize = 32;
int blockDemiSize = 16;
std::string reponse("None");
std::string rep("None");
std::string arret("None");

/**[Les Void] **/
void gestion_clavier();
void gestion_souris();
void gestion_bloque();
/**[Les Void] **/

int main()
{
//Création de la fenêtre 800x600
window.create(sf::VideoMode(800, 600), "Test SFML");
//Modifier la position
window.setPosition(sf::Vector2i(192, 0));
window.setFramerateLimit(60);

std::cout << "Lancement du jeu" << std::endl;

rect = PB_Rect(400, 300, 48, 48);

sf::Clock time;

if (!perso.loadFromFile("resources/image.png"))
{
std::cout << "Erreur chargement de image.png" << std::endl;
}

//En pofine les FPS
perso.setSmooth(true);

sprite_perso.setTexture(perso);

//Tant que la fenêtre est ouverte...
while (window.isOpen())
{
sf::Event event;
//Test des événements
while (window.pollEvent(event))
{
//Si on clique sur fermer
if (event.type == sf::Event::Closed)
window.close(); //On ferme la fenêtre

if (event.type == sf::Event::KeyPressed)
{ /*Pour activer l'anim*/
updateFPS = true;
}
else
updateFPS = false;
anim.x = 1;

}

/**[Les Void] **/
gestion_clavier();
gestion_souris();
gestion_bloque();
/**[Les Void] **/

if (updateFPS == true)
{
if (time.getElapsedTime().asMilliseconds() >= 50)
{ /*On change d'animation toutes les 50 milli secondes*/
anim.x--;
if (anim.x * blockSize >= perso.getSize().x)
anim.x = 2;
time.restart(); /*On relance le timer*/
std::cout << sprite_perso.getPosition().x << "," << sprite_perso.getPosition().y << std::endl;
}
}
//on "coupe" les parties de l'image pour les réutiliser en animation..
sprite_perso.setTextureRect(sf::IntRect(anim.x * blockSize, anim.y * blockSize, blockSize, blockSize));

if (arret == ("stop"))
{
    return 0;
}

// On dessine, on affiche et on met à jour
window.draw(rect);
window.draw(sprite_perso);
window.display();
window.clear();
}

return 0;
}



void gestion_clavier()
{



if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
anim.y = Up;
sprite_perso.move(0, -speed);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
anim.y = Down;
sprite_perso.move(0, speed);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
anim.y = Left;
sprite_perso.move(-speed, 0);
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
anim.y = Right;
sprite_perso.move(speed, 0);
}

if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
    std::cout << "[STOP]" << std::endl;
    arret = ("stop");

}
}
void gestion_souris() /** changer  "sprite" par "rect" **/
{
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
//On récupère les coordonnées de la souris
positionSouris = sf::Mouse::getPosition(window);
//std::cout << "Mouse.x" << positionSouris.x << "Mouse.y" << positionSouris.y << std::endl;
int mouseX = positionSouris.x;
int mouseY = positionSouris.y;
sprite_perso.setPosition(mouseX, mouseY); // On positionne le rect
}
}


void gestion_bloque()
{

/*Il va tout a gauche alors, il est bloqué*/
if (sprite_perso.getPosition().x <= 0)
{
sprite_perso.setPosition(sf::Vector2f(0, sprite_perso.getPosition().y));
}

/*Il va tout a droite alors, il est boqué*/
if (sprite_perso.getPosition().x >= 770)
{
sprite_perso.setPosition(sf::Vector2f(770, sprite_perso.getPosition().y));
}

/*Il va tout en bas alors, il est bloqué*/
if (sprite_perso.getPosition().y >= 569)
{
sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x, 569));
}

/*Il va tout en haut alors, il est bloqué*/
if (sprite_perso.getPosition().y <= 0)
{
sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x, 0));
}
}
(si vous avez remarqué un "void gestion_console" que j'ai supprimer pour racourcir ses lignes de codes

Shape.h
Citer
#ifndef DEF_SHAPE
#define DEF_SHAPE

#include <SFML/Graphics.hpp>


sf::RectangleShape PB_Rect(int posX, int posY, int width, int height)
{
    sf::RectangleShape rect(sf::Vector2f(width, height));
    rect.setPosition(posX, posY);
    rect.setFillColor(sf::Color(255, 0, 0, 255));

    return rect;
}
#endif // DEF_SHAPE

Wala mes deux question:

1)
Comment et ou je pourrais ajoutez ses lignes de codes :
Citer
if(collision(joueur, obstacle))
{
    switch(joueur.direction)
    {
        case UP: // le joueur vient d'en bas
            joueur.y = obstacle.y + obstacle.h; // on le place en bas de l'obstacle
            break;
        case DOWN:
            joueur.y = obstacle.y - joueur.h;
            break;
        case LEFT:
            joueur.x = obstacle.x + obstacle.w;
            break;
        case RIGHT:
            joueur.x = obstacle.x - joueur.w;
            break;
    }
}

2)
après avoir ajouter ses lignes de codes...comment je fait pour faire le test(if)

par exemple "joueur.y = obstacle.y - joueur.h;" si c'est a 0 ou plus petit je block le perso, mais ou et comment vuc il peut être de tous le côté svp? ???
« Modifié: Mai 10, 2014, 09:03:10 pm par spyker18 »

PtichapronRouge

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
    • E-mail
Re : Collision Tilemap
« Réponse #20 le: Mai 11, 2014, 12:02:37 am »
Visiblement tu geres les événements claviers et le déplacement dans la même fonction, c est pas optimal, mais bon ^^
Enfin puisque tu fais comme ça, gère la collision dans la même fonction. Au lieu d appliquer un le déplacement à ton sprite juste après le keypressed, calcule les coordonnées qu' aurait ton sprite si tu le déplaçais, et selon qu il y a collision ou non entre le perso virtuel et l obstacle, tu déplaces ton personnage en suivant la méthode de kimci ou non. :)

Et un conseil au passage : quand tu auras résolu ce problème, reprend ton code du début et essaie de le rendre plus oriente objet, en encapsulant ton perso et tout ce qui lui est lié dans une seule classe, ça sera beaucoup beaucoup plus lisible :D
Un coca, un ordinateur, et un livre SFML Game Development. Elle est pas belle la vie ?

PtichapronRouge

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
    • E-mail
Re : Collision Tilemap
« Réponse #21 le: Mai 11, 2014, 12:08:35 am »
Citer
après avoir ajouter ses lignes de codes...comment je fait pour faire le test(if)
Regarde dans les premiers messages, j ai donné une fonction booléenne pour les collisions personnage - tileMap ;)
Après, faudra sûrement l adapter un peu, mais c est pas trop compliqué ;)
Un coca, un ordinateur, et un livre SFML Game Development. Elle est pas belle la vie ?

spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #22 le: Mai 11, 2014, 09:28:48 am »
Salut, je avoue la je suis un peux perdu  :-\

peux te me montrer un exemple concré avec les lignes de codes?

pour que je puisse apres mieu comprendre
(je comprend mieu quand j'ai les lignes de codes devant moi (=)

Citer
Et un conseil au passage : quand tu auras résolu ce problème, reprend ton code du début et essaie de le rendre plus oriente objet

Je sais que j'ai des "void" de trop et autre petit truck dégeulasse  ;D

pour les void avant je faisais toujours avec un "gestion.cpp" mais avec la sfml même si je fais tous juste (comme avant) mon compilateur m'inscrit des fichier "efbewfo.cpp" avec des fautes

et vuc c'est sensé être un test je me suis pas embété a se sujet...
 :)



« Modifié: Mai 11, 2014, 09:31:05 am par spyker18 »

kimci86

  • Full Member
  • ***
  • Messages: 128
    • Voir le profil
Re : Collision Tilemap
« Réponse #23 le: Mai 11, 2014, 11:13:54 am »
Bonjour,
Citer
1)
Comment et ou je pourrais ajoutez ses lignes de codes

Même si le plus sage serait de tout recommencer proprement (faire des classes, ne pas utiliser de variables globales, etc), avec ton code actuel, tu peux ajouter la gestion des collisions dans la fonction gestion_bloque, après le code qui replace le personnage dans l'écran s'il en sortait.

Citer
2)
après avoir ajouter ses lignes de codes...comment je fait pour faire le test(if)

par exemple "joueur.y = obstacle.y - joueur.h;" si c'est a 0 ou plus petit je block le perso, mais ou et comment vuc il peut être de tous le côté svp? ???

Je ne suis pas sûr d'avoir bien compris ta question, mais il me semble que tu veux savoir si la gestion des collisions avec l'obstacle ne va pas faire sortir le personnage de l'écran.

En effet, si tu prends ton personnage en sandwich entre le bord de l'écran et l'obstacle et que l'obstacle est déplacé vers le bord de l'écran, le personnage va finir par se trouver "écrasé" entre les deux... On pourrait alors choisir dans ce cas de faire perdre la partie.

Pour gérer ça, tu pourrais vérifier à nouveau que le personnage est dans l'écran après la gestion des collisions.

spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #24 le: Mai 11, 2014, 11:54:32 am »
yo j'ai enfin trouver pour faire la collision

:
Citer
/**[Gestion:::Collision]**/

if ((std::abs((sprite_perso.getPosition().x + 20) - (rect.getPosition().x + 20)) < blockSize) &&
(std::abs((sprite_perso.getPosition().y + 20) - (rect.getPosition().y + 20)) < blockSize))
{/*Gestion::X*/
if ((sprite_perso.getPosition().x >= 375) &&
(sprite_perso.getPosition().x <= 380))
        {
         sprite_perso.setPosition(sf::Vector2f(375, sprite_perso.getPosition().y));
        }

if ((sprite_perso.getPosition().x >= 430) &&
(sprite_perso.getPosition().x <= 440))
        {
         sprite_perso.setPosition(sf::Vector2f(440, sprite_perso.getPosition().y));
        }
/*Gestion::Y*/
if ((sprite_perso.getPosition().y >= 270) &&
(sprite_perso.getPosition().y <= 275))
{
    sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x, 270));
}

if ((sprite_perso.getPosition().y >= 330) &&
(sprite_perso.getPosition().y <= 345))
{
    sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x, 345));
}

}
}

même si ça marche ce n'est pas du tout au point :-\

Du coup qqn pourrais me passer ses lignes de codes(d'un mur) par exemple ou autre..


comment faire pour que le perso ne traverse pas le carre(d'une autre manière) svp ???
ou comment améliorer ce code?

« Modifié: Mai 11, 2014, 11:57:25 am par spyker18 »

PtichapronRouge

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
    • E-mail
Re : Collision Tilemap
« Réponse #25 le: Mai 11, 2014, 12:45:32 pm »
Est ce que je me trompe ou tu utilise la fonction valeur absolue pour calculer une distance ? 
Citer
if ((std::abs((sprite_perso.getPosition().x + 20) - (rect.getPosition().x + 20)) < blockSize) &&
(std::abs((sprite_perso.getPosition().y + 20) - (rect.getPosition().y + 20)) < blockSize))

On a déjà fait mieux en terme de calcul de distance entre deux points  :P
Cependant tu n' en a as pas besoin a mon avis, si je comprends bien ce calcul te sert à determiner la distance entre ton perso et le carré et tu en déduis s'il y a collision c'est ca ? A ta place j'utiliserai plutot la fonction
sf::Rect::Intersects(const sf::Rect<U> &rectangle)
qui est faite pour ca ;)
Un coca, un ordinateur, et un livre SFML Game Development. Elle est pas belle la vie ?

spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #26 le: Mai 11, 2014, 12:53:58 pm »
Citer
sf::Rect::Intersects(const sf::Rect<U> &rectangle)
qui est faite pour ca ;)
Le problème est que j'ai stricktement aucune idée de comment ça marche ;D

Mon gros problème(d'apres moi) c'est que le personnage au coin gauche du carre et bas "bug"
au moment de la collision il y a comme une téléportation... :-\

PtichapronRouge

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
    • E-mail
Re : Collision Tilemap
« Réponse #27 le: Mai 11, 2014, 01:01:05 pm »
Pour le sf::Rect::Intersects,  voici un petit code de démo :
sf::FloatRect rect1(0,0,20,20);
sf::FloatRect rect2(10,10,30,30);
if(rect1.intersects(rect2))
     std::cout << "Collision" << std::endl;
else
     std::cout << "Pas collision" << std::endl;

Teste ce code avec differentes coordonnées, ca devrait être plus clair apres ;)
Un coca, un ordinateur, et un livre SFML Game Development. Elle est pas belle la vie ?

spyker18

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
Re : Collision Tilemap
« Réponse #28 le: Mai 11, 2014, 01:17:51 pm »
sf::FloatRect rect1(0,0,20,20);
sf::FloatRect rect2(10,10,30,30);
if(rect1.intersects(rect2))
     std::cout << "Collision" << std::endl;
else
     std::cout << "Pas collision" << std::endl;

Merci pour ton exemple, une dernière question :
"(0,0,20,20)" veulent dire les 4 angles de mon carrés?

si oui(ça semble logique), est-ce que je peux "blocké" mon personnage avec d'autre ligne de code(comme ::intersects) pour que mon perso je traverse pas mon rectangle..

PtichapronRouge

  • Newbie
  • *
  • Messages: 41
    • Voir le profil
    • E-mail
Re : Collision Tilemap
« Réponse #29 le: Mai 11, 2014, 01:28:15 pm »
Citer
"(0,0,20,20)" veulent dire les 4 angles de mon carrés?
nope raté  :P
si c'etait ca, tu aurais 8 valeurs ;)
Ici ce sont les coordonnées du coin haut-gauche (0,0), la hauteur(20) et la largeur(20) 

Cette fonction te permet de détecter une collision, après à toi de la gérer pour empêcher ton personnage de passer à travers un mur. Quand j'aurais l'occasion je veux bien essayer de te faire un petit code de démonstration de gestion de collision, mais d'ici là, essaie de trouver tes propres solutions, tu les retiendras mieux, tu les comprendras mieux, et ce sera plus facile de les adapter à tes futurs projets  :)
Un coca, un ordinateur, et un livre SFML Game Development. Elle est pas belle la vie ?

 

anything