Corona Game Engine: кога и как да се прилагат сблъсъци

Вероятно сте играли много мобилни игри, които са въвели физически свойства и поведение в определени аспекти на играта. Например скачане от платформите в Doodle Jump или събаряне на дървени купчини в Angry Birds.

Но питали ли сте се някога какво стои зад всички тези взаимодействия и как Doodler знае кога може да премине през платформа и кога да отскочи от нея? Как може тази реалистична купчина да се срути толкова реалистично, когато ядосана птица го удари? Всъщност не е толкова трудно. Всички се справят с малко помощ от сблъсъци.

Тъй като повечето ми игри са направени с Corona Game Engine, ще използвам реализацията на Corona Collision (Physics) и програмния език Lua, за да опиша и кодирам примерите, свързани с темата. Независимо от това, подобни принципи могат лесно да се прилагат и при други двигатели, тъй като много физически двигатели работят много. Corona, като цяло, върши толкова чудесна работа с документите, така че може да видите няколко препратки към документацията в този текст, тъй като просто нямаше смисъл да изобретявате колелото. :)

Така че, нека се потопим в него!

Общ преглед

На първо място, важно е да се подчертае, че всеки игрален двигател използва двигател на физиката на заден план, за да се занимава с физика. Корона, по-специално, се занимава с физика, използвайки двигателя на физиката Box2D. Това ви дава възможност да внедрите функционалности от света на физиката, като просто присвоите физическите свойства на обекти в играта и обработвате техните взаимодействия с правилни методи.

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

Тази проверка може да бъде толкова основна, колкото:

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

Например, можете да кажете:

Както можете да видите, тук са включени няколко определения: типът на тялото (динамичните тела се движат при симулация според силите като гравитация или реакционни сили на сблъсък и те приемат прилагането на скорост, статичните тела няма да реагират на силите като гравитацията и те ще действат така, че имат безкрайна маса, кинематичните тела се движат под симулация само според скоростта си и т.н. - можете да научите повече за това на coronalabs.com) и физическите свойства, които ще предприемат действия при различни физически взаимодействия. Например, ако нашият герой беше топка, удряща земята, тя ще отскочи доста високо, тъй като голяма част от скоростта й ще се върне след сблъсъка (скача = 0,8). Ако нашият герой беше човек, изкачващ се на хълм и не искаме той да се навежда назад и да пада надолу, докато го изкачваме, можем да замразим въртенето му около определена ос и т.н.

Всичко това може да звучи така, че са необходими много специализирани знания за внедряване, но всъщност не е така. Много прости игри могат лесно да бъдат създадени само с основното разбиране на физиката, тъй като двигателят се справя с повечето неща за вас.

Конкретни сблъсъци

Както казах преди, събитията при сблъскване ви дават възможност да откривате и обработвате сблъсък между физически обекти. Съществуват няколко типа сблъсъци, които могат да бъдат дефинирани с Corona:

  • предварително сблъсък
  • стълкновение
  • след сблъсък

Има също и случай на всяко сблъсък, определяйки го като:

  • локален сблъсък
  • глобален сблъсък

Кой от тях ще изберете зависи от това, което смятате да направите.

Да започнем с глобален срив срещу местни. Локалните сблъсъци се използват най-добре при сценарии на сблъсък с един към много, докато глобалните сблъсъци се използват най-добре в сценарии на сблъсък много към много - подробности можете да получите на coronalabs.com. Така че, нашият герой, улавяйки добрите падащи предмети и избягвайки лошите, би се вписал идеално с локално сблъсък. Ако играта ви е имала няколко знака, помислете за използване на глобално събитие на сблъсък, което се определя като глобално време на изпълнение, откривайки сблъсъци между всички физически обекти в играта.

Местните събития на сблъсък са описани с параметри на себе си и събития, представящи самия обект и, наред с други, други обекти на Корона, показващи, участващи в сблъсъка. Обектите на дисплея на Corona притежават наистина страхотна функция - те се държат като таблици на Lua, което означава, че към тях лесно могат да се добавят различни данни, като имена, идентификатори или категории. Това се използва по-специално при справяне със сблъсък. Идентификатор може да се добави към всеки добър и лош обект (например „добър“, „лош“) и чрез сравняване на тези идентификатори в събитието на сблъсъка е много лесно да разберете кой от тях е направил играча. Ако е добър, можете да наградите играч с точки. Ако не, бихте могли да намалите точките на живота му.

Този сценарий може лесно да бъде изграден с помощта на редовен сблъсък. Това означава, че сте в състояние да откриете физически контакти между обекти, на които е назначено физическо тяло. Това събитие се състои от начална и завършена фаза, така че можете да извършвате действия в начални и прекъснати моменти на контакт. Например, представете си, че изграждате космическа игра като Little Galaxy и сте дефинирали гравитационните полета на вашата планета, използвайки техниката на физическите стави. С започнати и завършени фази на сблъсъка можете да разберете кога сателит е навлязъл и напуснал гравитационното поле на планетата и след това да извършите определени действия. Нека се върнем към нашия герой, който улавя пречките и ще видим как това изглежда в действие.

Първо, ще създам някои глобални константи за работа с различни размери на екрана. Този подход може да варира от програмист до програмист. Този е свързан с размера на съдържанието, определен в config.lua и лично аз открих този метод за най-подходящ за моята употреба.

Ще създам и глобално изброяване, което ще използвам по-късно като идентификатор за падащи обекти:

Освен това ще внедря необходимата библиотека, ще започна физиката и ще „изключа гравитацията“:

След това ще създам нашия герой. За пример, той (както и падащите обекти) ще бъде представен с обикновен кръг:

Характерът има свойството Y котва, зададен като 1. Това означава, че неговата референтна точка на ос Y е зададена на най-ниската точка. Следователно, когато се позиционира в центъра на екрана, дъното на кръга ще бъде поставено там. Това ще бъде много важно в по-късния пример „Doodle Jump“ (след сблъсък).

Както бе споменато по-горе, всички обекти, които трябва да участват във физически взаимодействия, трябва да бъдат назначени на физическо тяло:

Забележете, че съм определил знака като сензор. Това означава, че друг физически обект няма да може да взаимодейства физически с героя (без отскачане, без триене и т.н.), но все още ще можем да откриваме сблъсъци. Този принцип често се прилага, когато не искаме обекти да се сблъскват и да летят около екрана поради следване на физическо поведение, а просто откриваме кога са взаимодействали и правят нещо въз основа на самото взаимодействие (например, увеличаване или намаляване на резултата).

Сега, нека създадем функция за генериране на падащи обекти:

Тази функция ще се извиква с таймер, генерира обект на всеки 2 секунди и го анимира от върха до дъното на екрана. Както можете да видите, всяка пречка се идентифицира с предварително дефинирано изброяване и за визуално разграничаване всеки добър падащ предмет ще бъде оцветен в зелено, докато лошите ще бъдат оцветени в червено.

Сега може да се чудите защо да поставя и падащи предмети като сензори? При разработения сценарий на играта може да искате да използвате акселерометъра, за да наклоните героя си наляво и надясно, за да събирате / избягвате падащи обекти и да генерирате произволно позицията, при която падащ обект ще започне своето пътуване до дъното на екрана. Ако стесните интервала от време, необходим за генериране на обекта, докато играчът напредва през играта, вероятно някои препятствия ще бъдат генерирани много близо един до друг.

Ако не бяха зададени като сензори, те щяха да се сблъскат и да се държат много неестествено, тъй като за преместване на обектите от върха към дъното на екрана се използват преходи (не гравитация!). По този начин, особено ако скоростите им на падане се различават, те могат свободно да преминават помежду си и все още можете да откриете сблъсъци на персонажи с тези обекти, тъй като и двете са определени като физически тела.

Сега е моментът да определим нашето сблъскване под формата на функция:

Това събитие трябва да бъде свързано и свързано с нашия герой, за да има някакъв ефект:

Нашият слушател сега „слуша“ за всякакви физически взаимодействия, в които се включва нашия герой. След като взаимодейства с падащ обект, се извършва проста проверка, за да се види дали потребителят е събрал добър или лош обект. За всеки събран добър обект, потребителят се награждава с 10 точки. От друга страна, ако той събере лош предмет, точките му се намаляват с 10. Когато това е направено, падащият обект ще бъде премахнат, а героят ще бъде анимиран добре, за да покаже визуално сблъсък.

Нека визуализираме резултатите!

Обектно-уловителна игра в действие

Както можете да видите, всичко това беше лесно постигнато, тъй като на заден план има двигател по физика, който се занимава с всички сложни неща за вас. Можете да изтеглите пълния код тук.

Сега, да видим как лесно може да се приложи предварително сблъсък, за да се постигне интересно поведение. Може би най-добрият пример за показване на това би било да се създаде игра на платформа, подобна на Doodle Jump, с подскачащ характер. Вярвате или не, тази съществена функционалност на играта не е по-трудна за изпълнение от предишната „обект на улов“. Ще започнем същото, като първо определим UI елементите и им дадем физическо тяло.

Този път това ще бъде играч и набор от твърдо кодирани платформи:

Отново забележете, че платформите получават идентификатор и този път те са определени като статични тела, докато символът все още е динамичен. Причината за това е гравитацията:

За да платформите да не се сринат и да паднат, те трябва да бъдат определени като статични тела, което означава, че няма да реагират на сили като гравитацията. Нашият играч, от друга страна, трябва да бъде свален всеки път, когато скочи. Забележете, че Y котвата на нашия характер отново е зададена на най-ниската му точка. Това ще бъде използвано при събитие преди сблъсък, като се проверява дали позицията на персонажа (краката му) са над или под платформата, с която ще се сблъска.

Ако краката му са отдолу, деактивирайте контакта. Ако краката му са отгоре, дайте му малко тласък във въздуха:

Предварителното сблъскване е малко шумно и може да задейства няколко пъти на контакт. За да дадем на героя си само едно натискане във въздуха на контакт, можем да получим неговата линейна скорост и въз основа на знака за скорост (Y посока) да определим дали героят пада и се приближава към платформата. Тъй като първоначалната скорост на нашия герой е 0, трябва да му дадем малко тласък в началото и той е добър да тръгне!

Игра на платформа скок в действие

Следващата стъпка ще бъде създаване на функция за произволно генериране на платформи и преместването им надолу, докато героят скача нагоре. Тъй като това не е темата, ще го оставя в друг блог. Искам само да спомена, че тази конкретна механика може да бъде постигната чрез използване на различни подходи. В името на примера, избрах този. Не се страхувайте да експериментирате! Можете да изтеглите пълния демо код тук.

Последното, но не на последно място е събитие след сблъсък. Това е единственото събитие на сблъсък, при което се отчита силата на сблъскване и триенето (отново повече информация на coronalabs.com). Какво означава това за вас като разработчик на игри? Въз основа на тези стойности можете например да определите силата и количеството на определени събития.

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

За този пример ще създам топка, удряща кръга на нашия герой.

Топката се поставя вертикално под знака. Сега ще приложа някаква сила към нея, насочвайки я към характера, но със случайни стойности на сила X и Y, така че можете да видите разликите в крайния резултат (поведение), след като топката се насочи малко по-различно и удари героя в различен момент.

Събитието след сблъсък може да бъде определено така:

И крайният резултат изглежда така:

Игра след сблъсък в действие

Героят се движи доста реалистично след хита, нали? Всичко, което направихме, беше да зададем няколко свойства на обектите и на самия свят на физиката. Това е така, защото всички механици зад това събитие се обработват от вас от физическия двигател. Пълният код можете да намерите тук.

заключение

Както можете да видите, манипулацията при сблъсък е доста удобна. Тъй като двигателят на физиката прави повечето неща за вас на заден план, много основни (но много ефективни) неща лесно могат да бъдат постигнати само с основното разбиране на физиката и, разбира се, с игровия двигател, с който работите.

Събитията в сблъсъка могат и трябва да бъдат сдвоени с различни други събития, оставяйки ви безкрайни възможности, ограничени само от представянето и вашето въображение.

__________
Ние сме на разположение за партньорства и отворени за нови проекти. Ако имате идея, която искате да обсъдите, споделете я с нашия екип!