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

Выделение памяти под объект на карте

02.07.2022, 01:44. Показов 1557. Ответов 10

Студворк — интернет-сервис помощи студентам
Доброе время суток. Я создаю игру (чтобы не вдаваться в подробности, пусть будет не игра, а симуляция того, как некие entity передвигаются по экрану) на sfml'е.
Так вот, если вкратце, то механизм, по которому я работаю следующий:
1) создаю карту (неважно)
2) создаю объекты-entity (важно)
3) рисую карту (неважно)
4) рисую объекты-entity (важно)
entity - объект класса Mob. Опять же для наглядности я его упростил и показываю только то, что нужно (см. ниже)

"Mob.h"
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "SFML/Graphics.hpp"
 
class Mob : public sf::Drawable, public sf::Transformable
{
private:
    /////////////////////////////* Моделька *//////////////////////////////////////////
    sf::Image image; // Изображение
    sf::Sprite sprite;  // Спрайт
    sf::Texture texture; // Текстура
 
public:
    /////////////////////////////* Конструктор *//////////////////////////////////////////
    Mob(const std::string& imageName, float VISIBILITY_DISTANCE);
}
"Mob.cpp"
C++
1
2
3
4
5
6
7
8
9
#include "Mob.h"
 
Mob::Mob(const std::string& imageName, float VISIBILITY_DISTANCE)
{
    // Загрузка спрайта и наложение на него текстуры
    image.loadFromFile("../entity/images/" + imageName + ".png");
    texture.loadFromImage(image);
    sprite.setTexture(texture);
}
Так вот собственно в чём и проблема: Я хочу, чтобы было несколько объектов, каждый с разными параметрами и текстурами, но все - объекты типа Mob. Если я каждый объект задаю явно в основном цикле (чего я делать не желаю по явным причинам), то всё хорошо рисуется (см. ниже)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//#include...
 
int main()
{
//...
std::vector<Mob> all_mobs;
 
Mob mob1("mob1", 50); // Пока рассмотрим на примере двух
Mob mob2("mob2", 60); 
 
all_mobs.push_back(mob1);
all_mobs.push_back(mob2);
 
//...
        for (Mob &mob : all_mobs)
        {
            window.draw(mob);
        }
/...
}
Однако если я хочу сделать хитрее, то есть, к примеру, в неком файле "mobsInit.cpp" этих мобов создавать и загружать в такой же вектор all_mobs, объявленный в основном цикле игры (см. ниже), то всё ломается, и вместо красивых, оттекстурированных мобов я вижу лишь белые квадратики (то бишь что-то ломается с sf::Image или sf::Texture, потому что с sf::Sprite всё хорошо).

"mobsInit.cpp"
C++
1
2
3
4
5
6
7
8
void loadMobs(std::vector<Mob> *mobsVectorToLoad)
{
    Mob mob1("mob1", 50);
    Mob mob2("mob2", 55);
 
    mobsVectorToLoad->push_back(mob1);
    mobsVectorToLoad->push_back(mob2);
}
"main.cpp"
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//#include...
 
int main()
{
//...
 
std::vector<Mob> all_mobs;
loadMobs(&all_mobs);
 
//...
        for (Mob &mob : all_mobs)
        {
            window.draw(mob);
        }
/...
}
Не понимаю, почему эту проблему решает изменение функции loadMobs() следующим образом (см. ниже)

"mobsInit.cpp"
C++
1
2
3
4
5
6
7
8
void loadMobs(std::vector<Mob> *mobsVectorToLoad)
{
    Mob mob1* = new Mob("mob1", 50);
    Mob mob2* = new Mob("mob2", 55);
 
    mobsVectorToLoad->push_back(*mob1);
    mobsVectorToLoad->push_back(*mob2);
}
Просьба объяснить, почему такая проблема возникает, и почему такое решение её решает). К тому же, если я начинаю, как я показал выше, выделять память под моих entity, то вопрос - как эту память потом очищать или здесь всё от начала и до конца - плохо и неверно?
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.07.2022, 01:44
Ответы с готовыми решениями:

Выделение памяти под новый объект
Люди, посоветуйте, пожайлуста, как в уже созданный массив из N объектов добавить ещё один объект? Преподаватель сказал, что просто надо...

Динамическое выделение памяти под объект
Здравствуйте, меня интересует несколько вопросов по поводу конструкции new. Есть такой код: struct element { std::string...

Влияет ли конструктор на выделение памяти под объект?
Прочёл в книге Р.Лафоре &quot;Объектно-ориентированное программирование в С++:&quot; Подобно конструкторам, деструкторы не возвращают значения и...

10
 Аватар для Storm Screamer
4898 / 1464 / 117
Регистрация: 21.04.2013
Сообщений: 8,777
02.07.2022, 04:24
Для того, чтобы самому отвечать на такие вопросы, надо проводить страшный ритуал, который называется "Отладка". И смотреть, что делает каждая строка, какой дает результат, насколько результат далек от ожидаемого.

Цитата Сообщение от g0rgol Посмотреть сообщение
C++
1
sprite.setTexture(texture);
Вы здесь устанавливаете текстуру, не проверив, загрузилась ли текстура?

Цитата Сообщение от g0rgol Посмотреть сообщение
C++
1
2
3
4
5
6
7
void loadMobs(std::vector<Mob> *mobsVectorToLoad)
{
    Mob mob1("mob1", 50);
    Mob mob2("mob2", 55);
    mobsVectorToLoad->push_back(mob1);
    mobsVectorToLoad->push_back(mob2);
}
По-моему тут ошибка. Почему у вас в аргументе указатель типа std::vector<Mob>? В функции по умолчанию и так передается указатель на вектор при использовании вектора.

Вектор нужно передать по ссылке:
C++
1
void loadMobs(std::vector<Mob>[B]&[/B] mobsVectorToLoad)
Цитата Сообщение от g0rgol Посмотреть сообщение
как эту память потом очищать
В зависимости от того, как она была занята. При динамическом выделении (куча) памяти потребуется вызвать delete[]. При использовании стека вызвать для вектора clear() и shrink_to_fit(). В классе моб есть деструктор?
1
0 / 0 / 0
Регистрация: 09.11.2020
Сообщений: 18
02.07.2022, 09:21  [ТС]
Storm Screamer, спасибо, надо учить ссылки и указатели.

Да, с передачей ссылки на вектор в функцию всё работает, но тут по прежнему нужен оператор new. И меня скорее интересует, почему он тут нужен и что принципиально разного происходило бы с полями создаваемых объектов, если я бы его не использовал и создавал бы объекты класса без new.
C++
1
2
3
4
5
6
7
8
void loadMobs(std::vector<Mob> &mobsVectorToLoad)
{
    Mob mob1* = new Mob("mob1", 50);
    Mob mob2* = new Mob("mob2", 55);
 
    mobsVectorToLoad.push_back(*mob1);
    mobsVectorToLoad.push_back(*mob2);
}
То есть, если грубо говоря, то вопрос в том, почему поле sf::Image image не сохраняется при коде (см. ниже)
C++
1
2
3
4
5
6
7
8
void loadMobs(std::vector<Mob> &mobsVectorToLoad)
{
    Mob mob1("mob1", 50);
    Mob mob2("mob2", 55);
 
    mobsVectorToLoad.push_back(mob1);
    mobsVectorToLoad.push_back(mob2);
}
Хотя тот же самый спрайт вполне себе нормально сохраняется.

Деструктора у класса Mob нет явно, но вроде как используется по умолчанию деструктор у sf::drawable, или же я ошибаюсь? Если это так, то как его лучше его будет оформить?

И да, проверка на неуспешную загрузку текстуры отсутствует...
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
02.07.2022, 13:57
Цитата Сообщение от g0rgol Посмотреть сообщение
/////////////////////////////* Моделька *//////////////////////////////////////////
    sf::Image image; // Изображение
    sf::Sprite sprite;  // Спрайт
    sf::Texture texture; // Текстура
И зачем моделька хранит изображение и текстуру?

Ваша проблема обсуждалась на этом форуме уже много раз, пользуйтесь поиском.
Вот из недавнего: При удалении элемента из вектора, соседний теряет текстуры
1
0 / 0 / 0
Регистрация: 09.11.2020
Сообщений: 18
02.07.2022, 13:58  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
И зачем моделька хранит изображение и текстуру?
Мне показалось логичным, чтобы каждый объект на экране хранил всю информацию о себе в своих полях - так не делают обычно?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
02.07.2022, 14:04
Цитата Сообщение от g0rgol Посмотреть сообщение
Мне показалось логичным, чтобы каждый объект на экране хранил всю информацию о себе в своих полях - так не делают обычно?
1) Зачем изображение? Я вижу только его использование для загрузки в текстуру, но текстуру можно напрямую загрузить...
2) Текстура и картинка - это тяжелый ресурс и он общий для многих сущностей, так зачем же это всё дублировать в памяти?
3) Из п.2 следует тот факт, что спрайт хранит указатель на текстуру(слабую ссылку), а вы это игнорируете, что и является причиной UB
4) По ссылке выше и ссылкам из той темы вы найдете некоторые детали и решение
1
0 / 0 / 0
Регистрация: 09.11.2020
Сообщений: 18
02.07.2022, 14:14  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
1) Зачем изображение? Я вижу только его использование для загрузки в текстуру, но текстуру можно напрямую загрузить...
2) Текстура и картинка - это тяжелый ресурс и он общий для многих сущностей, так зачем же это всё дублировать в памяти?
3) Из п.2 следует тот факт, что спрайт хранит указатель на текстуру(слабую ссылку), а вы это игнорируете, что и является причиной UB
То есть вы предлагаете хранить в объекте только текстуру (предварительно загруженную, например, в конструкторе) и спрайт, который ссылается на это поле?

Добавлено через 4 минуты
Что-то в роде:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "SFML/Graphics.hpp"
 
class Mob : public sf::Drawable, public sf::Transformable
{
private:
    /////////////////////////////* Моделька *//////////////////////////////////////////
    sf::Sprite sprite;  // Спрайт
    sf::Texture texture; // Текстура
 
public:
    /////////////////////////////* Конструктор *//////////////////////////////////////////
    Mob(const std::string& imageName, float VISIBILITY_DISTANCE)
    {
        texture.loadFromFile("../entity/images/" + imageName + ".png");
        sprite.setTexture(texture);
    }
}
Добавлено через 2 минуты
Благодарю, увидел ссылку
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
02.07.2022, 14:17
Лучший ответ Сообщение было отмечено g0rgol как решение

Решение

Цитата Сообщение от g0rgol Посмотреть сообщение
То есть вы предлагаете хранить в объекте только текстуру (предварительно загруженную, например, в конструкторе) и спрайт, который ссылается на это поле?
Я предлагаю хранить только спрайт, а текстуры хранить в отдельной глобальной сущности в единственном икземпляре, называемой менеджер ресурсов. В конструкторе моба запрашивать только ссылку на неё.
0
0 / 0 / 0
Регистрация: 09.11.2020
Сообщений: 18
02.07.2022, 14:23  [ТС]
Я натыкался уже на подобный ResourceHolder вот тут: Хранение текстуры
Вы говорите о таком менеджере ресурсов?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
02.07.2022, 14:40
Цитата Сообщение от g0rgol Посмотреть сообщение
Вы говорите о таком менеджере ресурсов?
Да, на эту же тему есть ссылка в теме по ссылке, что я дал.
0
0 / 0 / 0
Регистрация: 26.04.2013
Сообщений: 21
22.07.2022, 20:32
В тексте ошибка, там где Mob Mob1, Mob2;

в этом нет ошибки:

>Не понимаю, почему эту проблему решает изменение функции loadMobs() следующим образом (см. ниже)

"mobsInit.cpp"
C
1
2
3
4
5
6
7
8
void loadMobs(std::vector<Mob> *mobsVectorToLoad)
{
    Mob mob1* = new Mob("mob1", 50);
    Mob mob2* = new Mob("mob2", 55);
 
    mobsVectorToLoad->push_back(*mob1);
    mobsVectorToLoad->push_back(*mob2);
}
правильно:
C
1
2
3
4
5
struct{int a;int b;}subject;
 vector<subject> sub;
 
 //Push back new subject created with default constructor.
 sub.push_back(subject());
у Вас же
C
1
2
3
4
5
6
7
8
void loadMobs(std::vector<Mob> *mobsVectorToLoad)
{
    Mob mob1("mob1", 50);
    Mob mob2("mob2", 55);
 
    mobsVectorToLoad->push_back(mob1);
    mobsVectorToLoad->push_back(mob2);
}
Структура в C является имеющим размер, но не имеющим значений. Её размер всегда размер указателя байт!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
22.07.2022, 20:32
Помогаю со студенческими работами здесь

Динамическое выделение памяти под объект класса
Помогите динамически выделить память под объект класса.

Как работает динамическое выделение памяти под объект?
class A { public: A(int x){} ~A(){} }; const int n = 50; A* placementMemory = static_cast&lt;A*&gt;(operator new (n *...

VBO. Выделение памяти под буферный объект
Есть некоторая программа, с занимаемой оперативной памятью (ОП) ~11 Мб. Далее в целях эксперимента беру высокополигональную модель...

Выделение памяти под объект в нужное время
Задумался тут, а зачем нужно выделять память сразу под все объекты, которые будут использоваться, а не тогда когда это необходимо? ...

FillRectangle, выделение памяти под объект Rectangle
Помогите, пожалуйста. Почему вот так не работает: Rectangle^ rect = gcnew Rectangle(20, 20, 200, 100); ...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru