LINUX.ORG.RU

Проблемы архитектуры...

 , , , ,


0

2

Здравствуйте, товарищи погромисты :)

Немного поигравшись и вкусив все прелести изометрии решил её отложить в сторону и сделать «скелет» в 2D. Сейчас, реализовывая передвижение тайла по нажатию ПКМ, я «размазал» его по нескольким функциям: main.c: updateInput(), main.c: update() и main.c: moveCharacter(), что мне собственно не очень нравится, т.к. хотелось бы держать всё в одном месте. Натолкните, пожалуйста, на идею как можно сделать проще/красивее/иначе.

BTW, за критику и другие советы буду благодарен :)

main.c

репозиторий с кодом



Последнее исправление: ubik (всего исправлений: 1)

А цель то какая? Написать игорь или движок?

Если игорь, то проще не любить моск и взять готовый движок, ибо сейчас вообще все через неправильно - чего стоит только скорость перемещения зависящая от фреймрейта. Если движок написать - то опять лучше посмотреть как у людей сделано. Ибо в текущем виде дальше потыкать SDL ничего не выйдет. Да и вообще игры и голый Си - сильно так себе затея.

anonymous
()
Ответ на: комментарий от anonymous

А цель то какая? Написать игорь или движок?

Стратегическая цель — написать игрушку с движком :) Тактическая — потыкать в SDL2, и пройти по всему роадмапу, который себе накидал. Сейчас затык с движением.

Если игорь, то проще не любить моск и взять готовый движок

В этом случае нет смысла, т.к. игрушка простая + хочется чему-то научиться.

Если движок написать - то опять лучше посмотреть как у людей сделано.

Буду признателен за примеры тех самых людей :)

Ибо в текущем виде дальше потыкать SDL ничего не выйдет.

Почему же?

Да и вообще игры и голый Си - сильно так себе затея.

И ещё раз, почему?

ubik
() автор топика
Ответ на: комментарий от ubik

Буду признателен за примеры тех самых людей :)

Любой опенсорсный движок для примера (от огра и заканчивая годотом), чтобы просто посмотреть, что нужно игровому движку (ну там граф сцены, систему управления ресурсами, анимацию, встроенный скриптинг и еще вагон разных штук). Ну это если пытаться изобразить подобие приличного игрового движка.

Почему же?
И ещё раз, почему?

Например потому что при всем уважении к Си - это убогий низкоуровневый язык с куцей стандартной библиотекой и множеством способов отстрелить себе ноги/руки. И пытаться писать на нем что-то сложнее xbill - это сильно не любить себя.

anonymous
()

Не могу понять. В чём именно вопрос?

Я года полтора назад запилил свой 2Д движок на Java для Android.

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

Вполне так получился движок, есть куча встроенных возможностей по управлению объектами и выдаёт 60fps, нативная поддержка 10 пальцевого тачскрина, допиливаю нативную поддержку звуков и конструтор меню. Сейчас уже по инерции допиливаю напильником всё это безобразие и даже запилил на нём несколько программ.

А ты о чём конкретно спрашиваешь?

Serg_HIS
()

У тебя texture не texture а sprite. Вместо 0/1 можно EXIT_SUCCESS/EXIT_FAILURE. Еще

/* void textureRenderXYClipScale(Texture *texture, int x, int y, SDL_Rect *cliprect, float scale) */
/* { */
/*     fprintf(stdout, "Not implemented yet!\n"); */
/* } */
Можно заменить на
/* void textureRenderXYClipScale(Texture *texture, int x, int y, SDL_Rect *cliprect, float scale) 
{ 
   puts("Not implemented yet!");
} */
Просто это бросилось в глаза.)
-------------------------------------
Я бы встроил duktape, а на С бы написал рендер, физику, etc. Ну если все на С хочешь то сделай:
void player_update(struct player* self) {
  if(SDL_GetKeyboardState(NULL)[config->controll[CONTROLL_STEP_LEFT]]) {
    self->x--;
  }
}
--------------------------------------
Еще вместо проверок типа:
void func(void* ptr) {
  if(ptr == NULL) { 
     error!
  }
  ...
}
Можно писать
void func(void* ptr) {
  assert(ptr != NULL); /*или просто*/ assert(ptr);
  ...
}

linuhs_user
()
Последнее исправление: linuhs_user (всего исправлений: 2)
Ответ на: комментарий от anonymous

Позавчера щупал годот. Он уже торт. И обещают скоро еще тортее станет.

deep-purple ★★★★★
()
Ответ на: комментарий от linuhs_user

Вместо

printf("%function-name%: error message!\n");
можно писать
printf(__func__": error message!\n");
Тогда имя функции подставится автоматически, можно сделать макрос тогда даже в принципе
#define ERR(fmt,...)\
  printf("[file: %s, func: %s, line: %d]: " fmt, __FILE__, __func__, __LINE__, __VA_ARGS__)

ERR("Error open file %s\n", filename);
А вообще ты все равно выходишь если не удается память выделить поэтому можешь сделать себе
void* myalloc(size_t sz) {
  void* ptr;

  if(!(ptr = malloc(sz))) {
    error!
  }
  return(ptr);
}

linuhs_user
()
Ответ на: комментарий от linuhs_user

О! Спасибо тебе огромное за комментарии, добрый человек :)

Я бы встроил duktape, а на С бы написал рендер, физику, etc.

Ты про эту штуку: Duktape is an embeddable Javascript engine, with a focus on portability and compact footprint. Duktape is easy to integrate into a C/C++ project: add duktape.c, duktape.h, and duk_config.h to your build, and use the Duktape API to call Ecmascript functions from C code and vice versa.?

Если да, то мне бы не очень хотелось встраивать JS сюда, но можно подумать. Пока мне бы хотелось реализовать более примитивные вещи как:

  • движение юнита к точке, обозначенной ПКМ (интерполяция?).
  • collision detection
  • поиск пути через А*
  • многлослойный рендеринг карты
  • перевод 2d в изометрию и обратно
  • загрузка того куска карты и юнитов, которые попадают в рамку камеры и выгрузка остальных объектов (кстати, ты про это говорил в другом посте :D)
  • прикрутить скриптование тем же lua или python
  • возможно что-то ещё...

Тогда имя функции подставится автоматически, можно сделать макрос тогда даже в принципе

Вот за это отдельное спасибо :) Переделаю.

А что скажешь по поводу передвижения юнита? Рельно сделать передвижение в одном месте, чтобы не размазывать через несколько функций, чтобы не лочить main loop?

ubik
() автор топика

Для игр лучше всего использовать ООП, а именно - держать разделенными данные и логику поведения разных объектов. То есть, в твоем случае логику персонажа (загрузку его ресурсов, обновление состояния в зависимости от инпута, обновление позиции, рендеринг) вынести в отдельный файл и из мейна только дергать соответствующие функции. Логику инициализации движка и всякие низкоуровневые штуки тоже лучше держать отдельно от игровой логики.

Когда объектов станет много, мейну очевидно придется дергать функции для каждого объекта. Это не очень удобно, тогда на помощь приходят Observer, очереди сообщений и события.

Вообще, рекомендую почитать книжку http://www.gameprogrammingpatterns.com/contents.html, там как раз про паттерны проектирования в геймдеве. И, как посоветовал выше анонимус, почитать исходники других движков. Лично мне очень понравились исходники Urho3D, очень понятный и структурированный код, при этом хорошо расширяется и включает в себя разные подсистемы (физика, аудио, скрипты, 2д и т.д.)

kostik1
()

я б тебе подсказал, но увы на работе сижу.

твоя проблема в том, что ты «танцуешь от кода».

это в корне неверно. ты в SDL прицеплен к главному циклу, это факт. но твоя задача извлечь из него inputы, оттранслировать в внутренние события(ведь ты же не будешь прибивать клавиши намертво?) и забрать следующий кадр.

ckotinko ☆☆☆
()
Ответ на: комментарий от ubik

прикрутить скриптование тем же lua или python

duktape удобнее будет, имхо

Рельно сделать передвижение в одном месте

player_update же

linuhs_user
()
Ответ на: комментарий от ubik

Пока мне бы хотелось реализовать более примитивные вещи как:

Тут примитивных только 2 вещи

движение юнита к точке, обозначенной ПКМ (интерполяция?).

и

многлослойный рендеринг карты

Что под этим подразумевается

перевод 2d в изометрию и обратно

Мне вообще не понятно.

collision detection и загрузка того куска карты и юнитов, которые попадают в рамку камеры и выгрузка остальных объектов

это достаточно сложные штуки

Serg_HIS
()
Ответ на: комментарий от kostik1

Для игр лучше всего использовать ООП

пока я справляюсь через структуры, поинтеры которых кидаю в нужные функцию. Если буду захлёбываться, то придётся пересаживаться на крестики, конечно, а так не хочется :)

То есть, в твоем случае логику персонажа (загрузку его ресурсов, обновление состояния в зависимости от инпута, обновление позиции, рендеринг) вынести в отдельный файл и из мейна только дергать соответствующие функции. Логику инициализации движка и всякие низкоуровневые штуки тоже лучше держать отдельно от игровой логики.

Это логично. В принципе, так я и думаю сделать, но на этапе рефакторинга.

Когда объектов станет много, мейну очевидно придется дергать функции для каждого объекта. Это не очень удобно, тогда на помощь приходят Observer, очереди сообщений и события.

Спасибо большое. Очень мощная штуковина :)

Вообще, рекомендую почитать книжку http://www.gameprogrammingpatterns.com/contents.html, там как раз про паттерны проектирования в геймдеве.

ещё раз огромнейшее спасибо!

Лично мне очень понравились исходники Urho3D...

ок, гляну. Лучи позитива тебе )

ubik
() автор топика
Ответ на: комментарий от ckotinko

я б тебе подсказал, но увы на работе сижу.

я подожду ))) пиши когда сможешь.

ubik
() автор топика
Ответ на: комментарий от Serg_HIS

перевод 2d в изометрию и обратно

возможно, имеется ввиду что-то, типа, Falcon's Eye, Vulture или noeGNUd ?

anonymous
()
Ответ на: комментарий от Serg_HIS

Что под этим подразумевается

например, в первом слое я отрисовываю тайлы с травой, водой, песком, etc. Во втором слое я отрисовываю здания, самолёты, проституток и утят. В тетьем слое накладываются туловища негров, а в четвёртом их головы, которые умеют крутиться.

Мне вообще не понятно.

Посмотри на эту картинку. Белыми линиями я рисую Декартову систему координат, а зелёными изометрическую проекцию. В 2d я делаю все расчёты, а зрителю показываю в изометрии.

это достаточно сложные штуки

Почему же? Коллизии вычисляются очень просто, если у нас есть пересечение проекций на двух осях одновременно, значит есть коллизия.

Загрузка/выгрузка ресурсов немного сложнее, но обязательна для больших карт. Я знаю координаты прямоугольника камеры и знаю координаты каждого тайла на сцене. Те тайлы, которые выходят за пределы камеры, я выгружаю, иначе загружаю.

ubik
() автор топика
Ответ на: комментарий от ubik

например, в первом слое я отрисовываю тайлы с травой, водой, песком, etc

про слои понятно - это самое простое из всего.

Белыми линиями я рисую Декартову систему координат, а зелёными изометрическую проекцию

тю... одно умножение добавить по оси Y от X. И не забывать все спрайты так -же нарисовать с изометрии.

Коллизии вычисляются очень просто, если у нас есть пересечение проекций на двух осях одновременно, значит есть коллизия.

С коллизиями совсем не просто. Притом есть несколько вариантов из расчётов. есть с маленькой точностью, для пошаговых тормозоигр а есть континнуус в котором первый вариант окажется в пролёте когда на игровом поле есть быстродвижущиеся объекты (бильярд например).

в первом случае от количества объектов не сильно страшно грузится проц, во втором применяют многочисленные эвристики чтобы ты смог увидить как катятся шары и как они отлетают друг от друга в 60фпс, а не ждал 10 минут глядя на подвисшую картинку, а потом увидел уже стоящие шары в конечной позиции.

Serg_HIS
()
Ответ на: комментарий от ubik

Загрузка/выгрузка ресурсов немного сложнее, но обязательна для больших карт

многократно проще коллизий

Serg_HIS
()
Ответ на: комментарий от ubik

ошибся наоборот

в зависимости от координаты y пишешь функцию

Xshift = Ysprite*K

K - коэффициент «изометричности» :) от 0 до сколько надо

чем он больше 0 тем больше смещение

при K равно 1 твоя изометрия будет точно под 45 градусов.

Этот X1 нужно прибавлять ко всем координатам X объектов находящихся на конкретной позиции Y

Xscreen = Xsprite + Ysprite*K

Serg_HIS
()
Ответ на: комментарий от ubik

поправка,

Это если Y считается снизу вверх

обычно сверху вниз в графике. тоесть нужно координату Y отнять от высоты экрана

Serg_HIS
()
Ответ на: комментарий от ubik

Если тебе нужно такое же преобразование и по Y - то делаешь тоже самое от реальной координаты X

Serg_HIS
()
Ответ на: комментарий от ubik

Если буду захлёбываться, то придётся пересаживаться на крестики, конечно, а так не хочется :)

ООП не обязательно обозначает С++. Можно писать в объектном стиле и на С (хотя и сложнее чем на крестах), например полиморфизм прекрасно реализуется при помощи указателей на функции или тех же очередей сообщений. С инкапсуляцией сложнее, но это в принципе не столь важно, главное разделять поведение.

kostik1
()
Ответ на: комментарий от kostik1

ООП не обязательно обозначает С++

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

Предлагаю давать ему инфу последовательно.

Serg_HIS
()
Ответ на: комментарий от kostik1

главное разделять поведение.

Ок. Буду двигаться в этом направлении. Всех благ тебе за полезнейшую инфу!

ubik
() автор топика
Ответ на: комментарий от Serg_HIS

К стати изометрия совершенно простое умножение и всё.

Эдак ты тут выпрыгнул что коллизии это по твоему совсем простяк. ;)

Serg_HIS
()
Ответ на: комментарий от ubik

что за умножение?

Спасибо хоть сказал бы.

Какого хрена тогда спрашивал?

Serg_HIS
()
Ответ на: комментарий от ubik

Коллизии вычисляются очень просто, если у нас есть пересечение проекций на двух осях одновременно, значит есть коллизия.

Это коллизии с помощью AABB только так работают. Если захочется более точно считать, такой метод не подойдёт.

Допустим, у тебя двумерный случай. Представь два наклонных под 45 градусов к осям отрезка. Если их расположить рядом друг с другом, но на очень маленьком расстоянии, их проекции на оси почти что совпадут, но пересечения не будет. Или подкова и маленький кружок. Проекция кружка может быть целиком внутри проекции подковы, но опять-таки без пересечений самих объектов.

i-rinat ★★★★★
()
Ответ на: комментарий от Serg_HIS

Если тебе так это важно, то тебе тоже отдельное спасибо. Просто инфа от тебя мне никак не помогла, но мне не жалко ☺

Какого хрена тогда спрашивал?

Потому что у меня изометрия реализуется иным способом:

iX = dX - dY;
iY = (dX + dY) / 2;
Можно ещё через матрицы поворота, но это оверхэд для моего случая. Из текста, отражённого тобой, я ничего не понял ☺

Если дальше мудачиться будешь, сам себе будешь всё наяривать собственноручно.

Мэн, пойми, пожалуйста, одну штуку. Если ты здесь ничего не будешь писать, мне от этого не станет хуже или лучше. А ты, наверное, сможешь сделать что-то полезное, сэкономив время ☺

ubik
() автор топика
Ответ на: комментарий от ubik

Как же тогда они обрабатываются?

Десять минут поиска в гугле сообщили мне, что самый простой метод — представить невыпуклый объект комбинацией выпуклых, на этапе создания моделей.

А вообще, вот: https://github.com/jslee02/awesome-collision-detection. Надеюсь, найдёшь там что-нибудь полезное.

i-rinat ★★★★★
()
Ответ на: комментарий от ubik

iX = dX - dY;
iY = (dX + dY) / 2;

Что такое эти твои дельта?

Мэн, пойми, пожалуйста, одну штуку

Да, понял, спасибо.

А ты, наверное, сможешь сделать что-то полезное, сэкономив время

У меня сейчас застой по некоторым разработкам, знаю в принципе несколько методов как сделать, не могу выбрать «правильный». Пока мудачусь над выбором. Думал может помочь другим решить простые штуки чтобы «расшатать» свой мозг для решения своих задач.

Изометрия совсем простая штука.

Serg_HIS
()
Ответ на: комментарий от ubik

Такие случаи обрабатываются присвоением объектам геометрических примитивов. Обычно круги(сферы если 3Д) и прямоугольники(параллелепипеды в 3Д).

На каждый объект назначают по несколько таких фигур для простых вычислений.

Serg_HIS
()
Ответ на: комментарий от Serg_HIS

Что такое эти твои дельта?

d - декартовы координаты i - изометрические координаты

Думал может помочь другим решить простые...

Лучше девочку новую соблазни и шпильни хорошенько. Очень помогает

ubik
() автор топика
Ответ на: комментарий от ubik

d

Для школьников которые не учились в университетах - d (дельта)

Лучше девочку новую соблазни и шпильни хорошенько. Очень помогает

Согласен - помогает.

Думаю тебе до моего рейтинга в этом деле далеко. Как вобщем и по программингу.

Serg_HIS
()
Ответ на: комментарий от Serg_HIS

Думаю тебе до моего рейтинга в этом деле далеко.

Думай :)

ubik
() автор топика

Разместить функции в отдельном файле move.c Сделать над ними одну обёртку, функцию объединяющую их всех или задать структуру структуру которая содержит вызовы всех трёх, структура или общая функция может хранить промежуточные данные

типа


Общая функция
tmove(type update_input, type update, type moveCharacher);

Структура
tmove->uptade_input();
tmove->update()
tmove->moveCharacter();

Разбивать действия на отдельные функции хорошо, так как они становятся независимыми блоками что упростит дальнейшую жизнь. Для объединения использую функции уровня API то есть такие которые обеспечивают простой интерфейс к твоим низкоуровневым.

В обычной ситуации очень удобно писать в стиле ядро + api, где ядро это низкоуровневые функции разбитые по задачам и удобные в правке, но неудобные в использовании прямом и api где действия агрерируются последовательностями низкоуровневых функций для выполнения уже простых задач. В твоём случае api функция которой задаётся тайл и параметры его поведения, всё, остальная магия уже внутри неё происходит ты же просто жмёшь мышку и таскаешь тайл после запуска этой функции. Разделяй и властвуй! ::)

Deleted
()
Ответ на: комментарий от Serg_HIS

Думаю тебе до моего рейтинга в этом деле далеко. Как вобщем и по программингу.Ты же тот самый чувак

Ты же тот самый эпичный чувак из вот этого треда: Не хотят работать бесплатно (комментарий)

Которой умереть всем какой дизайнер, только без онлайн-портфолио почему-то.

Дай догадаться: у тебя нет профиля на гитхабе, и чтобы посмотреть на твой код, надо написать тебе запрос по электронной почте? :)

AP ★★★★★
()

почитать про Entity Component System, проникнуться, почитать еще, почитать про data driven approach, сходить посмотреть видео с GDC, почитать презентации, подумать, и взять готовый движок. Или с этого момента быть готовым сурово поколупаться. От языка не зависит. Язык тут вообще побоку. Правильная архитектура движка - это не вдруг, и каждый её с нуля постигает. Так как секрет она великий, и интеллектуальная собственность.

slapin ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.