Bir Flash Oyunu HTML5'e Dönüştürürken Neleri Bilmeniz Gerekir?
Yayınlanan: 2022-03-10HTML5 kullanımının artmasıyla birlikte birçok şirket, modası geçmiş Flash'tan kurtulmak ve ürünlerini en son endüstri standartlarıyla eşleştirmek için en popüler oyunlarını yeniden yapmaya başlar. Bu değişiklik özellikle Kumar/Kumarhane ve Eğlence sektörlerinde görülmektedir ve birkaç yıldır uygulanmaktadır, bu nedenle iyi bir oyun seçimi şimdiden dönüştürülmüştür.
Ne yazık ki, internette gezinirken, görünüşte aceleci bir işin örneklerine oldukça sık rastlayabilirsiniz, bu da nihai ürünün sevgili kalitesiyle sonuçlanır. Bu nedenle, oyun geliştiricilerinin zamanlarının bir kısmını Flash'tan HTML5'e dönüştürme konusuna aşina olmak ve işe başlamadan önce hangi hatalardan kaçınmaları gerektiğini öğrenmek için ayırmaları iyi bir fikirdir.
Flash yerine JavaScript'i seçmenin nedenleri arasında, bariz teknik sorunların yanı sıra, oyun tasarımınızı SWF'den JavaScript'e değiştirmenin daha iyi bir kullanıcı deneyimi sağlaması ve buna modern bir görünüm kazandırması da yer alıyor. Ama nasıl yapmalı? Bu eski teknolojiden kurtulmak için özel bir JavaScript oyun dönüştürücüsüne mi ihtiyacınız var? Pekala, Flash'tan HTML5'e dönüştürme çocuk oyuncağı olabilir - işte bunun nasıl icabına bakılacağı.
Önerilen okuma : HTML5 Oyun Tasarımının İlkeleri
HTML5 Oyun Deneyimi Nasıl İyileştirilir
Bir oyunu başka bir platforma dönüştürmek, onu geliştirmek, sorunlarını çözmek ve izleyiciyi artırmak için mükemmel bir fırsattır. Aşağıda kolayca yapılabilecek ve dikkate alınması gereken birkaç şey bulunmaktadır:
Destekleyen mobil cihazlar
Flash'tan JavaScript'e geçiş, daha geniş bir kitleye (mobil cihaz kullanıcıları) ulaşmayı sağlar; dokunmatik ekran kontrolleri için desteğin genellikle oyuna da uygulanması gerekir. Neyse ki, hem Android hem de iOS cihazları artık WebGL'yi de destekliyor, bu nedenle 30 veya 60 FPS oluşturma genellikle kolayca elde edilebilir. Çoğu durumda, 60 FPS herhangi bir soruna neden olmaz ve bu, mobil cihazlar giderek daha fazla performans gösterdiğinden yalnızca zamanla iyileşir.- Performansı iyileştirmek
ActionScript ve JavaScript'i karşılaştırmak söz konusu olduğunda, ikincisi birincisinden daha hızlıdır. Bunun dışında, bir oyunu dönüştürmek, oyun kodunda kullanılan algoritmaları tekrar gözden geçirmek için iyi bir fırsattır. JavaScript oyun geliştirme ile bunları optimize edebilir veya orijinal geliştiriciler tarafından bırakılan kullanılmayan kodu tamamen kaldırabilirsiniz. - Hataları düzeltme ve oynanışta iyileştirmeler yapma
Oyunun kaynak kodunu inceleyen yeni geliştiricilere sahip olmak, bilinen hataları düzeltmeye veya yeni ve çok nadir olanları keşfetmeye yardımcı olabilir. Bu, oyunu oynamayı oyuncular için daha az rahatsız edici hale getirecek, bu da sitenizde daha fazla zaman geçirmelerini sağlayacak ve diğer oyunlarınızı denemeye teşvik edecektir. - Web analitiği ekleme
Trafiği izlemeye ek olarak, web analitiği, oyuncuların bir oyunda nasıl davrandıkları ve oyun sırasında nerede takıldıkları hakkında bilgi toplamak için de kullanılabilir. - Yerelleştirme ekleme
Bu, izleyiciyi artıracaktır ve oyununuzu oynayan diğer ülkelerden gelen çocuklar için önemlidir. Ya da belki oyununuz İngilizce değildir ve bu dili desteklemek mi istiyorsunuz?
Oyun İçi Kullanıcı Arayüzü için HTML ve CSS'yi Atlamak Neden Oyun Performansını İyileştirecek?
JavaScript oyun geliştirme söz konusu olduğunda, oyun içi düğmeler, widget'lar ve diğer GUI öğeleri için HTML ve CSS'den yararlanmak cazip gelebilir. Benim tavsiyem burada dikkatli olmanızdır. Sezgisel değil, ancak aslında DOM öğelerinden yararlanmak karmaşık oyunlarda daha az performans gösteriyor ve bu, mobil cihazlarda daha fazla önem kazanıyor. Tüm platformlarda sabit 60 FPS elde etmek istiyorsanız, HTML ve CSS'den istifa etmeniz gerekebilir.
Sağlık çubukları, cephane çubukları veya puan sayaçları gibi etkileşimli olmayan GUI öğeleri, normal görüntüler ( Phaser.Image
sınıfı) kullanılarak, kırpma için .crop
özelliğinden ve basit işlemler için Phaser.Text
sınıfından yararlanılarak Phaser'da kolayca uygulanabilir. metin etiketleri.
Düğmeler ve onay kutuları gibi etkileşimli öğeler, yerleşik Phaser.Button
sınıfı kullanılarak uygulanabilir. Diğer, daha karmaşık öğeler, gruplar, resimler, düğmeler ve metin etiketleri gibi farklı basit türlerden oluşabilir.
Not: Bir Phaser.Text veya PIXI.Text nesnesini her başlattığınızda, üzerine metin işlenecek yeni bir doku oluşturulur. Bu ek doku, köşe gruplamasını bozar, bu yüzden çok fazla olmamasına dikkat edin .
Özel Yazı Tiplerinin Yüklendiğinden Nasıl Emin Olunur?
Özel bir vektör yazı tipiyle (örneğin TTF veya OTF) metin oluşturmak istiyorsanız, herhangi bir metin oluşturmadan önce yazı tipinin tarayıcı tarafından zaten yüklendiğinden emin olmanız gerekir. Phaser v2 bu amaç için bir çözüm sağlamaz, ancak başka bir kitaplık kullanılabilir: Web Font Loader.
Bir yazı tipi dosyanız olduğunu ve sayfanıza Web Yazı Tipi Yükleyicisini eklediğinizi varsayarsak, aşağıda bir yazı tipinin nasıl yükleneceğine dair basit bir örnek verilmiştir:
Web Font Loader tarafından yüklenecek basit bir CSS dosyası oluşturun (bunu HTML'nize eklemeniz gerekmez):
@font-face { // This name you will use in JS font-family: 'Gunplay'; // URL to the font file, can be relative or absolute src: url('../fonts/gunplay.ttf') format('truetype'); font-weight: 400; }
Şimdi WebFontConfig
adında global bir değişken tanımlayın. Bu kadar basit bir şey genellikle yeterli olacaktır:
var WebFontConfig = { 'classes': false, 'timeout': 0, 'active': function() { // The font has successfully loaded... }, 'custom': { 'families': ['Gunplay'], // URL to the previously mentioned CSS 'urls': ['styles/fonts.css'] } };
Sonunda, kodunuzu yukarıda gösterilen 'aktif' geri aramaya koymayı unutmayın. Ve bu kadar!
Kullanıcıların Oyunu Kaydetmesini Kolaylaştırma
Yerel verileri ActionScript'te kalıcı olarak depolamak için SharedObject sınıfını kullanırsınız. JavaScript'te, basit değiştirme, daha sonra almak için dizeleri depolamaya izin veren localStorage API'dir, hayatta kalan sayfa yeniden yüklemeleri.
Verileri kaydetmek çok basittir:
var progress = 15; localStorage.setItem('myGame.progress', progress);
Yukarıdaki örnekte bir sayı olan progress
değişkeninin bir dizgeye dönüştürüleceğini unutmayın.
Yükleme de basittir, ancak alınan değerlerin dize veya yoksa null
olacağını unutmayın.
var progress = parseInt(localStorage.getItem('myGame.progress')) || 0;
Burada dönüş değerinin bir sayı olmasını sağlıyoruz. Mevcut değilse, progress
değişkenine 0 atanacaktır.
Ayrıca JSON gibi daha karmaşık yapıları da depolayabilir ve alabilirsiniz:
var stats = {'goals': 13, 'wins': 7, 'losses': 3, 'draws': 1}; localStorage.setItem('myGame.stats', JSON.stringify(stats)); … var stats = JSON.parse(localStorage.getItem('myGame.stats')) || {};
localStorage nesnesinin kullanılamayacağı bazı durumlar vardır. Örneğin, file://
protokolünü kullanırken veya özel bir pencerede bir sayfa yüklendiğinde. Aşağıdaki örnekte gösterildiği gibi, kodunuzun hem çalışmaya devam etmesini hem de varsayılan değerleri kullanmasını sağlamak için dene ve yakala ifadesini kullanabilirsiniz:
try { var progress = localStorage.getItem('myGame.progress'); } catch (exception) { // localStorage not available, use default values }
Hatırlanması gereken başka bir şey de, saklanan verilerin URL başına değil, etki alanı başına kaydedilmesidir. Bu nedenle, birçok oyunun tek bir etki alanında barındırılması riski varsa, kaydederken bir önek (ad alanı) kullanmak daha iyidir. Yukarıdaki örnekte 'myGame.'
böyle bir önektir ve genellikle onu oyunun adıyla değiştirmek istersiniz.
Not : Oyununuz bir iframe içine yerleştirilmişse localStorage iOS'ta kalıcı olmaz. Bu durumda, bunun yerine verileri üst iframe'de saklamanız gerekir .
Varsayılan Fragment Shader'ı Değiştirmekten Nasıl Yararlanılır
Phaser ve PixiJS, hareketli görüntülerinizi oluşturduğunda, basit bir dahili parça gölgelendiricisi kullanırlar. Bir hıza uygun olduğu için pek fazla özelliği yoktur. Ancak, bu gölgelendiriciyi amaçlarınız için değiştirebilirsiniz. Örneğin, fazla çizimi denetlemek veya işleme için daha fazla özelliği desteklemek için bundan yararlanabilirsiniz.
Aşağıda kendi varsayılan parça gölgelendiricinizi Phaser v2'ye nasıl sağlayacağınıza dair bir örnek verilmiştir:
function preload() { this.load.shader('filename.frag', 'shaders/filename.frag'); } function create() { var renderer = this.renderer; var batch = renderer.spriteBatch; batch.defaultShader = new PIXI.AbstractFilter(this.cache.getShader('filename.frag')); batch.setContext(renderer.gl); }
Not: Varsayılan gölgelendiricinin TÜM hareketli grafikler için ve ayrıca bir doku oluştururken kullanıldığını unutmamak önemlidir. Ayrıca, tüm oyun içi hareketli grafikler için karmaşık gölgelendiriciler kullanmanın, oluşturma performansını büyük ölçüde azaltacağını unutmayın .
Varsayılan Gölgelendirici ile Renklendirme Yöntemi Nasıl Değiştirilir
Phaser ve PixiJS'de varsayılan renklendirme yöntemini değiştirmek için özel varsayılan gölgelendirici kullanılabilir.
Phaser ve PixiJS'de renklendirme, doku piksellerini belirli bir renkle çarparak çalışır. Çarpma her zaman renkleri koyulaştırır, bu açıkça bir sorun değildir; Flash renklendirmeden tamamen farklıdır. Oyunlarımızdan biri için Flash'a benzer bir renklendirme uygulamamız gerekiyordu ve özel bir varsayılan gölgelendiricinin kullanılabileceğine karar verdik. Aşağıda böyle bir parça gölgelendirici örneği verilmiştir:
// Specific tint variant, similar to the Flash tinting that adds // to the color and does not multiply. A negative of a color // must be supplied for this shader to work properly, ie set // sprite.tint to 0 to turn whole sprite to white. precision lowp float; varying vec2 vTextureCoord; varying vec4 vColor; uniform sampler2D uSampler; void main(void) { vec4 f = texture2D(uSampler, vTextureCoord); float a = clamp(vColor.a, 0.00001, 1.0); gl_FragColor.rgb = f.rgb * vColor.a + clamp(1.0 - vColor.rgb/a, 0.0, 1.0) * vColor.a * fa; gl_FragColor.a = fa * vColor.a; }
Bu gölgelendirici, renk tonuna bir temel renk ekleyerek pikselleri aydınlatır. Bunun çalışması için, istediğiniz rengin negatifini sağlamanız gerekir. Bu nedenle, beyaz elde etmek için şunları ayarlamanız gerekir:
sprite.tint = 0x000000; // This colors the sprite to white Sprite.tint = 0x00ffff; // This gives red
Oyunumuzdaki sonuç şöyle görünüyor (tankların vurulduğunda nasıl beyaz renkte parladığına dikkat edin):
Doluluk Oranı Sorunlarını Tespit Etmek İçin Overdraw Nasıl İncelenir
Varsayılan gölgelendiricinin değiştirilmesi, hata ayıklamaya yardımcı olması için de kullanılabilir. Aşağıda böyle bir gölgelendirici ile fazla çekmenin nasıl tespit edilebileceğini açıkladım.
Fazla çizim, ekrandaki piksellerin çoğu veya tamamı birden çok kez oluşturulduğunda gerçekleşir. Örneğin, birçok nesne aynı yeri alıyor ve birbiri üzerine işleniyor. Bir GPU'nun saniyede kaç piksel oluşturabileceği, doluluk oranı olarak tanımlanır. Modern masaüstü GPU'ları, olağan 2B amaçlar için aşırı doluluk oranına sahiptir, ancak mobil olanlar çok daha yavaştır.
PixiJS ve Phaser'daki varsayılan global parça gölgelendiriciyi bununla değiştirerek ekrandaki her pikselin kaç kez yazıldığını bulmanın basit bir yöntemi vardır:
void main(void) { gl_FragColor.rgb += 1.0 / 7.0; }
Bu gölgelendirici, işlenmekte olan pikselleri aydınlatır. 7.0 sayısı, pikseli beyaza çevirmek için kaç yazma gerektiğini gösterir; Bu numarayı beğeninize göre ayarlayabilirsiniz. Yani ekranda daha açık pikseller birkaç kez, beyaz pikseller ise en az 7 kez yazıldı.
Bu gölgelendirici ayrıca, hem bir nedenden dolayı hala oluşturulan "görünmez" nesneleri hem de çıkarılması gereken aşırı şeffaf alanlara sahip hareketli grafikleri bulmaya yardımcı olur (GPU'nun dokularınızdaki saydam pikselleri işlemesi gerekir).
Soldaki resim, bir oyuncunun oyunu nasıl gördüğünü gösterirken, sağdaki resim, aynı sahneye fazladan çekme gölgelendiricisinin uygulanmasının etkisini gösterir.
Fizik Motorları Neden Arkadaşınızdır?
Bir fizik motoru, fizik cisimlerini (genellikle katı cisim dinamikleri) ve çarpışmalarını simüle etmekten sorumlu olan bir ara katman yazılımıdır. Fizik motorları 2B veya 3B alanları simüle eder, ancak ikisini birden değil. Tipik bir fizik motoru şunları sağlayacaktır:
- hızları, ivmeleri, eklemleri ve motorları ayarlayarak nesne hareketi;
- çeşitli şekil türleri arasındaki çarpışmaları algılamak;
- çarpışma yanıtlarının hesaplanması, yani iki nesnenin çarpıştığında nasıl tepki vermesi gerektiği.
Merixstudio'da Box2D fizik motorunun büyük hayranlarıyız ve birkaç kez kullandık. Bu amaç için iyi çalışan bir Phaser eklentisi var. Box2D, Unity oyun motorunda ve GameMaker Studio 2'de de kullanılır.
Bir fizik motoru gelişiminizi hızlandıracak olsa da, ödemeniz gereken bir bedel vardır: azaltılmış çalışma zamanı performansı. Çarpışmaları tespit etmek ve yanıtları hesaplamak, CPU yoğun bir iştir. Cep telefonlarındaki bir sahnede birkaç düzine dinamik nesneyle sınırlı olabilirsiniz veya düşük performansla ve 60 FPS'nin altında düşük kare hızıyla karşılaşabilirsiniz.
Resmin sol kısmı bir oyundan bir sahnedir, sağ taraf ise üstte görüntülenen Phaser fizik hata ayıklama katmanıyla aynı sahneyi gösterir.
Bir .fla Dosyasından Sesler Nasıl Dışa Aktarılır
Bir .fla dosyasının içinde bir Flash oyun ses efektleriniz varsa, bu amaca hizmet eden menü seçeneğinin olmaması nedeniyle bunları GUI'den dışa aktarmak mümkün değildir (en azından Adobe Animate CC 2017'de değil). Ancak başka bir çözüm daha var - tam da bunu yapan özel bir komut dosyası:
function normalizeFilename(name) { // Converts a camelCase name to snake_case name return name.replace(/([AZ])/g, '_$1').replace(/^_/, '').toLowerCase(); } function displayPath(path) { // Makes the file path more readable return unescape(path).replace('file:///', '').replace('|', ':'); } fl.outputPanel.clear(); if (fl.getDocumentDOM().library.getSelectedItems().length > 0) // Get only selected items var library = fl.getDocumentDOM().library.getSelectedItems(); else // Get all items var library = fl.getDocumentDOM().library.items; // Ask user for the export destination directory var root = fl.browseForFolderURL('Select a folder.'); var errors = 0; for (var i = 0; i < library.length; i++) { var item = library[i]; if (item.itemType !== 'sound') continue; var path = root + '/'; if (item.originalCompressionType === 'RAW') path += normalizeFilename(item.name.split('.')[0]) + '.wav'; else path += normalizeFilename(item.name); var success = item.exportToFile(path); if (!success) errors += 1; fl.trace(displayPath(path) + ': ' + (success ? 'OK' : 'Error')); } fl.trace(errors + ' error(s)');
Ses dosyalarını dışa aktarmak için komut dosyası nasıl kullanılır:
- Yukarıdaki kodu bilgisayarınıza .jsfl dosyası olarak kaydedin;
- Adobe Animate ile bir .fla dosyası açın;
- Üst menüden 'Komutlar' → 'Komut Çalıştır'ı seçin ve açılan diyalogda komut dosyasını seçin;
- Şimdi dışa aktarma hedef dizinini seçmek için başka bir diyalog dosyası açılır.
Ve bitti! Artık belirtilen dizinde WAV dosyalarınız olmalıdır. Geriye bunları MP3'lere, OGG'ye veya AAC'ye dönüştürmek kalıyor.
Flash'ta MP3'leri HTML5'e Dönüştürmede Kullanma
Bazı patentlerin süresi dolduğundan ve artık her tarayıcı MP3'lerin kodunu çözüp çalabildiğinden, eski güzel MP3 formatı geri döndü. Bu, sonunda iki ayrı ses formatı hazırlamaya gerek olmadığı için geliştirmeyi biraz daha kolaylaştırır. Daha önce örneğin OGG ve AAC dosyalarına ihtiyacınız vardı, şimdi ise MP3 yeterli olacak.
Yine de MP3 hakkında hatırlamanız gereken iki önemli şey var:
- MP3'lerin yüklendikten sonra kodunu çözmesi gerekiyor, özellikle mobil cihazlarda ne zaman alıcı olabilir. Tüm varlıklarınız yüklendikten sonra bir duraklama görürseniz, bu muhtemelen MP3'lerin kodunun çözüldüğü anlamına gelir;
- döngülü MP3'leri aralıksız çalmak biraz sorunlu. Çözüm, Compu Phase tarafından yayınlanan makalede okuyabileceğiniz mp3loop kullanmaktır.
Peki, Neden Flash'ı JavaScript'e Dönüştürmelisiniz?
Gördüğünüz gibi, ne yapacağınızı biliyorsanız, Flash'tan JavaScript'e dönüştürme imkansız değildir. Bilgi ve beceri ile Flash ile uğraşmayı bırakabilir ve JavaScript'te oluşturulmuş akıcı, eğlenceli oyunların keyfini çıkarabilirsiniz. Flash'ı düzeltmeye çalışmayın - herkes bunu yapmaya zorlanmadan ondan kurtulun!
Daha fazla öğrenmek ister misiniz?
Bu yazıda ağırlıklı olarak Phaser v2'ye odaklandım. Ancak, Phaser'ın daha yeni bir sürümü artık mevcut ve birden fazla kamera, sahne, tilemap veya Matter.js fizik motoru gibi çok sayıda yeni, harika özellik sunduğu için bunu kontrol etmenizi şiddetle tavsiye ediyorum.
Yeterince cesursanız ve tarayıcılarda gerçekten dikkate değer şeyler yaratmak istiyorsanız, WebGL'yi baştan öğrenmek için doğru şey budur. Çeşitli oyun oluşturma çerçevelerinden veya araçlarından daha düşük bir soyutlama düzeyidir ancak 2B oyunlar veya demolar üzerinde çalışsanız bile daha yüksek performans ve kalite elde etmenize olanak tanır. WebGL'nin temellerini öğrenirken yararlı bulabileceğiniz birçok web sitesi arasında WebGL Temelleri (etkileşimli demolar kullanır) bulunur. Buna ek olarak, WebGL özelliğinin benimsenme oranları hakkında daha fazla bilgi edinmek için WebGL İstatistiklerine bakın.
Her zaman çok fazla bilgi diye bir şey olmadığını unutmayın - özellikle oyun geliştirme söz konusu olduğunda!