Зеленое счастье и никаких наркотиков!

воскресенье, октября 17, 2010

Первый "урок в неделю": Surface.

Добрый день! Сегодня я расскажу как использовать "поверхности"(surface) в своей игре. Меня попросил об этом постоянный читатель:
Ну а я принял его предложение, тем более что оно было самым первым, и на тот момент единственным.
Что нам нужно знать о поверхностях, прежде чем приступить к написанию кода?
  1. Определиться с тем, что мы будем программировать
  2. Стоит прочитать справку. Лучше конечно на английском языке.
  3. Хорошенько подумать, поискать варианты решения без поверхностей.
  4. И если таковых не осталось подумать еще раз. Попытаться отказаться от использования поверхностей.
И вот мы прочитали справку и пришли к выводу, что мы будем создавать подобие Paint на GM. Т.е. простую рисовалку, с минимумом функций. Давайте определимся с тем что у нас будет в программе?

  1. Можно рисовать карандашом различного размера.
  2. Можно рисовать кисточкой различной формы и размера
  3. Нужна удобная палитра
  4. При работе можно использовать несколько цветов на кнопках мыши.
  5. Должна быть стёрка, которая работает по принципу кисточки.
  6. Нужна пипетка.
Более чем скромные инструменты. Нет заливки, нет бесполезного распылителя, нет выделения и нет примитивов. Все это отличается высоким и низким уровнем реализации, их вы сможете сделать и сами. Думаю, никто против не будет, если я напишу задачи в OneNote?
Тут слегка больше чем я написал выше. Но еще не все. Во время написания программы, будем еще несколько раз обращаться к этому документу, исправляю пункты, и ставя галочки где нужно. Кстати, вот только что я добавил туда Масштаб и Текст ;).  Обычно игры пишут начиная с дизайн документа, я же рисую то, как игра будет выглядеть. Для меня это нечто вроде того самого документа.
В программе будут использоваться иконки с сайта dryicons.com в некоммерческих целях, использовать буду набор coquette. В нем я нашел почти все иконки, которые мне требовались, кроме стерки. Вместо нее будет тучка :). Обычно я рисую все аккуратно, но сегодня не судьба, потому что внешний вид не главное, и большая часть работы будет выполнена в GM автоматически. Замечу, цель нашего урока научиться рисовать на поверхностях, поэтому реализацию интерфейса я откладываю на следующий урок.
Поясню что-почем. Слева вверху - звездочка, это наша кисточка и ее размер. По середине - палитра, оранжевые кружки заготовки, их потом можно будет перетягивать на нижнюю палитру. На ней кстати, буквами R и L отмечены кружки, соответствующие правой и левой кнопке мыши. Сверху наши инструменты. Мне было лень добавлять все, поэтому они просто накиданы, но, настоятельно рекомендую в таких пытаться накидать все что можно и так как должно, ведь это ваш дизайн документ. Сама поверхность, на которой мы будем рисовать, под палитрой. Ее здесь невидно, но в исходном файле заметно. Прежде чем открыть GM нужно выполнить небольшую нарезку. Нам понадобится фон, и заготовка для кисточки. Фон может быть любым, я взял разблуренный скриншот своей игры, а в качестве кисточки взял звездочку.
Теперь мы готовы открыть GM8, и импортировать всю нашу нарезку. Создаем фон, называем его каким нибудь незатейливым именем, например bckBackground и загружаем туда фон. Также создаем спрайт кисточки sprBrush, ставим точку вращения по центру. Создаем объект objMain и добавляем его в комнату rmMain, у которой выбран фон. Кстати, размер нашей программы будет 640х480. Еще нужен шрифт, я выбрал Tahoma 10 кегль. В настройках проекта включите галочку interpolate color between pixels.
По хорошему, нужно тщательно спланировать, какие объекты у нас будут, как они будут взаимодействовать и все такое. Это правильно. Я не буду вдаваться в подробности, и попробую сделать это коротко:
У нас будет два объекта:
    objMain - который отвечает за отрисовку всего интерфейса, и за взаимодействие с игроком.
    objSurface - который отвечает за отрисовку поверхности рисования, а также за рисование на ней. При чем, объект поверхности может меняться, удаляться и т.п.
 Теперь приступаем к программированию, первым у нас будет объект objMain. Для начала, мы должны придумать все переменные, с которыми будет работать objMain и другие объекты. При чем некоторые нужно будет сделать глобальными.
  TOOL - глобальная переменная, отвечает за текущий инструмент  в наших лапках, равна 1.
  COLOR1,COLOR2  - глобальные переменные, отвечают за цвет.
  SURFACE - переменная типа objSurface. Это текущая живая поверхность. Здесь же, мы сразу и создаем ее оператором new... а нет, instance_create(0,0,objSurface);
Объявляем эти переменные в событии create, и присваиваем им начальные значения. Также делаем некоторые настройки внешнего вида, меняем шрифт на fntTahoma10.
После этого сохраняем проект с каким нибудь звучным именем, и незабываем добавлять число версии. Я например, сохранил как gmPaint_00.gmk .
Создаем новый объект, называем его objSurface, и сразу лезем в create. Нам требуется здесь создать саму поверхности и навести небольшой марафет. Код будет выглядеть так:
Чтобы потом не забыть, нужно сразу же создать событие destroy. В этом событии удобно освобождать ресурсы.
Собственно, мы убиваем нескольких зайцев одним выстрелом. Спрашиваем пользователя о сохранении картинки, освобождаем память, и сообщаем всем вокруг, что поверхность больше не существует. Кстати, тут есть ошибка. Попробуйте найти ;).
Теперь нужно нарисовать поверхность, это очень просто:
Я использовал draw_surface_ext на будущее, потому что масштабирование будет использовать эту фишку. Также я рисую рамку вокруг поверхности, это эстетично.
Уже можно запустить проект, и посмотреть на дело рук своих...
Вы увидите фон и на нем черную рамку. Нда, не густо. Сохраняем проект с новым именем gmPaint_01.gmk
Теперь займемся собственно отрисовкой на поверхности. Это делается также как и в событии draw. Но лучше делать это в другом месте. Мы будем делать это в событии step, объекта objSurface.
Первым нашим инструментом будет brush, ибо у него очень простая реализация.
На самом деле, на прозрачной поверхности рисовать весело, но иногда могут появиться различные артефакты вместо чистой поверхности. Поэтому в событие create объекта objSurface нужно дописать после создания поверхности такие строчки:

surface_set_target(surface);
 draw_clear(get_color(c_red));
surface_reset_target();

Здесь мы включаем режим рисования на поверхности surface, рисуем на всей поверхности выбранным цветом. Затем мы сбрасываем фокус рисования на экран. Это и есть принцип рисования на поверхности, ничего сложного ;).
Теперь заходим в событие step, и пишем туда такой код:
Здесь мы обрабатываем события нажатия кнопки мыши, для удобства, я завел две переменные mbl  и mbr. Если происходит клик на нарисованной поверхности, мы обрабатываем наш инструмент. Как и в событии create, мы переключаем фокус рисования на нашу поверхность, и рисуем на ней саму поверхность draw_surface.
Дело в том, что рисование на поверхности в gm сделано замещением исходных пикселей на новые. Т.е. если мы хотим нарисовать поверх непрозрачной поверхности прозрачным спрайтом, то на поверхности появиться дырка в виде прозрачного спрайта. Попробуйте закомментировать эту строчку, и попробовать порисовать на поверхности, думаю вы все поймете.
Теперь, в зависимости от того, нажата левая или правая кнопка мыши, мы рисуем на поверхности спрайт со случайным размером, вращением, прозрачностью, соответствующими цветами. Обратите внимание, что рисовать можно обеими клавишами одновременно. Позиция спрайта задается от 0,0 это локальная система координат для нашей поверхности. Проверяем наш проект, сохраняемся, и... на сегодня все. Теперь вы сможете нарисовать кровь на поверхности. Проект вы можете скачать, и пользоваться им в свое удовольствие.

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

6 комментариев:

  1. Хех, GM) Ностальгия. Ушел с него примерно 2 года назад. Сделали пару игр на энтузиазме. Флеш мне оказался больше по душе + заработок)

    ОтветитьУдалить
  2. Есть новости о том, что на GM скоро игры для мелких устройств писать можно будет, типа android, ipad, iphone.

    ОтветитьУдалить
  3. Если можно будет, то и у нас заработок будет: у бедных фанатов ГМ =)

    ОтветитьУдалить
  4. подпись...Фывапролдже...

    ОтветитьУдалить