Bagaimana menerapkan area tepi lunak dengan partikel

13

Game saya dibuat menggunakan Phaser, tetapi pertanyaannya adalah engine-agnostik.

Dalam permainan saya, saya memiliki beberapa lingkungan, pada dasarnya area poligonal yang dapat dipindahkan oleh karakter pemain dan dipengaruhi. Misalnya es, api, racun dll. Elemen grafis dari area ini adalah area poligon yang diisi warna itu sendiri, dan partikel dari jenis yang sesuai (dalam contoh ini pecahan es). Ini adalah bagaimana saya saat ini menerapkan ini - dengan topeng poligon menutupi tilesprite dengan pola partikel:

masukkan deskripsi gambar di sini

Tepi keras terlihat buruk. Saya ingin meningkatkan dengan melakukan dua hal: 1. Membuat area isian poligon memiliki tepi yang lembut, dan menyatu dengan latar belakang. 2. Suruh beberapa pecahan keluar dari area poligon, sehingga tidak terpotong di tengah dan area tersebut tidak memiliki garis lurus

misalnya (maket):

masukkan deskripsi gambar di sini

Saya pikir 1 dapat dicapai dengan mengaburkan poligon, tapi saya tidak yakin bagaimana caranya dengan 2.

Bagaimana Anda akan menerapkan ini?

OpherV
sumber
2
Itu terlihat luar biasa. Bisakah saya memiliki tautan ke game Anda ? :)
ashes999
@GameAlchemist Inilah gambar ubin i.imgur.com/y54CeQ9.png
OpherV
@ ashes999 Ini masih dalam proses. Saya pasti akan memposting tautan di sini setelah saya memilikinya :)
OpherV
Perhatikan itu adalah PNG transparan dengan objek putih. Jika Anda melihatnya di latar belakang putih (seperti yang sering terjadi ketika membuka gambar di browser) Anda tidak akan melihat apa pun
OpherV
@OpherV itu bagus sekali. Harap cukup edit pertanyaan Anda dan poskan tautan - itu mungkin cara yang paling sesuai topik untuk memasarkannya di situs ini :)
ashes999

Jawaban:

2

1.Jika Anda menginginkan sesuatu yang dekat dengan mockup Anda, saya akan menggunakan partikel (Itu tidak harus menjadi sistem partikel sepenuhnya meledak).

Render partikel Anda dalam bentuk poligon pada RenderTexture. Pastikan untuk menggunakan campuran aditif pada partikel. Partikel-partikel di dalam poligon akan saling berbaur dengan lancar sementara partikel di luar akan memberikan tepi lembut yang Anda inginkan. (Contoh efeknya dapat ditonton dalam video youtube ini: Video Partikel Aditif Sekarang render RenderTexture ke layar utama Anda dan Anda selesai. RenderTexture diperlukan agar partikel tidak menyatu dengan latar belakang Anda.

Anda bisa mencoba meletakkan segitiga langsung ke tekstur partikel dan lihat bagaimana hasilnya. Kalau tidak, render di atas "sup partikel" Anda sebagai lapisan terpisah.

Membuat mockup cepat dalam jsfiddle yang diperbarui yang terlihat seperti ini. Demo Anda dapat menemukan demo yang diperbarui di sini

2. Setiap partikel memiliki kecepatan dan asal. Ketika pemain Anda menyentuh poligon, Anda mengubah kecepatan setiap partikel sebanding dengan kecepatan pemain. Semakin jauh sebuah partikel menjauh dari pemain Anda, semakin sedikit itu dipengaruhi oleh kecepatan pemain.

Rumus untuk menghitung kecepatan partikel akan menjadi seperti ini:

//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);

Untuk menghitung posisi partikel Anda menempatkan ini dalam metode pembaruan Anda:

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;

Ini akan memberi Anda "cairan" di mana setiap partikel mengayunkan asalnya ketika pemain mengaduk cairan. SpringConstant mengubah seberapa banyak partikel berayun dari asalnya dan faktor peredam seberapa cepat partikel itu beristirahat. Anda mungkin harus mengubah kode karena versi modifikasi dari simulasi 1d yang saya gunakan dalam permainan saya.

Sekarang dengan demo: Demo. Hanya men-tweak 3 konstanta di atas sampai cairan berperilaku seperti yang Anda inginkan.

Zilluss
sumber
Itu ide yang sangat menarik untuk dipecahkan # 1! Saya suka itu. Bagaimana Anda menyarankan menerapkan gerakan segitiga \ spasi?
OpherV
1
Saya mengedit posting asli untuk menjawab pertanyaan # 2.
zilluss
menambahkan demo kecil efek partikel. Saya pikir Anda bisa mendapatkan efek yang diinginkan dengan sedikit mengutak-atik.
zilluss
Saya akhirnya menggunakan solusi Anda, itu yang paling dekat dengan efek yang ingin saya capai. Terima kasih! Namun satu pertanyaan - bagaimana saya akan menjepit springiness dalam contoh Anda, sehingga gerakan yang benar-benar kecil tidak akan menyebabkan partikel melompat jarak sangat besar?
OpherV
Anda dapat bermain-main dengan redamanFactor dan springConstant. Redaman tinggi akan membuat partikel lebih cepat beristirahat. Konstanta pegas yang lebih rendah menurunkan kecepatan partikel. Sayangnya, kedua nilai tersebut membuat sup partikel terasa lebih kental. Jadi sebagai gantinya, ketika pemain Anda menyentuh partikel, Anda dapat menjepit kecepatan maksimum yang ditambahkan pemain ke partikel, seperti ini: particle.velocity.x = clamp (maxVelocity, -maxVelocity, particle.velocity.x + ((playerInfluenceFactor * deltaVelocityX ) + particle.velocity.x) * (1 / distanceToPlayer)); untuk penjepit lihat: stackoverflow.com/a/11409944
zilluss
4

Pikiran saya tentang dua poin ini:

  1. Anda bisa menggunakan shader blur, tapi itu akan sangat mahal. Alih-alih, saya akan menggambar batas segitiga tambahan yang pudar dari tembus cahaya di tengah menjadi transparan di bagian tepi, untuk mensimulasikan "blur". Saya telah melakukan itu dalam permainan saya dan itu bekerja dengan cukup baik. Berikut adalah dua tangkapan layar penguat pelangi di game saya.

    masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

    Perbatasan luar memiliki gradien. Dalam situasi saya, perbatasan tidak dimulai pada opacity yang sama dengan bagian dalam, tetapi jika Anda mengatur opacity itu sama, Anda akan memiliki pudar yang bagus.

  2. Saya akan memprogram sistem partikel dan membuat partikel mengikuti poligon. Dengan melakukannya, Anda tidak perlu khawatir tentang apa yang akan terjadi di ujung-ujungnya. Dinamika sistem partikel Anda akan memastikan bahwa partikel berada di dalam poligon dan terdistribusi secara merata. Anda dapat mencoba membuat partikel terdekat mendorong satu sama lain, tetapi membuatnya dengan banyak "massa" sehingga Anda memiliki kelembaman dan terlihat halus. Untuk mempercepat hal ini, ada beberapa kemungkinan, tetapi masalah besar adalah kompleksitas waktu dari saling mendorong satu sama lain. Jika Anda membuat setiap partikel mendorong setiap partikel lainnya, Anda akan memiliki O (n ^ 2), yang tidak baik, jika Anda memiliki misalnya 100 partikel dalam sistem Anda. Bacaan yang bagus tentang bagaimana Anda dapat mengoptimalkan ini adalah presentasi PixelJunk ini:http://fumufumu.q-games.com/gdc2010/shooterGDC.pdf

    Pendekatan yang lebih sederhana adalah dengan menghubungkan setiap partikel ke tiga atau empat partikel lainnya ketika membangun sistem partikel. Sekarang setiap partikel hanya perlu mendorong empat partikel lain yang terhubung dengannya. Namun, pendekatan ini membuat turbulensi dalam sistem partikel Anda menjadi tidak mungkin. Tetapi ini tampaknya tidak menjadi masalah, karena situasi Anda saat ini menggunakan tekstur statis. Pendekatan ini akan menjadi O (n) yang bagus.

Martijn Courteaux
sumber
Terima kasih! 1. Saya mengalami kesulitan memvisualisasikan ini. Bisakah Anda memposting mockup tentang bagaimana tampilannya \ bekerja di game Anda? 2. Menarik! akan membaca tentang itu
OpherV
Terima kasih untuk fotonya. Saya bisa melihat bagaimana itu akan bekerja dalam bentuk berbasis tabung atau garis, tetapi bagaimana itu akan bekerja dengan poligon? Bukankah gradien segitiga yang diproyeksikan dari setiap sisi tidak sejajar dengan baik ...?
OpherV
Buat mereka pas. Itulah idenya. Ini melibatkan beberapa titik penghitungan dan penghitungan persimpangan, dll. Anda juga bisa membagi batas dan melicinkannya. Banyak sekali kemungkinan.
Martijn Courteaux
3

Ide yang saya miliki ketika membaca posting Anda adalah yang ini:
• membangun satu set ubin yang akan Anda gunakan untuk area Anda.
• membuat poligon area pada kanvas sementara kecil pada resolusi ubin (mis: jika ubin 16X16, render pada resolusi lebih rendah (16X, 16X)).
• gunakan kanvas sementara untuk memutuskan apakah akan membuat ubin atau tidak pada kanvas utama:
jika suatu titik ditetapkan pada kanvas beresolusi rendah, gambarkan ubin 'acak' pada kanvas utama. jika suatu titik hanyalah tetangga dari set point, gambarkan ubin 'acak' pada opacity yang lebih rendah (untuk melakukan transisi) pada kanvas utama.

Saya takut menurunkan resolusi akan membuat efek blok, tetapi bahkan dengan ubin 20X20, tampilannya cukup bagus:

masukkan deskripsi gambar di sini

Langkah-langkah untuk ini adalah: ambil poligon Anda:
masukkan deskripsi gambar di sini

Gambar poligon pada resolusi ubin Anda: masukkan deskripsi gambar di sini(!! ya itu hal mal merah).

Kemudian gunakan imageData kanvas resolusi rendah untuk memutuskan apakah akan menggambar ubin atau catatan.
Jika sebuah piksel diatur pada kanvas beresolusi rendah, itu artinya kita harus menggambar ubin: ambil indeks ubin 'acak' untuk memilih ubin mana yang akan digambar. Indeks acak itu harus selalu sama untuk area / ubin tertentu.
Jika suatu titik kosong tetapi di samping titik yang diisi, gambar juga ubin, tetapi dengan setengah opacity.

masukkan deskripsi gambar di sini

Jadi mari kita menggambar ubin:

masukkan deskripsi gambar di sini

Untuk poligon saya hanya menggambar beberapa kali poligon, menurunkannya, dan meningkatkan opacity pada setiap undian (orang mungkin menggunakan globalCompositeOperation 'lebih ringan', juga).

masukkan deskripsi gambar di sini

Setelah Anda menjumlahkan semuanya, itu memberi:

masukkan deskripsi gambar di sini

biola ada di sini:

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

beri tahu saya jika ini membantu.

GameAlchemist
sumber
Terima kasih telah menguraikan solusi Anda dan memberikan kode! Apa yang Anda maksud dengan "Lalu gunakan imageData dari kanvas resolusi rendah untuk memutuskan apakah akan menggambar ubin atau catatan". Bagaimana Anda menggunakan data gambar kecil untuk memutuskan di mana \ cara menggambar pada gambar besar? Dan menggunakan metode ini bagaimana saya bisa menghindari tumpang tindih segitiga sehingga mencapai jarak yang mirip dengan mockup saya?
OpherV
Maksud saya ini adalah tes boolean lengkap: Apakah saya perlu mengisi ubin ini? , benar atau salah, diberikan oleh tes tes res rendah pada imageData [(x + y * lebar) * 4]! = 0, yaitu == 'apakah saya menggambar sesuatu di kanvas res rendah di tempat genteng itu? '. Kemudian jika ya, saya menggunakan beberapa rumus diisi angka-prime yang diuraikan (getRandomNumber) untuk beralih dari (x, y) ke indeks ubin 'acak' yang akan selalu memberikan angka yang sama untuk area yang diberikan + (x, y). Saya tidak melihat bagaimana hal-hal bisa tumpang tindih jika Anda mendefinisikan poligon dengan benar sehingga saya tidak mendapatkan pertanyaan kedua.
GameAlchemist
1

Hanya sebuah ide:

Di ubin Anda, "potongan" adalah sekitar 80px paling lebar. Saya sarankan, membuat 2 area. Anda menggambar poligon asli Anda, dan Anda membuat maketnya sekitar 80 piksel dari setiap sisi. Anda kemudian menarik ubin Anda ke dalam poligon yang lebih besar.

Kemudian, Semua "potongan" yang memiliki piksel di luar poligon bagian dalam, dan tidak ada persimpangan dengan poligon bagian yang Anda dapat membanjiri mengisinya dengan transparansi.

Ini level yang sangat tinggi, tetapi saya pikir saya akan membaginya dengan Anda. Ada banyak detail yang harus ditentukan di sini.

Gambar kasar untuk diperagakan:

masukkan deskripsi gambar di sini

Jika poligon hitam bagian dalam adalah yang asli, Anda akan menghapus semua poligon dengan titik merah.

pengguna46560
sumber
Bagaimana Anda memeriksa persimpangan untuk potongan-potongan yang tertanam dalam gambar ubin dengan poligon bagian dalam?
OpherV
@OpherV Uhmm, Anda dapat menentukan apakah titik X ada di dalam poligon, bukan? Anda dapat mengulangi semua piksel dalam poligon luar, dan untuk setiap piksel putih, periksa semua piksel, dan lihat apakah ada kebohongan di bagian dalam / luar. Ini kedengarannya tidak terlalu efisien, tetapi begitu Anda memiliki sesuatu, Anda dapat memikirkan cara untuk mengoptimalkan?
user46560
Itu pasca-pemrosesan dilakukan pada CPU. Hampir tidak dapat dioptimalkan sendiri. Ide Anda bisa bekerja dengan baik jika poligon bagian dalam dan bagian luar dihubungkan oleh strip segitiga. OP dapat menambahkan info atribut titik dan menandai setiap titik sebagai di dalam atau di luar. Kemudian, dalam vertex shader, opacity / alpha dapat diinterpolasi secara linier dari nilai yang kurang transparan ke yang opak lengkap.
teodron
@teodron Inilah poin yang saya coba sampaikan dalam jawaban. Itu ide tingkat tinggi, dan saya bukan pengembang game. Saya hanya punya ide.
user46560
@ user46560 ya, tapi dengan cara ini Anda tidak perlu menghitung piksel apa yang ada dalam pita antar-poligon sama sekali .. baik pada GPU, maupun pada CPU. Karena Anda tidak terbiasa dengan cara pengembangan game seperti yang Anda katakan, Anda berhak mendapatkan +1 untuk ide Anda :).
teodron