Parçacıklı yumuşak kenar alanları nasıl uygulanır


13

Oyunum Phaser kullanılarak oluşturuldu, ancak sorunun kendisi motor agnostik.

Oyunumda, oyuncu karakterlerin taşınabileceği ve etkilenebileceği çokgen ortamlar var. Örneğin buz, ateş, zehir vs. Şu anda bunu nasıl uyguladığım - parçacık desenli bir tilesprite kapsayan çokgen maske ile:

resim açıklamasını buraya girin

Sert kenar kötü görünüyor. İki şey yaparak iyileştirmek istiyorum: 1. Çokgen dolgu alanını yumuşak bir kenar elde etmek ve arka plana karıştırmak. 2. Kırıklardan bazılarının çokgen alanından çıkmasını sağlayın, böylece ortada kesilmezler ve alan düz bir çizgiye sahip olmaz

örneğin (mockup):

resim açıklamasını buraya girin

Bence 1 poligonun bulanıklaştırılmasıyla elde edilebilir, ama 2 ile nasıl devam edeceğinden emin değilim.

Bunu nasıl uygularsınız?


2
Harika görünüyor. Oyununuza bir bağlantı alabilir miyim lütfen? :)
ashes999

@GameAlchemist İşte kiremit resmi i.imgur.com/y54CeQ9.png
OpherV

@ ashes999 Hala devam eden bir çalışma. Bir kez ben var sonra kesinlikle bir bağlantı
göndereceğim

Beyaz nesnelerle şeffaf bir PNG olduğuna dikkat edin. Beyaz bir arka planda görüntülerseniz (bir tarayıcıda resim açarken olduğu gibi) hiçbir şey
görmezsiniz

@OpherV harika olurdu. Lütfen sadece sorunuzu düzenleyin ve bir bağlantı gönderin - muhtemelen bu sitede pazarlamanın en konudaki yolu :)
ashes999

Yanıtlar:


2

1. mockup'ınıza yakın bir şey istiyorsanız, parçacıklar kullanırdım (tamamen şişmiş bir parçacık sistemi olması gerekmez).

Parçacıklarınızı bir RenderTexture üzerinde çokgen şeklinde işleyin. Parçacıklar üzerinde ilave karıştırma kullandığınızdan emin olun. Çokgenin içindeki parçacıklar birbirine karışır, dıştaki parçacıklar ise istediğiniz yumuşak kenarı verir. (Efektin bir örneği bu youtube videosunda izlenebilir: Ek Parçacıklar Videosu Şimdi RenderTexture'ı ana ekranınıza oluşturun ve işiniz bitti. RenderTexture, parçacıkların arka planınızla karışmaması için gereklidir.

Üçgenleri doğrudan parçacık dokusuna koymayı ve bunun nasıl çalıştığını görmeyi deneyebilirsiniz. Aksi takdirde, ayrı bir katman olarak "parçacık çorba" üstünde onları render.

Güncellenmiş bir jsfiddle'da buna benzeyen hızlı bir mockup oluşturuldu gösteri Güncellenmiş demoyu burada bulabilirsiniz

Her parçacığın hızı ve kaynağı vardır. Oynatıcınız çokgene dokunduğunda, her parçacık hızını oynatıcı hızıyla orantılı olarak değiştirirsiniz. Bir parçacık oynatıcınızdan ne kadar uzaksa, oyuncuların hızından o kadar az etkilenir.

Bir parçacık hızını hesaplamak için formül aşağıdaki gibi bir şey olacaktır:

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

Parçacığın konumunu hesaplamak için bunu güncelleme yönteminize koyun:

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;

Bu, oyuncu sıvıyı karıştırdığında her parçacığın başlangıç ​​noktasında sallandığı bir "sıvı" vermelidir. SpringConstant, bir parçacığın kaynağından ne kadar uzağa sallandığını ve sönümlemesini değiştirir. Oyunumda kullandığım bir 1d simülasyonunun değiştirilmiş versiyonu olduğu için kodu değiştirmeniz gerekebilir.

Şimdi bir demo ile: Demo Sadece sıvı istediğiniz gibi davranana kadar üstteki 3 sabitleri değiştirin.


Bu # 1'i çözmek için gerçekten ilginç bir fikir! Bunu sevdim. Üçgen hareketi \ aralığının uygulanmasını nasıl önerirsiniz?
OpherV

1
2. soruyu cevaplamak için orijinal yayını düzenledim.
zilluss

parçacık etkisinin küçük bir demosunu ekledi. Sanırım istediğin efekti biraz değiştirerek elde edebilirsin.
zilluss

Çözümünüzü kullandım, elde etmek istediğim etkiye en yakın olanı. Teşekkürler! Yine de bir soru - örneklerinizdeki yaylılığı nasıl sıkıştırırım, böylece gerçekten hafif hareketler parçacıkların bu kadar büyük mesafelere atlamasına neden olmaz?
OpherV

Sönümleme Faktörü ve yay ile oynayabilirsiniz. Yüksek sönümleme partikülleri daha hızlı bir şekilde dinlendirir. Daha düşük bir yay sabiti parçacıkların hızını düşürür. Ne yazık ki, her iki değer de partikül çorbasının daha viskoz hissetmesini sağlar. Bunun yerine, oynatıcınız parçacığa dokunduğunda, oynatıcının parçacığa eklediği maksimum hızı şu şekilde sıkıştırabilirsiniz: particle.velocity.x = kelepçe (maxVelocity, -maxVelocity, particle.velocity.x + ((playerInfluenceFactor * deltaVelocityX) ) + parçacık.sayısı.x) * (1 / distanceToPlayer)); kelepçe için bkz: stackoverflow.com/a/11409944
zilluss

4

Bu iki nokta hakkındaki düşüncelerim:

  1. Gölgelendirici bulanıklığını kullanabilirsiniz, ancak bu çok pahalı olacaktır. Bunun yerine, "bulanıklığı" simüle etmek için, merkezdeki yarı saydamdan kenarlarda saydam olana kadar fazladan bir üçgen kenarlığı çizerdim. Bunu bir oyunumda yaptım ve oldukça iyi çalışıyor. İşte benim oyunumda bir gökkuşağı-ish güçlendirici iki ekran görüntüleri.

    resim açıklamasını buraya girin resim açıklamasını buraya girin

    Dış kenarlığın bir gradyanı vardır. Benim durumumda, sınır iç kısım ile aynı opaklıkta başlamıyor, ancak bu opasiteleri eşit olarak ayarlarsanız, hoş bir solmaya sahip olacaksınız.

  2. Bir parçacık sistemi programlayıp parçacıkların çokgeni izlemesini sağlarım. Böylece kenarlarda ne olacağı konusunda endişelenmenize gerek kalmaz. Parçacık sisteminizin dinamiği, parçacıkların çokgenin içinde ve eşit olarak dağılmasını sağlayacaktır. En yakın parçacıkların birbirini itmesini sağlamaya çalışabilirsiniz, ancak bunu bir çok "kütle" ile yapabilirsiniz, böylece ataletiniz olur ve pürüzsüz görünür. Bu şeyi hızlı hale getirmek için bazı olasılıklar var, ancak büyük sorun, birbirlerini itme mekanizmasının zaman karmaşıklığı olacak. Her parçacığı diğer her parçacığı ittirirseniz, sisteminizde örneğin 100 parçacık varsa, iyi olmayan O (n ^ 2) olacaktır. Bunu nasıl optimize edebileceğinize dair iyi bir okuma, PixelJunk'ın bu sunumudur:http://fumufumu.q-games.com/gdc2010/shooterGDC.pdf

    Daha basit bir yaklaşım, partikül sistemi oluşturulurken her partikülü üç veya dört partiküle bağlamaktır. Şimdi her parçacık sadece bağlı olduğu diğer dört parçacığı itmek zorunda kalacak. Ancak, bu yaklaşım parçacık sisteminizdeki türbülansları imkansız hale getirir. Ancak bu durum bir sorun gibi görünmüyor, çünkü mevcut durumunuz statik bir doku kullanıyor. Bu yaklaşım harika O (n) olacaktır.


Teşekkürler! 1. Bunu görselleştirmekte zorlanıyorum. Oyunda nasıl göründüğüne dair bir model gönderebilir misiniz? 2. İlginç! bunu okuyacak
OpherV

Görüntüler için teşekkürler. Bunun tüp veya çizgi tabanlı bir şekilde nasıl çalıştığını görebiliyorum, ama bu bir poligonla nasıl çalışacak? Her iki taraftan yansıtılan üçgenlerin gradyanları iyi sıralanmayacak mı?
OpherV

Onları güzelce uydurun. Fikir bu. Bu, bazı matematik ve hesaplama kavşak noktalarını vb. İçerir. Ayrıca sınırı alt bölümlere ayırabilir ve düzeltebilirsiniz. Tonlarca olasılık.
Martijn Courteaux

3

Gönderinizi okurken sahip olduğum fikir şuydu:
• bölgeniz için kullanacağınız fayans seti oluşturun.
• alan çokgenini döşeme çözünürlüğünde küçük bir geçici tuval üzerinde oluşturun (örn: döşemeler 16X16 ise, (16X, 16X) daha düşük çözünürlükte render).
• ana tuvalde döşeme
yapıp yapmayacağınıza karar vermek için bu geçici tuvali kullanın: düşük çözünürlüklü tuvalde bir nokta ayarlanırsa, ana tuval üzerine 'rastgele' bir döşeme çizin. bir nokta sadece bir ayar noktasının komşusuysa, ana tuval üzerine daha düşük opaklıkta (geçiş yapmak için) 'rastgele' bir karo çizin.

Çözünürlüğün düşürülmesinin bir blok etkisi yaratacağından korktum, ancak 20X20 fayanslarda bile oldukça iyi görünüyor:

resim açıklamasını buraya girin

Bunun için adımlar şunlardır: çokgeninizi alın:
resim açıklamasını buraya girin

Çokgeni karo çözünürlüğünüzde çizin: resim açıklamasını buraya girin(!! evet bu alışveriş merkezi kırmızı şeydir).

Ardından, döşeme veya not çizip çizmemeye karar vermek için düşük çözünürlüklü tuvalin imageData öğesini kullanın.
Düşük çözünürlüklü tuval üzerinde bir piksel ayarlanırsa, döşemeyi çizmemiz gerektiği anlamına gelir: çizilecek döşemeyi seçmek için bir 'rastgele' döşeme dizini alın. Bu rastgele indeks belirli bir alan / döşeme için her zaman aynı olmalıdır.
Bir nokta boş, ancak doldurulmuş bir noktanın yanında ise, aynı zamanda yarı opaklıkla bir döşeme çizin.

resim açıklamasını buraya girin

Öyleyse fayansları çizelim:

resim açıklamasını buraya girin

Çokgen için, çokgenin birkaç katı çizilir, ölçeklenir ve her çizimde opaklık artar (biri globalCompositeOperation 'çakmağını da kullanabilir).

resim açıklamasını buraya girin

Her şeyi topladıktan sonra, verir:

resim açıklamasını buraya girin

keman burada:

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

bunun yardımcı olup olmadığını bana bildirin.


Çözümünüzü detaylandırdığınız ve kodu verdiğiniz için teşekkür ederiz! "Sonra bir karo veya not çizip çizmemeye karar vermek için düşük çözünürlüklü tuvalin imageData'sını kullanın" ile ne demek istersiniz? Büyük görüntüde nerede çizim yapılacağına karar vermek için küçük görüntü verilerini nasıl kullanırsınız? Ve bu yöntemi kullanarak üçgenlerin üst üste binmesini nasıl önleyebilirim, bu yüzden mockup'uma benzer boşluklar elde edebilirim?
OpherV

Yani tam bir boolean testi: Bu kutucuğu doldurmam gerekiyor mu? , true veya false, imageData [(x + y * width) * 4]! = 0 üzerindeki düşük çözünürlüklü testin testi ile verilir, yani == 'alt res tuvalinde bir şey çizdim mi o kiremit yeri mi? '' Sonra evet ise, (x, y) 'den belirli bir alan + (x, y) için her zaman aynı sayıyı sağlayacak bir' rastgele 'kiremit dizinine gitmek için bazı ayrıntılı asal sayı dolu formül (getRandomNumber) kullanın. Çokgeninizi doğru bir şekilde tanımlarsanız, işlerin nasıl üst üste gelebileceğini görmüyorum, bu yüzden ikinci sorunuzu alamıyorum.
GameAlchemist

1

Sadece bir fikir:

Karonuzda, "parçalar" en fazla yaklaşık 80 piksel genişliğindedir. Ben 2 alan yapma öneririm. Orijinal çokgeninizi çiziyorsunuz ve her kenarından yaklaşık 80 piksel dışarı bir model oluşturuyorsunuz. Daha sonra fayanslarınızı daha büyük çokgene çekersiniz.

Daha sonra, iç çokgenin dışında bir piksele sahip olan ve iç çokgenle kesişme olmayan tüm "parçalar", bunları saydamlıkla doldurabilirsiniz.

Bu çok yüksek bir seviyedir, ancak sizinle paylaşacağımı düşündüm. Burada belirlenecek çok fazla ayrıntı var.

Gösterilecek kaba bir görüntü:

resim açıklamasını buraya girin

İçteki siyah çokgen orijinal olsaydı, tüm çokgenleri kırmızı bir nokta ile silebilirsiniz.


Bununla birlikte, karo görüntüsüne iç çokgenle gömülü parçalar için kesişimi nasıl kontrol edersiniz?
OpherV

@OpherV Uhmm, X noktasının bir poligonda olup olmadığını belirleyebilirsiniz? Dış çokgendeki tüm pikseller arasında döngü yapabilirsiniz ve her bir beyaz piksel için taşkın tüm pikselleri kontrol edebilir ve iç / dışlarda herhangi bir yalan olup olmadığını görebilirsiniz. Bu özellikle etkili görünmüyor, ancak bir şeyiniz olduğunda optimize etmenin yollarını düşünebilirsiniz?
user46560

Bu işlem sonrası CPU'da yapılır. Kendi başına neredeyse hiç optimize edilemez. İç poligon ve dış üçgen şeritle bağlanırsa fikriniz iyi sonuç verebilir. OP köşe özniteliği bilgisi ekleyebilir ve her köşeyi içeride veya dışarıda etiketleyebilir. Daha sonra tepe gölgelendiricide, opaklık / alfa daha az saydam bir değerden tam bir opak olana doğrusal olarak enterpole edilebilir.
teodron

@teodron Cevapta yapmaya çalıştığım nokta bu. Bu üst düzey bir fikir ve ben aslında bir oyun geliştiricisi değilim. Sadece bir fikrim vardı.
user46560

@ user46560 evet, ancak bu şekilde o çokgenler arası bantta hangi piksellerin olduğunu hiç hesaplamak zorunda değilsiniz. Ne GPU'da ne de CPU'da. Dediğiniz gibi oyun geliştirme yollarına alışık olmadığınız için, fikriniz için bir +1 hak ediyorsunuz :).
teodron
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.