Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.94/48: Рейтинг темы: голосов - 48, средняя оценка - 4.94
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1

Как остановить поток std::thread ? Есть ли более подходящие аналоги?

19.07.2022, 11:02. Показов 12668. Ответов 45
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Итак, в моей игре код разделён на два потока, основной - рендеринг и прочее, второй - расчёт физики.

C++
1
2
3
void qqq() {
    while (true) { ... } //просчитывается физика
}
Но как остановить этот поток, чтобы запустить заново (когда это будет нужно)? Мне нужно, чтобы функция потока немедленно прекратила своё выполнение. Почему? Потому что вот фрагмент кода из этой функции qqq():
C++
1
2
3
for (i = 0; i < map_basic.size(); i++) {
    map_basic[i]->cycle();
}
Вектор, в котором хранятся все блоки карты,
C++
1
vector <Block*> map_basic;
, по закрытию уровня очистится. Из-за продолжения выполнения потока происходит ошибка и игра вылетает.

Вот фрагменты самого кода
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
//один из циклов игры. (сама игра, а не редактор, меню или прочее)
//после return, если mose == "game", функция вызовется заново
void test_game() {
 
       //очистка карты
 
    map_basic.clear();
    map_floor.clear();
    movables.clear();
    electric.clear();
 
        //пропустил постройку карты заново, ибо много кода. В ней багов нет
 
    std::thread physics(qqq);
 
    physics.detach();
 
    while (mode == "game") {
                //момент, в который нужно остановить игру
            if (Keyboard::isKeyPressed(Keyboard::Tab)) {
        onclick = true; 
        build(lvlnum); 
        //тут надо остановить поток физики, но как?
        return;
            }
        }
Итак, мне нужен способ задания потока, функция для его остановки и, разумеется, запуска. Уже вычитал, что std::thread не остановить, но нормального объяснения и аналогий так и не нашёл. Заранее спасибо
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.07.2022, 11:02
Ответы с готовыми решениями:

Почему при Thread.Abort закрывается программа? Как остановить поток?
Есть класс для инвертирования движения мыши. При вызове метода Stop программа продолжает работать. При применении Abort прога закрывается....

Std::thread как усыпить/ пробудить поток?
Есть ли в std::thread возможность как - то приостановить поток, не разрушая его, а потом, по какому - то сигналу / прерыванию - возобновить...

Как удалить зависший std::thread::detach поток без внедрения туда дополнительной контролирующей логики
Здравствуйте, имеет ли кто-то ссылочку на какой-нибудь ресурс где случайно окажется возможным для скачивания файл с книгой &quot;Энтони...

45
Just Do It!
 Аватар для XLAT
4221 / 2687 / 656
Регистрация: 23.09.2014
Сообщений: 9,246
Записей в блоге: 3
19.07.2022, 21:55
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Не по теме:
да. не по теме.
0
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1
20.07.2022, 10:13  [ТС]
К сожалению, ещё нет. Сейчас буду гуглить

Добавлено через 2 часа 19 минут
Итак, вот решение проблемы:
Данный поток нужно запускать с самого начала выполнения программы (с main()), и не трогать его вообще. Поскольку данный поток представляет из себя цикл, теперь его код выглядит так
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
void physics_processing() {
 
    while (true) {
 
        while (stop_physics || context_menu) { Sleep(2); } //Приостанавливаем, когда надо
 
        player_processing();
 
        for (i = 0; i < map_floor.size(); i++) { ... }
 
        for (i = 0; i < electric.size(); i++) {
            electric[i]->cycle();
        }
 
        for (i = 0; i < map_basic.size(); i++) {
            map_basic[i]->cycle();
        }
 
        for (i = 0; i < movables.size(); i++) { };
 
        Sleep(1);
 
    }
 
}
Решение хоть и на костылях, но рабочее. (Ошибка, кстати, была не в синхронизации, а в том, что физика по инерции могла начать высчитывать уже несуществующий объект, потому нужно просто дождаться её выполнения и приостановить на момент перестройки карты)
Механизм заморозки:
C++
1
2
stop_physics = true;
Sleep(100);
Разморозки
C++
1
stop_physics = false;
Всем спасибо за помощь!

Добавлено через 2 минуты
Ошибка точно не в синхронизации потому что физика читает и изменяет, а рендер только читает. Они физически, простите за каламбур, не могли конфликтовать, да и баги были бы только в отрисовке
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
20.07.2022, 10:30
Цитата Сообщение от tankoman228 Посмотреть сообщение
Ошибка, кстати, была не в синхронизации, а в том, что физика по инерции могла начать высчитывать уже несуществующий объект, потому нужно просто дождаться её выполнения и приостановить на момент перестройки карты)
Вы о чем это вообще?? Это и есть синхронизация. В данном случае через Sleep.
0
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1
20.07.2022, 10:46  [ТС]
Походу, я не до конца разобрался.
То есть, если ошибка возникает в результате использования и изменения одних и тех же объектов разными потоками, то это в любом случае связано с синхронизацией? Просто в той статье был пример чисто на int'ах, когда при попытке увеличить одну переменную двумя потоками, оба потока считывали неизменённое значение, потому могло получиться и 1, и 2.
0
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
20.07.2022, 10:55
Цитата Сообщение от tankoman228 Посмотреть сообщение
То есть, если ошибка возникает в результате использования и изменения одних и тех же объектов разными потоками, то это в любом случае связано с синхронизацией? Просто в той статье был пример чисто на int'ах, когда при попытке увеличить одну переменную двумя потоками, оба потока считывали неизменённое значение, потому могло получиться и 1, и 2.
Для начала вдумайтесь в само слово "синхронизация". Что оно означает?
0
 Аватар для lemegeton
4904 / 2697 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
20.07.2022, 12:40
Цитата Сообщение от tankoman228 Посмотреть сообщение
void physics_processing() {
while (true) {
Не делайте так. Хотя бы условный выход сделайте.

Цитата Сообщение от tankoman228 Посмотреть сообщение
Данный поток нужно запускать с самого начала выполнения программы (с main()), и не трогать его вообще.
Так не выйдет. Представьте себе, что вы прорисовали состояние игры когда физика отработала частично.

Вам нужно синхронизировать ваши процессы.

Добавлено через 22 минуты
Вообще, если вы не пишете что-то очень тяжелое типа 3д шутера, вам бы не лезть пока в потоки.
Запутаетесь, угрохаете тонну времени, результата не увидите и разочаруетесь. )
Забейте пока, пишите в один поток.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
20.07.2022, 13:15
Цитата Сообщение от lemegeton Посмотреть сообщение
Забейте пока, пишите в один поток.
Многие игры (включая Real-time) так были написаны
0
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1
20.07.2022, 13:38  [ТС]
Эта простейшая 2д головоломка, в которой из движущихся частей только особые блоки, да сам игрок. Мб. особые частицы, но их пока не добавил. Максимум, насколько такой рендер ошибётся, так это на 2 пикселя

Добавлено через 4 минуты
Сразу извиняюсь за качество, видеокарта сдохла. Без OBS графика отличная. Знаете ли, такой профан, как я, вряд-ли будет писать какой-то сложный 3д шутер

Добавлено через 1 минуту
https://youtu.be/wbHTAwgMguk
Никаких лагов, никаких видимых ошибок рендера

Добавлено через 4 минуты
Прикол в том, что физика прорабатывается быстрее рендера. На самой карте, даже на одном из сложнейших уровней, одновременно двигается не более 4 объектов. И то со скоростью чуть быстрее черепахи. Не думаю, что ряд [1,1,1,2,2,2...] сильно отличается от [1,1,1,1,2,2...]. Тут всё весьма медлительное
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,419
20.07.2022, 13:39
tankoman228, для такой игры не нужна многопоточность )
0
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1
20.07.2022, 13:46  [ТС]
https://youtu.be/FX6ZpVABbDk
Сорян, не ту ссылку кинул! Да и игра у меня частично испытательный полигон. Просто захотел разобраться, потому как на одном из калькуляторов альфа-тестеров оно умудрилось залагать, надо же учиться оптимизации
0
 Аватар для lemegeton
4904 / 2697 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
20.07.2022, 21:30
Цитата Сообщение от tankoman228 Посмотреть сообщение
Прикол в том, что физика прорабатывается быстрее рендера.
Вам же всё равно надо дождаться, когда физика проработает и только потом рендерить. Иначе будут артефакты.
Вообще, пока не упрётесь в производительность -- забейте на потоки. Единственное, подо что можно сделать отдельный поток это звук. И то спорненько.

Попробуйте сделать упор на качество кода. Посмотрите самый популярный паттерн ECS - Entity Component System.

Это даст вам гораздо больше возможностей в виде более гибкого кода, чем мультитрединг дал бы производительности.

Добавлено через 19 секунд
Цитата Сообщение от tankoman228 Посмотреть сообщение
https://youtu.be/FX6ZpVABbDk
Если это ваш код, то это круто!
0
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1
21.07.2022, 07:58  [ТС]
Это лишь малая его часть) Хотя самым сложным были блоки гравитации и провода с электричеством, всё равно ушло немало времени.
Про отдельный поток для звука: оно уже реализовано в самой графической библиотеке (SFML), так что над этим почти не парюсь. Недавно начал переписывать весь код, а то даже блоки были реализованы не через полиморфизм, а через банальный массив, цикл for и switch.
Что касается физики, она там максимально примитивная (в противном случае это либо неиграбельно, либо очень странно дёргается). Координаты объекта меняются в одно действие, а вот куда и насколько - высчитывается через вспомогательные переменные. Тут в любом случае максимальная ошибка - задержка позиции в один тик.
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
//AABB-alike physics model
struct Sq {
 
    float x = 100, y = 100; float sx = 0, sy = 0;
    float ax = 0, bx = 200, ay = 0, by = 200; //AABB
    float size = 62;
    float mass = 2; //not used, but don't delete
    float repulsion = 0; //this is how much the object is repulsed from the other. (0 is immovable)
    float max_speed = 6;
 
    void move() {
 
        x += sx;
        y += sy;
 
        ax = x - size;
        ay = y - size;
 
        bx = x + size;
        by = y + size;
 
        sx *= 0.90;
        sy *= 0.90;
 
        if (sx > max_speed) { sx = max_speed; } if (sx < -max_speed) { sx = -max_speed; }
        if (sy > max_speed) { sy = max_speed; } if (sy < -max_speed) { sy = -max_speed; }
 
        if (abs(sx) < 0.1) { sx = 0; } if (abs(sy) < 0.1) { sy = 0; }
 
    }
 
    void init_AABB() {
        ax = x - size;
        ay = y - size;
 
        bx = x + size;
        by = y + size;
    }
 
    void move(int x_, int y_) {
        x += x_; y += y_;
        init_AABB();
    }
 
    Sq() { sx = 0; sy = 0; }
    Sq(int _x, int _y, int _size) {
        //player spawn
 
        sx = 0; sy = 0;
 
        repulsion = 2;
        max_speed = 3;
        x = _x;
        y = _y;
        size = _size;
        init_AABB();
    }
 
};
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
//in case of intersection collision processing
bool collide(Sq& a, Sq& b) {
 
    if (a.bx < b.ax || a.ax > b.bx || a.ay > b.by || a.by < b.ay) { return false; }
 
    helper_s[0] = (a.x - b.x);
    helper_s[1] = (a.y - b.y);
 
 
    if (abs(helper_s[0]) > abs(helper_s[1])) {
 
        if (helper_s[0] > 0) {
            a.x += a.repulsion;
            b.x -= b.repulsion;
        }
        else {
            a.x -= a.repulsion;
            b.x += b.repulsion;
        }
 
    }
    else {
 
        if (helper_s[1] > 0) {
            a.y += a.repulsion;
            b.y -= b.repulsion;
        }
        else {
            a.y -= a.repulsion;
            b.y += b.repulsion;
        }
 
    }
 
    a.init_AABB();
    b.init_AABB();
 
    return true;
 
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct Block : public Sq {
 
    Sprite box;
    int id, rotation; float magnet = 0.2;
    short layer = 0;
 
    void update_scrolling() {
        box.setScale(scale, scale);
        box.setPosition(scale * (x - scrollx), scale * (y - scrolly));
    }
 
    //очень много неинтересного кода
 
    virtual void render() { update_scrolling(); window.draw(box); } //ВОТ ТАК ВЫГЛЯДИТ РЕНДЕР
        //P.S virtual, так как у некоторых типов блоков функция рендера содержит анимации
 
        //Бла-бла-бла
 
};
Делаю чисто для себя, потому на такую погрешность уж точно внимания обращать не буду. В любом случае, в колледже перепроходить будем, курсе так на 2-3
0
 Аватар для lemegeton
4904 / 2697 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
21.07.2022, 19:23
Цитата Сообщение от tankoman228 Посмотреть сообщение
(SFML)
В SFML так же реализована система коллизий и шейпы.

Цитата Сообщение от tankoman228 Посмотреть сообщение
Недавно начал переписывать весь код, а то даже блоки были реализованы не через полиморфизм, а через банальный массив, цикл for и switch.
Сейчас скажу внезапно, но этот подход в геймдеве устарел.
Популярность приобретает Data-Driven Design, в котором наследование, в общем-то, не нужно.

Наследование в принципе применять надо крайне осторожно. Только в крайних случаях.
Предпочитайте аггрегацию наследованию.

Цитата Сообщение от tankoman228 Посмотреть сообщение
virtual void render() { update_scrolling(); window.draw(box); } //ВОТ ТАК ВЫГЛЯДИТ РЕНДЕР
        //P.S virtual, так как у некоторых типов блоков функция рендера содержит анимации
Вам бы выделить весь рендер в отдельную сущность и отвязать её от сущностей акторов.
А как у вас выглядит основной цикл?


Еще раз скажу. Посмотрите на паттерн ECS - Entity Component System. Очень хорошая штука.
1
Just Do It!
 Аватар для XLAT
4221 / 2687 / 656
Регистрация: 23.09.2014
Сообщений: 9,246
Записей в блоге: 3
21.07.2022, 20:28
Цитата Сообщение от lemegeton Посмотреть сообщение
Data-Driven Design
спрайт загружающий в себя текстуру во время инициализации это оно?
0
 Аватар для lemegeton
4904 / 2697 / 921
Регистрация: 29.11.2010
Сообщений: 5,783
21.07.2022, 22:57
Пардон, это называется не Data Driven Design, a Data Oriented Design.

Это такая довольно старая концепция, когда дизайнят опираясь на процессинг данных в конкретном окружении (платформе), как в противоположность ориентации на бизнес-модели.

Самый пример это паттерн ECS, когда отходят от сущностей типа Игрок, Блоки, Противники и оперируют сущностями типа Координаты, Скорость, Физика, Спрайты.

Что позволяет существенно улучшить кэш-мисы на большинстве современных архитектур и сделать систему значительно более гибкой при изменениях.
1
Just Do It!
 Аватар для XLAT
4221 / 2687 / 656
Регистрация: 23.09.2014
Сообщений: 9,246
Записей в блоге: 3
21.07.2022, 23:19
Цитата Сообщение от lemegeton Посмотреть сообщение
Самый пример это паттерн ECS
ECS на ООП построен.
можно и сверху его в ООП завернуть.

про data-driven design тут я почитал.
ничего особенного, выглядит просто, как конфиг.

ну, и ваще ООП это парадигма, а data-driven design это приём или подход в рамках ООП'а.

ладно, спасибо, я понял.
0
Неэпический
 Аватар для Croessmah
18150 / 10732 / 2067
Регистрация: 27.09.2012
Сообщений: 27,047
Записей в блоге: 1
21.07.2022, 23:33
Цитата Сообщение от XLAT Посмотреть сообщение
ECS на ООП построен.
можно и сверху его в ООП завернуть.
про data-driven design тут я почитал.
Тут посмотрите: https://habr.com/ru/post/665276/

Цитата Сообщение от наверное, это
Стоит отдельно проговорить, что нередко Entity-Component-System путают с очень близким архитектурным паттерном Entity-Component(иногда пишут как Entity-Component System, далее EC), но это большое заблуждение.
1
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1
22.07.2022, 06:59  [ТС]
Может в следующем проекте я попробую что-то другое, но сейчас мне для этого придётся не то, чтобы переписывать весь код, а вообще изучать дофига всего. А бета-версию я планирую выпустить уже в следующем месяце, ибо код теперь куда лучше, да и из основной работы осталось переделать редактор, да уровни заново сделать
Что касается моего подхода, лишь бы работало и выглядело не криво (ну, чтобы не было запутавшимися наушниками). По идее, это вообще моя вторая игра, которая имеет реальный смысл. Код хоть и плохой, но мне бы с основами разобраться, о паттернах и не говорю.
Система, реализованная в SFML включает в себя именно коллизию OBBvsOBB, к тому же без разрешения. Когда я заменил на свою, ничего не поменялось (но вот на слабом железе скорость стала повыше).
Ну, а теперь основной цикл. Если вы стоите, сядьте, возможен пердечный систуп
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
    while (mode == "game") {
 
        //управление
        while (true) {
 
            if (Keyboard::isKeyPressed(Keyboard::F5)) {
                checkpoint();
                alpha = 40;
            }
 
            if (Keyboard::isKeyPressed(Keyboard::Tab) && !onclick) {
 
                onclick = true;
 
                stop_physics = true;
                
                Sleep(100);
                
 
                build(lvlnum);
 
                return;
            }
 
            if (Keyboard::isKeyPressed(Keyboard::Q)) {
                music.stop(); tick += rand() % 10;
            }
 
            break; //не ругайтесь, я так делаю, чтобы свернуть можно было(
        }
 
        for (i = 0; i < 8; i++) {
            bg_particles[i].cycle();
        }
 
        if (colint > 0) { colint--; }
 
        for (i = 0; i < map_floor.size(); i++) {
            map_floor[i]->render();
        }
 
        for (i = 0; i < electric.size(); i++) {
            electric[i]->render();
        }
 
        for (i = 0; i < map_basic.size(); i++) {
            map_basic[i]->render();
        }
 
        for (i = 0; i < movables.size(); i++) {
            window.draw(movables[i]->box);
        }
 
        for (i = 0; i < 5; i++) {
            spiral[i].rotate(3.2);
            if (i == teleport_to) { spiral[i].setScale((teleport_frame * 0.01 + 0.25) * scale, (teleport_frame * 0.01 + 0.25) * scale); }
            else { spiral[i].setScale(0.25 * scale, 0.25 * scale); }
            window.draw(spiral[i]);
            spiral[i].scale(2, 2);
            window.draw(spiral[i]);
            spiral[i].scale(0.5, 0.5);
            window.draw(spiral[i]);
            if (i == teleport_to) { spiral[i].setScale((teleport_frame * 0.01 + 0.25) * scale, (teleport_frame * 0.01 + 0.25) * scale); }
            else { spiral[i].setScale(0.25 * scale, 0.25 * scale); }
            spiral[i].setPosition((tx[i] - scrollx - 64) * scale, (ty[i] - scrolly - 64) * scale);
            window.draw(spiral[i]);
            spiral[i].scale(2, 2);
            window.draw(spiral[i]);
            spiral[i].scale(0.5, 0.5);
            window.draw(spiral[i]);
            spiral[i].setPosition(-200, -200);
        }
 
        /*player_processing(); */render_player();
 
        //zoom
        if (Mouse::isButtonPressed(Mouse::Middle)) {
            if (Mouse::isButtonPressed(Mouse::Right)) {
                if (scale > 0.5 * UI_scale) {
                    scale *= 0.99;
                }
            }
            else {
                if (Mouse::isButtonPressed(Mouse::Left)) {
                    scale *= 1.01;
                }
                else {
                    if (Mouse::getPosition().x > screenw - 200) {
                        scrollx += 2;
                    }
                    if (Mouse::getPosition().x < 200) {
                        scrollx -= 2;
                    }
                    if (Mouse::getPosition().y > screenh - 200) {
                        scrolly += 2;
                    }
                    if (Mouse::getPosition().y < 200) {
                        scrolly -= 2;
                    }
                }
            }
 
            //if (int(playerS.getPosition().x / 2) > screenw / 4) { scrollx += 2; }
            //if (int(playerS.getPosition().x / 2) < screenw / 4) { scrollx -= 2; }
            //if (int(playerS.getPosition().y / 2) > screenh / 4) { scrolly += 2; }
            //if (int(playerS.getPosition().y / 2) < screenh / 4) { scrolly -= 2; }
 
            eyes.setScale(scale, scale);
            block.setScale(scale, scale);
            playerS.setScale(scale, scale);
            playerCol.setScale(scale, scale);
        }
 
        if (Keyboard::isKeyPressed(Keyboard::Add) || Keyboard::isKeyPressed(Keyboard::Equal)) {
            scale *= 1.01;
 
            eyes.setScale(scale, scale);
            block.setScale(scale, scale);
            playerS.setScale(scale, scale);
            playerCol.setScale(scale, scale);
        }
        if ((Keyboard::isKeyPressed(Keyboard::Subtract) || Keyboard::isKeyPressed(Keyboard::Hyphen)) && (scale > 0.8 * UI_scale)) {
 
            if (scale > 0.5 * UI_scale) {
                scale *= 0.99;
            }
 
            eyes.setScale(scale, scale);
            block.setScale(scale, scale);
            playerS.setScale(scale, scale);
            playerCol.setScale(scale, scale);
        }
 
        //scrolling
        if (!Mouse::isButtonPressed(Mouse::Middle)) {
            if (playerS.getPosition().x > screenw * 0.8) {
                scrollx += 5;
            }
            if (playerS.getPosition().x < screenh * 0.1) {
                scrollx -= 5;
            }
            if (playerS.getPosition().y > screenh * 0.9) {
                scrolly += 5;
            }
            if (playerS.getPosition().y < screenh * 0.2) {
                scrolly -= 5;
            }
 
            if (playerS.getPosition().x > screenw - 400 * UI_scale) {
                scrollx += 1;
            }
            if (playerS.getPosition().x < 400 * UI_scale) {
                scrollx -= 1;
            }
            if (playerS.getPosition().y > screenh - 280 * UI_scale) {
                scrolly += 1;
            }
            if (playerS.getPosition().y < 280 * UI_scale) {
                scrolly -= 1;
            }
 
            if (playerS.getPosition().x > screenw - 200 * UI_scale) {
                scrollx += 3;
                if (playerS.getPosition().x > screenw) {
                    scrollx += 200; sx = 0;
                }
            }
            if (playerS.getPosition().x < 200 * UI_scale) {
                scrollx -= 3;
                if (playerS.getPosition().x < 0) {
                    scrollx -= 200; sx = 0;
                }
            }
            if (playerS.getPosition().y > screenh - 100 * UI_scale) {
                scrolly += 3;
                if (playerS.getPosition().y > screenh) {
                    scrolly += 200; sy = 0;
                }
            }
            if (playerS.getPosition().y < 100 * UI_scale) {
                scrolly -= 3;
                if (playerS.getPosition().y < 0) {
                    scrolly -= 200; sy = 0;
                }
            }
        }
 
        if (!on_teleport && (teleport_frame > 0)) {
            teleport_frame -= 3; spiral[teleport_to].rotate(-4);
 
            playerS.setColor(Color::Color(255, 255, 255, 260 - teleport_frame * 4));
            eyes.setColor(Color::Color(255, 255, 255, 260 - teleport_frame * 4));
 
            if (teleport_frame < 0) {
                teleport_frame = 0;
                playerS.setColor(Color::Color(255, 255, 255, 255));
                eyes.setColor(Color::Color(255, 255, 255, 255));
            }
        }
 
        for (i = 0; i < 3; i++) {
            if (particle[i][0].enabled) {
                for (j = 0; j < partnum; j++) {
                    particle[i][j].render();
                }
            }
        }
 
        if (abs(alpha) > 0) {
            alpha -= 5;
            if (alpha > 0) {
                blend.setColor(Color::Color(0, 0, 0, abs(alpha)));
            }
            if (alpha < 0) {
                blend.setColor(Color::Color(0, 0, 0, abs(alpha)));
                if (alpha < -253) {
 
                    stop_physics = true; Sleep(100);
 
                    if (levels_opened == lvlnum) {
                        levels_opened++;
                    }
                    if (lvlnum == -2) {
                        mode = "editor"; stop_physics = true; Sleep(100); lvlnum = -2; build(-2); return;
                    }
                    if (lvlnum == -3) {
                        mode = "achievements"; stop_physics = true; Sleep(100); lvlnum = -3; build(-2); return;
                    }
                    else {
                        if (lvlnum == -1) {
                            stop_physics = true; Sleep(100);
                            mode = "menu";
                            lvlnum = 1;
                        }
                        else { lvlnum++; build(lvlnum); stop_physics = true; Sleep(100); checkpoint(); return; }
                    }
 
                    build(lvlnum);
                }
            }
            window.draw(blend);
        }
 
        if (!music.getStatus()) {
            reset_music();
        }
 
        if (Keyboard::isKeyPressed(Keyboard::Escape)) {
            if (!onclick) {
                /*mode = "menu"; */
                onclick = true;
                context_menu = true;
            }
        }
        else {
            onclick = false;
        }
 
        if (context_menu) { game_context_menu(); }
 
        if (tp_rech > 0) { tp_rech -= 1; }
 
        if (achieve_fade > 0) {
            achieve_fade -= 3;
            if (achieve_fade > 955) {
                if (achieve_fade > 700) {
                    ach_box.setColor(Color::Color(255, 255, 255, 255));
                    ach_text.setFillColor(Color::Color(255, 255, 255, 255));
                    ach_BG.setColor(Color::Color(255, 255, 255, 255));
                    ach_box.setPosition(screenw - 1212 + achieve_fade, 0);
                    ach_BG.setPosition(screenw - 1650 + achieve_fade, 0);
                    ach_text.setPosition(screenw - 1600 + achieve_fade, 134);
                    achieve_fade -= 7;
                }
            }
            else {
                if (achieve_fade < 128) {
                    ach_box.setColor(Color::Color(255, 255, 255, achieve_fade * 2));
                    ach_BG.setColor(Color::Color(255, 255, 255, achieve_fade * 2));
                    ach_text.setFillColor(Color::Color(255, 255, 255, achieve_fade * 2));
                }
            }
 
            window.draw(ach_BG); window.draw(ach_box); window.draw(ach_text);
        }
 
        //CuRsOr!!!
        if (Mouse::isButtonPressed(Mouse::Middle)) {
            cursor.setPosition(Mouse::getPosition().x - window.getPosition().x, (Mouse::getPosition().y) - window.getPosition().y);
            cursor.setScale(1.5, 1.5);
            window.draw(cursor);
        }
 
        sf::Event event;
        while (window.pollEvent(event))
        {
            // "запрос закрытия" событие: мы закрываем окно
            if (event.type == sf::Event::Closed) {
                save_options();
                close = true; window.close();
            }
        }
 
        if (block_collision) { colint += 4; }
 
        block_collision = false;
 
        tick++;
        window.display();
        Sleep(1);
        window.clear();
    }
Параллельно с этим идёт просчёт физики (кстати, с этим разобрался уже на 100%)
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
void physics_processing() {
 
    while (window.isOpen()) {
 
        if (stop_physics || context_menu) {
            logg << "Physics was paused" << endl;
            while (stop_physics || context_menu) { Sleep(2); }
            logg << "Physics continue" << endl;
        }
 
        player_processing();
 
        for (i = 0; i < map_floor.size(); i++) {
            map_floor[i]->cycle();
 
            for (j = 0; j < movables.size(); j++) {
                if (intersection(*map_floor[i], *movables[j])) {
 
                    helper_s[0] = map_floor[i]->x - movables[j]->x;
                    helper_s[1] = map_floor[i]->y - movables[j]->y;
 
                    if (abs(helper_s[0]) > abs(helper_s[1])) {
 
                        if (abs(helper_s[0]) > 62 || abs(helper_s[0]) <= 1) {
                            continue;
                        }
 
                        movables[j]->x += map_floor[i]->magnet * sign(helper_s[0]);
                    }
                    else {
 
                        if (abs(helper_s[1]) > 62 || abs(helper_s[1]) <= 1) {
                            continue;
                        }
 
                        movables[j]->y += map_floor[i]->magnet * sign(helper_s[1]);
                    }
 
                }
            }
 
        }
 
        for (i = 0; i < electric.size(); i++) {
            electric[i]->cycle();
        }
 
        for (i = 0; i < map_basic.size(); i++) {
            map_basic[i]->cycle();
        }
 
        for (i = 0; i < movables.size(); i++) {
 
            for (j = 0; j < map_basic.size(); j++) {
                if (collide(*movables[i], *map_basic[j])) {
                    /*movables[j]->sx /= 2; movables[j]->sy /= 2;*/
 
                    /*collide(*movables[i], *map_basic[j]);*/
                }
            }
 
            for (j = 0; j < movables.size(); j++) {
                if (i != j) {
                    if (collide(*movables[j], *movables[i])) {
                        movables[i]->move(); movables[j]->move();
                        movables[j]->sx /= 2; movables[j]->sy /= 2;
                        movables[i]->sx /= 2; movables[i]->sy /= 2;
                    };
                }
            }
 
            if (collide(p, *movables[i])) {
                p.sx /= 1.04;
                p.sy /= 1.04;
 
                /*p.move(-p.sx, -p.sy);*/
            }
 
            movables[i]->cycle();
        }
 
        Sleep(1);
 
    }
    if (!window.isOpen()) {
        logg << "Error! Physics has been stopped!" << endl;
    }
    logg << "Physics has been stopped" << endl;
}
Cпасибо за советы, но изучение ECS я отложу до сентября

Добавлено через 7 минут
А, сорян, вот основной цикл
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
int main() {
 
    HWND Stealth;
    AllocConsole();
    Stealth = FindWindowA("ConsoleWindowClass", NULL);
    ShowWindow(Stealth, 0);
    //Заплатка, чтобы командная строка не мешалась
 
    logg.open("log.txt");
 
    do {
 
    ifstream screensize("Screen.txt");
    screensize >> helper;
    screenw = helper;
    screensize >> helper;
    screensize >> i;
    screensize >> UI_scale;  UI_scale /= 10;
    if (i == 0) { helper -= 80; }
    screenh = helper;
    screensize.close();
 
    window.close();
    window.create(sf::VideoMode(screenw, screenh), "Isn't hard 2");
 
    if (i == 1) {
        window.close();
        window.create(VideoMode(screenw, screenh), "Isn't hard 2", Style::Fullscreen);
        screenmode.is_checked = true;
    }
    window.setVerticalSyncEnabled(true);
    window.setMouseCursorVisible(false);
 
    std::thread physics(physics_processing);
 
    physics.detach();
 
    loading(); logg << "Loading was succesfully finished \n";
 
    while (window.isOpen())
    {
        cursor.setScale(0.2, 0.2);
        music.setVolume(30);
 
        if (mode == "game") {
            //game_cycle();
            test_game();
        }
 
        if (mode == "editor") {
            /*editor_cycle();*/
            test_editor();
        }
 
        if (mode == "achievements") {
            achievements_cycle();
        }
 
        if (mode == "menu") { 
 
            if (tick % 10 == 1) {
                if (!music.getStatus()) {
                    music.openFromFile("Sounds\\menu.ogg");
                    music.play();
                }
            }
 
            block.setTexture(bg); block.setOrigin(128, 128); block.setTextureRect(IntRect(0, 0, 256, 256)); block.setScale(1, 1);
            for (i = 0; i < 8; i++) {
                for (j = 0; j < 6; j++) {
                    switch((i + j) % 4) {
                    case 0: block.setRotation(0); break;
                    case 1: block.setRotation(90); break;
                    case 2: block.setRotation(180); break;
                    case 3: block.setRotation(270); break;
                    }
                    block.setPosition(i * 256 + 128, j * 256 + 128);
                    window.draw(block);
                }
            }
 
            text.setPosition(screenw / 2 - (352 * UI_scale), screenh / 20);
            text.setCharacterSize(150 * UI_scale);
            text.setFillColor(Color::Color(0, 0, 0, 255));
            text.setString("Isn't hard 2");
 
            window.draw(text);
 
            text.setPosition(screenw/2 - (350 * UI_scale), screenh / 20 + 2);
            text.setCharacterSize(150 * UI_scale);
            text.setFillColor(Color::Color(200,200,255,255));
            text.setString("Isn't hard 2");
            
            window.draw(text); context_menu = false;
 
            b_levels.cycle();
            b_ach.cycle();
            b_exit.cycle();
            b_options.cycle();
            b_play.cycle();
            b_editor.cycle();
 
            if (click_button_menu) {
                logg << "click_button_menu \n";
                switch (int(helper_s2)) {
                case 0: mode = "levels"; level_scroll = (levels_opened * 300 - 800) * -1; break;
                case 1: mode = "game"; block.setScale(scale, scale); block.setOrigin(64, 64); music.stop(); if (levels_opened < 35) { build(levels_opened); } else { build(rand()%36); } break;
                case 2: mode = "editor"; music.stop(); break;
                case 3: mode = "achievements"; break;
                case 4: mode = "options"; break;
                case 5: save_options(); close = true; window.close();  return 0;
                }
                click_button_menu = false;
            }
 
        }
 
        if (Keyboard::isKeyPressed(Keyboard::Escape)) {
            if (!onclick) {
                /*mode = "menu"; */
                onclick = true;
                if ((lvlnum == -1)&&(!context_menu)) { lvlnum = 1; }
            }
            if ((mode == "levels") || (mode == "options") || (mode == "editor")) { mode = "menu"; }
            else { context_menu = true; onclick = false; }
 
        }
 
        if (mode == "levels") {
            levels_cycle();
        }
 
        if (mode == "options") {
 
            if (tick % 10 == 1) {
                if (!music.getStatus()) {
                    music.openFromFile("Sounds\\menu.ogg");
                    music.play();
                }
            }
 
            block.setColor(Color::Color(100, 100, 100, 255));
            block.setTexture(bg); block.setOrigin(128, 128); block.setTextureRect(IntRect(0, 0, 256, 256)); block.setScale(1, 1);
            for (i = 0; i < 8; i++) {
                for (j = 0; j < 6; j++) {
                    switch ((i + j) % 4) {
                    case 0: block.setRotation(0); break;
                    case 1: block.setRotation(90); break;
                    case 2: block.setRotation(180); break;
                    case 3: block.setRotation(270); break;
                    }
                    block.setPosition(i * 256 + 128, j * 256 + 128);
                    window.draw(block);
                }
            }
            block.setColor(Color::Color(255, 255, 255, 255));
 
            particles_option.cycle();
 
            text.setFillColor(Color::Color(0, 0, 200, 255));
            text.setCharacterSize(50);
            text.setPosition(450, 420);
            text.setString("Particles density");
            window.draw(text);
            text.move(2, 2);
            text.setFillColor(Color::Color(0, 0, 0, 255));
            window.draw(text);
 
            reloader.cycle();
            auto_reloader.cycle();
 
            if (reloader.is_clicked) {
                for (i = 0; i < 2; i++) {
                    if (res_but[i].is_picked) {
                        helper_s[0] = res_but[i].W; helper_s[1] = res_but[i].H;
                        switch (i) {
                        case 0: UI_scale = 1; break;
                        case 1: UI_scale = 0.5; break;
                        }
                    }
                    ofstream scr;
                    scr.open("Screen.txt");
                    scr << helper_s[0] << " " << helper_s[1] << " ";
                    if (screenmode.is_checked) {
                        scr << 1 << " ";
                    }
                    else { scr << 0 << " "; }
                    scr << UI_scale * 10 << " ";
                    scr.close();
                }
                break;
            }
 
            if (auto_reloader.is_clicked) {
                ofstream scr;
                scr.open("Screen.txt");
                UI_scale = helper_s[0] / 1920;
                scr << helper_s[0] << " " << helper_s[1] << " ";
                scr << 1 << " ";
                scr << UI_scale * 10 << " ";
                scr.close();
                break;
            }
 
            screenmode.cycle();
 
            for (i = 0; i < 2; i++) {
                res_but[i].cycle();
                if (res_but[i].click) {
                    for (j = 0; j < 2; j++) {
                        if (i == j) {
                            res_but[j].is_picked = true;
                        }
                        else {
                            res_but[j].is_picked = false;
                        }
                    }
                }
            }
 
            if (Mouse::isButtonPressed(Mouse::Left)) {
                onclick = true;
            }
            else { onclick = false; }
 
        }
        
        //CuRsOr!!!
        if (true) {
            cursor.setPosition(Mouse::getPosition().x - window.getPosition().x, (Mouse::getPosition().y) - window.getPosition().y);
            cursor.setScale(1.5, 1.5);
            window.draw(cursor);
        }
 
        if (true) {
            if (Keyboard::isKeyPressed(Keyboard::Num1)) {
                UI_scale = 0.5;
                /*robot.next_path();
                system("pause");*/
            }
            if (Keyboard::isKeyPressed(Keyboard::Num2)) {
                UI_scale = 1;
            }
        }
 
        sf::Event event;
        while (window.pollEvent(event))
        {
            // "запрос закрытия" событие: мы закрываем окно
            if (event.type == sf::Event::Closed) {
                save_options();
                close = true; window.close(); return 1;
            }
 
        }
 
        tick++;
        window.display();
        Sleep(1);
        window.clear();
    }
    if (close) {
        window.close();
        return 1;
    }
    window.close();
    } while (true);
 
    return 3;
 
}
Пж, не критикуйте. Вы не видели того, что было, когда я не переписал код на полиморфическую версию. Вот там был настоящий звездец
0
фрилансер
 Аватар для Алексей1153
6510 / 5772 / 1135
Регистрация: 11.10.2019
Сообщений: 15,419
22.07.2022, 07:40
Цитата Сообщение от tankoman228 Посмотреть сообщение
        while (true) {
break; //не ругайтесь, я так делаю, чтобы свернуть можно было(
        }
предлагаю альтернативы ))

1)
C++
1
2
3
4
5
6
    //любой break или continue - выход из блока
    //и вообще - гарантированно выход, даже без этих ключевых слов
    do
    {
        
    }while(0);
2)
C++
1
2
3
4
5
    //любой return - выход из блока
    [&]
    {
        
    }();
Добавлено через 1 минуту
Цитата Сообщение от tankoman228 Посмотреть сообщение
чтобы свернуть можно было
а вообще, чтобы свернуть в IDE, достаточно просто блок и всё
C++
1
2
{
}
0
Век живи - век тупи
 Аватар для tankoman228
2 / 2 / 2
Регистрация: 12.05.2022
Сообщений: 83
Записей в блоге: 1
22.07.2022, 07:51  [ТС]
do while 0 и правда удобнее. Когда буду приводить код в порядок перед публикацией на гитхаб исправлю

Добавлено через 32 секунды
{
}
не работает(
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.07.2022, 07:51

Поток std::thread с шаблоном в классе
Доброго времени суток уважаемые! Уперся лбом в следующую проблему. При использовании параллельных потоков в основном потоке проблем...

Как остановить thread.Sleep по клику
дело такое - опрашиваю ком порты. есть функция и класс, отвечающие за разные методы. приходится ставить thread.sleep() чтобы получить...

Boost thread pool. Как остановить потоки?
Привет. Реализовал thread pool с помощью boost::thread_group и boost::asio::io_service for (unsigned int i = 0; i &lt;...

Как убить std::thread?
К сожалению мне так и не удалось найти информацию о том, как корректно убить std::thread в случае необходимости. Как правило, предлагают...

Как остановить поток?
Как остановить поток: Thread t = new Thread(NewThread); t.Start(); static void NewThread() { ...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
Генератор паролей (вариант №4)
Maks 01.11.2026
После публикации 3-го варианта генератора паролей, разослал его своим коллегам (с целью оценки), в итоге были получены следующие рекомендации: 1. Вернуть возможность использования знаков | 1 l I;. . .
Генератор паролей (вариант №3)
Maks 30.10.2026
Финальная версия генератора паролей 1С. Доработка решения в этот раз коснулась только визуальной части, а именно, добавлен реквизит ДопПараметры (тип Булево), который скрывает/ отображает реквизиты:. . .
Магическое мышление и магия, современная наука не отличима от магии (говорит ИИ Джемени)
zorxor 30.10.2026
Джемени, расскажи, пожалуйста, что такое магическое мышление, что такое магия, почему современная наука чем-то напоминает магию? Фраза «Любая достаточно развитая технология неотличима от магии». . .
За какое время ИИ может подобрать пароль по хешу (рассказывает Джемени ИИ)
zorxor 30.10.2026
Расскажи, Джемени, если известен хэш МД5, например, за сколько ИИ сможет подобрать соответствующий пароль? Искусственный интеллект (ИИ) может подобрать простой или средний по сложности пароль по. . .
Кто убил Suno? Почему наше солнышко погасло? (диалог с ИИ Джемени)
zorxor 30.10.2026
Как убивали Suno. Хронология. «Убийство» музыкальной нейросети Suno — это затяжной процесс, в котором технологический хайп стартапа разбился о жесткую реальность судебных исков от гигантов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru