مدیریت دارایی ساده برای بازی های HTML5

معرفی

HTML5 بسیاری از APIهای مفید را برای ساخت برنامه های وب مدرن، پاسخگو و قدرتمند در مرورگر ارائه کرده است. این عالی است، اما شما واقعاً می خواهید بازی بسازید و بازی کنید! خوشبختانه، HTML5 همچنین دوره جدیدی از توسعه بازی را آغاز کرده است که از APIهایی مانند Canvas و موتورهای قدرتمند جاوا اسکریپت استفاده می کند تا بدون نیاز به افزونه، بازی را مستقیماً به مرورگر شما ارائه دهد.

این مقاله شما را در ساخت یک جزء ساده مدیریت دارایی برای بازی HTML5 خود راهنمایی می کند. بدون مدیر دارایی، بازی شما برای جبران زمان دانلود ناشناخته و بارگذاری ناهمزمان تصویر مشکل خواهد داشت. برای مشاهده نمونه ای از یک مدیر دارایی ساده برای بازی های HTML5 خود، همراه باشید.

مشکل

بازی‌های HTML5 نمی‌توانند فرض کنند دارایی‌های آن‌ها مانند تصاویر یا صدا در دستگاه محلی پخش‌کننده باشد، زیرا بازی‌های HTML5 نشان می‌دهد که در یک مرورگر وب با دارایی‌های دانلود شده از طریق HTTP بازی می‌شوند. از آنجایی که شبکه درگیر است، مرورگر مطمئن نیست که دارایی های بازی چه زمانی دانلود و در دسترس خواهند بود.

راه اصلی برای بارگذاری برنامه‌ای یک تصویر در مرورگر وب، کد زیر است:

var image = new Image();
image.addEventListener("success", function(e) {
  // do stuff with the image
});
image.src = "/some/image.png";

حال تصور کنید که صد تصویر داشته باشید که باید هنگام شروع بازی بارگذاری و نمایش داده شوند. چگونه متوجه می شوید که همه 100 تصویر آماده هستند؟ آیا همه آنها با موفقیت بارگیری شدند؟ بازی واقعاً چه زمانی باید شروع شود؟

راه حل

به یک مدیر دارایی اجازه دهید صف دارایی ها را مدیریت کند و زمانی که همه چیز آماده شد به بازی گزارش دهد. یک مدیر دارایی منطق بارگیری دارایی ها را از طریق شبکه تعمیم می دهد و راهی آسان برای بررسی وضعیت ارائه می دهد.

مدیر دارایی ساده ما شرایط زیر را دارد:

  • صف دانلودها
  • دانلودها را شروع کنید
  • موفقیت و شکست را دنبال کنید
  • وقتی همه چیز تمام شد سیگنال دهید
  • بازیابی آسان دارایی ها

در صف

اولین نیاز این است که بارگیری ها را در صف قرار دهید. این طرح به شما این امکان را می دهد که دارایی های مورد نیاز خود را بدون بارگیری واقعی آنها اعلام کنید. این می تواند مفید باشد، برای مثال، اگر بخواهید تمام دارایی های یک سطح بازی را در یک فایل پیکربندی اعلام کنید.

کد سازنده و صف به نظر می رسد:

function AssetManager() {
  this.downloadQueue = [];
}

AssetManager.prototype.queueDownload = function(path) {
    this.downloadQueue.push(path);
}

دانلودها را شروع کنید

پس از اینکه همه دارایی‌ها را در صف قرار دادید تا دانلود شوند، می‌توانید از مدیر دارایی بخواهید دانلود همه چیز را شروع کند.

مرورگر وب می‌تواند بارگیری‌ها را موازی کند، خوشبختانه - معمولاً حداکثر تا 4 اتصال در هر میزبان. یکی از راه‌های افزایش سرعت دانلود دارایی، استفاده از طیف وسیعی از نام‌های دامنه برای میزبانی دارایی است. به عنوان مثال، به جای ارائه همه چیز از assets.example.com، سعی کنید از assets1.example.com، assets2.example.com، assets3.example.com و غیره استفاده کنید. حتی اگر هر یک از آن نام‌های دامنه صرفاً یک CNAME برای همان وب سرور باشد، مرورگر وب آنها را به عنوان سرورهای جداگانه می‌بیند و تعداد اتصالات مورد استفاده برای دانلود دارایی را افزایش می‌دهد. درباره این تکنیک از تقسیم کامپوننت ها در دامنه ها در بهترین روش ها برای افزایش سرعت وب سایت خود بیشتر بیاموزید.

روش ما برای مقداردهی اولیه دانلود، downloadAll() نام دارد. ما آن را به مرور زمان خواهیم ساخت. در حال حاضر، اینجا اولین منطق برای شروع دانلودها است.

AssetManager.prototype.downloadAll = function() {
    for (var i = 0; i < this.downloadQueue.length; i++) {
        var path = this.downloadQueue[i];
        var img = new Image();
        var that = this;
        img.addEventListener("load", function() {
            // coming soon
        }, false);
        img.src = path;
    }
}

همانطور که در کد بالا می بینید، downloadAll() به سادگی از طریق downloadQueue تکرار می شود و یک آبجکت Image جدید ایجاد می کند. یک رویداد شنونده برای رویداد بارگذاری اضافه می شود و src تصویر تنظیم می شود که بارگیری واقعی را آغاز می کند.

با این روش می توانید دانلودها را شروع کنید.

پیگیری موفقیت و شکست

یکی دیگر از الزامات این است که هم موفقیت و هم شکست را ردیابی کنید، زیرا متأسفانه همه چیز همیشه عالی پیش نمی رود. کد تا کنون فقط دارایی‌های دانلود شده با موفقیت را ردیابی می‌کند. با افزودن شنونده رویداد برای رویداد خطا، می‌توانید هم سناریوهای موفقیت و هم شکست را ثبت کنید.

AssetManager.prototype.downloadAll = function(downloadCallback) {
  for (var i = 0; i < this.downloadQueue.length; i++) {
    var path = this.downloadQueue[i];
    var img = new Image();
    var that = this;
    img.addEventListener("load", function() {
        // coming soon
    }, false);
    img.addEventListener("error", function() {
        // coming soon
    }, false);
    img.src = path;
  }
}

مدیر دارایی ما باید بداند که با چند موفقیت و شکست مواجه شده‌ایم، وگرنه هرگز نمی‌داند بازی چه زمانی می‌تواند شروع شود.

ابتدا شمارنده‌ها را به شی در سازنده اضافه می‌کنیم که اکنون به شکل زیر است:

function AssetManager() {
<span class="highlight">    this.successCount = 0;
    this.errorCount = 0;</span>
    this.downloadQueue = [];
}

سپس شمارنده‌ها را در شنوندگان رویداد افزایش دهید، که اکنون به شکل زیر است:

img.addEventListener("load", function() {
    <span class="highlight">that.successCount += 1;</span>
}, false);
img.addEventListener("error", function() {
    <span class="highlight">that.errorCount += 1;</span>
}, false);

مدیر دارایی اکنون هر دو دارایی با موفقیت بارگیری شده و دارایی های ناموفق را ردیابی می کند.

سیگنال دهی پس از اتمام

پس از اینکه بازی دارایی های خود را برای دانلود در صف قرار داد و از مدیر دارایی خواست که همه دارایی ها را دانلود کند، باید به بازی گفته شود که چه زمانی همه دارایی ها دانلود می شوند. به جای اینکه بازی بارها و بارها بپرسد که آیا دارایی ها دانلود شده اند، مدیر دارایی می تواند به بازی بازگردد.

مدیر دارایی باید ابتدا بداند که هر دارایی چه زمانی به پایان رسیده است. اکنون یک متد isDone اضافه می کنیم:

AssetManager.prototype.isDone = function() {
    return (this.downloadQueue.length == this.successCount + this.errorCount);
}

با مقایسه successCount + errorCount با اندازه downloadQueue، مدیر دارایی می داند که آیا هر دارایی با موفقیت به پایان رسیده است یا نوعی خطا دارد.

البته دانستن اینکه آیا این کار انجام شده است تنها نیمی از نبرد است. مدیر دارایی نیز باید این روش را بررسی کند. همانطور که کد زیر نشان می دهد، این بررسی را در هر دو کنترل کننده رویداد خود اضافه می کنیم:

img.addEventListener("load", function() {
    console.log(this.src + ' is loaded');
    that.successCount += 1;
    if (that.isDone()) {
        // ???
    }
}, false);
img.addEventListener("error", function() {
    that.errorCount += 1;
if (that.isDone()) {
        // ???
    }
}, false);

پس از افزایش شمارنده ها، خواهیم دید که آیا این آخرین دارایی در صف ما بوده است یا خیر. اگر واقعاً دانلود مدیر دارایی انجام شده باشد، دقیقاً چه کاری باید انجام دهیم؟

اگر مدیر دارایی دانلود تمام دارایی ها را انجام دهد، البته یک متد callback فراخوانی می کنیم! بیایید downloadAll() را تغییر دهیم و یک پارامتر برای callback اضافه کنیم:

AssetManager.prototype.downloadAll = function(downloadCallback) {
    ...

ما متد downloadCallback را در شنوندگان رویداد خود فراخوانی خواهیم کرد:

img.addEventListener("load", function() {
    that.successCount += 1;
    if (that.isDone()) {
        downloadCallback();
    }
}, false);
img.addEventListener("error", function() {
    that.errorCount += 1;
    if (that.isDone()) {
        downloadCallback();
    }
}, false);

مدیر دارایی بالاخره برای آخرین نیاز آماده است.

بازیابی آسان دارایی ها

هنگامی که به بازی سیگنال داده شد که می تواند شروع شود، بازی شروع به ارائه تصاویر می کند. مدیر دارایی نه تنها مسئول دانلود و ردیابی دارایی ها است، بلکه مسئولیت ارائه آنها به بازی را نیز بر عهده دارد.

نیاز نهایی ما مستلزم نوعی روش getAsset است، بنابراین اکنون آن را اضافه می کنیم:

AssetManager.prototype.getAsset = function(path) {
    return this.cache[path];
}

این شی کش در سازنده مقداردهی اولیه می شود که اکنون به شکل زیر است:

function AssetManager() {
    this.successCount = 0;
    this.errorCount = 0;
    this.cache = {};
    this.downloadQueue = [];
}

کش در انتهای downloadAll() پر می شود، همانطور که در زیر نشان داده شده است:

AssetManager.prototype.downloadAll = function(downloadCallback) {
  ...
      img.addEventListener("error", function() {
          that.errorCount += 1;
          if (that.isDone()) {
              downloadCallback();
          }
      }, false);
      img.src = path;
      <span class="highlight">this.cache[path] = img;</span>
  }
}

امتیاز: رفع اشکال

آیا اشکال را تشخیص دادید؟ همانطور که در بالا نوشته شد، روش isDone تنها زمانی فراخوانی می شود که رویدادهای بار یا خطا راه اندازی شوند. اما اگر مدیر دارایی هیچ دارایی در صف دانلود نداشته باشد چه؟ روش isDone هرگز راه اندازی نمی شود و بازی هرگز شروع نمی شود.

می توانید با اضافه کردن کد زیر به downloadAll() این سناریو را تطبیق دهید:

AssetManager.prototype.downloadAll = function(downloadCallback) {
    if (this.downloadQueue.length === 0) {
      downloadCallback();
  }
 ...

اگر هیچ دارایی در صف قرار نگیرد، پاسخ تماس بلافاصله فراخوانی می شود. مشکل برطرف شد!

مثال استفاده

استفاده از این مدیر دارایی در بازی HTML5 شما کاملاً ساده است. در اینجا اساسی ترین راه برای استفاده از کتابخانه آمده است:

var ASSET_MANAGER = new AssetManager();

ASSET_MANAGER.queueDownload('img/earth.png');

ASSET_MANAGER.downloadAll(function() {
    var sprite = ASSET_MANAGER.getAsset('img/earth.png');
    ctx.drawImage(sprite, x - sprite.width/2, y - sprite.height/2);
});

کد بالا نشان می دهد:

  1. یک مدیر دارایی جدید ایجاد می کند
  2. دارایی ها را در صف قرار دهید تا دانلود شوند
  3. دانلودها را با downloadAll() شروع کنید
  4. زمانی که دارایی ها آماده هستند، با فراخوانی تابع تماس مجدد سیگنال دهید
  5. بازیابی دارایی ها با getAsset()

مناطق برای بهبود

بدون شک با ساختن بازی خود از این مدیر دارایی ساده پیشی خواهید گرفت، اگرچه امیدوارم شروعی اساسی باشد. ویژگی های آینده می تواند شامل موارد زیر باشد:

  • نشان دادن اینکه کدام دارایی دارای خطا است
  • تماس ها برای نشان دادن پیشرفت
  • بازیابی دارایی ها از File System API

لطفاً پیشرفت‌ها، فورک‌ها و پیوندهای کد را در نظرات زیر ارسال کنید.

منبع کامل

منبع این مدیر دارایی و بازی که از آن خلاصه شده است، منبع باز تحت مجوز آپاچی است و می‌توانید آن را در حساب کاربری Bad Aliens GitHub پیدا کنید. بازی Bad Aliens را می توان در مرورگر سازگار با HTML5 بازی کرد. این بازی موضوع بحث Google IO من با عنوان Super Browser 2 Turbo HD Remix: Introduction to HTML5 Game Development ( اسلایدها ، ویدئو ) بود.

خلاصه

اکثر بازی‌ها دارای نوعی مدیریت دارایی هستند، اما بازی‌های HTML5 به یک مدیر دارایی نیاز دارند که دارایی‌ها را از طریق شبکه بارگیری کند و خرابی‌ها را مدیریت کند. این مقاله یک مدیر دارایی ساده را معرفی می‌کند که استفاده از آن و تطبیق آن با بازی بعدی HTML5 برای شما آسان باشد. از آن لذت ببرید و لطفاً نظرات خود را در نظرات زیر با ما در میان بگذارید. با تشکر!