SFML и C++ Уроки \ Разработка игр › Форумы › SFML Graphics › Неправильное торможение персонажа
В этой теме 12 ответов, 4 участника, последнее обновление Dench 7 года/лет, 10 мес. назад.
-
АвторСообщения
-
Всем добрый день. Возникла проблема с картой. Персонаж неправильно останавливается по координатам. На скрине показано красной чертой где он тормозится.Почему так?
Вложения:
You must be logged in to view attached files.C++123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230/////////////////////////////////////различные подсказки/////////////////////////////////////////делать прозрачным ненужный цвет :createMaskFromColor(Color(0, 0, 255));//для очищения консоли (cls) используется заголовок <conio.h>//для нахождения размера обьекта в памяти используется команда sizeof(x);//функция getline находится в заголовочном файле <string>. Ввести строку типа string можно только этой функцией, cin здесь бесполезен.#include<iostream>#include<SFML\Graphics.hpp>#include<cstdlib>#include<string>#include"map.h"#include"view.h"using namespace sf;///////////////////////////////////КЛАСС ИГРОКА////////////////////////////////////////////////class Player{private: float x, y;public://обеспечиваем доступ к нему из различных частей программы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(103, 103, 103));texture.loadFromImage(image);//закидываем наше изображение в текстуруsprite.setTexture(texture);//заливаем спрайт текстуройx = X; y = Y;//координата появления спрайта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;//по иксу задаем нулевое значение, по игреку положительное. получается, что персонаж идет только внизcase 3: 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()//соответственно У{return y;}void interactionWithMap()//функция взаимодействия с картой{for (int i = y / 32; i < (y + h) / 32; i++)//проходимся по тайликам, контактирующим с игроком, то есть по всем квадратикам размера 32*32, которые мы окрашивали в 9 уроке. про условия читайте ниже.for (int j = x / 32; j<(x + w) / 32; j++)//икс делим на 32, тем самым получаем левый квадратик, с которым персонаж соприкасается. (он ведь больше размера 32*32, поэтому может одновременно стоять на нескольких квадратах). А j<(x + w) / 32 - условие ограничения координат по иксу. то есть координата самого правого квадрата, который соприкасается с персонажем. таким образом идем в цикле слева направо по иксу, проходя по от левого квадрата (соприкасающегося с героем), до правого квадрата (соприкасающегося с героем){if (TileMap[i][j] == '0')//если наш квадратик соответствует символу 0 (стена), то проверяем "направление скорости" персонажа:{if (dy>0)//если мы шли вниз,{y = i * 32 - h;//то стопорим координату игрек персонажа. сначала получаем координату нашего квадратика на карте(стены) и затем вычитаем из высоты спрайта персонажа.}if (dy<0){y = i * 32 + 32;//аналогично с ходьбой вверх. dy<0, значит мы идем вверх (вспоминаем координаты паинта)}if (dx>0){x = j * 32 - w;//если идем вправо, то координата Х равна стена (символ 0) минус ширина персонажа}if (dx < 0){x = j * 32 + 32;//аналогично идем влево}}//if (TileMap[i][j] == 'a') { //если символ равен 's' (камень)// x = 150; y = 100;//какое то действие... например телепортация героя//TileMap[i][j] = ' ';//убираем камень, типа взяли бонус. можем и не убирать, кстати.}}};int main(){RenderWindow window(VideoMode(700,450), "game");view.reset(sf::FloatRect(0, 0, 640, 480));//размер "вида" камеры при создании объекта вида камеры. (потом можем менять как хотим) Что то типа инициализации/*создает обьект window - окно приложения.так же,после заголовка "game", можно задать различные параметры окна.например : Style::Fullscreen сделает окно развернутым во весь экран.*//*Image heroImage;//создаем обьект 'изображение'heroImage.loadFromFile("images/Human_HF1_Male_24.png");//загружаем изображение в обьект ImageTexture heroTexture; //создаем обьект 'текстура'heroTexture.loadFromImage(heroImage);//передаем в него обьект изображение.Sprite herosprite;//создаем обьект 'спрайт'herosprite.setTexture(heroTexture);//Передаем в него обьект текстураherosprite.setTextureRect(IntRect(0, 0, 70, 85));//таким образом выводим прямоугольникherosprite.setPosition(100, 100);//задаем спрайту начальную позицию// слово set переводится как "задавать"*/Player p("Human_HF1_Male_24.png", 200, 200, 70.0, 85.0);Image map_image;map_image.loadFromFile("images/map.png");Texture map;map.loadFromImage(map_image);Sprite s_map;s_map.setTexture(map);Clock clock;//создаем переменную времениfloat CurrentFrame = 0;//создаем переменную хранящую текущий кадрwhile (window.isOpen())// цикл с условием выполнения пока открыто окно.{float time = clock.getElapsedTime().asMicroseconds();//буквально переводится как "получить прошедшее время в миллисекундахclock.restart();//перезагружает времяtime = time / 800;//задаем скорость игры(можно сказать кол. кадров в сек.Event event;//событие,говорящее, что при его значении == Closed закрывается окно игры.while (window.pollEvent(event)){if (event.type == Event::Closed)window.close();}if (Keyboard::isKeyPressed(Keyboard::Left)){p.dir = 1; p.speed = 0.1;//dir =1 - направление вверх, speed =0.1 - скорость движения.время мы уже здесь ни на что не умножаем и нигде не используем каждый разCurrentFrame += 0.005*time; //служит для прохождения по "кадрам". переменная доходит до трех суммируя произведение времени и скорости. изменив 0.005 можно изменить скорость анимацииif (CurrentFrame > 3)//проходимся по кадрам с первого по третий включительно. если пришли к третьему кадру - откидываемся назад.{CurrentFrame -= 3;}p.sprite.setTextureRect(IntRect(70 * int(CurrentFrame), 85, 70, 85)); //проходимся по координатам Х. получается 70,85*2,70*3 и опять 70getPlayerCoordinateForView(p.getPlayerCoordinateX(), p.getPlayerCoordinateY());//функция слежения камеры за игроком}if ((Keyboard::isKeyPressed(Keyboard::Right))){p.dir = 0; p.speed = 0.1;CurrentFrame += 0.005*time;if (CurrentFrame > 3){CurrentFrame -= 3;}p.sprite.setTextureRect(IntRect(70 * int(CurrentFrame), 170, 70, 85));getPlayerCoordinateForView(p.getPlayerCoordinateX(), p.getPlayerCoordinateY());}if ((Keyboard::isKeyPressed(Keyboard::Up))){p.dir = 3; p.speed = 0.1;CurrentFrame += 0.005*time;if (CurrentFrame > 3){CurrentFrame -= 3;}p.sprite.setTextureRect(IntRect(70 * int(CurrentFrame), 255, 70, 85));getPlayerCoordinateForView(p.getPlayerCoordinateX(), p.getPlayerCoordinateY());}if ((Keyboard::isKeyPressed(Keyboard::Down))){p.dir = 2; p.speed = 0.1;CurrentFrame += 0.005*time;if (CurrentFrame > 3){CurrentFrame -= 3;}p.sprite.setTextureRect(IntRect(70 * int(CurrentFrame), 0, 70, 85));getPlayerCoordinateForView(p.getPlayerCoordinateX(), p.getPlayerCoordinateY());}p.update(time);viewmap(time);//функция скроллинга карты, передаем ей время sfmlwindow.setView(view);//"оживляем" камеру в окне sfmlchangeview();window.clear(Color(199, 167, 109));//очищает экран и поставили вместо черного фона за картой корочневыйfor (int i = 0; i < height_map; i++)for (int j = 0; j < width_map; j++){if (TileMap[i][j] == '0')s_map.setTextureRect(IntRect(63, 768, 32, 32));if (TileMap[i][j] == ' ')s_map.setTextureRect(IntRect(0, 480, 32, 32));if (TileMap[i][j] == 'a')s_map.setTextureRect(IntRect(65, 995, 32, 32));//256, 1088, 32, 32s_map.setPosition(i * 32, j * 32);window.draw(s_map);}window.draw(p.sprite);//рисует обьект.draw-рисоватьwindow.display();//выводит на экран}return 0;}C++12345678910111213141516171819202122232425262728293031323334#include<SFML\Graphics.hpp>const int height_map = 25;//размер карты-высотаconst int width_map = 40;//ширина картыsf::String TileMap[height_map] ={"0000000000000000000000000000000000000000","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 a 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0 0","0000000000000000000000000000000000000000",};Очевидно перепутал ширину с высотой.
я пытался поменять,но все начинает крашится
скрин ошибки
Вложения:
You must be logged in to view attached files.Это ошибка означает что вы пытаетесь получить доступ к несуществующему элементу массива.
сделай карту 10 на 10 для начала. мне кажется где то что то лишнее в размерности , либо не хватает.
Сделал. 10 на 10 то нормально, а вот делаю прямоугольник и все, стороны изменяются. попробовал поменять код таким образом карта отобразилась нормально, но теперь когда персонаж подходит к границе карты он отпрыгивает в середину. Что происходит? Код то, такой же как в уроках!
C++12345678for (int j = x / 32; j<(x + w) / 32; j++)for (int i = y / 32; i < (y + h) / 32; i++){...}может setOrigin установил где-то и не заметил ?
так же проверь ширину и высоту спрайта и тайликов самих. может они отличаются от размеров в уроке.
Dench, приветствую.
Обратите внимание на блок отрисовки карты. В нем переменная ‘i’ соответствует координате ‘y’ (“высоте” карты), а не ‘x’, в то время как ‘j’ – напротив – отвечает за ‘x’, а не за ‘y’. А именно:
C++12345678910for (int i = 0; i < height_map; i++)for (int j = 0; j < width_map; j++){if (TileMap[i][j] == '0')s_map.setTextureRect(IntRect(63, 768, 32, 32));if (TileMap[i][j] == ' ')s_map.setTextureRect(IntRect(0, 480, 32, 32));if (TileMap[i][j] == 'a')s_map.setTextureRect(IntRect(65, 995, 32, 32));//256, 1088, 32, 32// s_map.setPosition(i * 32, j * 32); - Ваш вариант...s_map.setPosition(j * 32, i * 32); // - правильный вариантwindow.draw(s_map);}мега-внимателен и проницателен))
Я просто аплодирую стоя) спасибо!
-
АвторСообщения
Для ответа в этой теме необходимо авторизоваться.