SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Проблема взаимодействия персонажа с картой. › Ответ в теме: Проблема взаимодействия персонажа с картой.
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
#include <SFML/Graphics.hpp> #include "map.h" #include"view.h" using namespace sf; //класс игрока// class Player { // класс Игрока private: float x, y = 0; public: bool onGround, life; float w, h, dx, dy, speed; //координаты игрока х и у, высота ширина, ускорение (по х и по у), сама скорость int dir; //направление (direction) движения игрока String File; //файл с расширением Image image;//сфмл изображение Texture texture;//сфмл текстура Sprite sprite;//сфмл спрайт Player(String F, float X, float Y, float W, float H) { //Конструктор с параметрами(формальными) для класса Player. При создании объекта класса мы будем задавать имя файла, координату Х и У, ширину и высоту dx = 0; dy = 0; speed = 0; dir = 0; File = F;//имя файла+расширение w = W; h = H;//высота и ширина image.loadFromFile("images/" + File);//запихиваем в image наше изображение вместо File мы передадим то, что пропишем при создании объекта. В нашем случае "hero.png" и получится запись идентичная image.loadFromFile("images/hero/png"); image.createMaskFromColor(Color(41, 33, 59));//убираем ненужный темно-синий цвет, эта тень мне показалась не красивой. texture.loadFromImage(image);//закидываем наше изображение в текстуру sprite.setTexture(texture);//заливаем спрайт текстурой x = X; y = Y;//координата появления спрайта sprite.setTextureRect(IntRect(0, 0, w, h)); sprite.setTextureRect(IntRect(0, 0, w, h)); //Задаем спрайту один прямоугольник для вывода одного льва, а не кучи львов сразу. IntRect - приведение типов } void update(float time) //функция "оживления" объекта класса. update - обновление. принимает в себя время SFML , вследствие чего работает бесконечно, давая персонажу движение. { switch (dir)//реализуем поведение в зависимости от направления. (каждая цифра соответствует направлению) { case 0: dx = speed; dy = 0; break;//по иксу задаем положительную скорость, по игреку зануляем. получаем, что персонаж идет только вправо case 1: dx = -speed; dy = 0; break;//по иксу задаем отрицательную скорость, по игреку зануляем. получается, что персонаж идет только влево case 2: dx = 0; dy = -speed; break;//по иксу задаем нулевое значение, по игреку отрицательное. получается, что персонаж идет только вверх } x += dx*time;// наше ускорение на время получаем смещение координат и как следствие движение y += dy*time;//аналогично по игреку speed = 0;//зануляем скорость, чтобы персонаж остановился. sprite.setPosition(x, y); //выводим спрайт в позицию x y , посередине. бесконечно выводим в этой функции, иначе бы наш спрайт стоял на месте. interactionWithMap();//вызываем функцию, отвечающую за взаимодействие с картой } float getplayercoordinateX() { //этим методом будем забирать координату Х return x; } float getplayercoordinateY() { //этим методом будем забирать координату Y return y; } void interactionWithMap()//ф-ция взаимодействия с картой { for (int k = y / 32; k < (y + h)/32; k++)//проходимся по тайликам, контактирующим с игроком, то есть по всем квадратикам размера 32*32, которые мы окрашивали в 9 уроке. про условия читайте ниже. for (int l = x / 32; l < (x + w)/32; l++)//икс делим на 32, тем самым получаем левый квадратик, с которым персонаж соприкасается. (он ведь больше размера 32*32, поэтому может одновременно стоять на нескольких квадратах). А j<(x + w) / 32 - условие ограничения координат по иксу. то есть координата самого правого квадрата, который соприкасается с персонажем. таким образом идем в цикле слева направо по иксу, проходя по от левого квадрата (соприкасающегося с героем), до правого квадрата (соприкасающегося с героем) { if (TileMap[k][l] == '0')//если наш квадратик соответствует символу 0 (стена), то проверяем "направление скорости" персонажа: { if (dy>0)//если мы шли вниз, { y = k * 32 - h;//то стопорим координату игрек персонажа. сначала получаем координату нашего квадратика на карте(стены) и затем вычитаем из высоты спрайта персонажа. } if (dy<0) { y = k * 32 + 32;//аналогично с ходьбой вверх. dy<0, значит мы идем вверх (вспоминаем координаты паинта) } if (dx>0) { x = l * 32 - w;//если идем вправо, то координата Х равна стена (символ 0) минус ширина персонажа } if (dx < 0) { x = l * 32 + 32;//аналогично идем влево } } } } }; int main() { RenderWindow window(VideoMode(640, 480), "SFML Application"); view.reset(sf::FloatRect(0, 0, 640, 480));//размер "вида" камеры при создании объекта вида камеры. (потом можем менять как хотим) Что то типа инициализации. Image map_image;//объект изображения для карты map_image.loadFromFile("images/map.png");//загружаем файл для карты Texture map;//текстура карты map.loadFromImage(map_image);//заряжаем текстуру картинкой Sprite s_map;//создаём спрайт для карты s_map.setTexture(map);//заливаем текстуру спрайтом Player p("hero.png", 30, 388, 64.0, 64.0);//создаем объект p класса player,задаем "hero.png" как имя файла+расширение, далее координата Х,У, ширина, высота float CurrentFrame = 0;//хранит текущий кадр Clock clock; while (window.isOpen()) { float time = clock.getElapsedTime().asMicroseconds(); clock.restart(); time = time / 800; Event event; while (window.pollEvent(event)) { if (event.type == Event::Closed) window.close(); } if (Keyboard::isKeyPressed(Keyboard::Left)) { p.dir = 1; p.speed = 0.2;//dir =1 - направление вверх, speed =0.2 - скорость движения. Заметьте - время мы уже здесь ни на что не умножаем и нигде не используем каждый раз CurrentFrame += 0.008*time; if (CurrentFrame > 8) CurrentFrame -= 8; p.sprite.setTextureRect(IntRect(64 * int(CurrentFrame), 128, 64, 64)); //через объект p класса player меняем спрайт, делая анимацию (используя оператор точку) } if ((Keyboard::isKeyPressed(Keyboard::Right) || (Keyboard::isKeyPressed(Keyboard::D)))) { p.dir = 0; p.speed = 0.2;//направление вправо, см выше CurrentFrame += 0.008*time; if (CurrentFrame > 8) CurrentFrame -= 8; p.sprite.setTextureRect(IntRect(64 * int(CurrentFrame), 0, 64, 64)); //через объект p класса player меняем спрайт, делая анимацию (используя оператор точку) } getPlayerCoorinateForView(p.getplayercoordinateX(), p.getplayercoordinateY());//передаем координаты игрока в функцию управления камерой p.update(time);//оживляем объект p класса Player с помощью времени sfml, передавая время в качестве параметра функции update. благодаря этому персонаж может двигаться //viewmap(time);//функция скроллинга карты, передаем ей время sfml window.setView(view);//"оживляем" камеру в окне sfml window.clear(); /////////////////////////////Рисуем карту///////////////////// for (int i = 0; i < H_MAP; i++) for (int j = 0; j < W_MAP; j++) { if (TileMap[i][j] == ' ') s_map.setTextureRect(IntRect(32, 0, 32, 32)); //если встретили символ пробел, то рисуем 1й квадратик if (TileMap[i][j] == 's') s_map.setTextureRect(IntRect(0, 0, 32, 32));//если встретили символ s, то рисуем 2й квадратик if ((TileMap[i][j] == '0')) s_map.setTextureRect(IntRect(64, 0, 32, 32));//если встретили символ 0, то рисуем 3й квадратик s_map.setPosition(j * 32, i * 32);//по сути раскидывает квадратики, превращая в карту. то есть задает каждому из них позицию. если убрать, то вся карта нарисуется в одном квадрате 32*32 и мы увидим один квадрат window.draw(s_map);//рисуем квадратики на экран } window.draw(p.sprite);//рисуем спрайт объекта p класса player window.display(); } } |