SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Ошибка доступа к файлу тайлов(TinyXML)
В этой теме 0 ответов, 1 участник, последнее обновление Interra 8 года/лет, 2 мес. назад.
Просмотр 1 сообщения - с 1 по 1 (всего 1)
-
АвторСообщения
-
Урок 22 по sfml, при запуске проекта появляется черный экран и пишется, что к файлу тайлов не хватает прав доступа. Через fopen_s и файл уровня, и файл картинки с тайлами открывается, через редактор карт открывается уровень тоже нормально. Вроде особо проект от того, что в уроке, не отличается. Level.h полностью скопирован из урока. После закрытия окна появляется сообщение(во вложениях). Сборка x64.
main.cpp
C++12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879#include <SFML/Graphics.hpp>#include <iostream>#include <sstream>#include "level.h"#include <vector>#include <list>#include "map.h"#include "Camera.h"#include "Player.h"using namespace sf;int main(){RenderWindow window(VideoMode(640, 480), "Monsters, portals and things");camera.reset(FloatRect(0, 0, 640, 480));FILE *stream;errno_t err;// Open for readerr = fopen_s(&stream, "images/tiles_large.png", "r");if (err == 0){printf("The file img was opened\n");}err = fopen_s(&stream, "levels/level1.tmx", "r");if (err == 0){printf("The file tmx was opened\n");}Level lvl;//создали экземпляр класса уровеньlvl.LoadFromFile("levels/level1.tmx");//загрузили в него карту, внутри класса с помощью методов он ее обработает.Image heroImage;heroImage.loadFromFile("images/hero1.png");heroImage.createMaskFromColor(Color(255, 255, 255));Image easyEnemyImage;easyEnemyImage.loadFromFile("images/enemy1.png");easyEnemyImage.createMaskFromColor(Color(88, 152, 144));easyEnemyImage.createMaskFromColor(Color(255, 255, 255));Object playerObject = lvl.GetObject("player");//объект игрока на нашей карте.задаем координаты игроку в начале при помощи негоObject easyEnemyObject = lvl.GetObject("easyEnemy");Player player(heroImage, "Player1", lvl, playerObject.rect.left, playerObject.rect.top, 32, 31);//передаем координаты прямоугольника player из карты в координаты нашего игрокаEnemy easyEnemy(easyEnemyImage, "EasyEnemy", lvl, easyEnemyObject.rect.left, easyEnemyObject.rect.top, 52, 26);//передаем координаты прямоугольника easyEnemy из карты в координаты нашего врагаClock clock;while (window.isOpen()){float time = clock.getElapsedTime().asMicroseconds();clock.restart();time = time / 800;Event event;while (window.pollEvent(event)){if (event.type == sf::Event::Closed)window.close();}player.update(time);// Player update functioneasyEnemy.update(time);//easyEnemy update functionwindow.setView(camera);window.clear();lvl.Draw(window);window.draw(easyEnemy.sprite);window.draw(player.sprite);window.display();}return 0;}Player.h
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150#pragma once#include <stdio.h>#include <SFML/Graphics.hpp>#include <iostream>#include <sstream>using namespace sf;class Creature{public:std::vector<Object> obj;//вектор объектов картыfloat dx, dy, x, y, speed, moveTimer;int w, h, health;bool life, onGround, isMove;Texture texture;Sprite sprite;String name;Creature(Image &image, String Name, float X, float Y, int W, int H){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 Creature {public:enum { left, right, up, down, jump, stay } state;//добавляем тип перечисления - состояние объектаint playerScore;//эта переменная может быть только у игрокаPlayer(Image &image, String Name, Level &lvl, float X, float Y, int W, int H) :Creature(image, Name, X, Y, W, H){playerScore = 0; state = stay;obj = lvl.GetAllObjects();if (name == "Player1"){sprite.setTextureRect(IntRect(288, 161, w, h));}}void control(){if (Keyboard::isKeyPressed(Keyboard::Left)){state = left;speed = 0.2;}if (Keyboard::isKeyPressed(Keyboard::Right)){state = right;speed = 0.2;}if ((Keyboard::isKeyPressed(Keyboard::Up)) && (onGround)){state = jump; dy = -0.7; onGround = false;}if (Keyboard::isKeyPressed(Keyboard::Down)){state = down;}}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 - int(w*0.03); }if (Dx<0) { x = obj[i].rect.left + obj[i].rect.width; }}}}void update(float time){control();switch (state){case right: dx = speed; break;case left: dx = -speed; break;case up: break;case down: dx = 0; break;case jump: break;case stay: break;}x += dx*time;checkCollisionWithMap(dx, 0);y += dy*time;checkCollisionWithMap(0, dy);sprite.setPosition(x + w / 2, y + h / 2);if (health <= 0) { life = false; }if (!isMove) speed = 0;if (life) { setPlayerCoordinateForView(x, y); }dy = dy + 0.0015*time;}};class Enemy :public Creature {public:Enemy(Image &image, String Name, Level &lvl, float X, float Y, int W, int H) :Creature(image, Name, X, Y, W, H) {obj = lvl.GetObjects("solid");if (name == "EasyEnemy") {sprite.setTextureRect(IntRect(1, 81, 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 (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; 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") {//для персонажа с таким именем логика будет такой//moveTimer += time;if (moveTimer>3000){ dx *= -1; moveTimer = 0; }//меняет направление примерно каждые 3 секx += dx*time;checkCollisionWithMap(dx, 0);//обрабатываем столкновение по Хsprite.setPosition(x + w / 2, y + h / 2); //задаем позицию спрайта в место его центраif (health <= 0) { life = false; }}}};camera.h
C++1234567891011121314using namespace sf;View camera;View setPlayerCoordinateForView(float x, float y){float tempX = x;float tempY = y;if (x < 320) tempX = 320;if (y < 240) tempY = 240;if (y > 624) tempY = 624;camera.setCenter(tempX, tempY);return camera;}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Вложения:
You must be logged in to view attached files. -
АвторСообщения
Просмотр 1 сообщения - с 1 по 1 (всего 1)
Для ответа в этой теме необходимо авторизоваться.