Bienvenue, Invité. Merci de vous connecter ou de vous inscrire. Avez-vous oublié d'activer ?

Voir les contributions

Cette section vous permet de consulter les contributions (messages, sujets et fichiers joints) d'un utilisateur. Vous ne pourrez voir que les contributions des zones auxquelles vous avez accès.


Sujets - Mayt

Pages: [1]
1
Graphique / [SFML 1.6] Tile mapping et collisions.
« le: Octobre 26, 2012, 10:29:07 pm »
Bonjour, bonsoir, je sais pas ^^
Bon, alors, j'ai deux trois petites questions. Tout d'abord, j'explique un peu mon projet. Pour le moment, j'essaye d'appliquer ce que j'ai appris en SFML en codant un jeu de plateforme basé sur le Tile Mapping. Je me suis renseigné sur des sites de tutos, et j'ai fini par trouver des cours en SDL. J'ai donc passé quelques (longues) heures à adapter le code en C++ avec SFML, et en le repensant de manière objet. Jusqu'à maintenant, j'ai une carte affichée en Tile Mapping, et un personnage qui se balade dedans sans gravité, mais avec des collisions.

Seulement, quelques problèmes viennent gâcher la fête : Les collisions sont censées être calculées pour les tiles dans lequel se situe le personnage, à savoir, celle qui sont en collisions directes avec le personnage (qui fait 16 * 32, d'ailleurs, puisque vous n'avez pas l'image). Sauf qu'en pratique, les seules collisions calculées sont... les collisions avec le point supérieur gauche du personnage. Résultat, bah.. ça marche pas comme il fait.

L'autre problème, c'est que pour une autre raison tout aussi mystérieuse. La ligne
if (xmin < 0 || ymin < 0 || xmax >= TILEL || ymax >= TILEH)
devrait normalement empêcher le personnage de sortir de l'écran, sauf qu'elle lui permet de sortir d'un tile avant de s'arrêter. Ce qui là non plus n'est pas normal. Sauf que, truc très étrange, si je met la limite à
xmin < 1 || ymin < 1
, le code fait.. exactement ce qu'il devrait, à savoir empêcher le personnage de s'approcher de plus d'un bloc du bord O_o (c'est là que je suis vraiment perdu).

Si vous pouviez m'aider, je vous en serez reconnaissant :)
D'ailleurs, si jamais il y a d'autres erreurs (je n'en au pas vu, mais bon), je suis preneur aussi.

Voilà le code (inutile de vous pencher sur la partie ou je définis les SubRect : c'est compliqué et c'est normal ^^)

// main.cpp

#include <SFML/Graphics.hpp>
#include <iostream>
#include <cstdlib>
#include <sstream>

#include "map.hpp"


using namespace sf;

int main()
{
    RenderWindow app(VideoMode(LARGEUR_SCREEN, HAUTEUR_SCREEN, 32), "It works !");
    app.SetFramerateLimit(80);

    Carte carte(app, "tileset.bmp", "level3.bmp");

    while (app.IsOpened())
    {
        Event event;
        while(app.GetEvent(event))
        {
            switch(event.Type)
            {
                case Event::Closed : // Croix de fermeture
                    app.Close();
                    break;

                case Event::KeyPressed : // Appui sur une touche
                {
                    switch(event.Key.Code)
                    {
                        case Key::Escape : // Touche echap
                            app.Close();
                            break;
                        default:
                            break;
                    }
                }
                    break;
                default :
                    break;
            }
        }
        carte.Afficher();
    }
    return 0;
}

//map.hpp

#ifndef MAP_HPP_INCLUDED
#define MAP_HPP_INCLUDED

#include <SFML/Graphics.hpp>
#include <iostream>
#include <ostream>
#include <cstdlib>
#include <sstream>

#define LARGEUR_TILE 16  // hauteur et largeur des tiles.
#define HAUTEUR_TILE 16
#define HAUTEUR_SCREEN 300
#define LARGEUR_SCREEN 400
#define TILEL 127
#define TILEH 39
#define LARGEUR_MAP (TILEL*LARGEUR_TILE)
#define HAUTEUR_MAP (TILEH*HAUTEUR_TILE)
#define VITESSE 100

#include "perso.hpp"


class Perso;

class Carte
{
public:
    Carte(sf::RenderWindow&, std::string, std::string);
    ~Carte();
    void Afficher();
    void Scroll(float, float);
    int GetBlocCarte(int, int);
    void AfficherPerso(sf::Sprite&);
private:
    sf::RenderWindow &app;
    Perso *joueur;
    float m_xscroll;
    float m_yscroll;
    sf::Event event;
    sf::Image i_tileset;
    sf::Sprite s_tileset;
    sf::Image i_map;
    int blocCarte[TILEL][TILEH];

    void ChargerTileset();
};

#endif // MAP_HPP_INCLUDED

//map.cpp

#include "map.hpp"


using namespace sf;
using namespace std;

Carte::Carte(RenderWindow& app, string tileset, string map) : app(app), m_xscroll(0), m_yscroll(0)
{
    if (!i_tileset.LoadFromFile(tileset)) // Si le chargement du fichier a échoué
        cerr << "Erreur durant le chargement du tileset" << endl;
    else // Si le chargement de l'image a réussi
    {
        i_tileset.SetSmooth(false);
        s_tileset.SetImage(i_tileset);
    }
    if (!i_map.LoadFromFile(map)) // Si le chargement du fichier a échoué
        cerr << "Erreur durant le chargement de la carte" << endl;
    else
        i_tileset.SetSmooth(false);

    ChargerTileset();
    joueur = new Perso(app, "test.bmp", *this);
}

Carte::~Carte()
{
    delete joueur;
}

void Carte::AfficherPerso(Sprite& personnage)
{
    app.Draw(personnage);
}

void Carte::Scroll(float xscroll, float yscroll)
{
    m_xscroll += xscroll * app.GetFrameTime();
    m_yscroll += yscroll * app.GetFrameTime();

    if (m_xscroll < 0)
        m_xscroll = 0;
    else if (m_xscroll > LARGEUR_MAP - LARGEUR_SCREEN)
        m_xscroll =  LARGEUR_MAP - LARGEUR_SCREEN;

    if (m_yscroll < 0)
        m_yscroll = 0;
    else if (m_yscroll > HAUTEUR_MAP - HAUTEUR_SCREEN)
        m_yscroll = HAUTEUR_MAP - HAUTEUR_SCREEN;
}

void Carte::Afficher()
{
    app.Clear();

    int minx = (int)m_xscroll / LARGEUR_TILE;
    int miny = (int)m_yscroll / HAUTEUR_TILE;
    int maxx = ((int)m_xscroll + LARGEUR_SCREEN)/LARGEUR_TILE;
    int maxy = ((int)m_yscroll + HAUTEUR_SCREEN)/HAUTEUR_TILE;

    for(int i = minx; i <= maxx; i++)
    {
        for(int j = miny; j <= maxy; j++)
        {
            switch (blocCarte[i][j])
            {
                case(1):
                    s_tileset.SetSubRect(IntRect(1, 1, 17, 17));
                    break;
                case(2):
                    s_tileset.SetSubRect(IntRect(2, 0, 18, 16));
                    break;
                case(3):
                    s_tileset.SetSubRect(IntRect(0, 0, 16, 16));
                    break;
                case(4):
                    s_tileset.SetSubRect(IntRect(0, 2, 16, 18));
                    break;
                case(5):
                    s_tileset.SetSubRect(IntRect(2, 2, 18, 18));
                    break;
                case(6):
                    s_tileset.SetSubRect(IntRect(1, 0, 17, 16));
                    break;
                case(7):
                    s_tileset.SetSubRect(IntRect(0, 1, 16, 17));
                    break;
                case(8):
                    s_tileset.SetSubRect(IntRect(1, 2, 17, 18));
                    break;
                case(9):
                    s_tileset.SetSubRect(IntRect(2, 1, 18, 17));
                    break;
                case(10):
                    s_tileset.SetSubRect(IntRect(19, 1, 35, 17));
                    break;
                case(11):
                    s_tileset.SetSubRect(IntRect(20, 0, 36, 16));
                    break;
                case(12):
                    s_tileset.SetSubRect(IntRect(18, 0, 34, 16));
                    break;
                case(13):
                    s_tileset.SetSubRect(IntRect(18, 2, 34, 18));
                    break;
                case(14):
                    s_tileset.SetSubRect(IntRect(20, 2, 36, 18));
                    break;
                case(15):
                    s_tileset.SetSubRect(IntRect(19, 0, 35, 16));
                    break;
                case(16):
                    s_tileset.SetSubRect(IntRect(18, 1, 34, 17));
                    break;
                case(17):
                    s_tileset.SetSubRect(IntRect(19, 2, 35, 18));
                    break;
                case(18):
                    s_tileset.SetSubRect(IntRect(20, 1, 36, 17));
                    break;
                case(19):
                    s_tileset.SetSubRect(IntRect(37, 1, 53, 17));
                    break;
                case(20):
                    s_tileset.SetSubRect(IntRect(38, 0, 54, 16));
                    break;
                case(21):
                    s_tileset.SetSubRect(IntRect(36, 0, 52, 16));
                    break;
                case(22):
                    s_tileset.SetSubRect(IntRect(36, 2, 52, 18));
                    break;
                case(23):
                    s_tileset.SetSubRect(IntRect(38, 2, 54, 18));
                    break;
                case(24):
                    s_tileset.SetSubRect(IntRect(37, 0, 53, 16));
                    break;
                case(25):
                    s_tileset.SetSubRect(IntRect(36, 1, 52, 17));
                    break;
                case(26):
                    s_tileset.SetSubRect(IntRect(37, 2, 53, 18));
                    break;
                case(27):
                    s_tileset.SetSubRect(IntRect(38, 1, 54, 17));
                    break;
                default:
                    s_tileset.SetSubRect(IntRect(1, 1, 17, 17));
                    break;
            }

            s_tileset.SetPosition((i * LARGEUR_TILE) - m_xscroll, (j * HAUTEUR_TILE) - m_yscroll);
            app.Draw(s_tileset);
        }
    }

    joueur->Evolue(app.GetFrameTime());
    joueur->Afficher();

    app.Display();
}

int Carte::GetBlocCarte(int a, int b)
{
    return blocCarte[a][b];
}

void Carte::ChargerTileset()
{
    Color FondF1(96,117,200);

    Color CoinHDF1(112,112,112);
    Color CoinHGF1(0,255,102);
    Color CoinBGF1(200,194,96);
    Color CoinBDF1(219,219,219);


    Color CoteHF1(255,0,108);
    Color CoteGF1(96,200,118);
    Color CoteBF1(186,66,255);
    Color CoteDF1(47,47,47);


    Color FondB1(48,0,255);

    Color CoinHDB1(106,68,85);
    Color CoinHGB1(255,204,0);
    Color CoinBGB1(255,102,0);
    Color CoinBDB1(116,2,53);

    Color CoteHB1(255,0,0);
    Color CoteGB1(0,85,40);
    Color CoteBB1(255,164,136);
    Color CoteDB1(0,0,0);


    Color FondB2(9,99,7);

    Color CoinHDB2(0,255,198);
    Color CoinHGB2(255,255,255);
    Color CoinBGB2(255,157,255);
    Color CoinBDB2(96,0,118);

    Color CoteHB2(253,255,86);
    Color CoteGB2(162,157,255);
    Color CoteBB2(126,74,0);
    Color CoteDB2(0,104,81);

    int i = 0,j = 0;

    for(i = 0; i < TILEL; i++)
    {
        for(j = 0; j < TILEH; j++)
        {
            if(i_map.GetPixel(i,j) == FondF1)
                blocCarte[i][j] = 1;
            else if (i_map.GetPixel(i,j) == CoinHDF1)
                blocCarte[i][j] = 2;
            else if (i_map.GetPixel(i,j) == CoinHGF1)
                blocCarte[i][j] = 3;
            else if (i_map.GetPixel(i,j) == CoinBGF1)
                blocCarte[i][j] = 4;
            else if (i_map.GetPixel(i,j) == CoinBDF1)
                blocCarte[i][j] = 5;
            else if (i_map.GetPixel(i,j) == CoteHF1)
                blocCarte[i][j] = 6;
            else if (i_map.GetPixel(i,j) == CoteGF1)
                blocCarte[i][j] = 7;
            else if (i_map.GetPixel(i,j) == CoteBF1)
                blocCarte[i][j] = 8;
            else if (i_map.GetPixel(i,j) == CoteDF1)
                blocCarte[i][j] = 9;
            else if (i_map.GetPixel(i,j) == FondB1)
                blocCarte[i][j] = 10;
            else if (i_map.GetPixel(i,j) == CoinHDB1)
                blocCarte[i][j] = 11;
            else if (i_map.GetPixel(i,j) == CoinHGB1)
                blocCarte[i][j] = 12;
            else if (i_map.GetPixel(i,j) == CoinBGB1)
                blocCarte[i][j] = 13;
            else if (i_map.GetPixel(i,j) == CoinBDB1)
                blocCarte[i][j] = 14;
            else if (i_map.GetPixel(i,j) == CoteHB1)
                blocCarte[i][j] = 15;
            else if (i_map.GetPixel(i,j) == CoteGB1)
                blocCarte[i][j] = 16;
            else if (i_map.GetPixel(i,j) == CoteBB1)
                blocCarte[i][j] = 17;
            else if (i_map.GetPixel(i,j) == CoteDB1)
                blocCarte[i][j] = 18;
            else if (i_map.GetPixel(i,j) == FondB2)
                blocCarte[i][j] = 19;
            else if (i_map.GetPixel(i,j) == CoinHDB2)
                blocCarte[i][j] = 20;
            else if (i_map.GetPixel(i,j) == CoinHGB2)
                blocCarte[i][j] = 21;
            else if (i_map.GetPixel(i,j) == CoinBGB2)
                blocCarte[i][j] = 22;
            else if (i_map.GetPixel(i,j) == CoinBDB2)
                blocCarte[i][j] = 23;
            else if (i_map.GetPixel(i,j) == CoteHB2)
                blocCarte[i][j] = 24;
            else if (i_map.GetPixel(i,j) == CoteGB2)
                blocCarte[i][j] = 25;
            else if (i_map.GetPixel(i,j) == CoteBB2)
                blocCarte[i][j] = 26;
            else if (i_map.GetPixel(i,j) == CoteDB2)
                blocCarte[i][j] = 27;
            else
                blocCarte[i][j] = 0;
       }
    }
}

//perso.hpp

#ifndef PERSO_HPP_INCLUDED
#define PERSO_HPP_INCLUDED

#define ABS(X) ((((X)<0)?(-(X)):(X)))
#define SGN(X) (((X)==0)?(0):(((X)<0)?(-1):(1)))

#include "map.hpp"


class Carte;

class Perso
{
public:
    Perso(sf::RenderWindow&, std::string, Carte&);
    void Evolue(float);
    void Afficher();
private:
    Carte& carte;
    sf::RenderWindow& app;
    const sf::Input& input;
    sf::Image i_perso;
    sf::Sprite s_perso;
    float posx;
    float posy;
    int l;
    int h;
    float vx;
    float vy;

    bool CollisionDecor(float, float);
    void Evenements(float);
    void Deplace();
    bool EssaiDeplace(float, float);
};

#endif // PERSO_HPP_INCLUDED

//perso.cpp

#include "perso.hpp"


using namespace sf;
using namespace std;

Perso::Perso(RenderWindow& app, std::string personnage, Carte& map) : carte(map), app(app), input(app.GetInput()), posx(10), posy(10), l(s_perso.GetSize().x), h(s_perso.GetSize().y), vx(0), vy(0)
{
    if (!i_perso.LoadFromFile(personnage)) // Si le chargement du fichier a échoué
        cerr << "Erreur durant le chargement du personnage" << endl;
    else // Si le chargement de l'image a réussi
    {
        i_perso.SetSmooth(false);
        s_perso.SetImage(i_perso);
    }
    s_perso.SetPosition(posx, posy);
    Afficher();
}

void Perso::Afficher()
{
    app.Draw(s_perso);
}

void Perso::Evolue(float time)
{
    Evenements(time);
    Deplace();
    s_perso.SetPosition(posx, posy);
}

void Perso::Evenements(float time)
{
    vx = 0; vy = 0;
    if (input.IsKeyDown(sf::Key::Left))
    {
        vx = -VITESSE * time;
    }

    if (input.IsKeyDown(sf::Key::Right))
    {
        vx = VITESSE * time;
    }

    if (input.IsKeyDown(sf::Key::Up))
    {
        vy = -VITESSE * time;
    }

    if (input.IsKeyDown(sf::Key::Down))
    {
        vy = VITESSE * time;
    }
}

void Perso::Deplace()
{
    int i;
    if (vx>=LARGEUR_TILE || vy>=HAUTEUR_TILE)
        {
            vx /= 2;
            vy /= 2;
                Deplace();
                Deplace();
                return;
    }

        if (EssaiDeplace(vx, vy)==true)
                return;

    for(i=0;i<ABS(vx);i++)
        {

                if (EssaiDeplace(SGN(vx),0)==false)
                        break;

        }
        for(i=0;i<ABS(vy);i++)
        {

                if (EssaiDeplace(0,SGN(vy))==false)
                        break;

        }
}

bool Perso::EssaiDeplace(float vxx, float vyy)
{
    float posxx = posx + vxx, posyy = posy + vyy;
    if (CollisionDecor(posxx, posyy)==false)
        {
                posx = posxx;
                posy = posyy;
                return true;
        }
        return false;
}

bool Perso::CollisionDecor(float nposx,float nposy)
{
        int xmin, xmax, ymin, ymax, i, j, type;
        xmin = nposx / LARGEUR_TILE;
        ymin = nposy / HAUTEUR_TILE;
        xmax = (nposx + l - 1) / LARGEUR_TILE;
        ymax = (nposy + h - 1) / HAUTEUR_TILE;
        if (xmin < 0 || ymin < 0 || xmax >= TILEL || ymax >= TILEH)
                return true;
        for(i = xmin ; i <= xmax ; i++)
        {
                for(j = ymin ; j <= ymax ; j++)
                {
                        type = carte.GetBlocCarte(i, j);
                        if (type >= 10)
                                return true;
        }
        }
        return false;
}


PS : Il y a des fonctions qui servent à rien, mais c'est pour plus tard dans le développement, donc c'est normal ^^

Pages: [1]