Bonjour à tous,
Je viens vous demander de l'aide car j'ai manifestement un problème d'affichage pour un sidescroller plateforme en 2D.
J'ai écrit une classe TileMap (très fortement) inspirée de celle présentée dans le tuto sur les vertexArray, afin d'alléger le dessin de la map au maximum. Le "monde 2D" dans lequel on pense le jeu a pour résolution naturelle de la fenêtre 512*384, et je gère le scrolling (et le redimensionnement si on change la résolution) à l'aide d'une vue, bref il me semble avoir appliqué les bons conseils des tutos.
Pour autant, lorsqu'on se déplace sur la map et que le scrolling joue, certains tiles s'affichent en tremblotant, ce qui est assez désagréable. J'ai testé cela sous 2 PC ubuntu et un windows 7, le problème y est toujours.
Donc je me demande ce que je fais de travers... je joins un petit code minimal reproduisant l'effet.
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;
using namespace sf;
class TileMap : public Drawable, public Transformable {
private :
Vector2u mSize; /**< Taille de la map en nombre de tiles */
sf::VertexArray mVertices; /**< sf::VertexArray servant à définir un draw optimal */
sf::Texture *mTileset; /**< Pointeur vers la texture contenant le Tileset */
public :
/** @brief Constructeur par défaut, ne fait presque rien : l'initialisation
* est faite lors de l'appel à load(MapName). */
TileMap() : mTileset(nullptr) {}
/** @brief Accesseur pour la taiille de la map. */
inline Vector2u getSize() const { return mSize; }
/** @brief Fonction pour charger la Map. Hardcodé pour l'exemple.
* @param text : Pointeur vers la texture associée. */
void load(sf::Texture *text) {
mTileset = text;
// Hardcodé pour l'exemple
std::vector< sf::Vector2f > textureCoordsTiles =
{ Vector2f(0,0), Vector2f(0,16), Vector2f(16,16), Vector2f(0,32),
Vector2f(16,32), Vector2f(32,16), Vector2f(16,0), Vector2f(0,48),
Vector2f(16,48), Vector2f(32,32), Vector2f(32,48) };
uint tSize = 16;
mSize = Vector2u(62,31);
// On prépare mVertices
mVertices.setPrimitiveType(sf::Quads);
mVertices.resize(mSize.x * mSize.y * 4);
vector< vector < int > > map;
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,5,5,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,5,5,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,0,0,0,0,0,0,0,0,5,0,0,0,5,5,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,5,5,5,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,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,5,0,0,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,5,5,5,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,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,6 });
map.push_back({ 6,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,6 });
map.push_back({ 6,0,0,0,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,0,0,0,0,0,0,6 });
map.push_back({ 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1 });
map.push_back({ 4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3,4,3 });
map.push_back({ 5,5,5,5,8,5,5,5,5,7,7,5,5,5,5,5,5,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,8,5,5,5,5,7,7,5,5,5,5,5,5,7,5,5,5,5,5,5,5,5,5,5,5,5,5,5 });
map.push_back({ 5,5,5,5,5,5,5,5,5,5,5,8,5,7,5,5,8,5,5,5,5,5,5,7,5,5,5,7,5,5,8,5,5,5,5,5,5,5,5,5,5,8,5,7,5,5,8,5,5,5,5,5,5,7,5,5,5,7,5,5,8,5 });
map.push_back({ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9 });
map.push_back({ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 });
for( int j=0 ; j<mSize.y ; ++j) {
for( int i=0 ; i<mSize.x ; ++i ) {
int label = map[j][i];
// on choisit un quad
sf::Vertex *quad = & mVertices[(i+j*mSize.x)*4];
// on définit ses quatre coins
quad[0].position = sf::Vector2f(i * tSize, j * tSize);
quad[1].position = sf::Vector2f((i + 1) * tSize, j * tSize);
quad[2].position = sf::Vector2f((i + 1) * tSize, (j + 1) * tSize);
quad[3].position = sf::Vector2f(i * tSize, (j + 1) * tSize);
// on définit ses quatre coordonnées de texture
quad[0].texCoords = textureCoordsTiles[label];
quad[1].texCoords = textureCoordsTiles[label] + sf::Vector2f(tSize,0);
quad[2].texCoords = textureCoordsTiles[label] + sf::Vector2f(tSize,tSize);
quad[3].texCoords = textureCoordsTiles[label] + sf::Vector2f(0,tSize);
}
}
}
/** @brief Doit être implémentée car héritage de sf::Drawable. */
void draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.transform *= getTransform();
states.texture = mTileset;
target.draw(mVertices, states);
}
};
int main() {
int tileSize=16, windowBaseWidth=512, windowBaseHeight=384;
int nonScrollWidth = 128, nonScrollHeight = 64;
RenderWindow window(VideoMode(windowBaseWidth,windowBaseHeight), "Test", Style::Titlebar|Style::Close);
// Options
window.setFramerateLimit(60);
window.setVerticalSyncEnabled(false);
window.setMouseCursorVisible(false);
window.setKeyRepeatEnabled(false);
TileMap map;
Texture text;
text.loadFromFile("tileset.png");
map.load(&text);
RectangleShape rect(Vector2f(3*tileSize,3*tileSize));
rect.setFillColor(sf::Color::Green);
rect.setOrigin(50,50);
rect.setPosition(400,200);
while (window.isOpen()) {
Event event;
Keyboard kbd;
while (window.pollEvent(event)) {
if (event.type == Event::Closed)
window.close();
}
if ( kbd.isKeyPressed(Keyboard::Key::Up) ) rect.move(0,-10);
else if ( kbd.isKeyPressed(Keyboard::Key::Down) ) rect.move(0,10);
else if ( kbd.isKeyPressed(Keyboard::Key::Left) ) rect.move(-10,0);
else if ( kbd.isKeyPressed(Keyboard::Key::Right) ) rect.move(10,0);
window.clear();
window.draw(map);
window.draw(rect);
// gestion du scrolling avec une vue
View view= window.getView();
Vector2f scroll, pos=rect.getPosition();
if ( pos.x - view.getCenter().x - nonScrollWidth > 0 )
scroll.x = pos.x - view.getCenter().x - nonScrollWidth ;
else if ( pos.x - view.getCenter().x + nonScrollWidth < 0 )
scroll.x = pos.x - view.getCenter().x + nonScrollWidth;
if ( pos.y - view.getCenter().y - nonScrollHeight > 0 )
scroll.y = pos.y - view.getCenter().y - nonScrollHeight;
else if ( pos.y - view.getCenter().y + nonScrollHeight < 0 )
scroll.y = pos.y - view.getCenter().y + nonScrollHeight;
view.move(scroll);
// bords de la map
float minX = windowBaseWidth/2,
maxX = map.getSize().x*tileSize - windowBaseWidth/2,
minY = windowBaseHeight/2,
maxY = map.getSize().y*tileSize - windowBaseHeight/2;
if ( view.getCenter().x < minX ) view.setCenter(minX,view.getCenter().y);
else if ( view.getCenter().x > maxX ) view.setCenter(maxX,view.getCenter().y);
if ( view.getCenter().y < minY ) view.setCenter(view.getCenter().x,minY);
else if ( view.getCenter().y > maxY ) view.setCenter(view.getCenter().x,maxY);
window.setView(view);
window.display();
}
return 0;
}
Quelqu'un aurait-il une idée de ce qui ne va pas ici ?
Merci d'avance