SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Tile Map Editor
Помечено: no tile information found, Tile Map Editor
В этой теме 12 ответов, 2 участника, последнее обновление KindRedSand 6 года/лет, 5 мес. назад.
-
АвторСообщения
-
Здравствуйте, после урока 22, когда запускаю проект пишет Bad map. No tile information found. Я думаю, что проблема в том, что в моей версии tile map editor нет Xml формта (при создании карты), есть csv и какие-то другие, старую версию найти не могу, что делать?
А ты не пробовал сохранить tmx формат карты и открыть его к примеру в notepad++? Думаю результат тебя приятно удивит так как это и есть искомый нами xml документ.
А есть какие-то идеи почему пишет No tile information found? Путь в подгрузке по идее правильный, у меня map.tmx находится в папке с проектом рядом с main.cpp, ну и прописано lvl.LoadFromFile(“map.tmx”); , код перепроверил, в level.h тоже все правильно, tinyXml подключена, в чем же проблема?
Либо парсер не смог найти ни одного тайла, либо он не нашёл тайлсет. Тайлсет расположен релативно к map.tmx? Перепроверь что бы относительно map.tmx текстуры находились именно там, от куда были превязаны: Скриншот
Так, окей значит я поставил файл mainmap.tmx в папку images где лежит картинка карты и все поменялось, больше не пишет старую проблему, но теперь пишет failed to load image “map.png”. Reason unable to open the file. , зайдя в tile map editor поменял расположение файла map.png. В той строке (где в блокноте открывать mainmap.tmx): <image source=”map.png”… Если ставлю по другому то tile map не видит и просит указать путь к файлу (когда в программе указываю путь к своему файлу: tile map сам оставляет <image source=”map.png”…)
Вот информация детальная: значит вот путь до mainmap.tmx и map.png:
C:\Users\spoty\Documents\Visual Studio 2013\Projects\Adventures\Adventures\images
Вот код:
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371#include <SFML/Graphics.hpp>#include <SFML/Audio.hpp>#include "view.h"#include <iostream>#include <sstream>#include "mission.h"#include "iostream"#include "level.h"#include <vector>#include <list>#include "tinyxml\tinyxml.h"using namespace sf;class Entity {public:std::vector<Object> obj;float dx, dy, x, y, speed, moveTimer;int w, h, health;bool life, isMove, onGround;Texture texture;Sprite sprite;String name;Entity(Image &image, float X, float Y, int W, int H, String Name) {x = X; y = Y; w = W; h = H; name = Name; moveTimer = 0;speed = 0; health = 100; dx = 0; dy = 0;life = true; onGround = false; isMove = false;texture.loadFromImage(image);sprite.setTexture(texture);sprite.setOrigin(w / 2, h / 2);}FloatRect getRect(){return FloatRect(x, y, w, h);}};class Player :public Entity {public:enum { left, right, jump, stay } state;int playerScore;Player(Image &image, Level &lev, float X, float Y, int W, int H, String Name) :Entity(image, X, Y, W, H, Name){playerScore = 0; state = stay; obj = lev.GetAllObjects();if (name == "Player1"){sprite.setTextureRect(IntRect(97, 227, w, h));}}void control() {if (life == true) {if (Keyboard::isKeyPressed(Keyboard::A)) {state = left;speed = 0.3;}if (Keyboard::isKeyPressed(Keyboard::D)) {state = right;speed = 0.3;}if ((Keyboard::isKeyPressed(Keyboard::Space) && (onGround == true))) {state = jump;dy = -0.5;onGround = false;}}}void update(float time){control();switch (state) {case left: dx = -speed; break;case right: dx = speed; break;case jump: break;case stay: break;}x += dx*time;checkCollisionWithMap(dx, 0);y += dy*time;checkCollisionWithMap(0, dy);if (!isMove) speed = 0;sprite.setPosition(x + w / 2, y + h / 2);if (health <= 0) { life = false; }if (life == true) { getplayercoordinateforview(x, y); }dy = dy + 0.0015*time;}float getplayercoordinateX() {return x;}void checkCollisionWithMap(float Dx, float Dy) {for (int i = 0; i<obj.size(); i++)if (getRect().intersects(obj[i].rect)){if (obj[i].name == "solid"){if (Dy>0) { y = obj[i].rect.top - h; dy = 0; onGround = true; }if (Dy<0) { y = obj[i].rect.top + obj[i].rect.height; dy = 0; }if (Dx>0) { x = obj[i].rect.left - w; }if (Dx<0) { x = obj[i].rect.left + obj[i].rect.width; }}}}};class Enemy :public Entity{public:Enemy(Image &image, Level &lvl, float X, float Y, int W, int H, String Name) :Entity(image, X, Y, W, H, Name) {obj = lvl.GetObjects("solid");if (name == "EasyEnemy") {sprite.setTextureRect(IntRect(0, 0, w, h));dx = 0.1;}}void checkCollisionWithMap(float Dx, float Dy) {for (int i = 0; i<obj.size(); i++)if (getRect().intersects(obj[i].rect)){if (Dy>0) { y = obj[i].rect.top - h; dy = 0; onGround = true; }if (Dy<0) { y = obj[i].rect.top + obj[i].rect.height; dy = 0; }if (Dx>0) { x = obj[i].rect.left - w; dx = -0.1; sprite.scale(-1, 1); }if (Dx<0) { x = obj[i].rect.left + obj[i].rect.width; dx = 0.1; sprite.scale(-1, 1); }}}void update(float time) {if (name == "EasyEnemy"){//moveTime += time; if (moveTimer>3000) {dx*=-1; moveTimer = 0; }checkCollisionWithMap(dx, 0);x += dx*time;sprite.setPosition(x + w / 2, y + h / 2); // ЭТО КСТАТИ ЗАДАЕТ ПОЗИЦИЮ СПРАЙТА В КГО ЦЕНТРif (health <= 0) { life = false; }}}};int main(){sf::RenderWindow window(sf::VideoMode(1980, 1080), "Glinskii Adventures");view.reset(sf::FloatRect(0, 0, 640, 400));Level lvl;lvl.LoadFromFile("images/mainmap.tmx");Image heroImage;heroImage.loadFromFile("images/hero.png");heroImage.createMaskFromColor(Color(41, 33, 59));Image easyEnemyImage;easyEnemyImage.loadFromFile("images/enemy1.jpg");easyEnemyImage.createMaskFromColor(Color(255, 255, 255));/*Image map_image;map_image.loadFromFile("images/map.png");Texture map;map.loadFromImage(map_image);Sprite map_sprite;map_sprite.setTexture(map);Image house_image;house_image.loadFromFile("images/house.png");house_image.createMaskFromColor(Color(255, 255, 255));Texture house;house.loadFromImage(house_image);Sprite house_sprite;house_sprite.setTexture(house);house_sprite.setPosition(80, 539);*/Image quest_image;quest_image.loadFromFile("images/tab.jpg");Texture quest_texture;quest_texture.loadFromImage(quest_image);Sprite s_quest;s_quest.setTexture(quest_texture);s_quest.setTextureRect(IntRect(0, 0, 224, 352));/*Image map2;map2.loadFromFile("images/map2.png");Texture map2texture;map2texture.loadFromImage(map2);Sprite map2s;map2s.setTexture(map2texture);*/Object player = lvl.GetObject("player");Object easyEnemyObject = lvl.GetObject("easyEnemy");SoundBuffer claySongBuffer;claySongBuffer.loadFromFile("sounds/claySong.ogg");Sound claySong(claySongBuffer);claySong.play();claySong.setLoop(true);/*SoundBuffer deathBuffer;deathBuffer.loadFromFile("sounds/deathS.ogg");Sound deathS(deathBuffer);deathS.setVolume(100);Music death;death.openFromFile("music/death.ogg");death.setVolume(50);*//*SoundBuffer lowhpBuffer;lowhpBuffer.loadFromFile("sounds/lowhp.ogg");Sound lowhp(lowhpBuffer);*//*SoundBuffer walkBuffer;walkBuffer.loadFromFile("sounds/walk.ogg");Sound walk(walkBuffer);walk.setVolume(100);*/Music soundtrack;soundtrack.openFromFile("music/soundtrack.ogg");soundtrack.setVolume(50);soundtrack.play();soundtrack.setLoop(true);Music soundtrack2;soundtrack2.openFromFile("music/soundtrack2.ogg");soundtrack2.setVolume(100);Font font;font.loadFromFile("fonts/classic.TTF");Text text("", font, 20);text.setStyle(Text::Bold);Text pickText("", font, 20);pickText.setStyle(Text::Bold);Text text2("", font, 20);text2.setStyle(Text::Bold);Text glinPlate("", font, 20);glinPlate.setStyle(Text::Bold);glinPlate.setStyle(Text::Underlined);Text nickname("", font, 20);Player p(heroImage, lvl, player.rect.left, player.rect.top, 94, 59, "Player1");Enemy easyEnemy(easyEnemyImage, lvl, easyEnemyObject.rect.left, easyEnemyObject.rect.top, 79, 59, "EasyEnemy");float CurrentFrame = 0;Clock clock;Clock gameTimeClock;int gameTime = 0;bool showMissionText = true;while (window.isOpen()){float time = clock.getElapsedTime().asMicroseconds();if (p.life == true) gameTime = gameTimeClock.getElapsedTime().asSeconds();else {p.sprite.setColor(Color(235, 65, 7));view.zoom(1.0090);view.move(0, 0.07);view.move(0.07, 0);view.rotate(1);}clock.restart();time = time / 800;sf::Event event;while (window.pollEvent(event)){window.setKeyRepeatEnabled(false);if (event.type == sf::Event::Closed)window.close();/*if (p.life == true){if ((event.type == Event::KeyPressed) && (event.key.code == Keyboard::D)){walk.play();}}*//*if (death.getStatus() == Sound::Playing){continue;}else{soundtrack.stop();claySong.stop();death.play();deathS.play();}*/if (event.type == Event::KeyPressed)if ((event.key.code == Keyboard::Tab)){switch (showMissionText){case true:{std::ostringstream task;task << getTextMission(getCurrentMission(p.getplayercoordinateX()));text2.setString("\n" + task.str());showMissionText = false;glinPlate.setString("Глиняная плита гласит:");nickname.setString("XxX_Daun_XxX");break;}case false:{text2.setString("");showMissionText = true;break;}}}}p.update(time);easyEnemy.update(time);changeview();window.setView(view);window.clear();lvl.Draw(window);std::ostringstream playerHealthString, gameTimeString;playerHealthString << p.health; gameTimeString << gameTime;text.setString("Здоровье: " + playerHealthString.str() + "\nВремя игры: " + gameTimeString.str());text.setPosition(view.getCenter().x - 315, view.getCenter().y - 200);window.draw(text);std::ostringstream playerScoreString;playerScoreString << p.playerScore;pickText.setString("Собрано: " + playerScoreString.str());pickText.setPosition(view.getCenter().x + 140, view.getCenter().y - 200);window.draw(pickText);if (!showMissionText){text2.setPosition(view.getCenter().x - 315, view.getCenter().y - 100);s_quest.setPosition(view.getCenter().x - 320, view.getCenter().y - 100);glinPlate.setPosition(view.getCenter().x - 315, view.getCenter().y - 100);nickname.setPosition(view.getCenter().x - 20, view.getCenter().y);window.draw(s_quest); window.draw(text2); window.draw(glinPlate); window.draw(nickname);}window.draw(easyEnemy.sprite);window.draw(p.sprite);window.display();}return 0;}Вот файл level.h
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345#ifndef LEVEL_H#define LEVEL_H#include <string>#include <vector>#include <map>#include <SFML/Graphics.hpp>#include <iostream>#include "tinyxml/tinyxml.h"struct Object{int GetPropertyInt(std::string name);//номер свойства объекта в нашем спискеfloat GetPropertyFloat(std::string name);std::string GetPropertyString(std::string name);std::string name;//объявили переменную name типа stringstd::string type;//а здесь переменную type типа stringsf::Rect<float> rect;//тип Rect с нецелыми значениямиstd::map<std::string, std::string> properties;//создаём ассоциатиный массив. ключ - строковый тип, значение - строковыйsf::Sprite sprite;//объявили спрайт};struct Layer//слои{int opacity;//непрозрачность слояstd::vector<sf::Sprite> tiles;//закидываем в вектор тайлы};class Level//главный класс - уровень{public:bool LoadFromFile(std::string filename);//возвращает false если не получилось загрузитьObject GetObject(std::string name);std::vector<Object> GetObjects(std::string name);//выдаем объект в наш уровеньstd::vector<Object> GetAllObjects();//выдаем все объекты в наш уровеньvoid Draw(sf::RenderWindow &window);//рисуем в окноsf::Vector2i GetTileSize();//получаем размер тайлаprivate:int width, height, tileWidth, tileHeight;//в tmx файле width height в начале,затем размер тайлаint firstTileID;//получаем айди первого тайлаsf::Rect<float> drawingBounds;//размер части карты которую рисуемsf::Texture tilesetImage;//текстура картыstd::vector<Object> objects;//массив типа Объекты, который мы создалиstd::vector<Layer> layers;};///////////////////////////////////////int Object::GetPropertyInt(std::string name)//возвращаем номер свойства в нашем списке{return atoi(properties[name].c_str());}float Object::GetPropertyFloat(std::string name){return strtod(properties[name].c_str(), NULL);}std::string Object::GetPropertyString(std::string name)//получить имя в виде строки.вроде понятно{return properties[name];}bool Level::LoadFromFile(std::string filename)//двоеточия-обращение к методам класса вне класса{TiXmlDocument levelFile(filename.c_str());//загружаем файл в TiXmlDocument// загружаем XML-картуif (!levelFile.LoadFile())//если не удалось загрузить карту{std::cout << "Loading level \"" << filename << "\" failed." << std::endl;//выдаем ошибкуreturn false;}// работаем с контейнером mapTiXmlElement *map;map = levelFile.FirstChildElement("map");// пример карты: <map version="1.0" orientation="orthogonal"// width="10" height="10" tilewidth="34" tileheight="34">width = atoi(map->Attribute("width"));//извлекаем из нашей карты ее свойстваheight = atoi(map->Attribute("height"));//те свойства, которые задавали при работе вtileWidth = atoi(map->Attribute("tilewidth"));//тайлмап редактореtileHeight = atoi(map->Attribute("tileheight"));// Берем описание тайлсета и идентификатор первого тайлаTiXmlElement *tilesetElement;tilesetElement = map->FirstChildElement("tileset");firstTileID = atoi(tilesetElement->Attribute("firstgid"));// source - путь до картинки в контейнере imageTiXmlElement *image;image = tilesetElement->FirstChildElement("image");std::string imagepath = image->Attribute("source");// пытаемся загрузить тайлсетsf::Image img;if (!img.loadFromFile(imagepath)){std::cout << "Failed to load tile sheet." << std::endl;//если не удалось загрузить тайлсет-выводим ошибку в консольreturn false;}img.createMaskFromColor(sf::Color(255, 255, 255));//для маски цвета.сейчас нет маскиtilesetImage.loadFromImage(img);tilesetImage.setSmooth(false);//сглаживание// получаем количество столбцов и строк тайлсетаint columns = tilesetImage.getSize().x / tileWidth;int rows = tilesetImage.getSize().y / tileHeight;// вектор из прямоугольников изображений (TextureRect)std::vector<sf::Rect<int>> subRects;for (int y = 0; y < rows; y++)for (int x = 0; x < columns; x++){sf::Rect<int> rect;rect.top = y * tileHeight;rect.height = tileHeight;rect.left = x * tileWidth;rect.width = tileWidth;subRects.push_back(rect);}// работа со слоямиTiXmlElement *layerElement;layerElement = map->FirstChildElement("layer");while (layerElement){Layer layer;// если присутствует opacity, то задаем прозрачность слоя, иначе он полностью непрозраченif (layerElement->Attribute("opacity") != NULL){float opacity = strtod(layerElement->Attribute("opacity"), NULL);layer.opacity = 255 * opacity;}else{layer.opacity = 255;}// контейнер <data>TiXmlElement *layerDataElement;layerDataElement = layerElement->FirstChildElement("data");if (layerDataElement == NULL){std::cout << "Bad map. No layer information found." << std::endl;}// контейнер <tile> - описание тайлов каждого слояTiXmlElement *tileElement;tileElement = layerDataElement->FirstChildElement("tile");if (tileElement == NULL){std::cout << "Bad map. No tile information found." << std::endl;return false;}int x = 0;int y = 0;while (tileElement){int tileGID = atoi(tileElement->Attribute("gid"));int subRectToUse = tileGID - firstTileID;// Устанавливаем TextureRect каждого тайлаif (subRectToUse >= 0){sf::Sprite sprite;sprite.setTexture(tilesetImage);sprite.setTextureRect(subRects[subRectToUse]);sprite.setPosition(x * tileWidth, y * tileHeight);sprite.setColor(sf::Color(255, 255, 255, layer.opacity));layer.tiles.push_back(sprite);//закидываем в слой спрайты тайлов}tileElement = tileElement->NextSiblingElement("tile");x++;if (x >= width){x = 0;y++;if (y >= height)y = 0;}}layers.push_back(layer);layerElement = layerElement->NextSiblingElement("layer");}// работа с объектамиTiXmlElement *objectGroupElement;// если есть слои объектовif (map->FirstChildElement("objectgroup") != NULL){objectGroupElement = map->FirstChildElement("objectgroup");while (objectGroupElement){// контейнер <object>TiXmlElement *objectElement;objectElement = objectGroupElement->FirstChildElement("object");while (objectElement){// получаем все данные - тип, имя, позиция, и тдstd::string objectType;if (objectElement->Attribute("type") != NULL){objectType = objectElement->Attribute("type");}std::string objectName;if (objectElement->Attribute("name") != NULL){objectName = objectElement->Attribute("name");}int x = atoi(objectElement->Attribute("x"));int y = atoi(objectElement->Attribute("y"));int width, height;sf::Sprite sprite;sprite.setTexture(tilesetImage);sprite.setTextureRect(sf::Rect<int>(0, 0, 0, 0));sprite.setPosition(x, y);if (objectElement->Attribute("width") != NULL){width = atoi(objectElement->Attribute("width"));height = atoi(objectElement->Attribute("height"));}else{width = subRects[atoi(objectElement->Attribute("gid")) - firstTileID].width;height = subRects[atoi(objectElement->Attribute("gid")) - firstTileID].height;sprite.setTextureRect(subRects[atoi(objectElement->Attribute("gid")) - firstTileID]);}// экземпляр объектаObject object;object.name = objectName;object.type = objectType;object.sprite = sprite;sf::Rect <float> objectRect;objectRect.top = y;objectRect.left = x;objectRect.height = height;objectRect.width = width;object.rect = objectRect;// "переменные" объектаTiXmlElement *properties;properties = objectElement->FirstChildElement("properties");if (properties != NULL){TiXmlElement *prop;prop = properties->FirstChildElement("property");if (prop != NULL){while (prop){std::string propertyName = prop->Attribute("name");std::string propertyValue = prop->Attribute("value");object.properties[propertyName] = propertyValue;prop = prop->NextSiblingElement("property");}}}objects.push_back(object);objectElement = objectElement->NextSiblingElement("object");}objectGroupElement = objectGroupElement->NextSiblingElement("objectgroup");}}else{std::cout << "No object layers found..." << std::endl;}return true;}Object Level::GetObject(std::string name){// только первый объект с заданным именемfor (int i = 0; i < objects.size(); i++)if (objects[i].name == name)return objects[i];}std::vector<Object> Level::GetObjects(std::string name){// все объекты с заданным именемstd::vector<Object> vec;for (int i = 0; i < objects.size(); i++)if (objects[i].name == name)vec.push_back(objects[i]);return vec;}std::vector<Object> Level::GetAllObjects(){return objects;};sf::Vector2i Level::GetTileSize(){return sf::Vector2i(tileWidth, tileHeight);}void Level::Draw(sf::RenderWindow &window){// рисуем все тайлы (объекты не рисуем!)for (int layer = 0; layer < layers.size(); layer++)for (int tile = 0; tile < layers[layer].tiles.size(); tile++)window.draw(layers[layer].tiles[tile]);}#endifПрошу прощения что ввёл в заблуждение. Картинка должна быть расположена по пути указаном в файле релативно рабочей папки , а не .tmx
СкриншотЯ что-то не понимаю, короче вот скрины
Это если я ставлю images/map.png то просто не видит карту tile map editor и пишет Bad map, no tile informatio found, НО если в пути написать просто image source=”map.png”, то tile map editor все видит, и в консоли пишет failed to load map.png, unable to open the file. Я чет ничего не понимаю
Вложения:
You must be logged in to view attached files.Либо вы забыли добавить криншоты, либо хостинг их не хочет принимать.
Возможно неверно были выставлены настройки в карте. Обязательно не должно быть никакого сжатия(Формат слоя тайлов = XML)
Так же твой код может парсить только ортогональную карту.у меня формат csv, xml в этой версии нету, карта ортогональная, прото как бы в настройках карты в тайл мап едиторе можно выьрать было только csv! И в блокноте (mainmap.tmx) стоит <data encoding=”csv”>
Скриншоты почему то не приходят, но если что, и mainmap.tmx и map.png у меня лежат в папке images, в коде прописано lvl.LoadFromFile(“images/mainmap.tmx”); В блокноте mainmap.tmx написано immage source=”map.png”; (image source=”images/map.png не работает), формт карты csv, может быьь мне стоит найти версию где есть xml формат? (Если добавить, я такую находку сделал, что ктдать в папку с проектом не сработает, нужно именно в подпапку (например: C:\Users\spoty\Documents\VisualStudio2013\Projects\Adventures\Adventures\images)
Подгрузились скрины. Вобще мучать телефон/фотоаппарат было незачем т.к. есть множество программ позволяющих захватить определённую часть экрана. К примеру те же самые системны ножницы(Пуск -> Стандартные) или Print Screen на клавиатуре отправит снимок экрана прямо в буфер обмена.
Ну и для tiled. Помести карту к main.cpp, открой её в tiled, укажи пусть до тайлсета, выставь в настройках карты Формат слоя тайлов = XML и пихай куда вздумается. После загружай его в программе и всё должно работать если нет сжатия.Спасибо, да, проблема была в слоях, я чет не додумался, что можно изменить в настройках именно уже сделаной карты (ну типо почему если в начале не было слоя, то потом он появится) оказывается появился, все сработало, спасибо
Вобще, когда надоест изобретать велосипе… *Кхм* парсер tmx карт можешь воспользоватся этим форком . В нём есть поддержка загрузки ConvexHull’ов (Фигур состоящих из вершин) а так же загрузка карт сжатых при помощи Base64 и zlib (Кстати, zlib хидеры в комплект не входят
да и воспользоваться zlib сжатием я так и не смог)
-
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.