Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Как через библиотеку SFML реализовать управление персонажем с помощью мышки

Как через библиотеку SFML реализовать управление персонажем с помощью мышки

Поделиться

Страницы: 1 2 Следующая

Azazel-SanПользовательwww7 сен. 201722:27#0
Можете подсказать как реализовать управление персонажем с помощью мышки, как в Action/RPG играх типо Diablo, когда зажав ПКМ и меняя лишь вектор направления курсора, меняются и спрайты, т.е. когда персонаж бежит за курсором. Никак не могу понять как это сделать, можете подсказать?
eugenelozaПостоялецwww8 сен. 20178:05#1
Что-то ничего не понял... это вопрос по библиотеке SFML, по управлению персонажем с помощью мыши или по управлению спрайтами?
Берёте motion мыши, проверяете, зажата ли клавиша.
Если клавиша зажата - направление движения = в точку, где сейчас мышь.
Выполнить движение и подставить/отрисовать соответствующий спрайт в зависимости направления движения.
Псевдокод:
M := ScreenToMapPosition(Mouse.Position);
If Mouse.RightKeyPress then Player.MoveTo(M);
Draw(MapPositionToScreen(Player.Position),Sprite[Player.Direction]);

Правка: 8 сен. 2017 8:05

Azazel-SanПользовательwww8 сен. 20179:44#2
eugeneloza
> это вопрос по библиотеке SFML, по управлению персонажем с помощью мыши или по
> управлению спрайтами?
Извиняюсь, если не так высловился, имелось ввиду, "Как через библиотеку SFML реализовать управление персонажем с помощью мышки".

eugeneloza
> Выполнить движение и подставить/отрисовать соответствующий спрайт в зависимости
> направления движения.
Вот это я какраз и не понимаю как реализовать, по вашему коду вроде понятно, но хотелось бы заглянуть внутрь ваших ф-й ( типо MoveTo/ScreenToMapPosition/MapPositionToScreen ) и посмотреть как это работает. Как дать понять что если курсор справа, надо рисовать спрайты "двигаться направо", а если снизу, то вниз? Или я не так понимаю как это работает?

З.Ы. - пишу на С++
ВасянУчастникwww8 сен. 20179:51#3
Azazel-San
Предлагаю NWE Game Maker (серьёзно)
Azazel-SanПользовательwww8 сен. 20179:54#4
Васян
> Предлагаю NWE Game Maker (серьёзно)
Нет, спасибо, не надо предлагать.
ВасянУчастникwww8 сен. 201710:37#5
Azazel-San
> З.Ы. - пишу на С++
Тогда предлагаю посмотреть исходники диабло-подобных игр на С++.
Ну либо взять игровой движок на С++, если тебя тошнит от ГМ.

Если же ты не хочешь игровые движки, а хочешь всё реализовывать руками, то что ты здесь делаешь с вопросами по реализации простейших штук?

eugenelozaПостоялецwww8 сен. 201710:52#6
Azazel-San
> но хотелось бы заглянуть внутрь ваших ф-й
Как предложил Васян, Вы такие функции найдёте в любой игре. Именно дьябло-подобную я не делал, по этому "моих" функций таких нет.

Но "штука" действительно простая.

ScreenToMapPosition преобразовывает координаты курсора (координаты на экране) в точку на карте, MapPositionToScreen - наоборот. В top-down варианте без скроллинга это будет просто

map_x := cursor_x / tileSize;
map_y := cursor_y / tileSize;
Естественно, в изометрии со скроллингом это несколько усложняется. И это за Вас никто не сделает :) По крайней мере бесплатно :) Впрочем, всё уже сделано до Вас и даже на этом форуме где-то было несколько тем как удобнее всё это преобразовывать. Гугль знает.

С MoveTo сложнее. В простейшем варианте это что-то типа:

Dir_x := Math.sign(target_x - actor_x/0;
Dir_y := Math.sign(target_y - actor_y);
Direction := Vector2(Dir_x,Dir_y); // определяет тот спрайт, который нужен
//и собственно, перемещение:
actor_x += Dir_x;
actor_y += Dir_y;

Хотя, в общем, согласен с Васяном, возможно Вам действительно стоит задуматься о выборе движка. Может, не Game Maker, но хотя бы Urho / Unity / UE. Там проще "начать", поскольку большую часть подобных вещей движок будет делать за Вас.
П.С. Возможно, уже SFML и является таким полу-движком. Я с ней не работал.

Правка: 8 сен. 2017 10:53

ВасянУчастникwww8 сен. 201710:57#7
Вот тебе ещё псевдокод (да, реализация движения к цели гавно. Конфетку сам сделаешь).

cameraX, cameraY - координаты верхнего левого угла экрана относительно верхнего левого угла карты.

void ScreenToMapPosition(int screenX, int screenY, int *mapX, int *mapY)
{
  *mapX = screenX + cameraX;
  *mapY = screenY + cameraY;
}

void MapPositionToScreen(int mapX, int mapY, int *screenX, int *screenY)
{
  *screenX = mapX - cameraX;
  *screenY = mapY - cameraY;
}

void MoveTo(int x, int y)
{
  playerTargetX = x;
  playerTargetY = y;
}

void Step(void)
{
  playerX += sign(playerTargetX - playerX) * playerHspeed;
  playerY += sign(playerTargetY - playerY) * playerVspeed;
}

Правка: 8 сен. 2017 10:58

Azazel-SanПользовательwww8 сен. 201716:40#8
Васян , eugeneloza
сделал вот как: создал enum для позначения сторон типо:
enum look
{
    right, left, down, up, downright, upright, upleft, downleft
};
функцию sign для возвращения значение знака переменной:
template <class Value>
int sign(Value Val)
{
    if (Val == 0.)  return 0;
    if (Val >  0.)  return 1;
    else return -1;
}
затем ф-ю, для обозначения куда нам двигаться
look lookAtMouse(int x, int y)
{
    if (x == 1 && y == 1)
    {
        return look::downright;
    }
    if (x == 1 && y == -1)
    {
        return look::upright;
    }
    if (x == -1 && y == -1)
    {
        return look::upleft;
    }
    if (x == -1 && y == 1)
    {
        return look::downleft;
    }
}
ну и собственно потом проверял if (lookAtMouse(dir_x, dir_y) == look::downright) в какую сторону бежать, НО есть ещё 1 проблема, как двигаться ровно по осям? для того чтобы бежать ровно вправо нам нужно бежать по оси X(0;+бесконечности), а у меня получается я проверяю относительно четвертей координат, т.к. для того чтобы двигаться вверх-вправо (я проверяю по 1/-1, т.е. первая чверть).

Правка: 8 сен. 2017 16:40

ВасянУчастникwww8 сен. 201717:26#9
Azazel-San
dir_x и dir_y - это с выхода функции sign? Если нет, то где у тебя используется sign? Если да, то в lookAtMouse не хватает проверок координат на 0.
Я в этом вашем сиплюсплюсе с шаблонами не разбираюсь, но вот это ты здесь сравниваешь числа с плавающей точкой?
> Val == 0.
Если да, то предлагаю так не делать и вместо самописного sign использовать sign из стандартной библиотеки (если есть)

Правка: 8 сен. 2017 17:27

Azazel-SanПользовательwww8 сен. 201717:33#10
Васян
> dir_x и dir_y - это с выхода функции sign?
Vector2f totalMovement;
totalMovement.x = Mouse::getPosition(window).x - hero_sprite.getPosition().x;
totalMovement.y = Mouse::getPosition(window).y - hero_sprite.getPosition().y;

int dir_x = sign(totalMovement.x); // sign()
int dir_y = sign(totalMovement.y); // sign()
Васян
> Если да, то в lookAtMouse не хватает проверок координат на 0.
точно, сейчас посмотрю
Васян
> вместо самописного sign использовать sign из стандартной библиотеки (если
> есть)
нету
ВасянУчастникwww8 сен. 201717:45#11
Azazel-San
> нету
Да, короче, забей. Я не до конца понимаю эти ваши шаблоны. Щас насоветую чего попало.
Я про вот это подумал:
https://ru.stackoverflow.com/questions/399420/%D0%91%D0%B5%D0%B7%… %D0%B0-double
Azazel-SanПользовательwww8 сен. 201718:30#12
Васян
> Да, короче, забей.
ну вообщем, я сделал.. но всеравно, на деле попасть в промежуток 1 0 / 0 1 или тому подобный, очень сложно (практически никогда не получается)
только если запускать отдельную ф-ю, к примеру только для движения вверх и специально искать 0 -1

Правка: 8 сен. 2017 18:37

ВасянУчастникwww8 сен. 201718:50#13
Azazel-San
Выбрасываем этот код
> look lookAtMouse(int x, int y)
> {
> if (x == 1 && y == 1)
> {
> return look::downright;
> }
> if (x == 1 && y == -1)
> {
> return look::upright;
> }
> if (x == -1 && y == -1)
> {
> return look::upleft;
> }
> if (x == -1 && y == 1)
> {
> return look::downleft;
> }
> }
Пишем функцию, которая будет возвращать направление от игрока до курсора. В зависимости от того, в какой из промежутков попадает направление (допустим 360 градусов поделено на 8 промежутков по 45 градусов), такую анимацию и проигрываем.
Щас, поищу, у меня что-то подобное было.
ВасянУчастникwww8 сен. 201719:06#14
#define MTR_2PI_F 6.283185307179586f
#define MTR_RADIAN_F 57.295779513082320876798154814105f

float mtrAngle_f(float x, float y)
{
    float dir;

    dir = acosf(x / sqrtf(powf(-x, 2.0f) + powf(-y, 2.0f)));
    if (y > 0.0f)
        dir = MTR_2PI_F - dir;

    return dir * MTR_RADIAN_F;
}

Я не помню, рабочий это код, или нет.
Использовать примерно так:
playerX, playerY - координаты игрока на карте.
mouseX, mouseY - координаты курсора мыши на карте
Угол 0 градусов должен указывать на 3 часа. Увеличение против часовой стрелки. В общем, как у нас в школе на математике было.

direction = mtrAngle_f(mouseX - playerX, mouseY - playerY)
if (direction > 337.5f && direction <= 0.0f) || (direction > 0f && direction <= 22.5f) {
  playerLook = look::right;
} else if (direction > 22.5f && direction <= 67.5f) {
  playerLook = look::upright;
} else if ...
...

Update:
Если mtrAngle_f будет возвращать значения в диапазоне отличном от 0..360 (я опять же не помню, как оно работает. Откудато скопипастил и подправил. С математикой не особо дружу), то использовать вот так:
direction = mtrAngle_f(mouseX - playerX, mouseY - playerY);
direction = fmodf(direction + 360, 360);

Правка: 8 сен. 2017 19:32

Страницы: 1 2 Следующая

/ Форум / Программирование игр / 2D графика и изометрия

2001—2017 © GameDev.ru — Разработка игр