2D 钻石(等距)地图编辑器 - 纹理无限扩展? [英] 2D Diamond (isometric) map editor - Textures extended infinitely?

查看:24
本文介绍了2D 钻石(等距)地图编辑器 - 纹理无限扩展?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发 2D 等轴测图编辑器.我显示包含点和纹理的实体(立方体,玩家).每个立方体由 12 个点组成.(12 个点,但在 sfml(sf::VertexArray) 显示时作为 4 个点的 3 个边处理).

(我知道我有时会包含一些.cpp",我的 IDE(visual studio)有问题,我正在尝试解决,请不要在意.)

ma​​in.cpp

#pragma once#include "globalfunctions.h"//全局函数+主要头文件+类头文件int main() {int mapSize = 0;int 立方体尺寸 = 0;cout<<"地图尺寸:";cin >>地图大小;cout<<结束;cout<<"立方体尺寸:";cin >>立方体尺寸;cout<<结束;int windowWidth = (mapSize * cubeSize) - (cubeSize * 2);int windowHeight = ((mapSize * cubeSize) - (cubeSize * 2))/2;渲染窗口窗口(窗口宽度,窗口高度,地图大小,立方体大小);int nbMaxTextures = 9;for (int t = 0; t 

globalfunctions.h

#pragma once#include #include #include #include #include <math.h>//#include #include <向量>使用命名空间标准;sf::Vector2u isometricToCartesian(int i, int j, int cubeSize) {SF::Vector2u 卡斯;carth.x = (j - i) * (cubeSize/2);carth.y = (j + i) * (cubeSize/4);返回卡斯;}sf::Vector2u cartesianToIsometric(int x, int y, int cubeSize) {//TODOSF::Vector2u iso;iso.x = 0;iso.y = 0;返回iso;}#include "entity.h"#include "renderWindow.h"

renderWindow.h

#pragma once类渲染窗口{民众:渲染窗口(浮动宽度,浮动高度,INT MAPSIZE,INT CUBESIZE);无效运行();void loadTexture(sf::String 文件夹,int numTexture);//设置者//...//获取者//...私人的:int mCurrentLayerID;int mMapSize;int mCubeSize;int mSelectedTexture;矢量实体地图;SF::RenderWindow mWindow;矢量纹理;SF::Texture mMemoryTexture;无效的过程事件();无效更新(sf::时间增量时间);无效渲染();//立方体动作----------------------------------------void addCube(int layerID, float x, float y);实体&getCube(int ID);实体&getCubeAt(float x, float y);矢量loadCube(int cubeID);//更新数据如坐标->创建/更改顶点void drawCube(int cubeID);//绘制顶点//变量矢量顶点Side1;矢量顶点Side2;矢量顶点Side3;//立方体动作----------------------------------------};#include "renderWindow.cpp"

renderWindow.cpp

#pragma oncerenderWindow::renderWindow(float WIDTH, float HEIGHT, int MAPSIZE, int CUBESIZE) : mWindow(sf::VideoMode(WIDTH, HEIGHT), "") {mMapSize = MAPSIZE;mCubeSize = CUBESIZE;mSelectedTexture = 6;mCurrentLayerID = -1;整数 x = 0;int y = 0;//默认图层for (int j = 0; j  TimePerFrame) {timeSinceLastUpdate -= TimePerFrame;进程事件();更新(每帧时间);}使成为();}}void renderWindow::loadTexture(sf::String 文件夹,int numTexture) {if (mMemoryTexture.loadFromFile("textures/" + folder + "/" + to_string(numTexture) + ".jpg"))mTextures.push_back(mMemoryTexture);别的cout<<纹理n°"<<numTexture<<因为加载失败."<<结束;}//设置者//...//获取者//...//私有方法void renderWindow::processEvent() {SF::事件事件;而(mWindow.pollEvent(事件)){开关(事件类型){案例 SF::Event::Closed:mWindow.close();休息;案例 sf::Event::KeyPressed:if (event.key.code == sf::Keyboard::Escape)mWindow.close();休息;案例 sf::Event::MouseButtonPressed:if (event.MouseButtonPressed == sf::Mouse::Left)getCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(0, mSelectedTexture);//TESTgetCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(1, mSelectedTexture + 1);//TESTgetCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(2, mSelectedTexture + 2);//TEST休息;/*case sf::Event::MouseMoved:cout<<"(" << event.mouseMove.x << ", " << event.mouseMove.y << ")" <<结束;休息;*/}}}void renderWindow::update(sf::Time deltaTime) {//记住:距离=速度*时间//运动,动画等....}void renderWindow::render() {mWindow.clear();for (int c = 0; c < mMap.size(); c++) {drawCube(c);}mWindow.display();}//立方体动作----------------------------------------void renderWindow::addCube(int layerID, float x, float y) {//这些使代码更具可读性:int half_cubeSize = mCubeSize/2;int oneQuarter_cubeSize = mCubeSize/4;int twoQuarter_cubeSize = oneQuarter_cubeSize * 2;int treeQuarter_cubeSize = oneQuarter_cubeSize * 3;mCurrentLayerID = layerID;实体虚拟(mMap.size(), 0, layerID);dummy.addPoint(12);dummy.addTexture(6);dummy.addTexture(7);dummy.addTexture(8);//SIDE 1----------------------------------------------——dummy.setPoint(0, x, y + oneQuarter_cubeSize);dummy.setPoint(1, x + half_cubeSize, y + twoQuarter_cubeSize);dummy.setPoint(2, x + half_cubeSize, y + mCubeSize);dummy.setPoint(3, x, y + treeQuarter_cubeSize);//SIDE 2----------------------------------------------——dummy.setPoint(4, x + half_cubeSize, y + twoQuarter_cubeSize);dummy.setPoint(5, x + mCubeSize, y + oneQuarter_cubeSize);dummy.setPoint(6, x + mCubeSize, y + treeQuarter_cubeSize);dummy.setPoint(7, x + half_cubeSize, y + mCubeSize);//SIDE 3----------------------------------------------——dummy.setPoint(8, x, y + oneQuarter_cubeSize);dummy.setPoint(9, x + half_cubeSize, y);dummy.setPoint(10, x + mCubeSize, y + oneQuarter_cubeSize);dummy.setPoint(11, x + half_cubeSize, y + twoQuarter_cubeSize);mMap.push_back(dummy);}实体&renderWindow::getCube(int ID) {for (int c = 0; c < mMap.size(); c++) {if (mMap[c].getID() == ID)返回 mMap[c];}}实体&renderWindow::getCubeAt(float x, float y) {//要做返回实体(-1, 0, 0);}矢量renderWindow::loadCube(int cubeID) {矢量顶点;vertices.push_back(sf::VertexArray());vertices.push_back(sf::VertexArray());vertices.push_back(sf::VertexArray());顶点[0].setPrimitiveType(sf::Quads);顶点[0].resize(4);顶点[1].setPrimitiveType(sf::Quads);顶点[1].resize(4);顶点[2].setPrimitiveType(sf::Quads);顶点[2].resize(4);sf::Vector2f tv0 = sf::Vector2f(0, 0);SF::Vector2f tv1 = SF::Vector2f(mCubeSize, 0);sf::Vector2f tv2 = sf::Vector2f(mCubeSize, mCubeSize);SF::Vector2f tv3 = SF::Vector2f(0, mCubeSize);sf::Vector2f v0 = sf::Vector2f(getCube(cubeID).getPoint(0, 0), getCube(cubeID).getPoint(0, 1));sf::Vector2f v1 = sf::Vector2f(getCube(cubeID).getPoint(1, 0), getCube(cubeID).getPoint(1, 1));sf::Vector2f v2 = sf::Vector2f(getCube(cubeID).getPoint(2, 0), getCube(cubeID).getPoint(2, 1));sf::Vector2f v3 = sf::Vector2f(getCube(cubeID).getPoint(3, 0), getCube(cubeID).getPoint(3, 1));sf::Vector2f v4 = sf::Vector2f(getCube(cubeID).getPoint(4, 0), getCube(cubeID).getPoint(4, 1));sf::Vector2f v5 = sf::Vector2f(getCube(cubeID).getPoint(5, 0), getCube(cubeID).getPoint(5, 1));sf::Vector2f v6 = sf::Vector2f(getCube(cubeID).getPoint(6, 0), getCube(cubeID).getPoint(6, 1));sf::Vector2f v7 = sf::Vector2f(getCube(cubeID).getPoint(7, 0), getCube(cubeID).getPoint(7, 1));sf::Vector2f v8 = sf::Vector2f(getCube(cubeID).getPoint(8, 0), getCube(cubeID).getPoint(8, 1));sf::Vector2f v9 = sf::Vector2f(getCube(cubeID).getPoint(9, 0), getCube(cubeID).getPoint(9, 1));sf::Vector2f v10 = sf::Vector2f(getCube(cubeID).getPoint(10, 0), getCube(cubeID).getPoint(10, 1));sf::Vector2f v11 = sf::Vector2f(getCube(cubeID).getPoint(11, 0), getCube(cubeID).getPoint(11, 1));顶点[0][0] = sf::Vertex(v0, tv0);顶点[0][1] = sf::Vertex(v1, tv1);顶点[0][2] = sf::Vertex(v2, tv2);顶点[0][3] = sf::Vertex(v3, tv3);顶点[1][0] = sf::Vertex(v4, tv0);顶点[1][1] = sf::Vertex(v5, tv1);顶点[1][2] = sf::Vertex(v6, tv2);顶点[1][3] = sf::Vertex(v7, tv3);顶点[2][0] = sf::Vertex(v8, tv0);顶点[2][1] = sf::Vertex(v9, tv1);顶点[2][2] = sf::Vertex(v10, tv2);顶点[2][3] = sf::Vertex(v11, tv3);返回顶点;}void renderWindow::drawCube(int cubeID) {mWindow.draw(verticesSide1[cubeID], &mTextures[getCube(cubeID).getTexture(0)]);mWindow.draw(verticesSide2[cubeID], &mTextures[getCube(cubeID).getTexture(1)]);mWindow.draw(verticesSide3[cubeID], &mTextures[getCube(cubeID).getTexture(2)]);}//立方体动作----------------------------------------

entity.h

 #pragma once类实体{民众:实体();实体(int id,int 类型,int numlayer);void addPoint(int nbPoints);无效添加纹理(int numTexture);//设置者void setPoint(int numPoint, float x, float y);void setTexture(int textureID, int numTexture);//获取者int getID();float getPoint(int numPoint, int numIndex);//如果 numIndex = 0 ->×||如果 numIndex = 1 ->是int getType();int getNumLayer();int getTexture(int numTexture);私人的:内部标识;int mType;int mNumLayer;矢量mPoints;向量纹理;};#include "entity.cpp"

entity.cpp

#pragma once实体::实体(){中 ID = 0;mType = -1;mNumLayer = 0;}entity::entity(int id, int type, int numlayer) {mID = id;mType = 类型;mNumLayer = 数层;}void entity::addPoint(int nbPoints) {mPoints.clear();int newSize = 0;for (int p = 0; p (newSize);}void entity::addTexture(int numTexture) {mTextures.push_back(numTexture);}//设置者void entity::setPoint(int numPoint, float x, float y) {mPoints[numPoint].x = x;mPoints[numPoint].y = y;}void entity::setTexture(int textureID, int numTexture) {mTextures[textureID] = numTexture;}//获取者int entity::getID() {返回 mID;}浮动实体::getPoint(int numPoint, int numIndex) {如果(数字索引 == 0)返回 mPoints[numPoint].x;别的返回 mPoints[numPoint].y;}int entity::getType() {返回 mType;}int entity::getNumLayer() {返回 mNumLayer;}int entity::getTexture(int numTexture) {返回 mTextures[numTexture];}

我已经做了很多测试,太多了,所以我现在不会发布它们,但是如果您有任何问题,请随时提问.

这是标题中描述的问题:

这里,只显示一张脸的屏幕(在代码中的顺序相同):

我唯一不明白的是,如果您手动输入坐标,单独显示的立方体工作得很好.即使是扩展的.但是坐标公式没问题......(我注意到立方体n°50对于具有64x64立方体的15x15地图显示宽度为无限"的矩形)如果纹理被扩展(可能到无限),它表明坐标在某处不断增加?那么,为什么立方体仍然放置得很好?

这是资产(64 * 64 png):目录:textures/test/

解决方案

并不是真正的答案(因为代码无论如何都会被重写)所以对新代码的提示很少(其中一些已经在评论中提到).

  1. 图块集

    在最终的等距引擎中使用精灵.它们速度更快并支持像素艺术.出于我的目的,我使用这两个免费使用的tilesets(64x64)的编译:

    • 白色 0x00FFFFFF 表示透明.精灵是不够的.我添加了有关瓷砖高度和旋转的信息.

      如果您从左上角看到前 4 个图块,它们都是旋转 90 度的同一个东西.所以我所有的瓷砖都有 4 个瓷砖的索引(90 度旋转)int rot[4].这样我就可以旋转整个地图或只是查看.我编译了这个集合,所以旋转彼此相邻.有 3 个选项:

      • tile[ix].rot[]={ ix,ix,ix,ix }; 其中 ix 是没有旋转的瓷砖(地面)
      • tile[ix].rot[]={ ix,ix+1,ix,ix+1 }; 其中 ix2 旋转(那 2 个瓦片,中间有一块切碎的树)
      • tile[ix].rot[]={ ix,ix+1,ix+2,ix+3 }; 其中 ix 是带有 的平铺4 旋转(如第一个图块)

      索引仅对第一个瓦片有效,其他的则将整个 rot[] 数组从邻居旋转 1 个值.一些旋转是不可见的(参见宽大的树),但仍然存在瓷砖以允许旋转.

      图块高度对于在编辑时放置图块以及自动生成地图很重要.

      我还计划为每个图块添加 A* 地图,以便我可以使用路径查找或计算水流等.

    • 地图编辑器

      我更喜欢 3D 地图.对于更大的分辨率,您需要正确选择查看区域以最大限度地提高性能.另外一个好主意是创建空心地下,以便渲染更快(这也可以在渲染过程中虚拟完成,无需更新地图).

      我建议对这些功能进行编码:

      • 使地面空心
      • 夯实基础
      • 随机地形(菱形和方形)
      • 过滤掉小孔和平滑边缘(将坡度瓷砖添加到立方体)
    • 磁贴编辑器

      除了明显的绘画编辑器之外,您还应该添加其他功能,例如:

      1. 地板 <-> 天花板
      2. <->
      3. 正面 <-> 背面
      4. 将大精灵分割成规则的图块
      5. 复制/合并/粘贴
      6. 左后调整灯光<->右后视镜操作

      它们在编译/编辑图块集资源时非常方便.如您所见,我的图块集有许多源图块集中不存在的图块.它们是由这些功能 + 一些小的油漆编辑创建的...图块集底部的彩色蒙版用于遮蔽并正确组合图块的部分以创建缺失的部分...(您可以从一侧取一个瓷砖和其他来自其他...)

[注释]

有关更多信息/想法,请查看一些相关的问答:

I'm currently developing a 2D isometric map editor. I display entity(cube, player) which contains points and textures. Each cubes are composed by 12 points.(12 points, but handled as 3 sides of 4 points when displayed by sfml(sf::VertexArray).

(I know I include some '.cpp' times to times, I have a problem with my IDE(visual studio) which I'm trying to resolve, please do not care about it.)

main.cpp

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

int main() {
    int mapSize = 0;
    int cubeSize = 0;

    cout << "Map size: "; cin >> mapSize; cout << endl;
    cout << "Cube size: "; cin >> cubeSize; cout << endl;

    int windowWidth = (mapSize * cubeSize) - (cubeSize * 2);
    int windowHeight = ((mapSize * cubeSize) - (cubeSize * 2)) / 2;

    renderWindow window(windowWidth, windowHeight, mapSize, cubeSize);
        int nbMaxTextures = 9;
        for (int t = 0; t < nbMaxTextures; t++) {
            window.loadTexture("test", t);
        }

    window.run();

    return EXIT_SUCCESS;
}

globalfunctions.h

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

using namespace std;

sf::Vector2u isometricToCartesian(int i, int j, int cubeSize) {
    sf::Vector2u carth;
        carth.x = (j - i) * (cubeSize / 2);
        carth.y = (j + i) * (cubeSize / 4);

    return carth;
}

sf::Vector2u cartesianToIsometric(int x, int y, int cubeSize) {//TODO
    sf::Vector2u iso;
        iso.x = 0;
        iso.y = 0;

    return iso;
}

#include "entity.h"
#include "renderWindow.h"

renderWindow.h

#pragma once

class renderWindow {
    public:
        renderWindow(float WIDTH, float HEIGHT, int MAPSIZE, int CUBESIZE);
        void run();
        void loadTexture(sf::String folder, int numTexture);

        //SETTERS
        //...

        //GETTERS
        //...

    private:
        int mCurrentLayerID;
        int mMapSize;
        int mCubeSize;
        int mSelectedTexture;

        vector<entity> mMap;

        sf::RenderWindow mWindow;
        vector<sf::Texture> mTextures;
            sf::Texture mMemoryTexture;

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

//CUBE ACTION-------------------------------------------
        void addCube(int layerID, float x, float y);
        entity& getCube(int ID);
        entity& getCubeAt(float x, float y);
        vector<sf::VertexArray> loadCube(int cubeID);//UPDATE DATA LIKE COORDINATES -> create/chnge the vertex
        void drawCube(int cubeID);//draw the vertex

        //VARIABLES
        vector<sf::VertexArray> verticesSide1;
        vector<sf::VertexArray> verticesSide2;
        vector<sf::VertexArray> verticesSide3;
//CUBE ACTION-------------------------------------------
};

#include "renderWindow.cpp"

renderWindow.cpp

#pragma once

renderWindow::renderWindow(float WIDTH, float HEIGHT, int MAPSIZE, int CUBESIZE) : mWindow(sf::VideoMode(WIDTH, HEIGHT), "") {
    mMapSize = MAPSIZE;
    mCubeSize = CUBESIZE;

    mSelectedTexture = 6;

    mCurrentLayerID = -1;

    int x = 0;
    int y = 0;

    //default layer
    for (int j = 0; j < mMapSize; j++) {
        for (int i = 0; i < mMapSize; i++) {
            x = isometricToCartesian(i, j, mCubeSize).x;
            y = isometricToCartesian(i, j, mCubeSize).y;
            addCube(0, x, y);
        }
    }

    for (int c = 0; c < mMap.size(); c++) {
        verticesSide1.push_back(loadCube(c)[0]);
        verticesSide2.push_back(loadCube(c)[1]);
        verticesSide3.push_back(loadCube(c)[2]);

        //then only do that when something the cube's coordinate changed
    }
}

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

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

        timeSinceLastUpdate += clock.restart();

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

            processEvent();
            update(TimePerFrame);
        }

        render();
    }
}

void renderWindow::loadTexture(sf::String folder, int numTexture) {
    if (mMemoryTexture.loadFromFile("textures/" + folder + "/" + to_string(numTexture) + ".jpg"))
        mTextures.push_back(mMemoryTexture);
    else
        cout << "Texture n°" << numTexture << " as failed to load." << endl;
}


//SETTERS
//...

//GETTERS
//...

//PRIVATE METHODE
void renderWindow::processEvent() {
    sf::Event event;

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

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

        case sf::Event::MouseButtonPressed:
            if (event.MouseButtonPressed == sf::Mouse::Left)
                getCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(0, mSelectedTexture);//TEST
                getCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(1, mSelectedTexture + 1);//TEST
                getCubeAt(event.mouseButton.x, event.mouseButton.y).setTexture(2, mSelectedTexture + 2);//TEST
            break;

            /*case sf::Event::MouseMoved:
                cout << "(" << event.mouseMove.x << ", " << event.mouseMove.y << ")" << endl;
                break;*/
        }
    }
}

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

void renderWindow::render() {
    mWindow.clear();

    for (int c = 0; c < mMap.size(); c++) {
        drawCube(c);
    }

    mWindow.display();
}

//CUBE ACTION-------------------------------------------
void renderWindow::addCube(int layerID, float x, float y) {
    //Thoses make the code more readable:
        int half_cubeSize = mCubeSize / 2;
        int oneQuarter_cubeSize = mCubeSize / 4;
        int twoQuarter_cubeSize = oneQuarter_cubeSize * 2;
        int treeQuarter_cubeSize = oneQuarter_cubeSize * 3;

    mCurrentLayerID = layerID;

    entity dummy(mMap.size(), 0, layerID);
        dummy.addPoint(12);
        dummy.addTexture(6);
        dummy.addTexture(7);
        dummy.addTexture(8);
    //SIDE 1------------------------------------------------
        dummy.setPoint(0, x, y + oneQuarter_cubeSize);
        dummy.setPoint(1, x + half_cubeSize, y + twoQuarter_cubeSize);
        dummy.setPoint(2, x + half_cubeSize, y + mCubeSize);
        dummy.setPoint(3, x, y + treeQuarter_cubeSize);
    //SIDE 2------------------------------------------------
        dummy.setPoint(4, x + half_cubeSize, y + twoQuarter_cubeSize);
        dummy.setPoint(5, x + mCubeSize, y + oneQuarter_cubeSize);
        dummy.setPoint(6, x + mCubeSize, y + treeQuarter_cubeSize);
        dummy.setPoint(7, x + half_cubeSize, y + mCubeSize);
    //SIDE 3------------------------------------------------
        dummy.setPoint(8, x, y + oneQuarter_cubeSize);
        dummy.setPoint(9, x + half_cubeSize, y);
        dummy.setPoint(10, x + mCubeSize, y + oneQuarter_cubeSize);
        dummy.setPoint(11, x + half_cubeSize, y + twoQuarter_cubeSize);

    mMap.push_back(dummy);
}

entity& renderWindow::getCube(int ID) {
    for (int c = 0; c < mMap.size(); c++) {
        if (mMap[c].getID() == ID)
            return mMap[c];
    }
}

entity& renderWindow::getCubeAt(float x, float y) {//TO DO
    return entity(-1, 0, 0);
}

vector<sf::VertexArray> renderWindow::loadCube(int cubeID) {
    vector<sf::VertexArray> vertices;
    vertices.push_back(sf::VertexArray());
    vertices.push_back(sf::VertexArray());
    vertices.push_back(sf::VertexArray());

    vertices[0].setPrimitiveType(sf::Quads);
    vertices[0].resize(4);

    vertices[1].setPrimitiveType(sf::Quads);
    vertices[1].resize(4);

    vertices[2].setPrimitiveType(sf::Quads);
    vertices[2].resize(4);

    sf::Vector2f tv0 = sf::Vector2f(0, 0);
    sf::Vector2f tv1 = sf::Vector2f(mCubeSize, 0);
    sf::Vector2f tv2 = sf::Vector2f(mCubeSize, mCubeSize);
    sf::Vector2f tv3 = sf::Vector2f(0, mCubeSize);

    sf::Vector2f v0 = sf::Vector2f(getCube(cubeID).getPoint(0, 0), getCube(cubeID).getPoint(0, 1));
    sf::Vector2f v1 = sf::Vector2f(getCube(cubeID).getPoint(1, 0), getCube(cubeID).getPoint(1, 1));
    sf::Vector2f v2 = sf::Vector2f(getCube(cubeID).getPoint(2, 0), getCube(cubeID).getPoint(2, 1));
    sf::Vector2f v3 = sf::Vector2f(getCube(cubeID).getPoint(3, 0), getCube(cubeID).getPoint(3, 1));

    sf::Vector2f v4 = sf::Vector2f(getCube(cubeID).getPoint(4, 0), getCube(cubeID).getPoint(4, 1));
    sf::Vector2f v5 = sf::Vector2f(getCube(cubeID).getPoint(5, 0), getCube(cubeID).getPoint(5, 1));
    sf::Vector2f v6 = sf::Vector2f(getCube(cubeID).getPoint(6, 0), getCube(cubeID).getPoint(6, 1));
    sf::Vector2f v7 = sf::Vector2f(getCube(cubeID).getPoint(7, 0), getCube(cubeID).getPoint(7, 1));

    sf::Vector2f v8 = sf::Vector2f(getCube(cubeID).getPoint(8, 0), getCube(cubeID).getPoint(8, 1));
    sf::Vector2f v9 = sf::Vector2f(getCube(cubeID).getPoint(9, 0), getCube(cubeID).getPoint(9, 1));
    sf::Vector2f v10 = sf::Vector2f(getCube(cubeID).getPoint(10, 0), getCube(cubeID).getPoint(10, 1));
    sf::Vector2f v11 = sf::Vector2f(getCube(cubeID).getPoint(11, 0), getCube(cubeID).getPoint(11, 1));

    vertices[0][0] = sf::Vertex(v0, tv0);
    vertices[0][1] = sf::Vertex(v1, tv1);
    vertices[0][2] = sf::Vertex(v2, tv2);
    vertices[0][3] = sf::Vertex(v3, tv3);

    vertices[1][0] = sf::Vertex(v4, tv0);
    vertices[1][1] = sf::Vertex(v5, tv1);
    vertices[1][2] = sf::Vertex(v6, tv2);
    vertices[1][3] = sf::Vertex(v7, tv3);

    vertices[2][0] = sf::Vertex(v8, tv0);
    vertices[2][1] = sf::Vertex(v9, tv1);
    vertices[2][2] = sf::Vertex(v10, tv2);
    vertices[2][3] = sf::Vertex(v11, tv3);

    return vertices;
}

void renderWindow::drawCube(int cubeID) {
    mWindow.draw(verticesSide1[cubeID], &mTextures[getCube(cubeID).getTexture(0)]);
    mWindow.draw(verticesSide2[cubeID], &mTextures[getCube(cubeID).getTexture(1)]);
    mWindow.draw(verticesSide3[cubeID], &mTextures[getCube(cubeID).getTexture(2)]);
}

//CUBE ACTION-------------------------------------------

entity.h

    #pragma once

    class entity {
    public:
        entity();
        entity(int id, int type, int numlayer);
        void addPoint(int nbPoints);
        void addTexture(int numTexture);

        //SETTERS
        void setPoint(int numPoint, float x, float y);
        void setTexture(int textureID, int numTexture);

        //GETTERS
        int getID();
        float getPoint(int numPoint, int numIndex);//if numIndex = 0 -> x || if numIndex = 1 -> y
        int getType();
        int getNumLayer();
        int getTexture(int numTexture);

    private:
        int mID;
        int mType;
        int mNumLayer;
        vector<sf::Vector2u> mPoints;
        vector<int> mTextures;
    };

    #include "entity.cpp"

entity.cpp

#pragma once

entity::entity() {
    mID = 0;
    mType = -1;
    mNumLayer = 0;
}

entity::entity(int id, int type, int numlayer) {
    mID = id;
    mType = type;
    mNumLayer = numlayer;
}

void entity::addPoint(int nbPoints) {
    mPoints.clear();

    int newSize = 0;
    for (int p = 0; p < nbPoints; p++) {
        newSize++;
    }

    mPoints = vector<sf::Vector2u>(newSize);
}

void entity::addTexture(int numTexture) {
    mTextures.push_back(numTexture);
}

//SETTERS
void entity::setPoint(int numPoint, float x, float y) {
    mPoints[numPoint].x = x;
    mPoints[numPoint].y = y;
}

void entity::setTexture(int textureID, int numTexture) {
    mTextures[textureID] = numTexture;
}

//GETTERS
int entity::getID() {
    return mID;
}

float entity::getPoint(int numPoint, int numIndex) {
    if (numIndex == 0)
        return mPoints[numPoint].x;
    else
        return mPoints[numPoint].y;
}

int entity::getType() {
    return mType;
}

int entity::getNumLayer() {
    return mNumLayer;
}

int entity::getTexture(int numTexture) {
    return mTextures[numTexture];
}

I've done a lot of test, too much, so I won't post them right now, but if you have any question, feel free to ask.

Here is the problem described in the title :

And here, screens with only one face displayed(in the same order in the code):

The only thing I don't understand is that a cube displayed alone work perfectly fine if you enter the coordinates manually. Even the extended ones. But the coordinates formula is ok... (I noticed that the cube n°50 for a 15x15 map with 64x64 cube display a rectangle 'infinite' in width) If the texture is extended(maybe to the infinite), it suggest that the coordinates are continuously increasing somewhere ? Then, why the cubes are still well placed ?

Here are the assets(64*64 png) : Directories : textures/test/

解决方案

Not really an answer (as the code will be rewritten anyway) so few hints for the new code instead (some of them are already mentioned in the comments).

  1. Tileset

    In the final isometric engine use sprites. They are faster and support pixel art. For my purposes I use compilation of these two free to use tilesets (64x64):

    Both are compatible. I compiled and edited them to suite the needs of my engine. So this is what I use (still work in progress):

    White color 0x00FFFFFF means transparent. The sprite is not enough. I added info about the height of tile and rotations.

    If you see first 4 tiles from upper left corner they all are the same thing rotated by 90 degrees. So all my tiles have index of 4 tiles (the 90 degree rotations) int rot[4]. This way I can rotate the whole map or just view. I compile the set so the rotations are next to each other. There are 3 options:

    • tile[ix].rot[]={ ix,ix,ix,ix }; where ix is tile without rotation (ground)
    • tile[ix].rot[]={ ix,ix+1,ix,ix+1 }; where ix is tile with 2 rotations (those 2 tiles with chunk of chopped tree in the middle right)
    • tile[ix].rot[]={ ix,ix+1,ix+2,ix+3 }; where ix is tile with 4 rotations (like the first tile)

    The indexes are valid of coarse only for the first tile only, the others have the whole rot[] array rotated by 1 value from neighbor. Some rotations are invisible (see the wide trees) but the tile is still present to allow rotations.

    The tile height is important for placing tiles while editing and also for automatic map generations.

    I plan to add also A* map for each tile so I can use path finding or compute watter flows and more.

  2. Map editor

    I prefer 3D maps. with bigger resolution you need to properly select the viewed area for viewing to maximize performance. Also a good idea is to create hollow underground so the rendering is much faster (this can be also done virtually during rendering process without the need of updating map).

    I recommend to code these features:

    • make ground hollow
    • make ground solid
    • random terrain (diamond & square)
    • filter out small holes and smooth edges (add the slope tiles to cubic ones)
  3. tile editor

    Apart from the obvious paint editor you should add also another features like:

    1. floor <-> ceiling
    2. left <-> right
    3. front <-> back
    4. divide large sprite into regular tiles
    5. copy/merge/paste
    6. adjust lighting after left <-> right mirror operation

    They are really handy while compiling/editing tileset resources. As you can see my tileset has many of tiles not present in the source tilesets. They were created by these functions + some minor paint editing... The colored masks on the bottom of the tileset are used to mask out and properly combine parts of tiles to create the missing ones ... (you can take one side form one tile and other from other ...)

[Notes]

For more info/ideas have a look at some related Q/As:

这篇关于2D 钻石(等距)地图编辑器 - 纹理无限扩展?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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