Барионикс 0.5.3a

laber.rlgclub.ru

Модератор: Maelstrom

Аватара пользователя
alexbard
Сообщения: 670
Зарегистрирован: 22 апр 2011, 17:15
Откуда: Украина
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение alexbard » 11 фев 2013, 10:44

kipar писал(а):Нет, ну не только же дверь открыть.
Скажем, "колдун кастует по вам фаерболл, использовать контрзаклинание? Выберите уровень"
"Гоблин замахивается по вам мечом, использовать контратаку (осталось за ход: 2 из 3)?"
Под такие действия я бы изначально разрабатывал систему с ходами жестко разбитыми на фазы (как в MTG), а не делал костыли из паузы на все приложение.

Аватара пользователя
Maelstrom
Мастер
Сообщения: 2062
Зарегистрирован: 26 ноя 2006, 14:19
Откуда: г. Усть-Кирдык
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Maelstrom » 11 фев 2013, 11:45

Да, как-то так.
Так у меня в прошлом бариониксе и сделано. И чем эта система плоха? Свою задачу - останавливать всю механику игры в абсолютно любом месте - исполняет на всё 100%, безо всяких изращений с измельчением событий.
Айв кнгенгах Йог-Сотот

Аватара пользователя
Cfyz
Сообщения: 776
Зарегистрирован: 30 ноя 2006, 10:03
Откуда: Санкт-Петербург
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Cfyz » 11 фев 2013, 12:32

Maelstrom писал(а):Так у меня в прошлом бариониксе и сделано. И чем эта система плоха? Свою задачу - останавливать всю механику игры в абсолютно любом месте - исполняет на всё 100%, безо всяких изращений с измельчением событий.
Просто это как GOTO или куча голых указателей в C++. Вроде бы сами по себе обычный инструмент, свою задачу выполняют на 100%, но одно их использование — верный признак, что код пошел по бороде или на пути к тому.

Есть архитектурная проблема: у игры должна быть возможность быть поставленной на паузу в любой момент. Идея заблочить UI, навесить глобальных флагов и прокачивать события ввода в двух (трех? десяти?) разных местах, некоторые из которых оказываются рекурсивно связаны — это жутчайший костыль. То, что это именно костыль, а не ловкий хак, легко увидеть выдумав еще какое-нибудь условие — например во время паузы на блок в бою дать возможность открывать окно персонажа и менять местами активные стратегии уклонения или хз что еще. И только не надо про "а мне такое не потребуется", рано или поздно что-то да потребуется, костыль треснет и код рухнет.

К слову, вообще идея блочить UI, где бы то ни было и каким бы то ни было способом — провальна сама по себе. Просто выйти из приложения в любой момент, открыть справку в любой момент, посмотреть окошки логов, персонажа, инвентаря, сделать пометку на карте посередине боя — какого черта это внезапно перестает работать только потому, что произошло какое-то якобы интересное мне событие?
Пытается раскуклиться

Аватара пользователя
Maelstrom
Мастер
Сообщения: 2062
Зарегистрирован: 26 ноя 2006, 14:19
Откуда: г. Усть-Кирдык
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Maelstrom » 11 фев 2013, 13:51

Так вешаться должен не УИ, а механика игры (ну, не знаю как назвать ещё). В какой момент ставиться, например, Pause = 1. И пока оно так, обработчик нажатий на кнопки будет принимать только команды, которые не приведут к изменению состояния игры. То есть посмотреть лог сообщений или окно персонажа - это спокойно, а вот сменить тактику или изучать новые навыки - ни за что.
Айв кнгенгах Йог-Сотот

Аватара пользователя
Cfyz
Сообщения: 776
Зарегистрирован: 30 ноя 2006, 10:03
Откуда: Санкт-Петербург
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Cfyz » 11 фев 2013, 14:53

Maelstrom писал(а):Так вешаться должен не УИ, а механика игры (ну, не знаю как назвать ещё). В какой момент ставиться, например, Pause = 1. И пока оно так, обработчик нажатий на кнопки будет принимать только команды, которые не приведут к изменению состояния игры. То есть посмотреть лог сообщений или окно персонажа - это спокойно, а вот сменить тактику или изучать новые навыки - ни за что.
Верно, полностью согласен. Нюанс только в подходе к реализации той самой "Pause = 1".

Я еще раз акцентирую внимание на том, что если поток один, то малой кровью ты не отделаешься. Для того, чтобы работал интерфейс (как минимум — выход/справка/etc.), нужно, чтобы ввод обрабатывался постоянно. Однако, помимо обработки ввода, есть еще обработка мира, всяких порожденных вводом событий и пр. Фактически, это вся остальная часть программы: между окончанием обработки ввода на текущей итерации и началом следующей обработки на следующей итерации. Вот это опасное место. Для простоты иллюстрации давай завернем всю обработку ввода в ProcessInput, а все остальное — в ProcessWorld:

Код: Выделить всё

while ( running )
{
    ProcessInput();
    ProcessWorld();
}
Теперь смотри: у тебя не получится просто так взять и поставить на паузу внутри ProcessWorld. Потому что выйти из этой функции обратно к обработке ввода будет означать бросить просчет хода на полпути, а не выходить из этой функции будет означать не вернуться к обработке ввода и подвесить UI. А теперь вспомним, что по построению ProcessWorld — это вообще все, кроме обработки ввода. Фактически у тебя вообще нет возможности элегантно поставить паузу где бы то ни было.

Отсюда есть только два выхода:
1. Раздробить обсчет мира на отдельные действия, тем самым дав возможность безболезненно выходить из ProcessWorld не просчитав ход до конца.
2. Сделать обсчет мира во втором потоке, который может быть поставлен на честную паузу независимо от потока UI.
Внимательный читатель может заметить, что выход на самом деле только один, п. 1 является предельно элементарной симуляцией многопоточности.

Ну и справедливости ради,
3. Не использовать механизм паузы в процессе хода.
Но реализация этого пункта не рассматривается как не соответствующая поставленному условию.
Пытается раскуклиться

Аватара пользователя
Maelstrom
Мастер
Сообщения: 2062
Зарегистрирован: 26 ноя 2006, 14:19
Откуда: г. Усть-Кирдык
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Maelstrom » 11 фев 2013, 16:17

Я тебя немного не понимаю. Рогалик - игра пошаговая, любые изменения состояния игры могут происходить ТОЛЬКО в результате нажатия кнопок. Поэтому мы имеем скорее ProccessInput и DrawFrame - второй тупо рисует картинку, которая изменяться не должна (анимация всяких эффектиков, допустим, идёт по своему закону, и, если состояние игры не изменилось, будет идти также неизменно).
В недрах кода, когда надо делать паузу, ставим следующее:

Код: Выделить всё

pause = 1;
while (pause == 1)
{
    ProcessInput();
    DrawFrame();
}
При этом по условию DrawFrame никак игру не изменяет, а ProcessInput в состоянии паузы игнорирует все команды, которые могли бы привести к изменению состояния игры.
Айв кнгенгах Йог-Сотот

Аватара пользователя
Cfyz
Сообщения: 776
Зарегистрирован: 30 ноя 2006, 10:03
Откуда: Санкт-Петербург
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Cfyz » 11 фев 2013, 16:52

В принципе, это и есть тот костыль, про который я говорил. Обработка ввода, внутри которого обсчет, внутри которого обработка ввода.
1. Будет работать до того момента, пока однажды не потребуется таки изменить состояние внутри паузы. Механизм-то один, а пауз может оказаться много: сегодня только <еще>, завтра пауза на блок, послезавтра в блоке можно выбрать действие. Решается волевым отказом от шанса на реализацию таких фич.
2. Должно соблюдаться условие согласованности всего влияющего на отображаемую информацию состояния игры перед любой паузой, что может стать неудобно. Не решается никак, с этим придется жить.
Ну то есть рано или поздно оно аукнется. Но поскольку похоже, что ты понимаешь, на что идешь (а не просто заблуждаешься, как я подумал вначале), вынужден оставить филосовскую часть дискуссии и это решение за тобою >_<.

По сугубо технической части, подобный трюк с обработкой внутри обработки прокатит не всегда. Консоль/BearLibTerminal и, возможно, SDL такое простят; HGE и похожие движки, WxWidgets и прочие окошки — черта с два. Ты что в итоге выбрал-то?
Пытается раскуклиться

Аватара пользователя
kipar
Сообщения: 2120
Зарегистрирован: 10 мар 2010, 13:16
Откуда: Москва

Re: Барионикс 0.5.3a

Сообщение kipar » 11 фев 2013, 17:36

На самом деле, есть простой способ реализации этой фичи. Никакая анимация не страдает.
Называется - модальные окна.
Т.е. мы в любой функции можем вызвать if dialog.showmodal = mrYes then ..., это вызовет окно, причем лежащее позади него окно будет продолжать анимированно работать. А в диалоге можно отобразить и другие окна, как модально так и немодально.
Вместо окна можно просто вывести <more>, мы ведь не виндовый механизм а свой используем, т.е. окно - абстрактная вещь, а не область на экране с рамкой.

Теперь - о том как это реализовать. Собственно, я у себя уже так сделал, просто как-то не задумывался. Суть проста - цикл обработки сообщений и находится в show_modal.

Код: Выделить всё

class UI
  def show_modal
    while getkey
      process_key
    end
    process_mouse
    update_screen
  end 
end
В абсолютно любой точке этого цикла можно вызвать Dialog.show_modal, который выглядит точно также. Если в процедуре update_screen обновлять не только текущее, но и вышележащие окна, то анимация будет продолжаться. По возврате из show_modal продолжится обработка предыдущего цикла.

Ну а при запуске игры мы просто вызываем MainUI.show_modal, он и выполняет роль основной игры.

Аватара пользователя
Maelstrom
Мастер
Сообщения: 2062
Зарегистрирован: 26 ноя 2006, 14:19
Откуда: г. Усть-Кирдык
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Maelstrom » 11 фев 2013, 18:23

1. Будет работать до того момента, пока однажды не потребуется таки изменить состояние внутри паузы. Механизм-то один, а пауз может оказаться много: сегодня только <еще>, завтра пауза на блок, послезавтра в блоке можно выбрать действие. Решается волевым отказом от шанса на реализацию таких фич.
Этого не потребуется в принципе. Выбор действия, равно как и (Y/N) и даже фраза в ответ на "What do you wish for?" - это ввод со стороны пользователя, и в коде вместе со снятием паузы будет сохранение этого ввода в какую-нибудь переменную, а потом уже, после паузы, с этой переменной что-нибудь сделать можно будет.
2. Должно соблюдаться условие согласованности всего влияющего на отображаемую информацию состояния игры перед любой паузой, что может стать неудобно. Не решается никак, с этим придется жить.
Ну то есть рано или поздно оно аукнется. Но поскольку похоже, что ты понимаешь, на что идешь (а не просто заблуждаешься, как я подумал вначале), вынужден оставить филосовскую часть дискуссии и это решение за тобою >_<.
С этим проблем вообще не вижу. Информация о отоброжаемых на экран тайлах уже в старом бариониксе жила своей жизнью, к этому ещё кое-что прибавиться, всякие надписи и т.д., которые в ВБ тупо задавались в форме. Но в целом никаких сложностей не предвижу.
У меня ж таким макаром уже было всё реализовано, я с дуру решил, что такое без виндусовских окошек и фреймворков не реализовать :oops:
Впрочем, в ходе дискусии ещё несколько тонкостей для себя отметил.
По сугубо технической части, подобный трюк с обработкой внутри обработки прокатит не всегда. Консоль/BearLibTerminal и, возможно, SDL такое простят; HGE и похожие движки, WxWidgets и прочие окошки — черта с два. Ты что в итоге выбрал-то?
Да я пока сам не знаю, пощупаю наверное первым делом SDL.
Называется - модальные окна.
Что-то я ниччего не понимаю. Что за окно, которого на самом деле нет?
Айв кнгенгах Йог-Сотот

Аватара пользователя
kipar
Сообщения: 2120
Зарегистрирован: 10 мар 2010, 13:16
Откуда: Москва

Re: Барионикс 0.5.3a

Сообщение kipar » 11 фев 2013, 18:38

Maelstrom писал(а):Что-то я ниччего не понимаю. Что за окно, которого на самом деле нет?
Ну т.е. есть базовый класс (пример буду на ruby давать, т.к. в С++ что-нибудь напутаю).

Код: Выделить всё

class Window

def show_modal
  @visible = true
  while not closed
    Poll_SDL_Event...что-то-там
    process_keys
    process_mouse
    update_screen
  end
end

end
Есть главное окно, наследник этого класса, переопределяющий функции process_keys, process_mouse, update_screen:

Код: Выделить всё

class MainUI < Window

def process_keys
  if keys.include? kbUp then
    player_go_up
  elsif...
  end
end

def process_mouse
  ...
end

def update_screen
  draw_background
  process_animations
  draw_player 
  log.update
...
end

end
И в произвольный момент, скажем внутри обработки клавиш, мы начинаем просчет игрового мира. Доходим до момента когда против гоблина можно поставить блок и там вызываем if AskBlock.show_modal = :Yes then do_block(goblin)

А AskBlock - другой потомок Window:

Код: Выделить всё

class AskBlock < Window

def process_keys
  if keys.include? 'Y' then
    modal_result = :Yes
    close_modal
  elsif...
  end
end

def process_mouse
  return false
end

def update_screen
    MainUI.update #это конечно для этого примера, на самом деле там будет что-то типа "обновить все предыдущие окна"
    show_text "Заблокировать удар гоблина? Y/N", x, y, color::red
end

end
Т.е. в этом окне происходит та же самая обработка, оно также отрисовывает вышележащее окно (если это нужно конечно), но обработка мыши и клавиатуры у него своя. Причем вызывающая функция ничего этого не заметит, для нее это просто вызов AskBlock.show_modal.

Аватара пользователя
Jolly Roger
Сообщения: 2973
Зарегистрирован: 27 ноя 2009, 09:10
Откуда: Minsk, Belarus

Re: Барионикс 0.5.3a

Сообщение Jolly Roger » 15 фев 2013, 13:27

Maelstrom писал(а):Visual Basic круче фсего. Остальное фтопку!
viewtopic.php?t=30
:D
Писать диздок спустя несколько лет разработки и множества изменений концепции - исконная русская девелоперская традиция.

Аватара пользователя
Cfyz
Сообщения: 776
Зарегистрирован: 30 ноя 2006, 10:03
Откуда: Санкт-Петербург
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Cfyz » 15 фев 2013, 14:02

Jolly Roger
Ну, помимо шуток, тут вроде бы проскальзывали аргументы вида "стал программистом" и "смотреть на востребованность". Но так как ничего конкретного озвучено все же не было, затаился и слежу за темой -- сам-то я люто, бешено люблю С++.
Пытается раскуклиться

Аватара пользователя
Maelstrom
Мастер
Сообщения: 2062
Зарегистрирован: 26 ноя 2006, 14:19
Откуда: г. Усть-Кирдык
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Maelstrom » 16 фев 2013, 07:44

Святая толстота...
Айв кнгенгах Йог-Сотот

Аватара пользователя
Uvadzucumi
Сообщения: 365
Зарегистрирован: 29 ноя 2011, 07:13
Откуда: Дубай, ОАЭ (Минск, Беларусь)
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Uvadzucumi » 16 фев 2013, 09:22

Cfyz писал(а):сам-то я люто, бешено люблю С++.
тут имеются ввиду конструкции вида?:

Код: Выделить всё

auto it = std::find_if (m_controls.begin(), m_controls.end(), [&] (Module * mod) { return mod == 0; });
:()
Меня окружали милые, добрые люди... медленно сжимая кольцо

Аватара пользователя
Jesus05
Сообщения: 1840
Зарегистрирован: 02 дек 2009, 07:50
Откуда: Норильск, сейчас Санкт-петербург.
Контактная информация:

Re: Барионикс 0.5.3a

Сообщение Jesus05 » 16 фев 2013, 11:27

Это уже не С++ :) это уже С++11

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

Ответить

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость