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
上使用显示
当我尝试绘制等轴测图时,我所有的精灵都颠倒了。
这是以下代码中提到的 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
上使用显示