Je ne vois pas comment je pourrais faire sans le masque vu qu'il me sert justement à savoir s'il y a une collision sur une case correspondant à mon tableau level. Ce que je peux peut-être faire c'est donner mon code entier avec mon personnage et mon tileset pour que quelqu'un de plus expérimenté l'essaie et comprenne pourquoi.
main.cpp#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
#include "TileMap.cpp"
sf::RenderWindow window; // Fenêtre
sf::RectangleShape rectangle; // un objet rectangle
int speed=2; // vitesse du personnage
sf::Texture perso; // Texture du perso
sf::Sprite sprite_perso; // Pour récupérer son sprite
enum Dir{Down,Left,Right,Up}; // Pour le déplacement
sf::Vector2i anim(1, Down); // Animation du personnage
bool updateFPS = false; // Fps
int blockSize = 32; // Taille du personnage
sf::View view; // Vue
int screenW = 800; // Largeur fenêtre
int screenH = 600; // Hauteur fenêtre
int LARGEUR_TILE = 40; // largeur d'une tuile du décor
int HAUTEUR_TILE = 40; // hauteur d'une tuile du décor
bool colisionTile; // Vraie si collision, faux si pas collision
sf::Vector2f position2; // Position du personnage calculée
int vitesseX = 0; // Vitesse du personnage
int vitesseY = 0; // Vitesse du personnage
// Déclaration des fonctions (comme elles ne sont pas dans un header...)
void gestionClavier();
void gestionSouris();
void playMusic();
void gestionClavier2();
bool collision(bool[], int, int, int);
// Fonction principale
int main()
{
// On crée la fenêtre et ses paramètres
window.create(sf::VideoMode(screenW,screenH), "Jeu");
window.setPosition(sf::Vector2i(192,200));
window.setFramerateLimit(60);
//window.setKeyRepeatEnabled(false);
sf::Texture myTexture;
if (!myTexture.loadFromFile("tileset.png"))
std::cout << "ERREUR : load tileset" << std::endl;
else
std::cout << "tileset : Done" << std::endl;
sf::Sprite mySprite(myTexture);
// On définit le niveau
const int level[] =
{
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 1, 1, 1, 1, 9, 9,
0, 0, 0, 0, 0, 1, 1, 1, 9, 1, 1, 0, 0, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 0, 0, 0, 0,
0, 8, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
};
// Le masque du niveau (0 : pas collision, 1 : collision)
bool masque[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
TileMap map;
if (!map.load("tileset.png", sf::Vector2u(40, 40), level, 16, 8))
return -1;
// Horloge
sf::Clock time;
// On vérifie que la sprite joueur est bien chargée
if(!perso.loadFromFile("player.png"))
{
std::cout << "Erreur: player.png non charge" << std::endl;
}
perso.setSmooth(true); // pour lisser la texture
// On applique les textures au sprite joueur
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();
// Gestion des FPS
if(event.type == sf::Event::KeyPressed)
{
updateFPS = true;
}
else
{
updateFPS = false;
}
}
if (updateFPS == true)
{
if (time.getElapsedTime().asMilliseconds() >= 50)
{
anim.x--;
if (anim.x * blockSize >= perso.getSize().x)
anim.x = 2;
time.restart();
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Gestion texture
sprite_perso.setTextureRect(sf::IntRect(anim.x * blockSize, anim.y * blockSize, blockSize, blockSize));
vitesseX = 0;
vitesseY = 0;
gestionClavier();
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
position2.y = sprite_perso.getPosition().y + vitesseY;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
position2.x = sprite_perso.getPosition().x + vitesseX;
}
colisionTile = collision(masque, position2.x, position2.y, 40);
if(colisionTile == false)
{
sprite_perso.setPosition(position2);
std::cout<<" pas Collision !"<<std::endl;
}
else
{
std::cout<<"Collision !"<<std::endl;
}
/* vue */
view.reset(sf::FloatRect(0,0, screenW, screenH));
sf::Vector2f position(screenW / 2, screenH / 2);
position.x = sprite_perso.getPosition().x + (blockSize / 2) - (screenW / 2);
position.y = sprite_perso.getPosition().y + (blockSize / 2) - (screenH / 2);
if(position.x <0)
position.x = 0;
if(position.y <0)
position.y = 0;
view.reset(sf::FloatRect(position.x, position.y, screenW, screenH));
window.setView(view);
// On dessine
window.draw(map);
window.draw(sprite_perso);
window.display();
window.clear();
}
return 0;
}
/* Fonctions */
// Deplacement personnage
void gestionClavier()
{
if(sf::Event::KeyPressed)
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
anim.y = Up;
vitesseY = -speed;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
anim.y = Down;
vitesseY = speed;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
anim.y = Left;
vitesseX = -speed;
}
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
anim.y = Right;
vitesseX = speed;
}
}
else
{
vitesseX=0;
vitesseY=0;
}
// collision avec les bords gauche et haut
if(sprite_perso.getPosition().x <= 0)
sprite_perso.setPosition(sf::Vector2f(0, sprite_perso.getPosition().y));
if(sprite_perso.getPosition().y <= 0)
sprite_perso.setPosition(sf::Vector2f(sprite_perso.getPosition().x,0));
}
// Fonction qui teste la collision entre le masque et le personnage
bool collision(bool masque[], int x, int y, int tailleCase)
{
if( masque[ int(x/tailleCase) + 16*int(y/tailleCase) ] == 1)
return true;
return false;
}
TileMap.cpp (celui de la doc)
class TileMap : public sf::Drawable, public sf::Transformable
{
public:
bool load(const std::string& tileset, sf::Vector2u tileSize, const int* tiles, unsigned int width, unsigned int height)
{
// on charge la texture du tileset
if (!m_tileset.loadFromFile(tileset))
return false;
// on redimensionne le tableau de vertex pour qu'il puisse contenir tout le niveau
m_vertices.setPrimitiveType(sf::Quads);
m_vertices.resize(width * height * 4);
// on remplit le tableau de vertex, avec un quad par tuile
for (unsigned int i = 0; i < width; ++i)
for (unsigned int j = 0; j < height; ++j)
{
// on récupère le numéro de tuile courant
int tileNumber = tiles[i + j * width];
// on en déduit sa position dans la texture du tileset
int tu = tileNumber % (m_tileset.getSize().x / tileSize.x);
int tv = tileNumber / (m_tileset.getSize().x / tileSize.x);
// on récupère un pointeur vers le quad à définir dans le tableau de vertex
sf::Vertex* quad = &m_vertices[(i + j * width) * 4];
// on définit ses quatre coins
quad[0].position = sf::Vector2f(i * tileSize.x, j * tileSize.y);
quad[1].position = sf::Vector2f((i + 1) * tileSize.x, j * tileSize.y);
quad[2].position = sf::Vector2f((i + 1) * tileSize.x, (j + 1) * tileSize.y);
quad[3].position = sf::Vector2f(i * tileSize.x, (j + 1) * tileSize.y);
// on définit ses quatre coordonnées de texture
quad[0].texCoords = sf::Vector2f(tu * tileSize.x, tv * tileSize.y);
quad[1].texCoords = sf::Vector2f((tu + 1) * tileSize.x, tv * tileSize.y);
quad[2].texCoords = sf::Vector2f((tu + 1) * tileSize.x, (tv + 1) * tileSize.y);
quad[3].texCoords = sf::Vector2f(tu * tileSize.x, (tv + 1) * tileSize.y);
}
return true;
}
private:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
{
// on applique la transformation
states.transform *= getTransform();
// on applique la texture du tileset
states.texture = &m_tileset;
// et on dessine enfin le tableau de vertex
target.draw(m_vertices, states);
}
sf::VertexArray m_vertices;
sf::Texture m_tileset;
};