Форум программистов, компьютерный форум, киберфорум
SFML
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
0 / 0 / 0
Регистрация: 06.01.2020
Сообщений: 5

Движение по диагонали и присваивание оружию хозяина SFML

23.01.2020, 22:18. Показов 2252. Ответов 5

Студворк — интернет-сервис помощи студентам
Здравствуйте!
Пытаюсь написать простенький 2д шутер на sfml и решил усложнить себе задачу - написать движение не как в уроках на ютубе - вверхвнизвлевовправо, но еще и по диагонали. Сложность возникла только с в одной ситуации - когда ерсонаж попадает в угол карты (или просто угол комнаты/тоннеля). Много методов испробовал - не могу понять что не так (простите за грязный код).
Вторая проблема - привязка оружия. Мне кажется, было бы правильно привязывать конкретный объект оружия к хозяину, чтобы можно было спрайт оружия перемещать вместе с хозяином и легко его подбирать, но почему-то при передаче объекта ходяина в конструкторе (как по ссылке так и без нее) координаты хозяина оружия не меняются, хотя по факту он перемещается.


counter_x - предыдущая координата по X, y, соответствеено, Y.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
if ((counter_x == x) && (dx > 0)) {
            counter_x--;
        }
        else if ((counter_x == x) && (dx < 0)) {
            counter_x++;
        }
        else counter_x = x;
        if ((counter_y == y) && (dy > 0)) {
            counter_y--;
        }
        else if ((counter_y == y) && (dy < 0)) {
            counter_y++;
        }
        else counter_y = y;
функция поверки столкновения со стенами. (очень побитая, много часов с ней сидел, если честно, страшно трогать)
TileMap - двумерный массив, задающий карту (25 в вусоту, 40 в ширину), ширина персонажа - 32, высота - 64.
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
    void go_map(float counter_x, float counter_y) {
        for (int i = y / 32; i < (y + h + 32) / 32; i++) {
            for (int j = x / 32; j < (x + w - 32) / 32; j++) {
                if (TileMap[i][j] == '0') {
                    if ((dy > 0) && (dx == 0)) {
                        y = i * 32 - h - 32;
                    }
                    else
                        if ((dx > 0) && (dy == 0)) {
                            x = j * 32 - w + 32;
                        }
                        else if ((dy < 0) && (dx == 0)) {
                            y = i * 32 + 32;
                        }
                        else if ((dx < 0) && (dy == 0)) {
                            x = j * 32 + 32;
                        }
                        else
                            if ((dx > 0) && (dy < 0)) {
                                if (((counter_y / 32) > i) && ((counter_x / 32) > j)) {
                                    y = i * 32 + 32;
                                }
                                else if (((counter_y / 32) < i) && (counter_x / 32 < j)) {
                                    x = j * 32 - w + 32;
                                }
                            }
                            else if ((dx < 0) && (dy < 0)) {
                                if (((counter_y / 32) > i) && ((counter_x / 32) > j) && TileMap[i + 1][j] != '0') {
                                    y = i * 32 + 32;
                                }
                                else if (((counter_y / 32) > i) && ((counter_x / 32) > j)) {
                                    if (TileMap[i][j + 1] != '0') {
                                        x = j * 32 + 32;
                                    }
                                    else {
                                        y = i * 32 + 32;
                                        x = j * 32 + 32;
                                    }
                                }
                            }
                            else if ((dx < 0) && (dy > 0)) {
 
                                if (((counter_y / 32) < i) && ((counter_x / 32) > j) && TileMap[i][j + 1] != '0') {
                                    x = j * 32 + 32;
                                }
                                else if ((counter_x / 32 > j) && (counter_y / 32 < i)) {
                                    if (TileMap[i + 1][j] != '0' || TileMap[i - 1][j] != '0'/*&& TileMap[i + 2][j] != '0' && TileMap[i + 3][j] != '0' && TileMap[i][j] != '0'*/) {
                                        y = i * 32 - h - 32;
                                    }
                                    /*else {
                                        x = j * 32;
                                        y = i * 32 - h - 32;
                                    }
                                    */
                                }
 
                            }
                            else if ((dx > 0) && (dy > 0)) {
                                if ((counter_x / 32 < j) && (counter_y / 32 < i) && TileMap[i][j - 1] != '0') {
                                    x = j * 32 - w + 32;
                                }
                                else if ((counter_x / 32 < j) && (counter_y / 32 < i)) {
                                    y = i * 32 - h - 32;
                                }
                            }
                }
            }
        }
 
    }
А это попытка передать хозяина оружию
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Weapon(String F, float X, float Y, float W, float H, int dmg, int CD, Person ow) {
        File = F;
        image.loadFromFile("https://www.cyberforum.ru/images/" + File);
        image.createMaskFromColor(Color(255, 255, 255));
        texture.loadFromImage(image);
        sprite.setTexture(texture);
        x = X;
        y = Y;
        w = W;
        h = H;
        damage = dmg;
        cooldown = CD;
        owner = ow;
        //sprite.setTextureRect(IntRect(0, 0, w, h));
        sprite.setOrigin(w / 2, h / 2);
    }
и изменить координаты
C++
1
2
3
4
5
6
void update(float x, float y) {
        //std::cout << owner.Get_x() << " " << owner.Get_y() << std::endl;
        sprite.setPosition(x + 16, y + 40);
        //x = owner.Get_x() + 16;
        //y = owner.Get_y() + 40;
    }
Буду рад, если кто-нибудь смодет помочь
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.01.2020, 22:18
Ответы с готовыми решениями:

Игра на SFML. Как реализовать движение по диагонали?
Всем привет. Пишу мелкую игрушку с видом сверху исключительно для самообразования. Застрял почти сразу на моменте управления. Жмем влево...

SFML движение фигуры
Почему неработает? не двигается фигура при нажатии. #include &lt;SFML/Graphics.hpp&gt; using namespace sf; const int orX = 100; ...

Движение тела в SFML
Здравствуйте! Пишу программу на с++ (Code::Blocks 16.01). По заданию следует написать приложение: В графическом окне размещается тело (я...

5
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
23.01.2020, 23:27
Цитата Сообщение от Bobr_JS Посмотреть сообщение
функция поверки столкновения со стенами. (очень побитая, много часов с ней сидел, если честно, страшно трогать)
А мне смотреть на неё страшно . Смотри, в SFML есть встроеная функция для проверки попадания точки внутрь прямоугольника. Персонаж - прямоугольник, тайл - прямоугольник, и вся карта - прямоугольник. Пользуйся.
Цитата Сообщение от Bobr_JS Посмотреть сообщение
А это попытка передать хозяина оружию
Оружие командует персонажем? Кто хозяин то?(шутка) Ну и передать это одно, надо как то взаимодействовать, например при отрисовке оружия отталкиваться от координат хозяина

Добавлено через 3 минуты
Цитата Сообщение от zayats80888 Посмотреть сообщение
функция для проверки попадания точки внутрь прямоугольника
Там есть метод, проверяющий пересечение прямугольников
0
0 / 0 / 0
Регистрация: 06.01.2020
Сообщений: 5
24.01.2020, 12:55  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
Персонаж - прямоугольник, тайл - прямоугольник, и вся карта - прямоугольник. Пользуйся.
с этим есть проблема - карта отрисовывается вот таким образом ('0' - стены)
C++
1
2
3
4
5
6
7
8
9
10
11
12
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] == '0')  s_map.setTextureRect(IntRect(32, 0, 32, 32));
                if ((TileMap[i][j] == 's')) s_map.setTextureRect(IntRect(64, 0, 32, 32));
                
 
                s_map.setPosition(j * 32, i * 32);
 
                window.draw(s_map);
            }
я так понимаю, что чтобы метод intersects работал, нужно будет сделать так, чтобы в нулях у нас появлялся спрайт, потому что сейчас это просто отрисованная в разных местах текстура одного страйта. и, на самом деле, вопрос в том, как с точностью отличать 3 возможных варианта событий при движении по диагонали (например, если движение идет вверх и влево, то можно попасть в угол, начать ползти по левой стене или по верхней стене). в случае с intersects(), я так понимаю, придется в цикле проверять пересечение с каждым из спрайтов стен... а положение относительно стены можно будет проверять разностью координат? но если сделать спрайты стен квадратными (у меня стены состоят из 32*32 кусков изображения), то спрайт героя будет одновременно с двумя спрайтами стен пересекаться(герой 32*64) и будет путанница...
Цитата Сообщение от zayats80888 Посмотреть сообщение
например при отрисовке оружия отталкиваться от координат хозяина
прикрепил сдучайно тестовый код)
C++
1
2
3
4
void update() {
        //std::cout << owner.Get_x() << " " << owner.Get_y() << std::endl;
        sprite.setPosition(owner.Get_x() + 16, owner.Get_y() + 40);
    }
при таком коде (т.е. как раз когда по идее спрайт оружия должен перемещаться вслед за координатами хозяина) также оружие остается на месте. когда вывожу координаты хозяина оружия (закомменченый код) выводится одно и то же, хотя хозяин перемещается.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
24.01.2020, 13:04
Цитата Сообщение от Bobr_JS Посмотреть сообщение
с этим есть проблема
Прмимтивный пример:
Кликните здесь для просмотра всего текста
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
class Map :public sf::Drawable
{
public:
    int check_collision(const sf::FloatRect& bounds) const
    {
        for (size_t i{}; i < arr_size; ++i)
        {
            for (size_t j{}; j < arr_size; ++j)
            {
                if (arr[i][j] && sf::FloatRect{ j*tile_size, i*tile_size, tile_size ,tile_size }.intersects(bounds))
                {
                    return true;
                }
            }
        }
        sf::FloatRect ir;
        return (m_bounds.intersects(bounds, ir) && ir != bounds);
    }
private:
    void draw(sf::RenderTarget& target, sf::RenderStates states) const override
    {
        for (size_t i{}; i < arr_size; ++i)
        {
            for (size_t j{}; j < arr_size; ++j)
            {
                if (arr[i][j])
                {
                    tile.setPosition(j*tile_size, i*tile_size);
                    target.draw(tile, states);
                }
            }
        }
    }
    static constexpr float tile_size = 64.;
    static constexpr size_t arr_size = 10;
    char arr[arr_size][arr_size] =
    {
        0,0,0,0,0,0,0,0,0,0,
        0,0,1,1,0,0,0,0,1,0,
        0,0,1,0,0,0,0,0,1,0,
        0,0,1,0,1,0,0,0,1,0,
        0,0,1,0,1,1,1,0,1,0,
        0,1,1,0,0,0,1,0,1,0,
        0,0,0,0,1,1,1,0,1,0,
        0,0,0,0,0,0,0,0,0,0,
        0,0,1,1,1,0,0,0,0,0,
        0,0,1,1,1,0,0,0,0,1
    };
    mutable sf::RectangleShape tile{ sf::Vector2f(tile_size, tile_size) };
    sf::FloatRect m_bounds{ 0.f,0.f, arr_size * tile_size, arr_size * tile_size };
};
class Player :public sf::Drawable
{
public:
    Player(const sf::Vector2f& size, Map* m) :img(size), tile_map(m) { img.setFillColor(sf::Color::Green); }
    void set_position(const sf::Vector2f& pos)
    {
        img.setPosition(pos);
    }
    void update(float dt)
    {
        sf::Vector2f direction;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::W))
            direction.y -= 1.f;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::A))
            direction.x -= 1.f;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::S))
            direction.y += 1.f;
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key::D))
            direction.x += 1.f;
        auto ds = direction * m_speed * dt;
        if(!tile_map->check_collision(sf::Transform{}.translate(ds).transformRect(img.getGlobalBounds())))
            img.move(ds);
    }
private:
    void draw(sf::RenderTarget& target, sf::RenderStates states) const override
    {
        target.draw(img, states);
    }
 
    sf::RectangleShape img;
    float m_speed = 100;
    const Map* tile_map;
};
 
int main()
{
    sf::RenderWindow window(sf::VideoMode(640, 640), "test", sf::Style::Close);
    
    sf::Clock clock;
    Map m;
    Player p(sf::Vector2f(32.f, 32.f), &m);
    p.set_position(sf::Vector2f(10.f, 10.f));
    while (window.isOpen()) {
        sf::Event e;
        while (window.pollEvent(e)) if (e.type == sf::Event::Closed) window.close();
 
        window.clear();
 
        p.update(clock.restart().asSeconds());
        window.draw(m);
        window.draw(p);
 
        window.display();
 
    }
    return 0;
}

Цитата Сообщение от Bobr_JS Посмотреть сообщение
когда вывожу координаты хозяина оружия (закомменченый код) выводится одно и то же, хотя хозяин перемещается
Цитата Сообщение от Bobr_JS Посмотреть сообщение
owner
должен быть ссылкой(указателем) на объект, а не копией
0
0 / 0 / 0
Регистрация: 06.01.2020
Сообщений: 5
24.01.2020, 14:18  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
Прмимтивный пример:
и правда более красивый вариант создания карты
но я, похоже, не совсем правильно описал чего пытаюсь обиться
цель в том, чтобы когда персонаж движется по диагонали и сталкивается со стеной, он продолжал движение и "полз" по стене
а для этого нужно точно знать, с какой стороны персонаж подходит к стене, при движении по диагонали влево и вверх он может подойти снизу к верхней стене, справа к левой стене, или доползти по одной из стен до угла, где он должен остановиться

Цитата Сообщение от zayats80888 Посмотреть сообщение
должен быть ссылкой(указателем) на объект, а не копией
да, но даже если передаю через указатель - ничего не меняется
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Weapon(String F, float X, float Y, float W, float H, int dmg, int CD, Person &ow) {
        File = F;
        image.loadFromFile("images/" + File);
        image.createMaskFromColor(Color(255, 255, 255));
        texture.loadFromImage(image);
        sprite.setTexture(texture);
        x = X;
        y = Y;
        w = W;
        h = H;
        damage = dmg;
        cooldown = CD;
        owner = ow;
        //sprite.setTextureRect(IntRect(0, 0, w, h));
        sprite.setOrigin(w / 2, h / 2);
    }
возможно это связано с тем, что передаю я объект класса player, являющийся наследником от person...
или с тем, что память для объектов выделяю динамически...
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
24.01.2020, 14:30
Цитата Сообщение от Bobr_JS Посмотреть сообщение
цель в том, чтобы когда персонаж движется по диагонали и сталкивается со стеной, он продолжал движение и "полз" по стене
тогда можно ввести понятие "свобода движения" и в проверке коллизий ограничивать одну из "свобод"
Цитата Сообщение от Bobr_JS Посмотреть сообщение
да, но даже если передаю через указатель - ничего не меняется
само поле owner должно быть указателем, как в моем примере tile_map в классе Player
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.01.2020, 14:30
Помогаю со студенческими работами здесь

Sfml движение по синусоиде
Ребят туплю как сделать , смотрите вот код , там круг двигается по синусоиде а можете пожалуйста помочь сделать так чтобы вместо круга был...

Движение машины в SFML
Здравствуйте! Нужна помощь в SFML - сделал двигающийся авто, но есть вопрос: Как сделать повороты с помощью передней оси, а не просто...

SFML движение под углом
Здравствуйте. Имеется шарик и платформа, шарик перемещается командой ball.move(x,y), x и y это количество пикселей на которое переместится...

Движение спрайта по синусоиде sfml
Ребят такая тема , как сделать так чтоб спрайт двигался по синусоиде помогите пожалуйста Вот код который написал но уже 5 часов не могу...

Очень быстрое движение фигуры sfml
У меня есть фигура(квадрат для примера): VertexArray quad(LinesStrip, 5); quad.position = Vector2f(0, 0); quad.position =...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru