Sprite etrafında anahat çizmenin etkili yolu


21

Bir oyunu programlamak için XNA kullanıyorum ve spritelarım üzerinde 'seçilmiş' bir etki elde etmenin çeşitli yollarını deniyorum. Karşılaştığım sorun, spritebatch'te çizilen her bir tıklanabilir öğenin, tek bir sprite kullanılarak çizilmesidir (her nesne 6 spritedan oluşabilir).

Birisi bana, X piksellerinin sprite'larına anahat eklemeyi nasıl başarabilirim konusunda tavsiyede bulunabilirse sevinirim.

Şimdiden teşekkürler,

  • Greg.

Yanıtlar:


20

Bunu yapmanın en kolay yolu (performans için gerçekten zorlanmadığınız sürece muhtemelen en iyi yol), spritelarınızdan iki kopyasına sahip olmaktır.

  • Normal sürüm
  • "Yağ", renklendirilmemiş bir versiyon - temelde sprite X-çok pikselinizin orijinalinden daha "fatter" in beyaz versiyonu.

Nesnenizi "yağ" versiyonunu kullanarak çizin, ardından normal versiyonun üzerine çizin.

"Yağ" sürümünü beyaz yaparak, seçim rengini dinamik olarak değiştirmek için SpriteBatch'in yerleşik renk renklendirmesini kullanabilirsiniz.

"Şişman" verison'ınızı oluşturmak için orijinal spritelarınızı otomatik olarak alabilen, alfa kanallarını okuyan, orijinal alfadaki maksimum alfa kanalını her pikselin etrafına örnekleyerek yeni alfa kanalı oluşturmanızı sağlayan bir İçerik Boru Hattı Uzantısı yazmanızı öneririm. ve RGB = (1,1,1) ayarı.

Spritelarınızın hepsinin anahatları eklemek için yeterli saydam kenarlıkları olduğundan emin olmalısınız (bunu içerik işlemcide kontrol edebilirsiniz - ve gerekirse de yer açın).

Eğer sadece birkaç karakteriniz varsa, o zaman sadece iyi bir görüntü düzenleyici (GIMP, Photoshop) kullanabilir ve elle yapabilirsiniz: Seçimi yapmak için alfa kanalı, seçimi genişletmek, alfayı seçmek, renkli kanalları beyaz doldurmak.


4

İlk önce her bir nesneye tek bir sprite çeken bütün parçaları çizmeniz gerekiyor. Öyleyse, sprite kenarlarını tespit etmek için bir gölgelendirici yazmak zorunda kalacağınızı düşünüyorum. Bunu yapmak için zaten kullanabileceğiniz veya kullanabileceğiniz bazı gölgelendiriciler olması gerektiğini düşünüyorum.


11
Bu tür bir gölgelendirici yazmak şaşırtıcı derecede sinir bozucu, duydum (3D oyunlarımızdan birinde kullandık ve son derece çirkin vakalarla karşılaşmaya devam ettik). Göz önünde bulundurmak isteyebileceğiniz bir şey, anahattı (0, 255, 255, 0) gibi belirli bir renge sahip doğrudan sprite dokusuna doğrudan kodlamak ve sprite seçildiğinde gölgelendiricinin bu rengi dönüştürmesini sağlamaktır. Öyleyse gölgelendirici önemsiz bir renk değişikliğidir ve ana hat üzerinde ve istediğiniz ayrıntılarda üst düzeyde bir sanatçı kontrolüne sahipsiniz.

4

Gereksinimlere bağlı olarak, etkili olabilecek şey sadece sprite için talep üzerine bir taslak oluşturmaktır. Sprite'larınızın şeffaflığa sahip olduğunu ve sadece dikdörtgen olmaktan ziyade düzensiz şekilli olduklarını farz ediyorum (bunun için iyi çalışsa da, anahat dikdörtgenleri önemsiz olmalı).

when selected:
   outline = new sprite canvas of appropriate size
   for sprite in object:
      # use larger numbers for thicker outlines
      for x in (-1, 0, 1) and y in (-1, 0, 1):
         render sprite mask into canvas at x,y with desired color

Bunu her çizimde yapmanız gerekmediğine dikkat edin (sanırım yapabildiğiniz halde), ancak sprite'ları değiştirirken yeni anahat sprite'ı oluşturun.


Evet, önermek istediğim de bu. Maskelenmiş hareketli grafiği, mevcut hareketli grafiğin altında, orijinal hareketli grafiğin soluna, sağına, üstüne ve altına 1 piksel kaldırın. Pek çok oyun, bu yöntemi oluşturulmuş metni ana hatlarıyla belirtmek için veya bir alt gölge oluşturmak için 4 konumdan yalnızca 2'siyle kullandı.
Kaj

1

En basit kaba kuvvet yaklaşımı, normal ve vurgulanmış her bir sprite için iki kopya oluşturmaktır. Ardından vurgulandığında onları değiştirin.

Yedeklenecek hafızanız varsa, bundan daha karmaşık hale gelmenize gerek yoktur. Ayrıca sanatçılar, vurgulandıklarında görünüm üzerinde tam kontrole sahipler, böylece bir taslak veya istediğiniz herhangi bir şeyi yapabilirsiniz.


Bence sorunun bir kısmı OP'nin her bir nesnenin birden fazla spritten yapılabileceğini söylediğidir. Bu nedenle, anahat her bileşen sprite etrafında ayrı bir anahattı yerine, birleştirilen nesnenin anahat olması gerektiğini düşünüyorum.
Chris Howe

1
Chris, birleştirilen nesnenin ana hatları olmak zorunda değildir ve birden çok sprite yapılmış bir nesne için iyi çalışacaktır. Sadece wkerslake'in söylediklerini yapın, ancak vurgulanan sprite'ları o nesnenin normal sprite'larının arkasına çizdiğinizden emin olun. Bu şekilde, bir nesnenin kaç spreni yapıldığı önemli değildir, vurgu, bu nesnenin çizim süresinin iki katından biraz daha azını kullanacaktır; bu, birleştirilen spritlerle çalışma zamanında anahatları oluşturmaktan çok daha az olmalıdır.
AttackHobo

1

Her sprite için, temel sprite'ın bir taslağı olan başka bir sprite da var. Seviyelendirilmiş bir nesneyi çizerken, temel spritleri çizin, ardından birleştirilmiş işlemenin bir maskesini yapın, ardından maskenin dışındaki anahat sprite'larını çizin.


2
Neden sadece ilk önce anahat sprite'larını çizmiyor ve normal spritelarını üstlerine çizmiyorsun?
Chris Howe

Bunu yapmamak için bir neden (veya Chris'in önerisi) iki kat daha fazla doku belleği kullanmasıdır; Bunun bir başka nedeni de sanatçının iş akışının berbat olması çünkü her bir sprite değiştirdiğinizde iki dosyayı güncellemeniz gerekiyor.

2
Evet, ideal olarak iki gerçek sprite varlığınız olmazdı. Spritelarınız için alfa testi kullanıyorsanız, taslağı sprite içerisine koyabilir ve saydam alanlarınızdan biraz daha yüksek bir alfa verebilirsiniz. Daha sonra alfa testi referans değerini kontrol ederek, anahattın görünür olup olmadığını kontrol edebilirsiniz. Tek söylediğim, eğer 2 sprite versiyonunuz varsa (2 varlığından mı yoksa aynı varlığın 2 durumundan mı) önce taslak versiyonunu, sonra normal versiyonunu çizmelisin. Bu şekilde, süslü gölgelendiriciler, maskeler veya başka bir şey gerektirmezsiniz.
Chris Howe

1
Chris'in fikri hak ediyor; Ek olarak, varlık / içerik hattınızın bir parçası olarak çalışan anahat sprite'ları için alfa oluşturmak üzere bir araç oluşturursanız, sanatçının 2 dosya güncellemesine (hatta aynı öğeye) sahip olmasından kaçınılabilir. Doku belleği bir sorun olabilir veya olmayabilir, ancak ayrı anahat sprite'ları yüksek oranda DXT ile sıkıştırılabilir olmalıdır; Orijinal hafızanın 1 / 6'sının video hafızasında ve aslına uygunluk kaybı olmadan.
jpaver

1

Farklı ticaretlerle birlikte birkaç farklı çözüm.

En kolay: Nesneyi düz bir renk kullanarak birden çok kez renderleyin ve konumu titreyin (sola, yukarı, aşağı, sağa vb.), Bu, üzerine ne koyduğunuzun ana hatlarını oluşturur; Çok fazla fazla işlenmemiş yağ sınırlarına izin verin. Bir veya iki piksel kenarlık 4x ile tamam olabilir.

En hızlı: Dokuyu önceden işleyin ve zaten kenarlıklı olan veya yalnızca kenarlık olan bir kopyasına sahip olan veya gölgelendiricide renklendirebileceğiniz düz gri tonlamalı 8 bitlik bir maskedir. Bu büyük olasılıkla bellek pahasına hızlı olacaktır.

En İyi: Benim fikrim, ancak nesnenizin İmzalı Mesafe Alanı (SDF) gösterimini oluşturmak muhtemelen en iyi çözüm olacaktır. Bu dokular kaynak dokusundan çok daha küçük olabilir ve yine de yararlı veriler yakalayabilir. Temel olarak her piksel, onu oluşturmak için kullanılan nesneden ne kadar uzakta olduğunu kodlar. Elinizdeki bu verilerle, parlamadan ana hatlara kadar her türlü efekti yazabilirsiniz. Sınır, boyut ve renk vb. Gibi değişebilir ve hala nispeten ucuz bir gölgelendirici ve sadece bir ekstra çizimdir. Dezavantajı takım ve ön işleme.


0

Verimlilikten emin değilim, ancak görebildiğim en kolay yol, sprite'ın daha büyük bir versiyonunu önce seçtiğiniz renge çekmek olacaktır. Bunun üzerine sprite çizin. Seçimin etkisini veren yalnızca ilk sprite kenarını göreceksiniz.

EDIT: Ancak, yorumlardan görebileceğiniz gibi, bu iyi bir fikir değil.


1
Sadece bir sprite yukarı ölçeklendirme gerçek bir taslak vermez
Iain

2
Öyle sanmıyorum ama kolay olurdu.
Komünist Ördek

2
Pek çok şey kolaydır, ancak sorunu çözmeyin. Her türlü ilginç silueti olan sprite için, bir ölçek büyütme mutlak çöp üretecektir.

Ölçeklendirme yalnızca kare veya dairesel nesneler için iyi görünür. Şekil çok geniş veya uzunsa veya boşluklar varsa, gerçekten kötü görünecektir.
AttackHobo

3
Ölçeklendirmek, hiçbir şey yapmamaktan daha iyi sonuçlar verecektir ve aynı zamanda “mükemmelliğe” giden yolda da yararlı bir adım olacaktır. Grafiksel sonuçlar mükemmel olmamakla birlikte, eğer bu dahili bir araç için olsaydı, Yeterince İyi olabilirdi.
çizgi-tom-bang

0

Sprite'ı büyütmekle aynı fikirdeyim. En kolay rotaya kadar ve özellikle bu amaç için ek sprite oluşturmak zorunda kalmadan HERHANGİ bir sprite seçmeye uygulayabilirsiniz.

  • yani, spriteOutline.Scale = spriteOriginal.Scale * 0.1f; spriteOutline.Color = yeni Renk (255, 0, 0, 255);

0

Orijinal sprite rengini anahat rengiyle değiştirin (veya isterseniz renklendirin). Bu düz gölgeli veya renkli sprite dört kez 1 piksel ofset ile işlenir: x, y = (- 1, -1), sonra (+ 1, -1), sonra (-1, + 1) sonra (+1) , +1). Nesneyi oluşturan tüm sprite için tekrarlayın.

Bundan sonra, orijinal spriteları (0,0) 'da üst üste uygun sırayla yapın.

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.