SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Проблемы с отображением карты.
В этой теме 17 ответов, 5 участников, последнее обновление Ivan 8 года/лет, 4 мес. назад.
-
АвторСообщения
-
C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298#include <SFML/Graphics.hpp>//#include "map.h"#include "view.h"#include <iostream>#include <sstream>#include <vector>#include "level.h"#include <list>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;//враги могут быть разные, мы не будем делать другой класс для различающегося врага.всего лишь различим врагов по имени и дадим каждому свое действие в update в зависимости от имениEntity(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);//soldier_sprite.setScale(1, 1);}FloatRect getRect(){//ф-ция получения прямоугольника. его коорд,размеры (шир,высот).return FloatRect(x, y, w, h);//эта ф-ция нужна для проверки столкновений}virtual void update(float time) = 0;};////////////////////////////////////////////////////КЛАСС ИГРОКА////////////////////////class Player :public Entity {public:enum { left, right, up, down, jump, stay } state;//добавляем тип перечисления - состояние объектаint playerScore;//эта переменная может быть только у игрокаPlayer(Image &image, String Name, Level &lev, float X, float Y, int W, int H) :Entity(image, Name, X, Y, W, H){playerScore = 0; state = stay; obj = lev.GetAllObjects();//инициализируем.получаем все объекты для взаимодействия персонажа с картойif (name == "Player1"){sprite.setTextureRect(IntRect(229, 467, w, h));//sprite.setScale(0.8, 0.8);}}void control(){if (Keyboard::isKeyPressed(Keyboard::A)) {state = left;speed = 0.1;// CurrentFrame += 0.005*time; //служит для прохождения по "кадрам". переменная доходит до трех суммируя произведение времени и скорости. изменив 0.005 можно изменить скорость анимации//if (CurrentFrame > 6) CurrentFrame -= 6; //если пришли к третьему кадру - откидываемся назад.// sprite.setTextureRect(IntRect(115 * int(CurrentFrame), 230, 102, 250)); //проходимся по координатам Х. получается 0, 96,96*2 и опять 0}if (Keyboard::isKeyPressed(Keyboard::D)) {state = right;speed = 0.1;// CurrentFrame += 0.005*time; //служит для прохождения по "кадрам". переменная доходит до трех суммируя произведение времени и скорости. изменив 0.005 можно изменить скорость анимации// if (CurrentFrame > 6) CurrentFrame -= 6; // если пришли к третьему кадру - откидываемся назад.// sprite.setTextureRect(IntRect(115 * int(CurrentFrame), +0, 115, 231)); //проходимся по координатам Х. получается начинаем рисование с координаты Х равной 0,96,96*2, и опять 0}if ((Keyboard::isKeyPressed(Keyboard::W)) && (onGround)) {state = jump; dy = -0.7; onGround = false;//то состояние равно прыжок,прыгнули и сообщили, что мы не на земле// CurrentFrame += 0.005*time; //служит для прохождения по "кадрам". переменная доходит до трех суммируя произведение времени и скорости. изменив 0.005 можно изменить скорость анимации// if (CurrentFrame > 3) CurrentFrame -= 3; // если пришли к третьему кадру - откидываемся назад.// sprite.setTextureRect(IntRect(115 * int(CurrentFrame), 480, 115, 231)); //проходимся по координатам Х. получается 0,96,96*2, и опять 0}if (Keyboard::isKeyPressed(Keyboard::S)) {state = down;speed = 0.1;//currentFrame += 0.005*time;//if (currentFrame > 3) currentFrame -= 3;//p.sprite.setTextureRect(IntRect(96 * int(currentFrame), 0, 96, 96));}}void checkCollisionWithMap(float Dx, float Dy)//ф ция проверки столкновений с картой{for (int i = y / 32; i < (y + h) / 32; i++)//проходимся по элементам карты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; }}}}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 stay: break;//и здесь тоже}x += dx*time;checkCollisionWithMap(dx, 0);//обрабатываем столкновение по Хy += dy*time;checkCollisionWithMap(0, dy);//обрабатываем столкновение по Ysprite.setPosition(x + w / 2, y + h / 2); //задаем позицию спрайта в место его центраif (health <= 0){ life = false; }if (!isMove){ speed = 0; }//if (!onGround) { dy = dy + 0.0015*time; }//убираем и будем всегда притягивать к землеif (life) { coorDinateforview(x, y); }dy = dy + 0.0015*time;//постоянно притягиваемся к земле}};class Enemy :public Entity{public:Enemy(Image &image, String Name, Level &lvl, float X, float Y, int W, int H) :Entity(image, Name, X, Y, W, H){obj = lvl.GetObjects("solid");//инициализируем.получаем нужные объекты для взаимодействия врага с картойif (name == "EasyEnemy"){sprite.setTextureRect(IntRect(0, 0, w, h));dx = 0.1;sprite.setScale(1.01, 1.01);}}void checkCollisionWithMap(float Dx, float Dy){/*вариант взаимодействия со старой картойfor (int i = y / 32; i < (y + h) / 32; i++)for (int j = x / 32; j<(x + w) / 32; j++){if (TileMap[i][j] == '0'){if (Dy>0){ y = i * 32 - h; }if (Dy<0){ y = i * 32 + 32; }if (Dx>0){ x = j * 32 - w; dx = -0.1; sprite.scale(-1, 1); }if (Dx<0){ x = j * 32 + 32; dx = 0.1; sprite.scale(-1, 1); }}}*/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 секcheckCollisionWithMap(dx, 0);//обрабатываем столкновение по Хx += dx*time;sprite.setPosition(x + w / 2, y + h / 2); //задаем позицию спрайта в место его центраif (health <= 0){ life = false; }//если здоровье меньше нуля, тогда забираем жизу}}};int main(){RenderWindow window(VideoMode(800, 550), L"GameDevelopment");view.reset(FloatRect(0, 0, 800, 550));Level lvl;//создали экземпляр класса уровеньlvl.LoadFromFile("mapp.tmx");//загрузили в него карту, внутри класса с помощью методов он ее обработает./*Image map_image;map_image.loadFromFile("images/map.png");Texture map;map.loadFromImage(map_image);Sprite s_map;s_map.setTexture(map);*/Image heroImage;heroImage.loadFromFile("images/example013-yellow.png");Image easyEnemyImage;easyEnemyImage.loadFromFile("images/example-cayan.png");//easyEnemyImage.createMaskFromColor(Color(255, 0, 0));//сделали маску по цвету.но лучше изначально иметь прозрачную картинкуstd::list<Entity*> entities;//создаю список, сюда буду кидать объекты.например врагов.std::list<Entity*>::iterator it;//итератор чтобы проходить по эл-там спискаstd::vector<Object> e = lvl.GetObjects("EasyEnemy");//все объекты врага на tmx карте хранятся в этом вектореfor (int i = 0; i < e.size(); i++)//проходимся по элементам этого вектора(а именно по врагам)entities.push_back(new Enemy(easyEnemyImage, "EasyEnemy", lvl, e[i].rect.left, e[i].rect.top, 100, 230));//и закидываем в список всех наших врагов с картыObject player = lvl.GetObject("player");//объект игрока на нашей карте.задаем координаты игроку в начале при помощи него//Object easyEnemyObject = lvl.GetObject("easyEnemy");//объект легкого врага на нашей карте.задаем координаты игроку в начале при помощи него//Player p(heroImage, 250, 250, 118, 225, "Player1");//объект класса игрока//Enemy easyEnemy(easyEnemyImage, 850, 532, 100, 230, "EasyEnemy");//простой враг, объект класса врагаPlayer p(heroImage, "Player1", lvl, player.rect.left, player.rect.top, 115, 235);//передаем координаты прямоугольника player из карты в координаты нашего игрока//Enemy easyEnemy(easyEnemyImage, "EasyEnemy", lvl, easyEnemyObject.rect.left, easyEnemyObject.rect.top, 100, 230);//передаем координаты прямоугольника easyEnemy из карты в координаты нашего врагаClock clock;while (window.isOpen()){float time = clock.getElapsedTime().asMicroseconds();float CurrentFrame = 0;clock.restart();time = time / 800;Event event;while (window.pollEvent(event)){if (event.type == sf::Event::Closed)window.close();}p.update(time);// Player update function//easyEnemy.update(time);//easyEnemy update functionfor (it = entities.begin(); it != entities.end(); it++) { (*it)->update(time); }//для всех элементов списка(пока это только враги,но могут быть и пули к примеру) активируем ф-цию update/* do {CurrentFrame += 0.0010*time; //служит для прохождения по "кадрам". переменная доходит до трех суммируя произведение времени и скорости. изменив 0.005 можно изменить скорость анимацииif (CurrentFrame > 6) CurrentFrame -= 6; // если пришли к третьему кадру - откидываемся назад.(p.sprite.setTextureRect(IntRect(115 * int(CurrentFrame), 480, 115, 705)));}while (Keyboard::isKeyPressed(Keyboard::Tilde));*/window.setView(view);window.clear();lvl.Draw(window);//рисуем новую карту/*for (int i = 0; i < HEIGHT_MAP; i++)for (int j = 0; j < WIDTH_MAP; j++){if (TileMap[i][j] == ' ') s_map.setTextureRect(IntRect(0, 0, 32, 32));if (TileMap[i][j] == 's') s_map.setTextureRect(IntRect(32, 0, 32, 32));if ((TileMap[i][j] == '0')) s_map.setTextureRect(IntRect(64, 0, 32, 32));if ((TileMap[i][j] == 'f')) s_map.setTextureRect(IntRect(96, 0, 32, 32));if ((TileMap[i][j] == 'h')) s_map.setTextureRect(IntRect(128, 0, 32, 32));s_map.setPosition(j * 32, i * 32);window.draw(s_map);}*/for (it = entities.begin(); it != entities.end(); it++){window.draw((*it)->sprite); //рисуем entities объекты (сейчас это только враги)}//window.draw(easyEnemy.sprite);//старый вариант рисования одного врагаwindow.draw(p.sprite);window.display();}return 0;}
Переустановил Windows, после того как я поместил папки в то место, где они были ранее (для удобства) перестала загружаться карта, пишет ошибку “Loading level “mapp.tmx” failed.” Настройки карты правильные, расположение файлов прежнее, в чем проблема может быть?
Вложения:
You must be logged in to view attached files.Файл карты называется map или mapp?
<p style=”text-align: left;”>Там всё правильно, я несколько раз переделывал карту с 0, ошибка сохранилась.</p>
Перенастроил весь проект заново… Библиотеки (SFML и TinyXML) не помогло и это
Разобрался.
P.S. Ошибка была в том, что путь к изображению, карты, хранился здесь: “C:\Users\Адреналин\Documents\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\images” Как я мог забыть что проблемы и кириллица недопустимы… Будьте внимательны ребятподскажите пожалуйста, кто знает. какую команду нужно написать после – if (TileMap[i][j] == ‘ ‘), если я хочу, чтобы в ‘ ‘ ничего не отрисовывалось?
Создай логическую переменную bool isDraw = true;
if(isDraw) {
draw…
}if (TileMap[i][j] == ‘ ‘) continue;
Я так понимаю эта проверка в цикле идет?
Если да то при встрече ” ” он будет просто пропускать данный элемент и ничего не отрисовыватья пробовал “continue”. забивает вообще весь фрейм не нужным мне тайлом
а вот, как видно в коде- карта вообще пуста, но почему-то рисуются 2 тайла которые мне там не нужны
Вложения:
You must be logged in to view attached files.Ivan, ты хочешь отсутствие тайла “нарисовать” в определенном месте? Предположим , что у тебя получится – тогда у тебя будет черный фон окна в этом месте. Зачем оно тебе? Какая задача стоит вобще?
мне надо чтобы небо было как есть, а из тайлов землю только хочу
а вот эти два кирпича в небе хоть тесни, все-равно есть. хотя в коде карта пустая. более того, что бы я не менял в ней- ничего не меняется на деле, только два одиноких кирпича в небесах)
хоть тресни*
рисуй карту поменьше высотой, для земли только.
немного смести камеру вниз как надо, чтобы земля была видна хорошо, затем ты можешь программно задать фон window.clear() принимает в качестве параметра цвет, который и закрасит окно консоли.
звездочки тоже можно сделать программно, задав им координаты (возможно эти координаты надо для крутости рандомными сделать, в промежутке от земли до верхнего края и так по всей ширине карты соответственно). -
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.