Войти
ПроектыФорумОцените

Разработка open-source игры в прямом эфире (2 стр)

Страницы: 1 2 3 4 5 Следующая »
#15
(Правка: 4:42) 4:14, 8 июня 2021

Походу я всё пропустил. У меня стрим начался в 4 часа утра. ) Ну ладно.


#16
4:46, 8 июня 2021

Давай в следующий раз пораньше.

#17
(Правка: 13:26) 5:58, 8 июня 2021

Когда в следующий раз начнешь трансляцию, вставь в сообщение вот этот код.
Символы XXXXXXXXXXXXXX замени на те, которые есть в адресе трансляции, ниже они выделены жирным.

Пример: youtube.com/watch?v=7gM8yevOpgw
тебе надо взять это из адреса твоего текущего видео, там эти символы будут другими конечно.

<iframe width="900" height="540" src="https://www.youtube.com/embed/XXXXXXXXXXXXXX" 
title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; 
encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<iframe width="300" height="400" 
src="https://www.youtube.com/live_chat?is_popout=1&v=XXXXXXXXXXXXXX&embed_domain=gamedev.ru">
</iframe>

Тогда у тебя будет вот такая штука - сразу и видео и чат с ютуба.

+ Показать
#18
13:07, 8 июня 2021

std::cin
интересно, попробую

#19
14:19, 8 июня 2021

GhostCoderPPetrov
а это нормальная практика в с++ использовать memset и memcopy?

#20
14:24, 8 июня 2021

Mephistopheles
вообще - нет. но какие у тебя есть предложения?

#21
(Правка: 15:42) 15:42, 8 июня 2021
string str = "gamedev";
int len = str.length();
char arr[len + 1];
strcpy(arr, str.c_str());
#22
17:46, 8 июня 2021

std::cin
да, strcpy() немного лучше memcpy() - однако примерно то же самое.
только у нас не char [] произвольного размера, а char[64], чтобы уложиться в максимальный размер UDP пакета без фрагментации - у меня задана константа 1024.

#23
17:55, 8 июня 2021

std::cin
поэтому сейчас у меня вот так:

void setString(char var[64], const std::string& new_value)
{
    const size_t effective_size = std::min(std::size(var) - 1, new_value.size());
    memcpy(var, new_value.c_str(), effective_size);
    var[effective_size] = 0;
}
в рантайме ограничиваю размер строки
#24
17:55, 8 июня 2021

GhostCoderPPetrov
> вообще - нет. но какие у тебя есть предложения?
Использовать стандартные средства не требующие ручной работы с памятью? Если они конечно есть в с++

#25
18:32, 8 июня 2021

Mephistopheles
Такие средства в с++ есть.
Но я вижу некоторое непонимае с твоей стороны решаемой нами задачи и способов ее решения.

А задача у нас такая:
Объявить структуру данных для UDP пакета для пересылки по сети.

Соответственно, данный пакет и стуктура данных должна определять жесткий формат бинарных данных. Другими словами, определяя эту структуру данных мы определяем сам бинарный формат взаимодействия, сетевой протокол нашей игры.

Открой любую спецификацию по любому формату или протоколу.
Везде будут указаны размеры данных в байтах, битах. Будет указан порядок байт (little vs big endian).
И прочее. По-хорошему нам тут и endian надо тоже определить. Это хорошо что мы не используем big endian как в большинстве сетевых протоколов, иначе бы при чтении\записи обычных целых изгаляться - менять байты в нужную последовательность.

То есть memory layout должен быть определен явным образом.

Для этого мы определяем нашу структуру с использованием только низкоуровневых примитивов,
таких как std::uint32_t (беззнаковое целое), std::int32_t, std::uint16_t, std::int16_t и прочее. По стандарту С++ char имеет всегда размер 1 байт.
Однака я слышал прокомпиляторы, в которых он не равняется 1 байту. Поэтому, по-хорошему мы должны использовать тип
std::uint8_t вместо типа char.

Сейчас мы используем фикированный размер поля для login \ password \ full_name.
Это 64 байта. Первый символ с кодом 0 будет означать конец строки. Или, если все 64 байта не имеют нулевого символа,
то считать что наша строка имеет размер 64 байта.

Другим подходом будет является, например, явное хранения размера строки в начале, например:
std::uint8_t password_length;
char password[1]; // и здесь "1" уже будет условновстью - так как формат уже пойдет с плавающими длинами.

Способов двоичного представления можно придумать множество. Мы испольщуем самый простейший,
так как пароль и логин обычно короткие, и 64 байт достаточно.

В случае хранения и передачи длины строки явно - нужно будет делать дополнительные проверки - что длина строки не больше общего размера пакета и т.д.

Стандартые средства, такие как std::string нам совершенно не подходят. Как как они задают логический, высокоуровневый доступ к строке, набор операций над строкой, но совершенно не задают как эта строка std::string реализована (реализация может быть любой), и как std::string хранит строку в памяти.

Если ты предлащаешь вместо char [64] в стуктуре данных Login использовать просто поле std::string, то такая структура не будет задавать какой-то формат хранения бинарных данных.

Потому что реализация Microsoft std::string может быт одной, в gcc - другой, а в clang - третьей.

То есть сама структура Login у нас низкоуровневая, с жестким порядков байт.
Но с такой структурой не очень удобно работать, например при присваивании поля password
надо следить чтобы мы не вышли за границу массива, и не перетерли соседнее поле - full_name.

Для таких целей пишутся высокоуровневые хелперы - у нас это методы std::string getPassword() и void setPasswod(const std::string&) принимающие и возвращающие высокоуровневые "удобные" классы - std::string.

Чтобы весь низкоуровневый код, перегонки char [64] из\в std::string был локазован в этих методах,
а не был равномерно разбросан по всему проекту.

#26
18:34, 8 июня 2021

GhostCoderPPetrov
научись именовать переменные
это же ад, тебя C# покусал чтоли

#27
18:43, 8 июня 2021

u960
что означает "научись именовать переменные"? :)
в моем проекте есть принятый code style и он применяется.
вот он

Arguments for methods, interface methods, functions, constructors and destructors should use snake_case naming convention.
Local variables should use snake_case naming convention.
Class and structure fields should use snake_case naming convention starting without any prefix. For instance, buffer. If field name conflicts with argument name then add '_' suffix to the argument name, for instance, buffer_.

snake_case naming convention. Naming convention where all letters in a name are small. Name can consist from several words and each word is separated from other words by using under-scope symbol. Some examples are memory_buffer, triangle_fan, create_memory_buffer.

#28
18:45, 8 июня 2021

GhostCoderPPetrov
> void setString(char var[64], const std::string& new_value)
тебя тут ничего не смущает?

>const size_t effective_size = std::min(std::size(var) - 1, new_value.size());
а тут?
ты раздул код на ровном месте

#29
18:51, 8 июня 2021

u960
> void setString(char var[64], const std::string& new_value)
> тебя тут ничего не смущает?
смущает, поэтому изначально этих методов setString \ getString не было,
а весь функционал был реализован в getPassword \ setPassword и подобных.
Поэтому что сам по опыту знаю, что чтобы избавиться от копипасты на 3-4 строчки
нужно писать метод на эти 3-4 строчки, с не очень красивыми аргументами.

>const size_t effective_size = std::min(std::size(var) - 1, new_value.size());
>а тут?
>ты раздул код на ровном месте
а как нужно?

Страницы: 1 2 3 4 5 Следующая »
ПроектыФорумОцените