Страницы

пятница, 11 сентября 2009 г.

Описание примера к предыдущему посту

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

Итак, начинаем обзор. Вспоминаем картиночку из предыдущего поста. Структура исходника примерно схожа с ней. Т.е. начальное состояние "intro", из него мы попадаем в "menu", из меню мы можем попасть в остальные места. Конечное состояние "quit" после которого следует выход из программы. В принципе, это стандартная схема и она используется в 99% игр.

А теперь мы, используя методы ООП, создаём Главный объект oGame. Объект oGame будет иметь доступ в любое место нашей программы (т.с. глобальный объект, синглтон и подобие функций main в одном лице). Это очень важно понять, особенно если вы занимаетесь ООП программированием. У этого объекта будет 3 части, как и у любого другого: Инициализация, Тело и Уничтожение. Запоминаем, 3 части.

Объект oGame обрабатывает все состояния, в нём инициализируется состояние начальным состоянием. Чтобы не корпеть с рисованием, занимаем цикл Draw. В нём делаем свитч на состояния. Опять так же, у каждого состояния 3 части, но не всем они нужны все 3. Здесь выбираем по обстоятельствам.

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

Теперь мы можем безопасно переходить от состояния к состоянию. Соответственно, разберём нужность 3 частей состояний (а именно 2 из них, инициализации и уничтожения). Входим мы в состояние "menu", нам же нужно меню? Нужно. Делаем его через список или любой другой вариант, но его нужно создать. Также нужно создать начальное положение игры, всё это происходит в инициализации. Но вот такая ситуация, вы хотите выйти из игры в меню, не теряя при этом саму игру, чтобы вернуться обратно. В данной ситуаций, ни инициализация, ни уничтожение не нужна в игре (чтобы при возврате в игру всё оставалось на своих местах). Вот такой момент нужно будет контролировать, когда нужна инициализация, а когда нет (соответственно, когда нужно удалять данные из памяти, а когда нет).

Идём далее. Проблема - пухнущий код. С этой проблемой вы столкнётесь при растущем проекте (уже где-то несколько сот строк кода). Решение позаимствуем у профи: запихиваем похожие по смыслу части кода в функций (в Game Maker - скрипты). Это действительно вам поможет структурировать программу. Всё что связано с вводом данных в input, инициализация и уничтожение, в init и destroy, соответственно и т.д. Хочу заметить, пока кода немного, это кажется детской забавой, но когда его будет очень много (>10000 строк) вот тогда вы действительно оцените по достоинству этот приём. Группировать функций можно по состоянию, если состояние game, то названия всех функций может начинаться с "game_".

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

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

Подведём итог:
  • Используем общий объект для общего управления.
  • У кода есть 3 части: инициализация, тело и уничтожение. Используем их по мере надобности.
  • Если кода слишком много, засуньте его в ... функцию.
  • Если структура программы слишком сложная, постройте вспомогательное ПО.

1 комментарий: