Сюда я буду писать свои небольшие уроки. Итак первый урок: создание миникарты.
Итак, многие хотят, что бы в их игре был радар или миникарта. Сделать его довольно легко. Итак сейчас мы познакомимся с новым оператором with. Вот его схема:
Code
with(объект воздействия) {действие}
Он нужен для того что бы произвести действия на все экземпляры объекта не зависимо друг от друга. (не слишком загнул?) Итак создадим миникарту. Для этого подготовим спрайты: s_radar – спрайт радара (обычно 100 на 100 px.) s_hero_r – спрайт героя на радаре 2 пк. s_monster_r - спрайт монстра 2 px. s_hero - спрайт героя (любой размер) s_monster - спрайт монстра (любой размер) Кстати советую использовать различные префиксы к именам объектов, спрайтов, звуков и т.д. Я использую префикс s_ для спрайтов и o_ для объектов. Так в коде вы сразу сможете разобрать что это. Создадим объект о_radar и в событии рисования (Draw)пишем отрисовку:
Code
draw_sprite(s_radar,1,view_xview[0]+0,view_yview[0]+x);//отрисовка самого радара с учётом вида. draw_sprite(s_hero_r,1,view_xview[0]+o_hero.x/10,view_yview[0]+ o_hero.y/10);//отрисовка героя на радаре с учётом вида. with(o_monster)//действовать на все экземпляры обьекта o_monster... draw_sprite(s_monster,1,view_xview[0]+0+x/10,view_yview[0]+y/10);//отрисовка КАЖДОГО монстра на радаре с учётом вида.
Тут я использовал оператор with для того что бы нарисовать на радаре каждый экземпляр объекта. Теперь создадим объекты o_hero и o_monster. В событии шага (step) у героя пишем его движение:
Code
if keyboard_check(ord("W"))//если нажата W {y-=4}//Движение на 4 px. вверх. (координата Y в game maker перевёрнута!) if keyboard_check(ord("S")) {y+=4} if keyboard_check(ord("A")) {x-=4} if keyboard_check(ord("D")) {x+=4}
А объект o_monster оставьте без изменений. Теперь расставляем все объекты в комнате и тестируем игру. Исходник:
Итак вот пример умного бота для платформера:
Итак, давайте займёмся созданием умного АИ для бота в платформенной игре. Наш бот должен лазить по лестницам за игроком, перепрыгивать ямы, перепрыгивать различные препятствия типа ящиков, блоков и т.д. Для начала подготовим спрайты: S_hero - герой S_pol - пол S_bot- бот S_les-лестница Далее создадим объект o_hero и в событии шага напишем :
Code
gravity_direction = 270 //Направление гравитации - вниз. if place_free(x,y+1) //Если снизу нет столкновений... gravity = 2 //...гравитация равна двум. else //А если столкновения есть... gravity = 0 //...гравитация отключается.
if keyboard_check(ord("A")) //если нажата клавиша A... { image_xscale = -1 //...отразить героя влево... if place_free(x-5,y)//...И если нет столкновений... { x-=5; image_speed = 0.5 // переместиться влево на 5 пк. со скоростью анимации 0.5. } } // if keyboard_check(ord("D")) { image_xscale = 1 if place_free(x+5,y) { x+=5; image_speed = 0.5; } }
if keyboard_check(ord("W"))//если нажат пробел... { if not place_free(x,y+1)//...и снизу есть опора... { vspeed-=20//верт. скорость равна -20 (герой прыгает). } }
Столкновение с объектом пола (создайте объект o_pol):
Code
if (vspeed > 0 && not place_free(x,y+vspeed)) { move_contact(270); vspeed = 0; }
И наконец, создайте лестницу, поставьте маску столкновений как узкий прямоугольник и у героя в событии столкновения с лестницей напишите это:
Code
if keyboard_check(ord("W"))//если нажата W {vspeed=-4//лезем по лестнеце if distance_to_object(global.ak)<=5 { x=global.ak.x } }
Теперь сделайте пол твёрдым. Ну вот, наконец, мы можем сделать AI бота. Но для начала немного теории довольно скучной но полезной для понимания (её можете и не читать): В теории AI можно реализовать так: если до героя меньше 300 px и если герой слева от монстра то проверяем есть ли слева столкновения. Если их нет то движемся в лево, а если есть то прыгаем. Так же делаем если герой справа от монстра. Вот и весь код. Конечно, его ещё можно доработать и сделать ещё больше функциональным, но это я оставлю вам. И ещё совет – не скупитесь не различные проверки, пусть даже код будет от этого уродливым. Но напишем это кодом. Для этого создайте скрипт scr_ai с таким кодом:
Code
if distance_to_object(o_hero)<=argument0 and distance_to_object(o_hero)>=2//если дист. до героя меньше аргумента0 { if o_hero.x<x//если герой левее монстра { if place_free(x-1,y)//и слева есть место { x-=4//передвигаемся туда. } else //иначе if not place_free(x-1,y)//если там нет места... { vspeed=-10 //...то прыгаем. } } else//иначе if o_hero.x>x//если герой правее монстра... { if place_free(x+1,y)//если справа есть место... { x+=4//двигаемся туда. } else //инача if not place_free(x+1,y)//если там нет места... { vspeed=-10//то прыгаем. } } } if place_meeting(x,y+2,o_les) { if y<o_hero.y//если герой ниже монстра... { if global.ak2.x<x {x+=4} else if global.ak2.x>x {x-=4}
if distance_to_object(global.ak2)<=5 {x=global.ak2.x vspeed=+4//верт. скорость равна +4 } } А теперь создайте объект o_bot и пропишите ему в событие создание такую переменную (значение объясню немного позже): [code]pr=true//переменная прыжка
И в событие шага поставим гравитацию и активируем наш скрипт AI: gravity_direction = 270 //Направление гравитации - вниз. if place_free(x,y+1) //Если снизу нет столкновений... gravity = 2 //...гравитация равна двум. else //А если столкновения есть... gravity = 0 //...гравитация отключается. scr_ai(300)//выполняем скрипт if place_meeting(x,y+2,o_les) { if y<o_hero.y//если герой ниже монстра... { vspeed=+4//верт. скорость равна +4//опускаемся по лестнице if distance_to_object(global.ak2)<=5 {x=global.ak2.x} } } if x<o_hero.x+4 and x>o_hero.x-4 {x=o_hero.x}//устранение дёрганья [/code] Теперь надо сделать что бы монстр не проваливался сквозь пол. Для этого в столкновение с полом напишем:
Code
if (vspeed > 0 && not place_free(x,y+vspeed)) { move_contact(270); vspeed = 0; }
А что бы научить его карабкаться по лестницам в событие столкновения с лестницей напишем:
Code
if y>o_hero.y//если герой выше монстра... { vspeed=-4//верт. скорость равна -4 if distance_to_object(global.ak2)<=2 {x=global.ak2.x} }
Теперь откроем объект лестницы и в создание напишем:
Code
global.ak=0//актив global.ak2=0//актив2
В столкновение с героем:
Code
global.ak=id
А в столкновение с монстром:
Code
global.ak2=id
Так если герой полезет по лестнице, то бот последует за ним. Ну и наконец, научим бота перепрыгивать ямы. Для этого в событии начального шага надо написать:
Code
if pr=true//если можно прыгать. { if place_empty(x,y+1)//если снизу ничего нет { vspeed=-20//прыжок pr=false//нельзя прыгать alarm[0]=30//ставим будильник } }
Теперь я расскажу, для чего нужна переменная pr. Она нужна для того что бы бот ни летел по воздуху всё время, а только перепрыгивал ямы. И в событии будильника 0 напишем разрешение прыжка:
Code
pr=true//можно прыгать
Теперь расставьте объекты по комнате и протестируйте игру. Скрипт бота вы можете свободно использовать! Вот исходник:
ID и выбор активного объекта:
Итак, на этот раз я решил написать что такое ID объекта и с чем его едят). ID это уникальный номер объекта по которому можно узнать с которым объектосм как либо взаимодействовал герой, куда должен идти монстр и т.д. С помощью ID’а можно реализовать выбор активного объекта. В теории это легко: При клике мышкой записываем ID объекта в глобальную переменную. После этого игрок движется к активному объекту. Вот так! Но сделаем это с помощью кода: Для этого создадим спрайты s_monster – это спрайт монстра. s_vib – это рамочка вокруг выбранного объекта. s_hero – герой. s_baza – штаб. Теперь создадим одноимённые объекты, но с префиксом o_ вместо s_. Дальше в объекте o_vib (он будет контролером) в создании объявим переменную хранящую ID активного объекта:
Code
global.vib=0//нуль значит что ничего не выбрано.
А в событии рисования напишем что вокруг активного объекта рисуется рамочка:
Code
if global.vib!=0//если что-то выбранно... { draw_sprite(s_vib,-1,global.vib.x,global.vib.y)//…то рисуем рамочку вокруг активного объекта. }
А теперь опишем «активирование» монстра (уже в объекте o_monster). В событии клика по нему (left Pressed) надо написать присвоение этой переменной его ID:
Code
global.vib=id//присваиваем ID.
Теперь вместо имени активного объекта вы можете писать эту переменную. Прверим это. В объекте o_hero, в событии шага напишем:
Code
if global.vib!=0 //если активный объект есть… { move_towards_point(global.vib.x,global.vib.y,5)//то двигаемся к нему. } if x<global.vib.x+3 and x>global.vib.x-3 {speed = 0;global.vib=0;alarm[0]=120;} //если мы к нему подошли то останавливаемся и запускаем будильник.
И в событии будильника (alarm 0) напишем это:
Code
global.vib=o_baza.id
То есть если герой подождёт у монстра три секунды то ему это надоест и он вернётся на базу). Ах, да при клике на базу напишите:
Code
global.vib=id//теперь активный объект – база.
Вот и всё! Исходник к статье:
Сообщение отредактировал stalker5889 - Четверг, 21 Июля 2011, 21:03
Зачем создавать кучу спрайтов, если можно использовать draw_circle?
Спрайтом можно задать нестандартную фигуру, звезду например, или флаг, или кресткик. На перспективу так сказать.
Добавлено (14.07.2011, 12:07) --------------------------------------------- Хотя в целом мне подход не нравится. Слишком специфический пример и много воды. Почему например происходит вот это:
Quote (stalker5889)
view_xview[0]+0+0
Или вот это:
Quote (stalker5889)
view_yview[0]+y/10
Ну со вторым понятно, попытка что-то масштабировать, а с первым это такой фетиш? Новичкам изучающим GML кликать сюда. Много примеров, исходников, библиотек и вообще всего что вам только может пригодиться. Автор портала, прости меня за ссылку, наболело =)
Спасибо всем за уместную критику! Статья была расчитана на новичков и я решил не грузить координатами бедных людей. Это самый лёгкий способ на мой взгляд.
Добавлено (14.07.2011, 20:56) --------------------------------------------- Кстати пишите темы для следующих уроков, если вам не сложно.
Кстати пишите темы для следующих уроков, если вам не сложно.
Ок. Хотелось бы урок по реализации ИИ в платформере. Чтобы бот мог преследовать игрока, лазить за ним по лестницам. Steel Standoff - 2D аркада. Мои статьи
О, классно! Самый простейший пример радара который я встретил! Все что то там так закапываются в скриптах... ужос! Простое гениально))) Бесспорно плюс!
По просьбе аТнОтХоАн добавлена статья по созданию AI для платформера. Бот может прыгать через ямы, перепрыгивать препятствия и лазить по лестницам. миха, спасибо за лестный отзыв) Кстати предлагайте ещё темы для уроков.
По просьбе аТнОтХоАн добавлена статья по созданию AI для платформера.
stalker5889, спасибо . Сейчас прочту и сделаю на GM AI для платформера по уроку!
Добавлено (15.07.2011, 18:15) --------------------------------------------- Сначала скачал исходник... Нашёл в AI минусы: 1) Если игрок спрыгнул с платформы, AI ещё не успел спрыгнуть, происходит следующее: AI трясётся и не спускается к игроку. 2) Если прыгнуть игроком в яму, AI охотно прыгает за ним.
Нашёл в AI минусы: 1) Если игрок спрыгнул с платформы, AI ещё не успел спрыгнуть, происходит следующее: AI трясётся и не спускается к игроку. 2) Если прыгнуть игроком в яму, AI охотно прыгает за ним.
Понял, постараюсь исправить как можно скорее. Просто сейчас усердно изучаю 39DLL
Добавлено (16.07.2011, 10:45) --------------------------------------------- Всё, код бота откоректирован.
stalker5889, если нужно убрать только дёрганье, тогда: В Step бота: if x<игрок.x+3 and x>игрок.x-3 {speed = 0} Как-то так. Steel Standoff - 2D аркада. Мои статьи
stalker5889, для новичков довольно таки познавательно! (Я про статью о AI в платформере). Молодца! Буду ждать новых интересных уроков!
Добавлено (16.07.2011, 20:10) --------------------------------------------- Эммм.. Неплохо было бы, если бы ты написал, как написать AI для соперников в гоночной игре.
stalker5889, опять же предлагаю тему: Урок по созданию разрушаемой поверхности с возможностью передвижения по ней. Steel Standoff - 2D аркада. Мои статьи