2D 等距(菱形)游戏引擎 - 反转精灵

2D Isometric(diamond shape) game engine - Reversed sprites

当我尝试绘制等轴测图时,我所有的精灵都颠倒了。

这是以下代码中提到的 tileset.png:

对象.h/Object.cpp

我可以用它们画瓷砖,UI元素等等...

#pragma once

class Object {
public:
    //FUNCTIONS
    Object();
    void addComponent(float value);
    int getComponent(float index);
    void editComponent(float index, float value);
    void deleteComponent(float index);

private:
    vector<int> components;
};

#include "Object.cpp"

-

#pragma once

//FUNCTIONS
Object::Object() {
    //...
}

void Object::addComponent(float value) {
    components.push_back(value);
}

int Object::getComponent(float index) {
    return components[index];
}

void Object::editComponent(float index, float value) {
    components[index] = value;
}

void Object::deleteComponent(float index) {
    components.erase(components.begin() + index);
}

注意:我可能有奇怪的包含,我正在努力visual studio哈哈。

场景.h/Scene.cpp

处理数据和图形

#pragma once

class Scene {
public:
    Scene(float w, float h, int mapx, int mapy, int tilesize, int mapwidth, int mapheight);
    void run();

    void addLayer();
    void loadTileset(sf::String url);
    void loadUiTileset(sf::String url);

    //functions
    //...

    //getters
    //...

    //setters
    //...

private:
    sf::RenderWindow window;

    float width;
    float height;

    int nb_layers;

    int map_x;
    int map_y;
    int map_width;
    int map_height;
    int tile_size;
    int selected_tile_index;

    sf::RenderTexture texture;
    sf::Sprite tile;
    sf::Sprite map;
    sf::Texture tileset;
    vector<Object> tiles;

    sf::Texture uiTileset;

    //private functions
    void updateMap();

    //...

    void processEvent();
    void update(sf::Time deltaTime);
    void render();

    //...
};

#include "Scene.cpp"

-

#pragma once

//functions
Scene::Scene(float w, float h, int mapx, int mapy, int tilesize, int mapwidth, int mapheight) : window(sf::VideoMode(w, h), "Editor") {
    width = w;
    height = h;

    map_x = mapx;
    map_y = mapy;
    map_width = mapwidth;
    map_height = mapheight;

    tile_size = tilesize;

    selected_tile_index = 0;//default

    nb_layers = 0;
}

void Scene::run() {
    sf::Clock clock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;
    sf::Time TimePerFrame = sf::seconds(1.f / 60.f);

    while (window.isOpen()) {
        processEvent();

        timeSinceLastUpdate += clock.restart();

        while (timeSinceLastUpdate > TimePerFrame) {
            timeSinceLastUpdate -= TimePerFrame;

            processEvent();
            update(TimePerFrame);
        }

        render();
    }
}

void Scene::addLayer() {
    nb_layers += 1;

    int tile_x = map_x,
        tile_y = map_y,
        num_layer = nb_layers - 1,
        layer_pos = (num_layer * tile_size) / 2,
        tile_zOrder = -1;

    tile_y -= layer_pos;

    int x = map_x,
        y = map_y;

    for (int h = 0; h < map_height; h++) {
        for (int w = 0; w < map_width; w++) {
            tile_zOrder = (w * (h + 1)) + (num_layer * 10);

            x = carthesianToIsometric(tile_x, tile_y)[0];
            y = carthesianToIsometric(tile_x, tile_y)[1] - layer_pos;

            cout << x << ", " << y << endl;

            Object tile;
            tile.addComponent(selected_tile_index);
            tile.addComponent(x);
            tile.addComponent(y);
            tile.addComponent(tile_zOrder);
            tile.addComponent(num_layer);

            tiles.push_back(tile);
            tile_x += tile_size;
        }
        tile_x = 0;
        tile_y += tile_size;
    }

    updateMap();
}

void Scene::loadTileset(sf::String url) {
    if (!tileset.loadFromFile(url))
    {
        cout << std::string(url) << "couldn't be loaded..." << endl;
    }
}

void Scene::loadUiTileset(sf::String url) {
    if (!uiTileset.loadFromFile(url))
    {
        cout << std::string(url) << "couldn't be loaded..." << endl;
    }
}

//getters
//...

//setters
//...

//private functions
void Scene::updateMap() {
    int tile_position_x = 0,
        tile_position_y = 0;

    int tile_x = 0,
        tile_y = 0;

    if (!texture.create(map_width * tile_size, (map_height * tile_size) / 2))
        cout << "Texture couldn't be loaded... " << endl;

    texture.clear(sf::Color(133, 118, 104, 255));

    sf::Sprite image;
    image.setTexture(tileset);
    int tileset_width = image.getGlobalBounds().width,
        tileset_height = image.getGlobalBounds().height;

    tile.setTexture(tileset);

    for (int tile_index = 0; tile_index < tiles.size(); tile_index++) {
        tile_position_x = getTilePosition(tileset_width, tileset_height, tiles[tile_index].getComponent(0), tile_size)[0];
        tile_position_y = getTilePosition(tileset_width, tileset_height, tiles[tile_index].getComponent(0), tile_size)[1];

        tile.setTextureRect(sf::IntRect(tile_position_x, tile_position_y, tile_size, tile_size));

        tile_x = tiles[tile_index].getComponent(1);
        tile_y = tiles[tile_index].getComponent(2);

        tile.setPosition(sf::Vector2f(tile_x, tile_y));

        texture.draw(tile);
    }

    map.setTexture(texture.getTexture());
}

void Scene::processEvent() {
    sf::Event event;

    while (window.pollEvent(event)) {
        switch (event.type) {
        case sf::Event::Closed:
            window.close();
            break;

        case sf::Event::KeyPressed:
            if (event.key.code == sf::Keyboard::Escape)
                window.close();
            break;
        }
    }
}

void Scene::update(sf::Time deltaTime) {
    //REMEMBER: distance = speed * time
    //MOVEMENT, ANIMATIONS ETC. ..
}

void Scene::render() {
    window.clear();

    window.draw(map);

    window.display();
}

main.cpp

#pragma once
//global functions + main headers + class headers =>
#include "globalfunctions.h"

int main() {
    int map_width = 15,
        map_height = 15,
        tile_size = 64;

    float scene_width = map_width * tile_size,
        scene_height = (map_height * tile_size) / 2;

    Scene engine(scene_width, scene_height, 0, 0, tile_size, map_width, map_height);
    engine.loadTileset("tileset.png");
    //engine.loadUiTileset("menu.png");

    engine.addLayer();
    //...

    engine.run();
    return EXIT_SUCCESS;
}

globalfunctions.h

一些实用函数。 getTilePosition(...) 允许我在具有给定图块索引的纹理上获取 x、y。示例:如果我想绘制瓦片集纹理的瓦片 n°0。

#pragma once
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <iostream>
#include <math.h>
#include <vector>

using namespace std;

vector<float> getTilePosition(float tileset_width, float tileset_height, float tile_index, float tile_size) {//In a tileset
    float tileX = 0,
        tileY = 0,
        tilePerLine = 0;

    tilePerLine = tileset_width / tile_size;

    tileY = floor(tile_index / tilePerLine);
    tileX = ((tile_index + 1) - (tileY * tilePerLine)) - 1;

    tileX *= tile_size;
    tileY *= tile_size;

    vector<float> coords;
        coords.push_back(tileX);
        coords.push_back(tileY);

    return coords;
}

vector<int> carthesianToIsometric(int x, int y) {
    vector<int> coords;

    float isoX = (x - y) / 2,
        isoY = (x + y) / 4;

    coords.push_back(isoX);
    coords.push_back(isoY);

    return coords;
}

#include "Object.h"
#include "Scene.h"

//...

这里是我得到的 WTF 结果:

感谢阅读所有这些奇怪的代码!

编辑:

当我改变

tile.setPosition(sf::Vector2f(tile_x, tile_y));

tile.setPosition(sf::Vector2f(0, 0));

updateMap() 来自 scene.cpp :

不幸的是,我无法解释原因。也许它会帮助你理解问题。

如果有人遇到同样的问题: 正如@Spectre 所说,这是 sfml 函数 draw() 的问题。

http://en.sfml-dev.org/forums/index.php?topic=6903.0 清除后需要在sf::renderTexture上使用显示