Разработка стратегии шаг за шагом. Создание стратегии с нуля – подробное руководство Как самому сделать стратегию для pc

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

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

Хотя рассматривать будем вариант создания стратегии с нуля, начиная с идеи и заканчивая введением фильтром и окончательной доводкой ТС до ума, это не означает, что все готовые системы сразу нужно отбросить как заведомо неэффективные. Ряд ТС вполне можно использовать как основу и просто добавить несколько фильтров с тем, чтобы отсеять ложные сигналы.

Основные этапы создания стратегии

Если взять наугад штук 5-7 индикаторов и пробовать создать из них рабочую ТС, то что-то годное вряд ли получится. Сперва нужно продумать основную идею стратегии и только потом переходить к подбору инструментов. Можно предложить такую последовательность действий:

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

Важно ! При выборе таймфрейма нежелательно сильно уж мельчить, особенно если у трейдера нет опыта спекуляций на малых временных интервалах. Для новичков вообще лучше не спускаться ниже Н1-Н4, подробнее о выборе оптимального временного интервала можно прочесть .

  • следующий этап – подбор подходящих инструментов, и вот здесь обилие выбора может сыграть с трейдером злую шутку, ведь в его распоряжении десятки индикаторов, возможность использовать свечной, волновой, технический, фундаментальный анализ. Из всего этого разнообразия нужно выбрать несколько инструментов, лучше всего подходящих под предполагаемый стиль торговли;
  • одно из главный правил любой стратегии – полученный сигнал должен подтверждаться несколькими фильтрами, но желательно ограничить их количество. Например, для индикаторных стратегий нежелательно, чтобы число индикаторов превышало 3-4, иначе возникнет путаница в сигналах, а если работать планируется с использованием теханализа, то индикаторы и вовсе будут выполнять вспомогательную роль;
  • разрабатываются правила сопровождения позиции, в результате должен получиться алгоритм действий на любой вариант развития событий;
  • последний этап – обкатка ТС сперва на истории, а потом и на демо-счете, а лучше на реальном центовом счете. Основная цель – проверка жизнеспособности стратегии в реальных условиях, а реальный счет (пусть даже и центовый) позволит прочувствовать весь спектр эмоций, начиная от эйфории и заканчивая горечью потерь.

Еще можно посоветовать не зацикливаться на сложности ТС. Практика показывает, что чрезмерная сложность – вовсе не показатель эффективности. Чем проще система, тем легче торговать.

Что стоит включить в ТС

Создание стратегии немного напоминает конструктор, нужно только удачно подобрать детали. При создании ТС использовать можно и нужно:

  • индикаторы. Причем не стоит гнаться ни за их числом, ни за чрезмерной сложностью, даже в полностью механических ТС достаточно 3-5штук;
  • графические паттерны – хорошо известные флаги, вымпелы, треугольники, голова и плечи, двойные дно и вершина по-прежнему хорошо отрабатывают;
  • графические построения;
  • Фибо уровни;
  • элементы фундаментального анализа – сейчас зарабатывать исключительно на новостях сложно, но учитывать экономический календарь в торговле необходимо. Хотя бы просто переставить сделки в безубыток перед выходом важной статистики по США или Европе, а то и полностью закрыть прибыль.

Есть и ряд приемов, польза которых вызывает сомнения:

  • мартингейл – изначально убыточная тактика, единственный шанс на успех заключается в том, что до момента слива удастся отбить величину депозита и немного заработать;

  • локирование без крайней нужды также использовать нежелательно, потом выйти из замка довольно трудно;
  • сигналы со стороны также лучше не использовать. Под сигналами со стороны подразумевается, например, сравнение количества продавцов/покупателей, различные индексы настроя большинства трейдеров и т. д. Но есть и ряд ресурсов, к которым можно прислушаться, например, Авточартист дает неплохие сигналы по графическим паттернам;
  • элементы волнового анализа также лучше неиспользовать (по крайней мере новичкам). Хотя и здесь есть исключения, например, торговля по Волнам Вульфа основана как раз на волновом анализе, но сложностью не отличается.

Разработка простейшей индикаторной стратегии

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

Стратегия должна работать практически на любой валютной паре, это необходимо потому, что из-за крупного таймфрейма сигналы будут возникать не очень часто. Так что оценивать ситуацию будет одновременно по 5-7 валютным парам. Что касается таймфрейма, то подойдет D1, исходим из того, что форекс на начальном этапе – лишь дополнение к основной работе, поэтому и торговать будем на дневныхсвечах.

Теперь нужно определиться с тем, как именно будет определяться момент для входа. Вариантов идентификации тренда можно придумать немало:

  • визуально – но оценка на глаз не позволит выработать четкие правила торговли;
  • с помощью одной или нескольких скользящих средних;
  • по значению индикатора ADX, если больше 30 – то сильный тренд, меньше 20 – на рынке штиль;
  • с помощью графических построений;
  • Bollinger Bands позволяет судить о силе тренда по расстоянию между верхней и нижней границами канала.

В общем, вариантов много, но так как стратегия нужна максимально простая, остановимся на скользящих средних. А точнее одной МА, судить о направлении тренда будем по положению цены относительно нее. Начать можно с периодов, усредняющих цену за целый промежуток времени (неделя, месяц, квартал и т. д.), например, 20 – усреднит цену за прошлый месяц. Самое сложное – подобрать подходящий период МА, но тут уже придется действовать методом проб и ошибок.

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

  • сперва проверяем положение цены относительно МА, цена должна быть выше линии;
  • далее нужно найти трендовое движение, нам нужна свеча с большим телом и малыми тенями (желательно, чтобы величина тени не превышала 10-15% от величины тела свечи);
  • после нее должна следовать свеча с малым дневным диапазоном (расстояние от High до Close). Цена Close не должна доходить до уровня 50% от предыдущего дня – в этот день происходит коррекция цены.

При этом коррекция может проходить по 2 сценариям:

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

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

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

Вход в начале тренда

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

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

Это не революционный подход, нечто подобное использовал еще Билл Уильямс в своем знаменитом Аллигаторе. Так что этот индикатора даже можно взять как основу ТС.

Если добавить Аллигатор со стандартными настройками на Н1, то видно, что он дает немало ложных сигналов, наша задача – отсеять их. Для этого входить в рынок будем отложенным ордером, а уровень его выставления будет определяться с помощью Фракталов.

В итоге схема работы будет выглядеть так (на примере покупок):

  • ищем флетовый участок на графике (все линии Аллигатора хаотично переплетены друг с другом);
  • далее нужна фрактальная свеча (причем она должна располагаться над линиями, не касаясь их даже нижней тенью);
  • ордер buy stop выставляется чуть выше ее максимума, а защитный ордер – за нижней границей зоны консолидации;
  • ТР либо фиксированный (50-70 п), либо использовать трейлинг-стоп. Вообще предсказать силу трендового движения довольно сложно, поэтому лучше использовать трейлинг-стоп, чем фиксированный ТР либо определять целевой уровень с помощью того же теханализа.

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

Пример простой комбинированной системы

Идея все та же – вход на окончании коррекции, но решать эту задачу будем другим способом. Цель остается прежней – определить момент завершения коррекции и войти в направлении тренда, но если раньше мы применяли скользящую среднюю, то теперь будет использовать Фибо уровни и осциллятор для определения завершения отката.

Нас будет интересовать ярко выраженное трендовое движение, его можно определить и визуально. После этого нужно просто растянуть Фибо уровни на него, это нужно для определения потенциальных уровней завершение коррекции. Наибольшую значимость имеет уровень коррекции 38,2%, допускается торговать на отбой от 50% и 61,8%.

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

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

Фибо уровни и осциллятор – лишь необходимый минимум, нужный для получения сигнала. При желании можно усложнить систему, введя дополнительные фильтры.

Стратегии на основе технического анализа

Если использоваться будет теханализ в чистом виде, то задача несколько упрощается, разрабатывать ТС с нуля уже не нужно. Есть ряд приемов и инструментов, эффективность которых проверена годами, а трейдеру остается только выбрать подходящие и использовать их при построениях.
В принципе, для успешной торговли достаточно:

  • трендовых линий – их строим на разных таймфреймах, начиная со старшего и постепенно опускаясь к рабочему;
  • Фибо уровней, их следует растягивать на значимые движения ценына истории. Ключевое значение будут иметь уровни коррекции 38,2, 50 и 61,8%, практика показывает, что коррекция чаще всего завершается как раз у этих отметок;
  • в МТ4 реализован и ряд других инструментов теханализа, например, вилы Эндрюса, набор инструментов Ганна, несколько видов каналов и т. д.

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

Что касается дополнительных фильтров, то добавить можно свечные паттерны и какой-нибудь индикатор для поиска дивергенций (тот же Стохастик или MACD). Подробнее о применении теханализа можно прочесть .

Фильтры для торговых систем

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

Есть ряд фильтров, которые подойдут практически под любую стратегию:

  • ситуация на старших таймфреймах. Если, например, стратегия ведется на Н1 по механической стратегии, то не лишним будет взглянуть на то, что творится на Н4 и D1;
  • средний дневной диапазон, имеется ввиду расстояние, которое цена проходит в среднем за день, при внутридневной торговле это поможет отфильтровать ряд сигналов. Представим, что за день цена в среднем проходит 100-120 п, если в один из дней цена к вечеру уже прошла в одном направлении пунктов 90-100, а ТС дает сигнал на вход в рынок в том же направлении, то есть смысл его проигнорировать, статистика говорит, что движение в этот день вряд ли продолжится;

Важно ! Соблюдение этого правила приведет к тому, что часть прибыльных сделок будет упущена, зато повысится соотношение прибыльных/убыточных сделок.

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

Когда ТС дает сигнал, то в идеале ситуация должна начать развиваться в нашу пользу практически сразу же после заключения сделки (имеется ввиду на следующих 1-3 свечах). Если этого не происходит, то чем больше прошло времени с момента заключения сделки, тем меньшее влияние на рынок окажут те факторы, которые имели значение, когда трейдер входил в рынок. Их влияние затухает со временем.

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

Это условие применимо практически ко всем таймфреймам (за исключением m1-m5). Конечно, сохраняется вероятность, что цена, потоптавшись около одной отметки, уйдет в нужную сторону, но наш выбор – стабильность. Лучше пожертвовать парой прибыльных сделок, зато избежать 3-5 убыточных.

Подведение итогов

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

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

Сам процесс напоминает сбор конструктора – сперва ставим задачу, а потом просто подбираем нужные инструменты для ее решения. После проверки на истории можно переходить к тесту ТС на демо- или центовом счете.

theme_park:
IНам понадобиться:
спрайт здания
спрайт меню
спрайтЫ разнЫХ кнопОк таких как:
срайт с надписью(стройка, строительство, построить и т.д.)
окошко, которое будит появляться
рисунок со зданием,
1)остальное сами будим добавлять
2) слово подделочные-создал сам, т.к. нам понадобиться подделывать под свой исходник)
IIПриступим:
1)создаём всё что написано в пункте I кроме 1)
Создадим глобальную переменную под названием money, установите любое изначальное кол-во денег
Так же сделаем объект mouse & keyboard
Создаём текст назовём его info, сделаем событие always, в нём создаём action:
выбираем info в выборе действий выбираем set text в тексте пропишем вот это:
"money: " &(global("money".
2)добавим меню ,главной задачей меню: не мешать, а помогать игроку ориентироваться(как оно может мешать?-легко, если вы поставите его по середине игры);прежде чем сделать меню создадим новый layer, который назовём menu,в его пропорциях(настройках, опциях) в пункте display пропишем:


в нём добавим спрайт и возьмём изображение меню, которое было в предделочных материалах(пункт I) и поместим наше меню в укромное местечко где оно не будет мешать, но будет видимым на экране
поместим также кнопку из предделочных материалов(пункт I) с надписью СТРОИТЬ(или что-то в этом роде)
положим её на меню
теперь заходим в Event Sheet Editor
создаём событие(#бла-бла-бла#-это моё сообщение(пояснение) вам только вместо бла-бла-бла будет стоять мой комментарий для вас;>>-действие;ll-деление окошками например:

mouse&keyboard ll on object clicked ll left clicked to object #кнопка вашего меню с надписью СТРОИТЬ(или что-то в этом роде)##остальное потом (см. 3пункт)#
3)теперь Самое сложное (я разбил это на два пункта чтобы это не было столь за мудрено),
создаём спрайт из предделочных материалов "окошко, которое будит появляться"
потом создаём пустой спрайт под названием p1, окошко отодвинем за пределы экрана, а p1 поставим на место где должно появиться ваше окошко при нажатии кнопки строить(или что-то в этом роде ЧВЭР)
отлично!Теперь переходим в event sheet editor
пропишем не доделанное событие до конца:
Text ll set text ll bla-bla-bla)
mouse&keyboard ll on object clicked ll left clicked to object #кнопка вашего меню с надписью СТРОИТЬ(ли что-то в этом роде)#>>
4)Вторая часть самого сложного :
создадим спрайт спрайт где будет нарисовано изображение здания(предделочные материалы)назовём h1
создадим пустой спрайт, назовём p2, теперь поместим его на место где должно открыться окошко,
создадим спрайт-тоже окошко(предделочные материалы),в окошке красиво напишем название здания, его стоимость и описание(по желанию)назовём i1
создадим ещё один пустой спрайт, под названием р3, поместим его рядом с р2, только чтобы он касался р2 только верхним левым углом
теперь создадим несколько событий,но сначала до делаем прошлое событие одним новым действием:
mouse&keyboard ll on object clicked ll left clicked to object #кнопка вашего меню с надписью СТРОИТЬ(ли что-то в этом роде)#>> sistem ll create object relative to object ll #ваше окошко# #номер layer под именем menu# #X;Y-не меняем# to object p1
>>sistem ll create object relative to object ll #ваше второе окошко# #номер layer под именем menu# #X;Y-не меняем# to object p2
Нам надо ещё сделать обратно ему событие:
копируем событие и инвертируем
new event
mouse&keyboard ll is over object ll h1>>sistem ll creat object to relative to object ll i1 #номер layer под именем menu# #X;Y-не меняем# to object p3
Cделаем спрайт со зданием(пользуйся предделочными материалами)назовём house
Создадим окно где будут появляться наши здания при их выборе в меню назовём rlo
события:
mouse&keyboard ll on object clicked ll left clicked to h1>>sistem ll create to object relative to object ll house #номер layer под именем menu# #X;Y-не меняем# to object rlo
>> sistem ll subtract from value ll #кол-во денег которое должно отняться при строительстве#
теперь событие чтобы строить было нельзя
я вам расскажу мой бывший способ запрещения (когда закончу писать исследую ещё один способ, которому меня о синило когда я вспомнил игру theme park world)
события:
house ll on collision with another object ll to house
>>house ll destroy
>> sistem ll subtract from value ll - #удвоенное кол-во денег которое отнялось при строительстве##заметьте вы должны поставить - кол-во#
в принципе всё.
IIIчто хочу сказать:

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

KaMiKaZa:
Все "системные" выражения нужно внести в тег "Код".
Тогда, думаю, лучше будет.
Ещё, мне кажется, скрины тут бы не помешали. А также исходник, для новичков.

theme_park:
я не умею делать скрины событий.

ну это не обязательно.

iamnp:
theme_park , есть спец кнопка на клаве - PrintScreen

theme_park:
я знаю просто некоторые по другому делают.Тем более у каждого свой спрайт
и если я понаставлю все эти спрайты мало кому будет понятно.
ну может кто плюсанёт? Не зря же я корячился?

burlachenko:
Что бы такой урок кого-то заинтересовал, его нужно соответственно оформить, а здесь "абы было".
И все таки если будет желание, по чуть чуть, когда будет время "прихорошите" его пожалуйста.

theme_park:
окей, приду со школы прохорошу.
ПС. добавил исходник

Serega Lebedev:

iamnp , а куда эти скрины потом деваются?

KaMiKaZa:

В буфер обмена.
Зайди в любой текстовый редактор, и выполни операцию "Вставить", либо нажми Ctrl+V.

Формирование стратегии
нельзя доверять дилетантам:
их планы могут неожиданно сработать,
а к этому никто не готов.

(А.Канингем)

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

На этот раз мы перейдем от аркад к более «серьезному» жанру - стратегиям. Здесь нам придется освоить целую серию новых механизмов, но ничего сложного не будет и здесь. В этой статье мы изучим устройство пошаговой стратегии (а также и стратегии реального времени - ее с ЛКИ-Creator"ом делать даже проще) и сделаем для примера игру, рассчитанную, однако, только на многопользовательский режим (а также редактор карт для нее). Одиночным же режимом мы займемся в следующем выпуске нашей рубрики - посвященном основам искусственного интеллекта .

Поскольку это уже третье занятие, мы не будем в подробностях разбирать весь код примера - благо многое сделано точно так же, как в два предыдущих раза. Для справок есть программа-пример (в ней немало комментариев) и предыдущие статьи.

Ну, а материалы наших прошлых занятий вы можете найти на нашем компакт-диске , в специально созданном для этой цели разделе «Игра своими руками».

Постановка задачи

Напишем стратегическую игру, состоящую из сражения двух фэнтези-армий. Цель битвы - захват нескольких обелисков , расставленных по карте. Перед сражением мы расставляем свои войска, состоящие из 6 мечников , 4 лучников , 2 рыцарей , 2 магов и 1 призрака , в пределах отведенной нам территории. Кроме них, на карте бывают нейтральные драконы .

Характеристики бойцов
Боец Передвижение Хиты Дальнобойность Повреждения Защита Способности
Мечник 4 8 1 7 2 -
Лучник 4 5 7 5 1 -
Рыцарь 3 15 1 9 4 Лечение, рыцарский удар
Маг 3 12 5 6 0 Огненный шар
Привидение 4 7 2 5 5 Регенерация
Дракон 6 30 2 12 5 Полет

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

Игра идет в многопользовательском режиме, в варианте Hot Seat (игра с одного компьютера, ходы по очереди). После хода игроков делают свой ход нейтральные драконы, атакуя любого противника в радиусе 7 клеток.

Партия заканчивается, когда одна из сторон либо захватывает более половины присутствующих на карте обелисков, либо гибнет полностью.

Карта задана изначально в редакторе карт. На ней расставлены обелиски, драконы и препятствия (объекты, через которые нельзя двигаться и атаковать).

Подготовка к работе

Перед началом работы нам потребуется переустановить пакет ЛКИ-Creator . Дело в том, что по сравнению с прошлым разом в него внесено немало изменений и дополнений.

(Надеюсь, что Delphi у вас уже установлен; если нет, то рекомендации на эту тему читайте в нашей предыдущей статье - в июньском номере журнала или на CD этого номера или на сайте .)

Это важно: в предыдущей версии ЛКИ-Creator были некоторые проблемы совместимости с новыми версиями Delphi. В этом варианте они устранены.

Возьмите с нашего компакт-диска (раздел «Игра своими руками») файл с текстами программ и картинками и распакуйте его в каталог проектов.

Теперь вы можете скачать нужные файлы отсюда .

У нас должно получиться три подкаталога. В одном - Units - хранятся библиотеки DirectX и модули пакета ЛКИ-Creator. В другом - Project - мы будем работать; туда заблаговременно положены картинки, которые нам понадобятся, и предыдущая версия нашей аркады. В третьем - Escort - готовая программа, которая должна у нас получиться.

Теперь установим (переустановим) ЛКИ-Creator. В меню Delphi откройте пункт Component, в нем выберите Install Component. Если у вас уже был установлен этот пакет, оставайтесь на закладке Into existing package, иначе перейдите на закладку Into new package и заполните пустые строчки, как показано на рисунке (в верхней строчке проще всего выбрать файл LKI2dEngine.pas с помощью кнопки Browse, а в нижней просто запишите LKI). После чего нажмите OK и выберите Install. В верхней панели Delphi у вас должна появиться закладка LKI.

Теперь осталось только загрузить наш проект. В меню File выбираем Open, открываем файл Project\Obelisk.dpr…

Где карта, Билли? Нам нужна карта!

Однако прежде, чем заняться «высокими материями», нам понадобится еще немного потрудиться над графическим движком.

В «Звездном эскорте», нашем предыдущем проекте, «карта» никакого значения не имела: звезды расставлялись случайно и не влияли ни на что, а положение остальных объектов либо задавалось прямо в коде, либо определялось случайно. Это годится далеко не для всякого проекта. А значит, нам пора добавить к нашему движку карту местности .

Как это будет выглядеть, вы, вероятно, уже догадываетесь - ставим на окно проекта объект-карту, а потом прописываем ее в свойстве Map нашего движка.

Так-то оно так… но у нас далеко не один класс карты. Посмотрим подробнее…

Типы карт

Карта состоит из некоего ландшафта и объектов , установленных на нем. Ландшафт чаще всего (но не всегда) разбит на клетки, которые называют tiles - плитками .

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

С квадратами, в некотором смысле, жить проще: если у нас есть двумерный массив клеток, сразу понятно, как найти соседние с заданной клетки. Это +1 и -1 по каждому из двух индексов. С шестиугольниками все несколько сложнее… но зато гексагональная доска обладает очень ценным свойством: все направления в ней одинаковы. У квадратной сетки это не так: диагонали существенно отличаются от горизонталей и вертикалей. Поэтому для серьезных стратегических расчетов шестиугольники могут быть лучше квадратов.

Бывают и неплиточные карты. ЛКИ-Creator поддерживает два их типа: графовые и лоскутные.

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

Лоскутная карта разбита на области, и внутри области все точки одинаковы, двигаться по «лоскутку» нельзя. Это хорошо для глобальных стратегий, где провинция - минимальная единица территории.

Примеры карт из разнообразных игр, с указанием типа - на рисунках.

Итак, большинство двумерных карт (трехмерные - особая статья) можно разделить на четыре класса:

  • Прямоугольная - TLKIRectMap . Это плиточная карта, клетки - квадраты. Такая карта, например, в Civilization III.
  • Шестиугольная - TLKIHexMap . Плиточная карта с шестиугольными клетками. Используется во множестве wargames, и не только: так, например, традиционно делалась боевая карта Heroes of Might & Magic.

    Два этих типа карт - потомки общего класса TLKITileMap .

  • Графовая - TLKIGraphMap . У этой карты есть фон (свойство Background) и выделенные на ней ключевые точки - статичные объекты. Положение других объектов на этой карте выражается либо обычными координатами (как у космического корабля в межзвездном пространстве), либо привязкой к объекту (тот же корабль - на орбите планеты). Таковы карты Master of Orion, Arcanum (глобальная) и так далее.
  • Лоскутная - TLKIClusterMap . У нее есть свойство фона, как и у графовой, и второе свойство - маска (Mask) , которое определяет, какая точка к какой области принадлежит, и свойство Borders , задающее связи между «лоскутками». Так устроены карты, например, в Medieval: Total War или Victoria.

Это важно: классы карт описаны не в модуле LKI2dEngine, а в LKI2dMap.

Углы наклона

Но если вы думаете, что этим и исчерпываются возможности ЛКИ-Creator"а по отображению карт, то вы сильно ошибаетесь.

Карта может быть представлена видом сверху или же изометрическим - взгляд под углом к вертикали. Например, карта Civilization III или Heroes of Might & Magic IV - изометрические, а в Civilization I принят вид сверху.

Обычно изометрия в ходу у плиточных карт, а графовые обходятся видом сверху, поскольку масштаб у графовых карт обычно мельче. Но бывают и исключения: например, в Medieval: Total War - лоскутная изометрическая карта.

За изометричность отвечает свойство карты IsIsometric и два параметра, задающие угол, под которым смотрит наша камера: Phi и Theta .

Первый отвечает за поворот карты относительно вертикальной оси: например, если задать его равным 45 градусов (он измеряется именно в градусах), то клетка прямоугольной решетки будет ориентирована углом вверх, как в Civilization. При Phi=0 одна из сторон клетки будет горизонтальной.

Второй заведует наклоном камеры по отношению к вертикали. Для удобства он задан как соотношение горизонтальных и вертикальных единиц длины. Скажем, если мы хотим, чтобы наша клетка рисовалась по высоте вдвое меньше, чем по ширине, нам надо присвоить Theta значение 2.

При плиточной карте выбирать эти углы произвольно нам не дано: все-таки у нас (пока) не 3D. Они напрямую зависят от параметров плиток. Например, если она у нас ромбообразная, углом вверх, и вертикальная ось вдвое меньше горазионтальной, то мы обязаны задать параметры 45 и 2.

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

Стыки

Лоскутная карта, вид сверху.

У плиточных карт есть еще одна проблема - стыковка плиток. Ею заведует параметр TileBorderStyle . Чаще всего это tileStraight , режим, в котором плитки просто прилегают друг к другу без каких-либо краевых эффектов, или tileBorder , в котором рисуются линии, отсекающие одну плитку от другой - границы клеток (в последнем случае не забудьте определить цвет решетки в параметре TileBorderColor ).

Но есть и более хитрый вариант, когда одинаковые плитки прилегают друг к другу без изменений, а разные - с использованием специальной «переходной» плитки. Так делают обычно, если карта состоит в основном из широких пространств одного типа территории, скажем, больших зеленых площадей, а отдельная клетка не важна и не должна замечаться игроком. Такова карта Heroes of Might Magic. А вот если каждая клетка обрабатывается отдельно, как в Civilization, тогда этот метод не годится, и лучше четко отделить клетки друг от друга. «Слитная» технология (ее еще называют масочной ) задается значением TileBorderStyle, равным tileMasked . Об их устройстве мы поговорим в другой раз - это достаточно сложная тема.

Плитка

Элемент карты - объект класса TLKITile - обладает простой структурой. В нем изначально заложены: координаты, спрайт, который его рисует, код типа плитки (по которому определяется, что у нас тут - холм, пустыня, дорога, море?) и проходимость (это актуально в большинстве игр). Последняя - это число единиц хода, которые тратятся на передвижение через эту плитку сухопутным отрядом. Для непроходимых плиток здесь стоит отрицательное число.

Еще один параметр - Objects , список находящихся на этой плитке объектов (типа TLKIGameObject).

Чтобы узнать, по какой клетке щелкнули мышкой, у карты есть метод MouseTile (x,y), возвращающий выбранную плитку.

В числе методов плитки есть IsNeighbour (Tile, Distance). Эта функция возвращает истину, если плитка Tile отстоит от данной не более, чем на Distance клеток (по умолчанию этот параметр приравнивается единице, то есть, если вы напишете просто IsNeighbour(Tile), функция даст истину для непосредственно прилегающей к данной плитки. У квадратной решетки «соседями» считаются и те плитки, что граничат по диагонали.

Функции FirstNeighbour и NextNeighbour используются для проверки всех клеток, соседних с данной. Первая из них указывает на какую-то клетку-соседа, а вторую можно вызвать только после вызова первой, и она выдает следующих соседей, по одному.

Перебор соседей

// Нанесение повреждений по клетке

procedure TObeliskTile.Damage(dmg: integer);

if (Objects.Count > 0) and // У нас может быть

// не больше одного объекта на клетке

(Objects.ID > 0) // Пассивные объекты

// не повреждаются

Dec(Objects.Hits,

// Автоматически вычитаем из повреждений защиту

Max(0,dmg-(Objects as TObeliskGameObject).Defense);

if Objects.Hitsthen Die; // Убираем убитых

// Атака огненным шаром

procedure TObeliskTile.Fireball;

var Neighbour: TObeliskTile;

Neighbour:= FirstNeighbour as TObeliskTile;

Neighbour.Damage(6);

Neighbour:= NextNeighbour as TObeliskTile;

until Neighbour = nil; // Пока не кончатся соседи

Пример - на врезке «Перебор соседей». Эта процедура обсчитывает удар огненным шаром по клетке и всем ее соседям.

Это интересно : для ее работы совершенно неважно , шестиугольная у нас решетка или квадратная.

Часто нам требуются еще какие-то параметры, и обычно класс плиток, из которых состоит карта - потомок TLKITile. Так и в примере - TObeliskTile унаследовано от TLKITile.

Это важно: если мы вносим на наш игровой экран плиточную карту, координаты, а также методы TLKIGameObject, связанные с дистанцией, по умолчаниюначинают измерять расстояние в плитках, а не в точках. Координаты же кнопок, значков и т.п. продолжают мериться в пикселах! Но этот режим можно и отключить - это бывает полезно для стратегий реального времени.

Выбор карты

Итак, возьмем для начала прямоугольную решетку (TLKIRectMap), изометрическое отображение (угловые параметры 0, 1.5). Пусть сетка у нас рисуется (стиль tileBorder). Укажем движку, что именно эту карту надо отображать. Пока что все нужные действия совершены без написания единой строки кода.

Эти операции надо сделать до инициализации движка, как и объявление шрифтов.

Фигурки объявим, как и раньше - спрайтами.

Редактор карты

Лоскутная карта, изометрическая.

Трудностей тут довольно немного. Такой же точно движок, такие же объявления плиток… Интерфейс, вроде выбора плитки, загрузки/сохранения и т.п., можно запросто сделать стандартными средствами Delphi: никто же не заставляет нас переводить его в полноэкранный режим. Разбирать это здесь мы не будем - все есть в файле с примером. В коде примера сознательно использован простейший способ; при желании можно, например, палитру объектов и палитру плиток делать графическими.

В редакторе есть всего две незнакомых нам особенности. Первая довольно проста: это новая функция мыши, предназначенная специально для «плиточных» карт. Функция TLKIRectMap.SelectTile возвращает нам указатель на именно ту плитку, по которой щелкнули мышью, так что мы легко можем обработать нажатие.

А вот вторая новинка заслуживает более тщательного рассмотрения.

Вообще-то существует множество способов сохранять в файл и считывать из него данные. Мы выбрали способ, закодированный в файле CannonBase . Cannon - это средство для считки и записи объектов-потомков TCannonObject с контролем типов и некоторыми другими особенностями.

Посмотрим на код («Запись карты»).

Запись карты

procedure TObeliskMap.Save;

var i,j: integer;

InitSave(FName);

WriteStr(MapName);

Write(Map.Width, SizeOf(Map.Width));

Write(Map.Height, SizeOf(Map.Height));

for i:=0 to Map.Width-1 do

for j:=0 to Map.Height-1 do

Write(Map.Tiles.Code, SizeOf(integer);

Вот как это работает. Сперва нужно открыть файл специальной процедурой InitSave , у которой единственный параметр - имя файла. Затем сохраняем заголовок для контроля типов - специальной процедурой WriteHeader . Потом записываем все, что нам нужно, используя процедуру WriteStr для строк, а для всех остальных полей - Write (ее второй параметр - размер записываемых данных в байтах). По мере необходимости для полей-объектов можно написать собственные процедуры Save c записью заголовка. Наконец, закрываем файл процедурой FinSave .

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

RegisterUserName(tpMap, "TObeliskMap");

TpMap - это константа, которую вы тоже должны объявить. Приравняйте ее, скажем, 1. А в конструкторе объекта TObeliskMap присвойте значение этой константы параметру TypeID .

Зачем такая возня? Помимо проверки соответствия типов, вы получаете одно очень важное преимущество.

Если формат файла изменится, скажем, из-за добавления новых полей - вам не понадобится писать никаких «конвертеров», преобразующих старые файлы в новые. Ваш код автоматически прочитает их.

Такой код автоматически инициализирует новое поле как пустое, если в файле оно не сохранено. А записывать файл можно, просто добавив строку WriteStr(Name) в самый конец.

Замечание: если вам все равно пока непонятно, для чего такой процесс, не беспокойтесь. Можно пользоваться более привычными методами записи-сохранения. Но в действительно масштабных игровых проектах этот путь дает изрядные преимущества.

Играем

Первым делом нам нужно создать новый класс, порожденный от TLKIGameObject. Свойств старого нам будет не хватать. В новом классе нужно добавить поля для основных характеристик: дальнобойности, передвижения и так далее.

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

На наш экран нанесем кнопки TLKIButton в форме лучников, мечников, мага, призрака, рыцарей.

Сначала у нас идет расстановка. Определим зону расстановки для одной стороны как верхние три «строки» карты, для другой - как нижние три «строки».

Код устроен так. При нажатии на любую из кнопок активизируется установка соответствующего бойца; щелчок по незанятой клетке в области расстановки помещает фигурку туда и отключает кнопку. Как только все кнопки отключены - ход передается противнику.

В начале каждого нового хода все кнопки включаются снова: это делается затем, чтобы человеку было проще заметить, кем он еще не походил. Соответственно, щелчок по кнопке выделяет фигурку, а как только ход сделан - кнопка пропадает. Еще одна кнопка - «Конец хода» - появляется только после фазы расстановки.

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

Ход фигуры

// Если выбранная клетка занята противником - атакуем,

// если свободна - передвигаемся, если занята своими

// или препятствием - игнорируем нажатие

Tile:= Map.MouseTile(MouseX, MouseY);

if (Tile = nil )// Щелчок за пределами игрового окна

then exit;

// Перемещение

if (Tile.Objects.Count = 0)

and (Dist(Self)

and not Moved then

// Проверяем, удается ли прийти туда

if not HasWay(Tile) then exit;

MoveObj(ID, Tile.x, Tile.y);

// Игра походовая - перемещаем сразу же

Moved:= true;

//

if Attacked then

Icon.IsVisible:= false ;

// Атака

if (Tile.Objects.Count > 0)

and (Dist(Self)

and not Attacked then

Obj:= Tile.Objects;

// Атакуем только врагов

if Obj.Side = Side then exit;

Obj.Damage(dmg);

Attacked:= true;

// Если ход сделан полностью - убираем значок

if Moved then

Icon.IsVisible:= false ;

Ход обрабатывается так (см. «Ход фигуры»). Находится клетка, по которой щелкнули. Если на ней враг, и они в пределах дальнобойности - ему наносится вред, если она пустая и в пределах дальности хода - фигура перемещается (если позволяют препятствия), если же она занята, но не врагом - нажатие игнорируется.

Когда походили обе стороны, действуют драконы. Они действуют очень просто: выбирают ближайшего не-дракона, который находится в пределах 7 клеток от них, и атакуют. См. код «Действия дракона».

Действия дракона

// Проверяем плитки в пределах 7 клеток от дракона

for i:= Max(0, x - 7) to Min(MaxSize, x + 7) do

for j:= Max(0, y - 7) to Min(MaxSize, y + 7) do

if (Map.Tiles.Objects.Count > 0) and

(Map.Tiles.Objects.Code>1)

// 0 - код препятствия, 1 - дракона

then begin

// Выбираем точку для перемещения

if x=i then ax:= i

else if x>i then ax:= i+2

else ax:= i-2;

if y=j then ay:= j

else if y>j then ay:= j+2

else ay:= j-2;

MoveObj(NO, ax, ay);

// Атакуем

Map.Tiles.Damage(12);

// Прерываем цикл: не больше одной атаки

// каждым драконом за раунд

Наконец, осталось только проверить, не занято ли больше половины обелисков войсками одной стороны - и если занято, то остановить игру и объявить победителя!


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

В будущих номерах

В следующих номерах мы поговорим о:

  • системах «частиц» (particles) для отображения дыма, искр и т.п.;
  • работе с прозрачностью;
  • трехмерных движках;
  • основах AI;
  • отладке программы;
  • создании замысла и сценария игры,
  • написании дизайн-документа;
  • игровом балансе;
  • продумывании игровых персонажей и их реплик;
  • работе с Photoshop и трехмерными пакетами;
  • анимации;
  • музыке и озвучке;
  • и многом другом.

Все это вполне реально научиться делать своими руками. Вы скоро в этом убедитесь.

Пишите нам…

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

Для самостоятельной работы

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

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

А если в реальном времени?

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

  • не понадобится поле GameSpeed у класса TObeliskObject - пользуемся скоростью Speed из базового движка (cкорость перемещения по экрану равна игровой скорости);
  • отключается целочисленный обсчет расстояний;
  • переписывается код движения фигуры - с учетом того, что надо отрисовать траекторию в обход препятствий;
  • убирается кнопка "конец хода".

Вот и все. Попробуете сделать сами?

Привет всем! Сейчас я расскажу вам как сделать простую ртс-ку (РТС - RTS - Real Time Strategy то есть стратегия в реальном времени) открываем гамак 8.1 (на 8.0 работоспособность не гарантируется) создаём объект objControl, то есть это будет наш главный объект создаём событие создания (Create) Добавить событие => Создание (Add event => Create) событие создание делается всего один раз - при создании, нажимаем на вкладку control в правом вертикальном меню и нажимаем ПКМ по Execute code (Выполнить код) и пишем код (лучше всего не копировать код, а писать его самому, так гораздо легче запомнить):

200?"200px":""+(this.scrollHeight+5)+"px");">startx=0; //Объявляем переменную начала точки по х
starty=0; //Объявляем переменную начала точки по у
draw_rect=false; //Не рисуем прямоугольник выбора


Переменная: часть памяти, которая содержат информацию. Они имеют своё имя, с помощью которого Вы можете обратиться к ним. Переменные в GML могут содержать реальное число или строку. К примеру, стол - это переменная, деревянный или стеклянный - значение
Теперь создаём событие шага (Step, Add Event = > Step) и выполняем операцию заново (нажимаем ПКМ по Execute code (Выполнить код)):

200?"200px":""+(this.scrollHeight+5)+"px");">
if mouse_check_button_pressed(mb_left) //Если ЛКМ нажата
{
draw_rect=true; //Мы рисуем прямоугольник
startx=mouse_x; //Стартовая х позиция = положение х мыши
starty=mouse_y; //Стартовая у позиция = положение у мыши
with all selected=false; //Это пока не объявленная переменная, что она будет делать мы узнаем позже
}

If mouse_check_button_released(mb_left) //Если ЛКМ отпущенна
{
draw_rect=false; //Мы не рисуем прямоугольник
for(i=0;i<=instance_number(par);i+=1) //Читайте про цикл for ниже
{
ii=instance_find(par,i); //Мы ищем пока не сделанный объект
if(collision_rectangle(startx,starty,mouse_x,mouse_y,ii,true,false)) //Вот наш прямоугольник коллизии (соприкосновения)
{
ii.selected=true;
}
}
}

Код большой и сложный, пока мы узнаем про оператор условия if:
Код с if выполняется так:

200?"200px":""+(this.scrollHeight+5)+"px");">
if (условие)
{
действие
}

Также в нём может быть оператор else (иначе), пример:

200?"200px":""+(this.scrollHeight+5)+"px");">if (условие)
{
действие
}
else
{
действие 2
}

А for - это оператор цикла, он выполняется так:

200?"200px":""+(this.scrollHeight+5)+"px");">
for (<переменная> ; <выражение> ;<действие переменной>)
{
<действия>
}


оператор for очень мощная вещь, он очень помогает в трудных ситуациях

Оператор - встроенные в ЯП действия, например, самая распространённая это int, if, else, string, switch, for, case, break, exit, и т.д и т.п.

Теперь также создаём событие рисования (draw) и таким же путём пишем:

200?"200px":""+(this.scrollHeight+5)+"px");">if draw_rect=true
{
alpha=.8;
draw_rectangle_color(startx,starty,mouse_x,mouse_y,c_green,c_green,c_green,c_green,true);
}

Здесь всё легко, вот то же самое только по Русски:
если нам нужно рисовать прямоугольник, то мы выбираем прозрачность и рисуем прямоугольник
вот аргументы

200?"200px":""+(this.scrollHeight+5)+"px");">draw_rectangle_color(x1,y1,x2,y2,color 1, color 2, color 3, color 4, outline)


outline - будет ли рисоваться только грань (true) или залитый прямоугольник (false)
Мы нашли новое слово - константа, это заменённое словом числовое выражение или код, в гамаке есть встроенные константы:

200?"200px":""+(this.scrollHeight+5)+"px");">true (правда) - 1
false (ложь) - 0
pi - 3.1415...


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

200?"200px":""+(this.scrollHeight+5)+"px");">selected=false; //Вот и наша переменная, выбран ли объект

Это всё. Теперь нам конечно же нужен объект, который может передвигаться, называем его objTest, в событие создания пишем код:

200?"200px":""+(this.scrollHeight+5)+"px");">gox=x; //Куда идти по х...
goy=y; //по у
selected=false; //Мы не выбраны =)
object_set_parent(self,par) //Вот и выбор родителя

Новое действие:

200?"200px":""+(this.scrollHeight+5)+"px");">object_set_parent(ind,obj)

Устанавливает родительский объект для объекта с именем ind.
И новый оператор: self, он означает что действие будет переходить к себе
Не бойтесь, ещё немного осталось, в событие шага:

200?"200px":""+(this.scrollHeight+5)+"px");">if distance_to_point(gox,goy) > 20
{
mp_potential_step(gox,goy,6,solid);
}
if(selected=true) && mouse_check_button_pressed(mb_right)
{
gox=mouse_x;
goy=mouse_y;