Як реалізувати м'які краї краю з частинками


13

Моя гра створена за допомогою Phaser, але саме питання є моторно-агностичним.

У моїй грі у мене є декілька середовищ, по суті полігональних областей, до яких персонажі гравців можуть переходити і впливати на них. Наприклад, лід, вогонь, отрута тощо "Графічним елементом цих областей є сама кольорова площа полігону, а також частинки відповідного типу (у цьому прикладі ожеледиця). Ось як це я зараз реалізую - з багатокутною маскою, що покриває плитку з малюнком частинок:

введіть тут опис зображення

Жорсткий край виглядає погано. Я хотів би вдосконалитись, зробивши дві речі: 1. Зробіть ділянку заповнення полігону м’яким краєм і змішайтесь із фоном. 2. Нехай частина черепашок виходить з області багатокутника, щоб вони не були розрізані посередині, а область не мала прямої лінії

наприклад (макет):

введіть тут опис зображення

Я думаю, що 1 можна досягти розмиттям багатокутника, але я не впевнений, як пройти з 2.

Як би ви вирішили це здійснити?


2
Це виглядає приголомшливо. Чи можу я отримати посилання на вашу гру, будь ласка? :)
ashes999

@GameAlchemist Ось зображення плитки i.imgur.com/y54CeQ9.png
OpherV

@ ashes999 Ще триває робота. Я обов'язково опублікую посилання тут, як тільки я його
вставлю

Зауважте, що це прозорий PNG з білими предметами. Якщо ви переглядаєте його на білому тлі (як це часто буває при відкритті картинки в браузері), ви нічого не побачите
OpherV

@OpherV, це було б чудово. Будь ласка, просто відредагуйте своє запитання та опублікуйте посилання - це, мабуть, самий тематичний спосіб продавати його на цьому сайті :)
ashes999

Відповіді:


2

1.Якщо ви хочете чогось, що є близьким до вашого макета, я б використовував частинки (це не повинно бути повністю продутою системою частинок).

Візуалізуйте свої частинки у формі багатокутника на RenderTexture. Обов’язково використовуйте добавки, що змішуються на частинки. Частинки всередині багатокутника плавно змішатимуться один з одним, тоді як частинки зовні нададуть м'який край, який ви хочете. (Приклад ефекту можна переглянути у цьому відео на YouTube: Aditive Particle Video Тепер винесіть RenderTexture на головний екран, і ви закінчите. RenderTexture необхідний, щоб частинки не зливалися з вашим фоном.

Ви можете спробувати нанести трикутники безпосередньо на текстуру частинок і подивитися, як це виходить. В іншому випадку візуалізуйте їх поверх «супу з частинок» як окремий шар.

Створений швидкий макет із оновленої jsfiddle, що виглядає приблизно так. Демо Оновлену демонстрацію ви можете знайти тут

2. Кожна частинка має швидкість і початок. Коли ваш гравець торкається багатокутника, ви змінюєте швидкість кожної частинки, пропорційну швидкості гравців. Чим далі частинка подалі від вашого гравця, тим менше на неї впливає швидкість гравців.

Формула для обчислення швидкості частинок була б приблизно такою:

//player.velocity and particle.velocity are vectors 
//k is a factor to enhance or weaken the influence of players velocity
var distanceToPlayer = (player.position - particle.position).length();
particle.velocity = particle.velocity + ((k * player.velocity) + particle.velocity) * (1/distanceToPlayer);

Щоб обчислити положення частинки, ви поставите це у своєму методі оновлення:

var speedY = -(springConstant * (particle.position.y - particle.origin.y)) - (dampingFactor * particle.velocity.y);
var speedX = -(springConstant * (particle.position.x - particle.origin.x)) - (dampingFactor * particle.velocity.x);

particle.position.y = particle.position.y + speedY;
particle.position.x = particle.position.x + speedX;

particle.velocity.x = particle.velocity.x + speedX;
particle.velocity.y = particle.velocity.y + speedY;

Це повинно дати вам "рідину", коли кожна частинка розгойдується навколо свого походження, коли гравець переміщує рідину. SpringConstant змінює, наскільки частинка відхиляється від свого походження і демпфуючийФактор, як швидко частинка спочиває. Можливо, вам доведеться налаштувати код, оскільки його модифіковану версію 1d-симуляції я використовую в своїй грі.

Тепер з демонстрацією: демонстрація Просто налаштуйте 3 константи вгорі, поки рідина не поводиться так, як ви цього хочете.


Це дійсно цікава ідея вирішити №1! Мені це подобається. Як би ви запропонували реалізувати рух трикутника \ інтервал?
OpherV

1
Я відредагував оригінальний пост, щоб відповісти на питання №2.
zilluss

додала невелику демонстрацію ефекту частинок. Я думаю, ви могли б отримати бажаний ефект за допомогою невеликого налаштування.
zilluss

Я в кінцевому підсумку використовував ваше рішення, це найближчий до ефекту, який я шукав. Спасибі! Хоча одне питання - як би я зафіксував пружинистість у ваших прикладах, щоб дійсно незначні рухи не змусили частинок стрибати такі величезні відстані?
OpherV

Ви можете пограти разом із демпфіруючим Фактором та весноюКонстант. Високе затухання швидше приведе в спокій частинки. Нижня пружинна константа знижує швидкість частинок. На жаль, обидві значення дозволяють супу з частинок відчувати себе більш в'язким. Тому замість цього, коли ваш гравець торкається частинки, ви можете зафіксувати максимальну швидкість, яку гравець додає до частинки, як-от так: particle.velocity.x = clamp (maxVelocity, -maxVelocity, particle.velocity.x + ((playerInfluenceFactor * deltaVelocityX) ) + particle.velocity.x) * (1 / відстаньToPlayer)); для затиску см: stackoverflow.com/a/11409944
zilluss

4

Мої думки щодо цих двох моментів:

  1. Ви можете використовувати розмивання шейдера, але це буде дуже дорого. Натомість я намалював би додаткову межу трикутників, які затухають від напівпрозорого в центрі до прозорого на краях, щоб імітувати "розмиття". Я це зробив у моїй грі, і вона працює досить добре. Ось два скріншоти підсилювача веселки в моїй грі.

    введіть тут опис зображення введіть тут опис зображення

    Зовнішня межа має градієнт. У моїй ситуації межа не починається з тієї ж непрозорості, що і внутрішня частина, але якщо встановити непрозорість однаковою, у вас буде приємно зникати.

  2. Я б запрограмував систему частинок і змусив частинки слідувати за полігоном. Роблячи це, вам не потрібно турбуватися про те, що відбуватиметься на краях. Динаміка вашої системи частинок гарантує, що частинки знаходяться всередині багатокутника і рівномірно розподіляються. Ви можете спробувати змусити найближчі частинки відштовхувати один одного, але зробіть це з великою кількістю "маси", щоб у вас була інерція, і це виглядає гладко. Щоб зробити цю справу швидкою, є деякі можливості, але великою проблемою буде складність у часі механізму натискання один на одного. Якщо ви змусите кожну частинку штовхати кожну другу частинку, у вас з'явиться O (n ^ 2), що не добре, якщо у вас, наприклад, 100 частинок у вашій системі. Гарне прочитання про те, як можна оптимізувати це, - це презентація PixelJunk:http://fumufumu.q-games.com/gdc2010/shooterGDC.pdf

    Більш простим підходом було б з'єднання кожної частинки з трьома-чотирма іншими частинками при побудові системи частинок. Тепер кожній частинці потрібно буде лише проштовхнути чотири інші частинки, до яких вона пов'язана. Однак такий підхід унеможливлює турбулентність у вашій системі частинок. Але це, здається, не є проблемою, оскільки ваша поточна ситуація використовує статичну текстуру. Цей підхід буде O (n), що чудово.


Спасибі! 1. Мені важко уявити це. Чи можете ви опублікувати макет того, як це виглядає \ працює у вашій грі? 2. Цікаво! буде читати з цього
приводу

Дякую за образи Я бачу, як це буде працювати в формі трубки або лінії, але як це буде працювати з багатокутником? Чи не будуть градієнти трикутників, спроектованих з кожної сторони, не вирівнятися добре ...?
OpherV

Зробіть їх добре. Це ідея. Це включає деякі математичні та обчислювальні точки перетину тощо. Ви також можете розділити кордон і згладити її. Тон можливостей.
Мартійн Курто

3

Ідея, яку я мав при читанні вашої публікації, була така:
• побудувати набір плиток, які ви будете використовувати для своїх областей.
• візуалізуйте полігон області на невеликому тимчасовому полотні з роздільною здатністю плитки (наприклад: якщо плитка 16X16, візуалізуйте з (16X, 16X) меншою роздільною здатністю).
• використовуйте це тимчасове полотно, щоб вирішити, чи потрібно виводити плитки чи ні на основне полотно:
якщо на полотні з низькою роздільною здатністю встановлено крапку, намалюйте на випадковому полотні «випадкову» плитку. якщо точка є лише сусідом заданої точки, намалюйте «випадкову» плитку з меншою непрозорістю (для переходу) на основне полотно.

Я побоювався, що зниження роздільної здатності створить ефект блоку, але навіть з плитками 20X20 це виглядає цілком непогано:

введіть тут опис зображення

Кроками для цього є: візьміть свій багатокутник:
введіть тут опис зображення

Намалюйте багатокутник за роздільною здатністю плитки: введіть тут опис зображення(!! так, це червона річ).

Потім використовуйте imageData полотна низької роздільної здатності, щоб вирішити, як намалювати плитку чи нотатку.
Якщо на полотні з низькою роздільною здатністю встановлено піксель, це означає, що ми мусимо намалювати плитку: підберіть «випадковий» індекс плитки, щоб вибрати, яку плитку намалювати. Цей випадковий індекс повинен бути завжди однаковим для даної області / плитки.
Якщо точка порожня, але поруч із заповненою точкою, також намалюйте плитку, але з половиною непрозорості.

введіть тут опис зображення

Тож давайте намалюємо плитку:

введіть тут опис зображення

Для багатокутника я просто намалюю багатокутник кілька разів, зменшивши його і збільшуючи непрозорість на кожному малюнку (можна також використовувати «легший» GlobalCompositeOperation).

введіть тут опис зображення

Після того, як ви додасте все, це дає:

введіть тут опис зображення

скрипка тут:

http://jsfiddle.net/gamealchemist/T7b4Y/

дайте мені знати, якщо це допомагає.


Дякуємо за детальну розробку вашого рішення та надання коду! Що ви маєте на увазі під "Потім використовуйте imageData полотна низької роздільної здатності, щоб вирішити, чим намалювати плитку чи нотатку". Як ви використовуєте малі дані зображення, щоб вирішити, де \ як намалювати велике зображення? І використовуючи цей метод, як я можу уникнути накладання трикутників, щоб досягти проміжків, подібних моєму макету?
OpherV

Я маю на увазі це повний булевий тест: чи потрібно мені заповнити цю плитку? , true або false, задається тестом тесту з низькою роздільною здатністю на imageData [(x + y * width) * 4]! = 0, тобто == 'я намалював щось на полотні нижнього розміру на це плиткове місце? '. Тоді, якщо так, я використовую розроблену формулу, заповнену простими числами (getRandomNumber), щоб перейти від (x, y) до "випадкового" індексу плитки, який завжди надасть однакове число для даної області + (x, y). Я не бачу, як все може перетинатися, якщо ви правильно визначите свій багатокутник, щоб я не отримав ваше друге запитання.
GameAlchemist

1

Просто ідея:

У вашій плитці "шматки" мають ширину приблизно 80 пікселів. Я б запропонував зробити 2 області. Ви малюєте свій оригінальний багатокутник, і ви робите з нього макет приблизно 80 пікселів з кожного краю. Потім ви малюєте свою плитку в більший багатокутник.

Потім усі "шматки", які мають піксель поза внутрішнім багатокутником, і не перетинаються з внутрішнім багатокутником, ви можете залити, заповнити їх прозорістю.

Це дуже високий рівень, але я подумав, що поділюсь із вами. Тут потрібно визначити багато деталей.

Сирий образ для демонстрації:

введіть тут опис зображення

Якби внутрішній чорний багатокутник був оригінальним, ви видалили б усі багатокутники червоною крапкою.


Як би ви перевірили на перехрестя деталі, вбудовані у зображення плитки із внутрішнім багатокутником?
OpherV

@OpherV Uhmm, Ви можете визначити, чи точка X знаходиться в полігоні правильно? Ви можете прокрутити всі пікселі у зовнішньому багатокутнику, а для кожного білого пікселя затоплення перевірити всі пікселі та побачити, чи немає у внутрішньому / підключеному. Це здається не особливо ефективним, але коли ви щось отримаєте, можете придумати шляхи оптимізації?
user46560

Це післяобробка робиться на процесорі. Навряд чи оптимізується на собі. Ваша ідея могла б спрацювати, якщо внутрішній багатокутник і зовнішній з'єднаються трикутною смужкою. ОП може додавати інформацію про атрибут вершини та мітити кожну вершину як всередині, так і зовні. Тоді у вершинній шейдері непрозорість / альфа може бути лінійно інтерпольована від менш прозорого значення до повного непрозорого.
теодрон

@teodron Це пункт, який я намагався зробити у відповіді. Це ідея високого рівня, і я насправді не розробник ігор. У мене просто була ідея.
user46560

@ user46560 Так, але таким чином вам зовсім не доведеться обчислювати, які пікселі є у цій міжполігонічній смузі. Ні на GPU, ні на процесорі. Оскільки ви не звикли до шляхів розвитку ігор, як ви кажете, ви заслуговуєте +1 на свою ідею :).
теодрон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.