2D 等距(菱形)游戏引擎 - 反转精灵 [英] 2D Isometric(diamond shape) game engine - Reversed sprites

查看:31
本文介绍了2D 等距(菱形)游戏引擎 - 反转精灵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试绘制等轴测图时,我所有的精灵都反转了.

All my sprites are reversed when I try to draw my isometric map.

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

Here is the tileset.png mentionned in the following code :

Object.h/Object.cpp

Object.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 中苦苦挣扎,哈哈.

Note: I may have weird includes, I'm struggling with visual studio ha ha.

Scene.h/Scene.cpp

Scene.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;
}

全局函数.h

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

Some utility functions. getTilePosition(...) allow me to get x, y on a texture with a given tile index. Example : if I want to draw the tile n°0 of the tileset texture.

#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 结果:

And here, the WTF result I get :

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

Thanks for reading all that weird code !

当我改变时

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

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

updateMap() 中来自scene.cpp :

in updateMap() from scene.cpp :

很遗憾,我无法解释原因.也许它会帮助你理解问题.

Unfortunatly, I cannot explain why. Maybe it will help you to understand the problem.

推荐答案

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

In case someone encounter the same problem : As @Spectre suggested it was a problem of the sfml function draw().

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

http://en.sfml-dev.org/forums/index.php?topic=6903.0 You need to use display on the sf::renderTexture after your cleared it.

这篇关于2D 等距(菱形)游戏引擎 - 反转精灵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆