Суббота, 27 Апреля 2024, 18:41

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 2 из 2
  • «
  • 1
  • 2
Форум игроделов » Ваши проекты » Разработка движков и сред разработки » Разработка движка (детальное описание для новичков) [C++] (BADCOIQ Engine)
Разработка движка (детальное описание для новичков) [C++]
afqДата: Вторник, 04 Июля 2023, 19:13 | Сообщение # 21
Разработчик
Сейчас нет на сайте
Цитата
Книжку прочитал, оказывается это элементарщина.

BADCOIQ, какую книжку перечитал?
afqДата: Вторник, 04 Июля 2023, 19:19 | Сообщение # 22
Разработчик
Сейчас нет на сайте
Storm54, не пойму почему у тебя такой негатив к разработчикам движков? Это же форум разработчиков игр. Ты цепляешься к словам, как будто нет опыта в общении. Я например пришел в разработку игр из software разработки. Да я уже состоявшийся разработчик, но я не знал как движки делать и конечно же будут тупняки. Почему я тебе должен как тупому объяснять? Ты вообще игру свою походу до сих пор делаешь, и ещё смеешь придераться к более сложным задачам. Если людям нравиться, то почему такой хейт на форуме разработчиков игр? Ты наверное очень сильно завидуешь, что люди умнее тебя и делают потрясающие вещи, а ты только и можешь, что делать диалоги с помощью готовых инструментов. Вообще мне не нравиться с тобой общаться, я начинаю нервничать. Ты как критикан, который думает, что его мнение самое правильное, но на самом деле каждый занимается тем чем хочет. Если ты видишь, что я его подбадриваю и пишу как это круто, а ты начинаешь критиковать, то ты до..баеб.
afqДата: Вторник, 04 Июля 2023, 19:35 | Сообщение # 23
Разработчик
Сейчас нет на сайте
BADCOIQ, вообще этот форум стал каким-то токсичным. Здесь есть всего несколько человек, которые нормально относятся к любым выборам разработки, будь то движок или игра. Но есть такие придурки, которые топят только за construct и unity и всё остальное отрицают. Им не важно что ты умный, им важно что они за счет твоего унижения будут чувствовать себя не такими тупыми какими являются.
afqДата: Вторник, 04 Июля 2023, 19:37 | Сообщение # 24
Разработчик
Сейчас нет на сайте
Я думаю, я даже видел интервью, где разработчик говорил что очень плохая ошибка размещать свои проекты на gcup. И это действительно так. Здесь не ценят твой труд, здесь только смотрят на картинку и если она им не нравиться, то польется тонна говна, что ты ничего не стоишь.
BADCOIQДата: Вторник, 04 Июля 2023, 19:46 | Сообщение # 25
Отец-основатель BADCOIQ Corporation © 2010
Сейчас нет на сайте
Цитата afq ()
этот форум стал каким-то токсичным

Это везде так. Было и будет.
Пока одни ноют, люди пишут. В итоге, когда у одного человека написано, у другого нихера нет кроме накопленного флуда.

Эти сообщения уже давно пролетают мимо.

Некоторые потом заходят с другого аккаунта пишут "Чувак ты крут."


"Do you think we can fly?
Well, I do."
afqДата: Вторник, 04 Июля 2023, 19:58 | Сообщение # 26
Разработчик
Сейчас нет на сайте
BADCOIQ, ты кстати можешь ещё заработать на уроках по своему движку, если сделаешь видео и выложишь на https://coursebook.ru/ , это замена онлайн площадки по видео урокам udemy. Здесь я почти ничего не заработал, но директор говорит, что некоторые зарабатывают по 100 000.
Вот мой профиль, профиль
Вот какие темы я затрагивал, но кстати о разработке движка как видео урока тоже можно будет замутить как только доведу до ума.
Storm54Дата: Вторник, 04 Июля 2023, 20:07 | Сообщение # 27
постоянный участник
Сейчас нет на сайте
afq, Да нет никакого хейта. Но, ты пишешь в духе: Разрабатывать движки круто, их делают состоявшиеся разработчики, а все остальные - лошки.
В следующем предложении: невозможно придумать, мало опыта, пишешь каждый раз заново.
Вот и назревает вопрос: что ты сам то сделал, чтобы выдвигать такие умозаключения? Выглядит как пустозвонство. И никто не обязан соглашаться с твоими выводами (как и с моими), если пруфов никаких нет.

По курсам: я предлагал тебе еще пару лет назад сделать курс по написанию майнкрафта на C, с разбиением на чанки, с батчинком, достойной оптимизацией. Я даже честно оплатил бы его в качестве поощрения за развитие, если он стоящий.


Сообщение отредактировал Storm54 - Вторник, 04 Июля 2023, 20:39
afqДата: Вторник, 04 Июля 2023, 20:49 | Сообщение # 28
Разработчик
Сейчас нет на сайте
Цитата
По курсам: я предлагал тебе еще пару лет назад сделать курс по написанию майнкрафта на C, с разбиением на чанки, с батчинком, достойной оптимизацией. Я даже честно оплатил бы его в качестве поощрения за развитие, если он стоящий.

Storm54, я в 3d мало развиваюсь и если и буду, то мы должны договориться насчет твоего заказа. на kwork можешь оплатить. только не 20 000, это мало. Такие деньги очень маленькие для игр, которые тебе требуются. Ты не правильно оценил мой труд и у меня пропал интерес этим заниматься. На kwork у меня бывают заказы, где я за дней 5 могу 50 000 урвать, а ты мне предлагаешь 3d майнкрафт, где я не развивался и ещё хочешь чтобы я тебе сделал за такую сумму. Понимаю, если бы у меня был свой интерес, не денежный, то я бы развился и возможно для меня это было бы легко и я сделал бы и за 20 000, если бы было уже что-то готовое. но за 20 000, когда кто-то предлагает и не закрепляет это документально, ну наслово я не верю уже давно. только друзьям доверяю, но никак не форумчанам, которые просто хотят взять на слабо.
afqДата: Вторник, 04 Июля 2023, 20:59 | Сообщение # 29
Разработчик
Сейчас нет на сайте
Цитата
Разрабатывать движки круто, их делают состоявшиеся разработчики, а все остальные - лошки.

Storm54, даже если ты и лошок, то я тебя никак не пытаюсь унижать. Я к тому, что некоторые хотят чего-то большего, чем просто логику для игр делать. Ну вот что ты можешь сделать кроме логики на unity? Если уж на то пошло. Ведь состоявшийся разработчик, это тот, который много что умеет, ведь так? Если ты умеешь только передвигать персонажа по карте и выводить бонусы, то ты себя тоже считаешь состоявшимся разработчиком? Если да, то пожалуйста, я не навязываю своё мнение, я только хочу делать свои продукты или игры и не слушать тех, кто против того, что я делаю. Мне не нравиться критиканство типа как графика говно, ничем не обосновывая. такие люди даже не умеют рисовать скорее всего и всё по нейросетях делают. Да, они могут сказать что игрокам пофиг, но здесь такие люди, которые вообще труд не ценят. Таким разработчикам неважен какой труд был принесен человеком, они просто все обсирают. Если бы предложили спецификации по графике, то это было бы интересно, а когда какому то нехудожнику не понравилась картинка, то как ты думаешь, с психологической точки зрения, стоит ли писать что графика говно? Или лучше помочь улучшить, раз это форум разработчиков? Если не можешь подсказать советом, то зачем мне твое мнение слушать, кто ты такой, чтобы я к тебе прислушивался? если я буду зависеть от мнения разных людей, то это будет капец. так что у меня есть люди, которых я знаю хорошо и могу прислушаться, а эти, которых я не знаю и они сразу так пишут, как будто эксперты, то их мнение ничего для меня не стоит. Да я зацепился сначала, но понял что они просто токсики. а мне с моей инвалидностью не нужен вообще негатив, так как это плохо сказывается на психике. Но я понимаю, что эти токсики, они же ну такие, типа высказал негатив и пусть человек отвечает на него, чтобы токсик получил кайф.
afqДата: Вторник, 04 Июля 2023, 21:10 | Сообщение # 30
Разработчик
Сейчас нет на сайте
Storm54, ну или у тебя есть примеры, где несостоявшиеся разработчики начинали делать свой движок, если так, то круто, есть куда расти?
Storm54Дата: Вторник, 04 Июля 2023, 23:45 | Сообщение # 31
постоянный участник
Сейчас нет на сайте
Цитата afq ()
на kwork можешь оплатить. только не 20 000

Задумка была оформить тебе это как курс и продавать, чтобы тебе же получить небольшой бонус я бы его купил первым, чисто ради поддержки и может какого-нибудь фидбека. О каком-то формате фриланса, естественно, речи быть не может, для меня такие поделки какой-либо ценности не представляют. Выше я уже написал, какие алгоритмы нужно использовать, чтобы это создать, как бы намекая, что я в этом разбираюсь.

Цитата afq ()
Я к тому, что некоторые хотят чего-то большего, чем просто логику для игр делать

В этом то и заключается главное недопонимание. Ты думаешь, что помимо написания движка больше нет каких-то технически сложных задач. Отсюда и тезисы про "передвижение персонажа по карте, вывод бонусов и т.п.". Открой тот же Unity, который ты воспринимаешь как конструктор, и посмотри, какой там функционал вообще есть. Да, там не нужно всегда писать свой рендер луп (хотя при необходимости можно, даже на плюсах, на чем крупные проекты и базируются), да, в Unity не нужно заниматься полным менеджментом ресурсов и добавлять свою библиотеку с математикой или писать свой скиннинг на GPU. Это уже есть. Но, когда дело доходит до разработки РЕАЛЬНОЙ игры, то оказывается, что нужно реализовать уйму дополнительных вещей: Кастомный батчинг; тонны оптимизированных шейдеров; Если игра с большим открытым миром: упаковка локаций в специальный формат, желательно оптимизированный для последовательного чтения; кастомный поиск пути для большого открытого мира; Если делается игра по типу гонок: то физическое поведение машины, с учетом поведения двигателя, коробки передач и трения шин, управление такой машиной через AI; Если делается стратегия: Lockstep детерминированная симуляция мира, система применения команд и все что на этом строится, от сохранения игры, до мультиплеера. Если же говорим про мультиплеер в жанрах RPG/FPS, то сразу куча дополнительных тем: Авторитарный сервер, Reliable/Unreliable сетевой трафик, lag compensation and reconciliation. Это лишь немногие из направлений, с которыми лично я работал за последние 10 лет и поэтому мне смешно и одновременно грустно читать этот треш про разработку движка в 600 строк и мысли, что если проект базируется на каком-то коммерческом игровом движке, то в нем лишь примитивный код.
Ну и последнее: с чего ты взял, что я вообще работаю с Unity?) Последний проект, который я скидывал и который ты посмотрел, на самописном плюсовом движке, самописном мультиплеере с поддержкой 2K CCU на сервер, системой реплеев, сражениями в 300x300 юнитов и вдовесок системой автообновления клиента, автообновления сервера и самописным античитом и обфускатором кода. Вот и получается, что я критикую сообщения, потому что мне действительно есть что сказать на большинство тем геймдева, т.к. я в этом варюсь уже очень и очень долго.


Сообщение отредактировал Storm54 - Вторник, 04 Июля 2023, 23:48
afqДата: Вторник, 04 Июля 2023, 23:55 | Сообщение # 32
Разработчик
Сейчас нет на сайте
Цитата
Это лишь немногие из направлений, с которыми лично я работал за последние 10 лет и поэтому мне смешно и одновременно грустно читать этот треш про разработку движка в 600 строк и мысли, что если проект базируется на каком-то игровом движке, то в нем лишь примитивный код.

Ну ok, если ты мой код понимаешь, значит я его хорошо написал. А чем плох движок в 600 строк кода, если игра работает и всё что в ней нужно есть? Я ничего лишнего не написал, всё что нужно для игры всё есть. Если столкнусь с более сложными задачами, то и их решу. Но нужно придумать игру.
Цитата
Последний проект, который я скидывал и который ты посмотрел, на самописном плюсовом движке, самописном мультиплеере с поддержкой 2K CCU на сервер, системой реплеев, сражениями в 300x300 юнитов и вдовесок системой автообновления клиента, автообновления сервера и самописным античитом и обфускатором кода. Вот и получается, что я критикую сообщения, потому что мне действительно есть что сказать на большинство тем геймдева, т.к. я в этом варюсь уже очень и очень долго.

А это ты сам всё написал или твоя команда? Ты критикуешь чужой код, когда как сам код своего движка не можешь показать. Что это за позиция такая?
afqДата: Среда, 05 Июля 2023, 00:04 | Сообщение # 33
Разработчик
Сейчас нет на сайте
Storm54, подожди, мы ведь когда обсуждали мой движок, ты зацепился насчет камеры и потом ты сказал, что не знаешь как должно быть, но в других играх несколько камер. Я не очень понимаю тогда что именно ты делаешь. Ну имею ввиду что именно ты знаешь, а то критикуешь движок, хотя не знаешь как должна камера работать, хотя не видел ни один движок с несколькими камерами, а в unity пример привел с камерами, но не знаешь как внутри это работает.
Storm54Дата: Среда, 05 Июля 2023, 00:13 | Сообщение # 34
постоянный участник
Сейчас нет на сайте
Цитата afq ()
Ну ok, если ты мой код понимаешь, значит я его хорошо написал. А чем плох движок в 600 строк кода, если игра работает и всё что в ней нужно есть? Я ничего лишнего не написал, всё что нужно для игры всё есть. Если столкнусь с более сложными задачами, то и их решу. Но нужно придумать игру.

Ничем он не плох, просто это очень маленький объем работы и движком это назвать нельзя, ведь в такое количество кода какие-то серьезные вещи не вмещаются по определению, что уже подразумевает, что это не движок, а тонкая обертка над OpenGL.

Цитата afq ()
А это ты сам всё написал или твоя команда

Оригинальный движок одиночной игры я не писал. Все остальное написано лично мной за последние 3.5 года - примерно 200к строк кода. Еще 150к строк написано присоединившейся командой (2 человека) за 2 года.

Цитата afq ()
Что это за позиция такая?

Позиция очень простая: есть продукт и он работает, клиент обновляется, сервера функционируют с 99% аптаймом. В него можно зайти и поиграть, а это уже говорит само за себя.
afqДата: Среда, 05 Июля 2023, 00:30 | Сообщение # 35
Разработчик
Сейчас нет на сайте
Цитата
Оригинальный движок одиночной игры я не писал. Все остальное написано лично мной за последние 3.5 года - примерно 200к строк кода. Еще 150к строк написано присоединившейся командой (2 человека) за 2 года.

Не ну смотри, ты движки не писал, зато критикуешь по части архитектуры, будто ты спец. Позиция твоя, что ты только критикуешь чужой движок, но свой не можешь показать, показывает что ты лишь любишь сливать негатив, так как еще раз повторяю, ты не вкурсе как движки писать и не надо меня учить и вообще что-либо писать в теме которой ты не разбираешься. И я сделал вывод, что твои сообщения тоже не буду читать так как ты неадекватный. Понимаю если бы ты разбирался, а тут критикуешь то, в чем не разбираешься. Всё давай, до свидания. Можешь даже больше мне ничего не писать, я всё-равно читать не буду.
qomyqoДата: Среда, 05 Июля 2023, 14:26 | Сообщение # 36
был не раз
Сейчас нет на сайте
Цитата afq ()
construct

Хороший пример коммерческого успеха.

Цитата afq ()
движок

Сложно продать.
Storm54Дата: Среда, 05 Июля 2023, 18:42 | Сообщение # 37
постоянный участник
Сейчас нет на сайте
Цитата afq ()
Не ну смотри, ты движки не писал, зато критикуешь по части архитектуры, будто ты спец

Ок, приведи пример в котором я ошибся. Если видение ситуации отлично от твоего, то это не значит, что ты автоматом молодец, а все остальные - нет. Веди дискуссию: приводи аргументы, обсуждай озвученные тезисы, а не уходи в обидку, как ты обычно делаешь, скипая большую часть каждого из написанных сообщений.
MagicHeroДата: Среда, 05 Июля 2023, 19:27 | Сообщение # 38
участник
Сейчас нет на сайте
Storm54, да так и есть он несет сплошной бред не обращая внимания что ему пишут по существу, указывая на недочеты, а после когда ответить нечего то как ребенок просто убегает. Он походу живет в своем выдуманном мирке где кроме него никого нет.
Когда мне по моей игре указывали на недочеты или ошибки то я как баран не писал им в ответ что они ничего не понимают и пускай сами попробуют сделать а читал и вникал и как ни странно потом исправлял если аргументы реально значимые. Да еще и благодарил что помогли. Но этот ничего слушать не хочет, даже когда ему указывают на проблемы, он же пуп земли ))))))) А ему всего то показывают реальное положение дел его игры чтобы помощь ему ее улучшить. Но видимо до него этого не доходит и прикол в том что потом в еденичных отзываю, причем с положительным уклоном указывали на то же что и я изначально.


Сообщение отредактировал MagicHero - Среда, 05 Июля 2023, 19:34
BADCOIQДата: Среда, 05 Июля 2023, 20:05 | Сообщение # 39
Отец-основатель BADCOIQ Corporation © 2010
Сейчас нет на сайте
Нужно где-то хранить размеры, например, ширину и высоту. И ещё надо хранить 4 значения обозначающих прямоугольную область.
Нужны
Код

bqPoint
bqRect


Куда их сунуть? Где написать?
Добавлю новый .h файл
inc/badcoiq/common/bqBasicTypes.h
Напишу туда.
Код

template<typename T>
class bqPoint_t
{
public:
    bqPoint_t() {}
    bqPoint_t(T X, T Y) : x(X), y(Y) {}

    T x = 0;
    T y = 0;
};

using bqPoint = bqPoint_t<int32_t>;
using bqPointf = bqPoint_t<float>;

template<typename T>
class bqRect_t
{
public:
    bqRect_t() {}
    bqRect_t(T Left, T Top, T Right, T Bottom) :
  left(Left),
  top(Top),
  right(Right),
  bottom(Bottom)
    {}

    T left = 0;
    T top = 0;
    T right = 0;
    T bottom = 0;
};

using bqRect = bqRect_t<int32_t>;
using bqRectf = bqRect_t<float>;


Окно

При создании окна ничего указывать не надо. Просто Призовём окно. Все настройки будем делать методами.
Окну нужен коллбэк, оно будет вызывать методы когда с окном что-то случиться.

inc/badcoiq/system/bqWindow.h
Код

// Когда с окном что-то происходит, оно будет вызывать эти коллбэки
// При создании окна мы обязаны послать указатель на коллбэк
class bqWindowCallback
{
public:
    bqWindowCallback() {}
    virtual ~bqWindowCallback() {}

    // Когда переключились к этому окну
    virtual void OnActivate(bqWindow*) {}
    // Когда переключились к другому окну
    virtual void OnDeactivate(bqWindow*) {}

    // После изменении размера
    virtual void OnSize(bqWindow*) {}
    // Пока изменяем размер
    virtual void OnSizing(bqWindow*) {} // when resizing

    // Свернули окно
    virtual void OnMinimize(bqWindow*) {}
    // Развернули на весь монитор
    virtual void OnMaximize(bqWindow*) {}
    // Восстановили (из Maximized и Minimized в обычное)
    virtual void OnRestore(bqWindow*) {}

    // Когда окно перерисовывается
    virtual void OnDraw(bqWindow*) {}

    // Когда двигается
    virtual void OnMove(bqWindow*) {}

    // Когда кликается кнопка закрытия
    virtual void OnClose(bqWindow*) {}
};


Окна для разных ОС имеют что-то общее.
Нужно сунуть общие данные в структуру.
Код

struct bqWindowCommonData
{
    // тут хранится указатель на коллбэк
    bqWindowCallback* m_cb = 0;

    // размер рамки
    bqPoint m_borderSize;

    // минимальный размер окна
    bqPoint m_sizeMinimum;
    
    // текущий размер окна (клиентской области)
    bqPoint m_sizeCurrent;

    // окно видимо или нет
    bool m_isVisible = false;

    // данные специфичные для ОС
    void* m_implementation = 0;
};


Данные специфичные для ОС могут понадобиться. Надо добавить ещё одну структуру, которая видна только для Windows платформы.

Надо добавить отдельный .h файл, для Windows данных, так как нужно подключать windows.h, а лишний раз это делать не нужно (я за скорость компиляции).
inc/badcoiq/system/bqWindowWin32.h
Код

#ifdef BQ_PLATFORM_WINDOWS
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

struct bqWindowWin32
{
    wchar_t m_className[20];
    HWND m_hWnd = 0;
    HRAWINPUT m_rawInputData[0xff];
    LONG m_style = 0;
    LONG m_stylePreFullscreen = 0;
    WINDOWPLACEMENT m_wndPlcmnt;
};
#else
#error Для Windows
#endif


m_rawInputData для ввода, m_stylePreFullscreen и m_wndPlcmnt понядобятся для fullscreen

Нужны ОС данные? Подключай bqWindowWin32.h и делай так
Код

bqWindowWin32* WindowOSData = (bqWindowWin32*)myWindow->GetData()->m_implementation;


Теперь класс окна. Возвращаюсь в bqWindow.h
Код

// Окно
class bqWindow
{
    bqWindowCommonData m_data;
public:
    BQ_PLACEMENT_ALLOCATOR(bqWindow);
    bqWindow(bqWindowCallback* cb);
    ~bqWindow();

    // Установить заголовок
    void SetTitle(const char*);

    // Скрыть\показать
    void SetVisible(bool v);

    // Узнать, видимо ли окно.
    // Можно скипать рисование если окно например свёрнуто.
    bool IsVisible() { return m_data.m_isVisible; }

    // Развернуть в полный экран
    void Maximize();
    // Свернуть
    void Minimize();
    // Восстановить оконное состояние (ну типа оконное, не полный экран)
    void Restore();

    // Установить\убрать рамку
    void SetBorderless(bool);

    // Установить\убрать возможность изменять размер
    void SetNoResize(bool);

    // Показать\скрыть кнопку "свернуть окно"
    void SetNoMinimize(bool);

    // Тут, указатели для того чтобы получить их и сохранить где-то, и
    //  не вызывать эти методы каждый раз, так как в таком случае потребуется
    //    вызывать постоянно.
    // Получить минимальный размер окна.
    bqPoint* GetSizeMinimum() { return &m_data.m_sizeMinimum; }
    // Получить размер рамки
    bqPoint* GetBorderSize() { return &m_data.m_borderSize; }

    // Получить данные
    bqWindowCommonData* GetData() { return &m_data; }
    
    // Установить позицию и размер
    void SetPositionAndSize(int x, int y, int sx, int sy);
};


Реализация
src/badcoiq/system/bqWindow.cpp

Код

#include "badcoiq.h"

#include "badcoiq/system/bqWindow.h"

#ifdef BQ_PLATFORM_WINDOWS
#include "badcoiq/system/bqWindowWin32.h"
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

// Нахождение текущего размера окна (клиентской области)
void bqWindowWin32_findCurrentSize(bqWindow* w, bqWindowWin32* w32)
{
    RECT rc;
    GetClientRect(w32->m_hWnd, &rc);
    w->GetData()->m_sizeCurrent.x = rc.right - rc.left;
    w->GetData()->m_sizeCurrent.y = rc.bottom - rc.top;
}
#endif


Окно создаётся в конструкторе
Код

bqWindow::bqWindow(bqWindowCallback* cb)
{
#ifdef BQ_PLATFORM_WINDOWS
    // Выделю память для ОС данных
    bqWindowWin32* w32 = (bqWindowWin32*)bqMemory::malloc(sizeof(bqWindowWin32));
    // Сохраню адрес
    m_data.m_implementation = w32;

    // Обычные WinAPI действия
    WNDCLASSEXW wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = GetModuleHandle(0);
    wcex.hIcon = 0;
    wcex.hCursor = LoadCursor(0, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = 0;

    // нужен уникальный lpszClassName
    static int windowCount = 0;
    wsprintf(w32->m_className, L"w%i", windowCount++);
    wcex.lpszClassName = w32->m_className;
    wcex.hIconSm = 0;
    RegisterClassExW(&wcex);

    w32->m_hWnd = CreateWindowExW(
        0,
        w32->m_className,
        L"bqWindow",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        800,
        600,
        0,
        0,
        wcex.hInstance,
        this
    );

    // сохраню стиль окна
    w32->m_style = GetWindowLongPtr(w32->m_hWnd, GWL_STYLE);

    // получаю размер рамки
    int padding = GetSystemMetrics(SM_CXPADDEDBORDER);
    m_data.m_borderSize.x = GetSystemMetrics(SM_CXFRAME) + padding;
    m_data.m_borderSize.y = (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION) + padding);
   
   bqWindowWin32_findCurrentSize(this, w32);

    SetWindowLongPtr(w32->m_hWnd, GWL_USERDATA, reinterpret_cast<LONG_PTR>(this));
#endif

    m_data.m_cb = cb;
}


Уничтожение окна
Код

bqWindow::~bqWindow()
{
    if (m_data.m_implementation)
    {
#ifdef BQ_PLATFORM_WINDOWS
        bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
        if (w32->m_hWnd)
        {
            DestroyWindow((HWND)w32->m_hWnd);
            UnregisterClass(w32->m_className, GetModuleHandle(0));
        }
#endif

        bqMemory::free(m_data.m_implementation);
    }
}


Остальные методы
Код

void bqWindow::SetTitle(const char* s)
{
    BQ_ASSERT_ST(s);
    BQ_ASSERT_ST(m_data.m_implementation);
#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    if (w32->m_hWnd)
        SetWindowTextA(w32->m_hWnd, s);
#endif
}

void bqWindow::SetVisible(bool v)
{
    BQ_ASSERT_ST(m_data.m_implementation);
    m_data.m_isVisible = v;
#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    if (w32->m_hWnd)
        ShowWindow(w32->m_hWnd, v ? SW_SHOW : SW_HIDE);
#endif
}

void bqWindow::Maximize()
{
    BQ_ASSERT_ST(m_data.m_implementation);
    m_data.m_isVisible = true;
#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    ShowWindow(w32->m_hWnd, SW_MAXIMIZE);
#endif
}

void bqWindow::Minimize()
{
    BQ_ASSERT_ST(m_data.m_implementation);
    m_data.m_isVisible = false;
#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    ShowWindow(w32->m_hWnd, SW_MINIMIZE);
#endif
}

void bqWindow::Restore()
{
    BQ_ASSERT_ST(m_data.m_implementation);
    m_data.m_isVisible = true;
#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    ShowWindow(w32->m_hWnd, SW_RESTORE);
#endif
}

void bqWindow::SetBorderless(bool v)
{
    BQ_ASSERT_ST(m_data.m_implementation);

#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    if (v)
        SetWindowLongPtr(w32->m_hWnd, GWL_STYLE, WS_POPUP);
    else
        SetWindowLongPtr(w32->m_hWnd, GWL_STYLE, w32->m_style);
    SetWindowPos(w32->m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
    ShowWindow(w32->m_hWnd, SW_NORMAL);
#endif
}

void bqWindow::SetNoResize(bool v)
{
    BQ_ASSERT_ST(m_data.m_implementation);

#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    if (v)
    {
        w32->m_style &= ~WS_THICKFRAME;
        w32->m_style &= ~WS_MAXIMIZEBOX;
    }
    else
        w32->m_style |= WS_THICKFRAME | WS_MAXIMIZEBOX;
    SetWindowLongPtr(w32->m_hWnd, GWL_STYLE, w32->m_style);
    SetWindowPos(w32->m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
    ShowWindow(w32->m_hWnd, SW_NORMAL);
#endif
}

void bqWindow::SetNoMinimize(bool v)
{
    BQ_ASSERT_ST(m_data.m_implementation);

#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;
    if (v)
    {
        w32->m_style &= ~WS_MINIMIZEBOX;
    }
    else
        w32->m_style |= WS_MINIMIZEBOX;
    SetWindowLongPtr(w32->m_hWnd, GWL_STYLE, w32->m_style);
    SetWindowPos(w32->m_hWnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
    ShowWindow(w32->m_hWnd, SW_NORMAL);
#endif
}

void bqWindow::SetPositionAndSize(int x, int y, int sx, int sy)
{
    BQ_ASSERT_ST(m_data.m_implementation);
#ifdef BQ_PLATFORM_WINDOWS
    bqWindowWin32* w32 = (bqWindowWin32*)m_data.m_implementation;

    SetWindowPos(w32->m_hWnd, 0, x, y, sx, sy, 0);
    bqWindowWin32_findCurrentSize(this, w32);
#endif
}


Оконная процедура
Код

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId = LOWORD(wParam);
    bqWindow* pW = reinterpret_cast<bqWindow*>(GetWindowLongPtr(hWnd, GWL_USERDATA));

    switch (message)
    {
    case WM_ACTIVATE:
    {
        switch (wmId)
        {
        case WA_ACTIVE:
        case WA_CLICKACTIVE:
        {
            if (pW)
                pW->GetData()->m_cb->OnActivate(pW);
            return DefWindowProc(hWnd, message, wParam, lParam);
        }break;
        case WA_INACTIVE:
            if (pW)
                pW->GetData()->m_cb->OnDeactivate(pW);
            break;
        }
        break;
    }
    case WM_GETMINMAXINFO:
    {
        if (pW)
        {
            LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
            lpMMI->ptMinTrackSize.x = pW->GetSizeMinimum()->x;
            lpMMI->ptMinTrackSize.y = pW->GetSizeMinimum()->y;
        }
    }
    break;
    case WM_SIZE:
    {
        if (pW)
        {
            int wmId = LOWORD(wParam);
            switch (wmId)
            {
            case SIZE_MINIMIZED:
                pW->GetData()->m_cb->OnMinimize(pW);
                break;
            case SIZE_RESTORED:
                pW->GetData()->m_cb->OnRestore(pW);
                break;
            case SIZE_MAXIMIZED:
                pW->GetData()->m_cb->OnMaximize(pW);
                break;
            }

            bqWindowWin32_findCurrentSize(pW, (bqWindowWin32*)pW->GetData()->m_implementation);

            pW->GetData()->m_cb->OnSize(pW);
        }

    }return DefWindowProc(hWnd, message, wParam, lParam);
    case WM_SIZING:
    {
        if (pW)
        {
            bqWindowWin32_findCurrentSize(pW, (bqWindowWin32*)pW->GetData()->m_implementation);

            pW->GetData()->m_cb->OnSizing(pW);
        }
    }break;

    case WM_ERASEBKGND:
    case WM_PAINT:
    {
        if (pW)
            pW->GetData()->m_cb->OnDraw(pW);
    }break;
    case WM_MOVE:
    {
        if (pW)
            pW->GetData()->m_cb->OnMove(pW);
    }break;
   
    case WM_CLOSE:
        if (pW)
            pW->GetData()->m_cb->OnClose(pW);
        return 0;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}


Update метод у bqFramework
Код

void bqFramework::Update()
{
    BQ_ASSERT_ST(g_framework);

#ifdef BQ_PLATFORM_WINDOWS
    // без этого окно не будет реагировать
    MSG msg;
    while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
    {
  GetMessage(&msg, NULL, 0, 0);
  TranslateMessage(&msg);
  DispatchMessage(&msg);
    }
#endif
}


Создание окна у bqFramework
Код

bqWindow* bqFramework::SummonWindow(bqWindowCallback* cb)
{
    BQ_ASSERT_ST(g_framework);
    BQ_ASSERT_ST(cb);
    return new bqWindow(cb);
}


Всё. Тестовая программа
Код

#include "badcoiq.h"
#include "badcoiq/system/bqWindow.h"

BQ_LINK_LIBRARY("badcoiq");

bool g_run = true;

class bqFrameworkCallbackCB : public bqFrameworkCallback
{
public:
    bqFrameworkCallbackCB() {}
    virtual ~bqFrameworkCallbackCB() {}
    virtual void OnMessage() {}
};

class bqWindowCallbackCB : public bqWindowCallback
{
public:
    bqWindowCallbackCB() {}
    virtual ~bqWindowCallbackCB() {}

    virtual void OnClose(bqWindow*)
    {
        printf("Q\n");
        g_run = false;
    }
};

int main()
{
    bqFrameworkCallbackCB fcb;
    bqFramework::Start(&fcb);

    bqWindowCallbackCB wcb;
    auto window = bqFramework::SummonWindow(&wcb);
    if (window)
    {
  window->SetPositionAndSize(10, 10, 300, 200);
        window->SetVisible(true);

        while (g_run)
        {
            bqFramework::Update();
        }

        delete window;
    }
    
    return EXIT_SUCCESS;
}


Надо сделать Fullscreen


github

Добавлено (06 Июля 2023, 18:45)
---------------------------------------------
Delta time
Вычисление Delta Time реализую в bqFramework::Update

Код

static clock_t then = 0;
clock_t now = clock();

g_framework->m_deltaTime = (float)(now - then) / CLOCKS_PER_SEC;
then = now;


для clock_t надо подключить <time.h>

User Data
Бывает объектам нужно добавить поля GetUserData SetUserData
Добавлю базовый класс.

inc/badcoiq/common/bqUserData.h
Код

// Если для какого-то класса нужен user data, то можно наследовать этот класс
class bqUserData
{
    void* m_data = 0;
public:
    bqUserData() {}
    virtual ~bqUserData() {}

    virtual void* GetUserData() { return m_data; }
    virtual void SetUserData(void* d) { m_data = d; }
};


github

Добавлено (07 Июля 2023, 22:40)
---------------------------------------------
Математика

Хочу использовать заранее вычисленные значения для sin cos atan2 и т.д.
Нецелесообразно вычислять большой диапазон. Функции принимают значения например от -1 до +1, от -Пи до +Пи и т.д.

Добавлю файл
inc/badcoiq/math/bqMath.h

Код

class bqMath
{
public:
    static float DegToRad(float degrees);
    static double DegToRad(double degrees);
    static float RadToDeg(float radians);
    static double RadToDeg(double radians);

    static float Abs(float);
    static double Abs(double);
    static int32_t Abs(int32_t);

    // Expect value form -1 to +1
    static float Acos(float);
    static double Acos(double);

    // Expect value form -1 to +1
    static float Asin(float);
    static double Asin(double);

    // Expect value form -2 to +2
    static float Atan(float);
    static double Atan(double);

    // Expect value form -1 to +1
    static float Atan2(float y, float x);
    static double Atan2(double y, double x);

    static float Clamp(float, float mn, float mx);
    static double Clamp(double, double mn, double mx);

    // Expect value from -PI to +PI
    // It will do this
    // if (v > 3.141f) v = 3.141f;
    // if (v < -3.141f) v = -3.141f;
    static float Cos(float);
    static double Cos(double);
    static float Sin(float);
    static double Sin(double);
    static float Tan(float);
    static double Tan(double);

    // wikipedia:
    // Imprecise method, which does not guarantee v = v1 when t = 1, due to floating-point arithmetic error.
    // This method is monotonic. This form may be used when the hardware has a native fused multiply-add instruction.
    //
    // типа, Lerp1 не гарантирует что x станет равным y (...Lerp2 тоже)
    //  ... имеет 1 умножение. Lerp2 имеет 2 умножения.
    static float Lerp1(float x, float y, float t);
    static double Lerp1(double x, double y, double t);

    // wikipedia:
    // Precise method, which guarantees v = v1 when t = 1. This method is monotonic only when v0 * v1 < 0.
    // Lerping between same values might not produce the same value
    static float Lerp2(float x, float y, float t);
    static double Lerp2(double x, double y, double t);

    // Находится ли точка в прямоугольной области
    static bool PointInRect(const bqPoint&, const bqRect&);
};


Опять класс со статическими методами(...очень удобно).
Постепенно будут добавлены множество других методов когда появятся вектор, матрица, кватернион.

Некоторая реализация
src/badcoiq/math/bqMath.cpp
Код

#include "badcoiq.h"
#include "badcoiq/math/bqMath.h"

#include "math_private.h"

// Сгенерированные результаты функций:

static float g_acosf[] = {
#include "acosf.inl"
};
static double g_acos[] = {
#include "acos.inl"
};
...


Как работает
Код

float bqMath::Cos(float v)
{
    if (v < -3.141f) v = -3.141f;
    if (v < 0.f) v = bqMath::Abs(v);
    if (v > 3.141f) v = 3.141f;

    uint32_t ind = (uint32_t)roundf(v * 1000.0f);

    if (ind < 3143)
  return g_cosf[ind];
    return 0;
}


Пока не особо тестировал. Я замутил это ради скорости.

Вектр

2D, 3D и 4D вектора. Правильнее называть 2х компонентный и т.д.
Используется в том числе как координата.

2D использует 2 значения - x и y
3D - x y z
4D - x y z w

В векторе не должно быть других данных. Его размер в байтах должен быть равен размеру компонентов в сумме.

Вот типичный 4D вектр


В bqForward.h добавил
Код

template<typename T>
class bqVec2_t;
template<typename T>
class bqVec3_t;
template<typename T>
class bqVec4_t;
template<typename T>
class bqMatrix4_t;

using bqVec2  = bqVec2_t<bqReal>;
using bqVec2f = bqVec2_t<float>;
using bqVec2i = bqVec2_t<int32_t>;
using bqVec3  = bqVec3_t<bqReal>;
using bqVec3f = bqVec3_t<float>;
using bqVec3i = bqVec3_t<int32_t>;
using bqVec4  = bqVec4_t<bqReal>;
using bqVec4f = bqVec4_t<float>;
using bqVec4i = bqVec4_t<int32_t>;
using bqMat4  = bqMatrix4_t<bqReal>;


так-же некоторые функции для векторов добавил в класс bqMath, чтобы не нагружать bqVector.h

Матрица
Матрица для 3D мира это четыре 4D вектора

Код

vec4 matrix[4];

Ещё называют матрица 4на4

Есть матрица 3на3
Матрица 3на3 является как бы частью матрицы 4на4
Та часть что 3 на 3 это базис. Он отвечает за вращение.
Раньше делали игры на матрицах 3на3. ХЗ как сейчас, везде 4 на 4.
Необходима позиция, например, объект на сцене перемещается изменяя позицию. В матрице 4на4 указывается эта позиция. А при использовании матрицы 3на3 видимо посылали позицию отдельно, я честно не изучал это.

Напримр мы имеем
Код

vec4 matrix[4];


четырёх компонентный вектр, четыре раза

матрица выглядит так
Код

[x][y][z][w]
[x][y][z][w]
[x][y][z][w]
[x][y][z][w]


и в памяти он должен занимать это так-же, вот почему вектр должен НЕ содержать ничего лишнего.

Вот эта часть (помечено единичками) отвечает за положение точки в пространстве, ориентация, всмысле вращение относительно центра, так-же там находится так называемый масштаб
Код

[1][1][1][0]
[1][1][1][0]
[1][1][1][0]
[0][0][0][0]

то есть
Код

matrix[0]
matrix[1]
matrix[2]


Эта часть отвечает за позицию в 3D мире. Как бы, сначала повернули (значениями выше), потом отодвинули на нужное место.
Код

[0][0][0][0]
[0][0][0][0]
[0][0][0][0]
[1][1][1][0]

то есть
Код

matrix[3]


Ещё в некоторых не очень популярных реализациях устанавливают значение позиции в эти места
Код

[0][0][0][1]
[0][0][0][1]
[0][0][0][1]
[0][0][0][0]

то есть
Код

matrix[0].w
matrix[1].w
matrix[2].w

неудобно. Используем первый вариант.

За масштаб отвечают эти значения
Код

[1][0][0][0]
[0][1][0][0]
[0][0][1][0]
[0][0][0][0]

Если поставить 2 то моделька увеличиться\координата сдвинеться.
Если 0.5 то уменьшится\сдвинеться в обратную сторону.
Если там будут нули и мы рисуем модель то модельки не будет видно.

В углу должна стоять единица, для математической магии.
Код

[0][0][0][0]
[0][0][0][0]
[0][0][0][0]
[0][0][0][1]


Простая матрица должна выглядеть вот так
Код

[1][0][0][0]
[0][1][0][0]
[0][0][1][0]
[0][0][0][1]


Для рисования объекта в 3D пространстве нужна матрица этого объекта.
Её принято называть World матрица.
Достаточно минимальной матрицы
Код

[1][0][0][0]
[0][1][0][0]
[0][0][1][0]
[0][0][0][1]


Для того чтобы вращать объект, масштабировать и перемещать, можно создать отдельные матрицы
Код

Matrix4x4 Scale = Matrix4x4(
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
);

Matrix4x4 Rotation = CreateRotationMatrix(углы поворота);

Matrix4x4 Position = Matrix4x4(
0,0,0,0,
0,0,0,0,
0,0,0,0,
x,y,z,1
);

Matrix4x4 World = Position * Rotation * Scale;
// справа на лево - масштабируем, вращаем, и устанавливаем на позицию.


Матрица нужна для преобразования 3D координаты...
например позиция [132.25][2556.23][1.52]
...в 2D координаты куда идёт рисование (напрямую на экран, или в текстуру)...назавём "холст"
а координатная система холста от -1 до +1

Позиция умножается на матрицу - получается нужное значение.

Нужно создать удобный класс.
Код

// кратко
template<typename T>
class bqMatrix4_t
{
public:
    bqMatrix4_t() { Identity(); }
    
    bqMatrix4_t(const bqQuaternion& q)
    {
  Identity();
  SetRotation(q);
    }
    
    void Identity() {
  auto* p = this->Data();
  p[0] = static_cast<T>(1.f);
  p[1] = static_cast<T>(0.f);
  p[2] = static_cast<T>(0.f);
  p[3] = static_cast<T>(0.f);

  p[4] = static_cast<T>(0.f);
  p[5] = static_cast<T>(1.f);
  p[6] = static_cast<T>(0.f);
  p[7] = static_cast<T>(0.f);

  p[8] = static_cast<T>(0.f);
  p[9] = static_cast<T>(0.f);
  p[10] = static_cast<T>(1.f);
  p[11] = static_cast<T>(0.f);

  p[12] = static_cast<T>(0.f);
  p[13] = static_cast<T>(0.f);
  p[14] = static_cast<T>(0.f);
  p[15] = static_cast<T>(1.f);
    }
    
    void SetRotation(const bqQuaternion& q)
    {
  T d = q.Length();
  T s = 2.0f / d;
  T xs = q.x * s, ys = q.y * s, zs = q.z * s;
  T wx = q.w * xs, wy = q.w * ys, wz = q.w * zs;
  T xx = q.x * xs, xy = q.x * ys, xz = q.x * zs;
  T yy = q.y * ys, yz = q.y * zs, zz = q.z * zs;
  Set(
   1.0f - (yy + zz), xy - wz, xz + wy,
   xy + wz, 1.0f - (xx + zz), yz - wx,
   xz - wy, yz + wx, 1.0f - (xx + yy));
    }

.......
    
    bqVec4_t<T> m_data[4];
    T* Data() { return &m_data[0].x; }
};


Кватернион

Что такое кватернион не объяснить, ибо это высшая математика, комплексное число. Читайте википедию.

Простыми словами, кватернион хранит вращение, наверно более корректно - ориентацию.
Указываем углы, получаем кватернион, преобразуем в матрицу вращения.
Вращать объект кватернионом можно в любое направление.
Главное я покажу в будущем, во "Вращение объектов"

В коде кватернион это четыре float
Код

class bqQuaternion
{
public:
    bqQuaternion() {
  Identity();
    }
...
void Set(float _x, float _y, float _z)
    {
  _x *= 0.5f;
  _y *= 0.5f;
  _z *= 0.5f;
  float c1 = cos(_x);
  float c2 = cos(_y);
  float c3 = cos(_z);
  float s1 = sin(_x);
  float s2 = sin(_y);
  float s3 = sin(_z);
  w = (c1 * c2 * c3) + (s1 * s2 * s3);
  x = (s1 * c2 * c3) - (c1 * s2 * s3);
  y = (c1 * s2 * c3) + (s1 * c2 * s3);
  z = (c1 * c2 * s3) - (s1 * s2 * c3);
    }
...
    float x, y, z, w;
    float* Data() { return &x; }
};


Добавлено (07 Июля 2023, 22:49)
---------------------------------------------
Кватернионы можно интерполировать. Обычно такая функция называется Slerp

на форуме тупизм, невозможно продолжить публиковать сообщения пока кто-то другой не напишет
статейки пишутся в текстовый документ, будут опубликованы позже, тут или где-то ещё.

github


"Do you think we can fly?
Well, I do."


Сообщение отредактировал BADCOIQ - Суббота, 08 Июля 2023, 15:12
JordanCppДата: Суббота, 25 Ноября 2023, 21:36 | Сообщение # 40
был не раз
Сейчас нет на сайте
Интересный проект. Я создаю, что то похожее но пока без абстракций над 3D. Посмотрел ваш dx11 рендер, хотел бы с изменениями утащить в свой проект.

Фреймворк LDL

Добавлено (25 Ноября 2023, 21:37)
---------------------------------------------
Для начала добавить простое 2D api для разных рендеров. Сейчас реализовано для opengl 1.2 и 3.3

Добавлено (08 Декабря 2023, 11:03)
---------------------------------------------
BADCOIQ,
Продолжение будет?

Форум игроделов » Ваши проекты » Разработка движков и сред разработки » Разработка движка (детальное описание для новичков) [C++] (BADCOIQ Engine)
  • Страница 2 из 2
  • «
  • 1
  • 2
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг