مطالعه موردی - تغییر اندازه خودکار بازی‌های HTML5

معرفی

در تابستان 2010، بازی Sand Trap را ایجاد کردیم که در مسابقه بازی های HTML5 برای تلفن های همراه شرکت کردیم. اما اکثر تلفن‌های همراه یا فقط بخشی از بازی را نمایش می‌دادند یا بازی را خیلی کوچک می‌کردند و آن را کاملا غیرقابل بازی می‌کردند. بنابراین ما این وظیفه را بر عهده گرفتیم که بازی را طوری تنظیم کنیم که با هر وضوحی مطابقت داشته باشد. پس از کمی برنامه‌ریزی مجدد و استفاده از ایده‌های ذکر شده در این مقاله، بازی‌ای داشتیم که در هر مرورگر مدرنی، چه در دسک‌تاپ و چه در دستگاه تلفن همراه، قابل اجرا بود.

اسکرین شات از thwack تمام صفحه
اسکرین شات از thwack کوچکتر در پنجره مرورگر

این رویکرد برای Sand Trap به خوبی جواب داد، بنابراین ما از همین روش در آخرین بازی خود Thwack استفاده کردیم. همانطور که در اسکرین شات های زیر نشان داده شده است، بازی به طور خودکار رزولوشن صفحه نمایش را به گونه ای تنظیم می کند که هم برای پنجره های تمام صفحه و هم با اندازه سفارشی مناسب باشد.

پیاده سازی این نیاز به استفاده از CSS و JavaScript داشت. استفاده از CSS برای پر کردن کل صفحه بی اهمیت است، اما CSS به شما اجازه نمی دهد که نسبت عرض به ارتفاع یکسان را حفظ کنید تا از کشیده شدن بوم و ناحیه بازی جلوگیری کنید. اینجاست که جاوا اسکریپت وارد می شود. می توانید عناصر سند را با جاوا اسکریپت تغییر اندازه دهید و تغییر اندازه را در رویدادهای پنجره فعال کنید.

آماده سازی صفحه

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

اگر دو بخش در منطقه بازی خود دارید، یک منطقه بازی و یک منطقه برای حفظ امتیاز، ممکن است به این صورت باشد:

<div id="gameArea">
  <canvas id="gameCanvas"></canvas>
  <div id="statsPanel"></div>
</div>

هنگامی که یک ساختار سند اولیه دارید، می توانید به این عناصر چند ویژگی CSS بدهید تا آنها را برای تغییر اندازه آماده کنید. بسیاری از ویژگی های CSS برای "gameArea" مستقیماً توسط جاوا اسکریپت دستکاری می شوند، اما برای اینکه آنها کار کنند، چند ویژگی دیگر CSS را تنظیم کنید که با بلوک div والد gameArea شروع می شود:

#gameArea {
  position: absolute;
  left:     50%;
  top:      50%;
}

این گوشه سمت چپ بالای بوم را در مرکز صفحه قرار می دهد. تابع تغییر اندازه خودکار جاوا اسکریپت که در بخش بعدی توضیح داده شد، ویژگی های اضافی CSS را برای تغییر اندازه منطقه بازی و مرکز آن در پنجره دستکاری می کند.

از آنجایی که اندازه ناحیه بازی به طور خودکار با توجه به ابعاد پنجره تغییر می‌کند، شما نمی‌خواهید که ابعاد به پیکسل برای عناصر فرزند بلوک div gameArea باشد. در عوض، شما آن را در درصد می خواهید. مقادیر پیکسل به عناصر داخلی اجازه نمی‌دهند که با تغییر در div والد مقیاس شوند. با این حال، ممکن است مفید باشد که با پیکسل ها شروع کنید و بعد از اینکه طرحی را که دوست دارید دارید، آنها را به درصد تبدیل کنید.

برای این مثال، منطقه بازی را با ارتفاع 300 پیکسل و عرض 400 پیکسل شروع کنید. بوم کل منطقه بازی را پوشش می دهد و یک پنل آمار نیمه شفاف در امتداد پایین با ارتفاع 24 پیکسل قرار دارد، همانطور که در شکل 1 نشان داده شده است.

ابعاد عناصر فرزند GameArea بر حسب پیکسل
شکل 1: ابعاد عناصر فرزند GameArea در پیکسل

ترجمه این مقادیر به درصد، بوم را 100% عرض و 100% ارتفاع (از gameArea، نه پنجره) می کند. تقسیم 24 بر 300 ارتفاع پانل آمار را 8 درصد نشان می دهد و از آنجایی که قسمت پایینی بازی را پوشش می دهد، عرض آن نیز 100 درصد خواهد بود همانطور که در شکل 2 مشاهده می شود.

ابعاد عناصر کودک GameArea بر حسب درصد
شکل 2: ابعاد عناصر فرزند GameArea بر حسب درصد

اکنون که ابعاد منطقه بازی و عناصر فرزند آن را مشخص کرده اید، می توانید ویژگی های CSS دو عنصر داخلی را به صورت زیر کنار هم قرار دهید:

#gameCanvas {
  width: 100%;
  height: 100%;
}
#statsPanel {
  position: absolute;
  width: 100%;
  height: 8%;
  bottom: 0;
  opacity: 0.8;
}

تغییر اندازه بازی

اکنون شما آماده ایجاد یک تابع برای مدیریت اندازه پنجره در حال تغییر هستید. ابتدا یک مرجع به عنصر سند والد gameArea بگیرید.

var gameArea = document.getElementById('gameArea');

از آنجایی که شما نگران عرض یا ارتفاع دقیق نیستید، اطلاعات بعدی که باید تنظیم کنید، نسبت عرض به ارتفاع است. با استفاده از مرجع قبلی خود از یک منطقه بازی با عرض 400 پیکسل و ارتفاع 300 پیکسل، می دانید که می خواهید نسبت تصویر را در عرض 4 واحد و ارتفاع 3 واحد تنظیم کنید.

var widthToHeight = 4 / 3;

از آنجایی که هر زمان که اندازه پنجره تغییر می کند این تابع فراخوانی می شود، شما همچنین می خواهید ابعاد جدید پنجره را نیز بگیرید تا بتوانید ابعاد بازی خود را مطابق با آن تنظیم کنید. این مورد را با استفاده از ویژگی های innerWidth و innerHeight پنجره پیدا کنید.

var newWidth = window.innerWidth;
var newHeight = window.innerHeight;

همانطور که نسبت عرض به ارتفاع مورد نظر خود را تعیین کردید، اکنون می توانید نسبت عرض به ارتفاع فعلی پنجره را تعیین کنید:

var newWidthToHeight = newWidth / newHeight;

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

اتصال عنصر gameArea به پنجره با حفظ نسبت ابعاد
شکل 3: اتصال عنصر gameArea به پنجره با حفظ نسبت ابعاد

اگر شکل منطقه بازی مورد نظر عریض‌تر از شکل پنجره است (و ارتفاع کوتاه‌تر است)، باید پنجره را به صورت افقی پر کنید و حاشیه‌هایی را در امتداد بالا و پایین بگذارید. به همین ترتیب، اگر شکل ناحیه مورد نظر بازی بالاتر از شکل پنجره باشد (و عرض باریکتر باشد)، باید پنجره را به صورت عمودی پر کنید و حاشیه هایی را در امتداد چپ و راست بگذارید.

برای انجام این کار، نسبت عرض به ارتفاع مورد نظر خود را با نسبت عرض به ارتفاع پنجره فعلی آزمایش کنید و تنظیمات مناسب را به شرح زیر انجام دهید:

if (newWidthToHeight > widthToHeight) {
  // window width is too wide relative to desired game width
  newWidth = newHeight * widthToHeight;
  gameArea.style.height = newHeight + 'px';
  gameArea.style.width = newWidth + 'px';
} else { // window height is too high relative to desired game height
  newHeight = newWidth / widthToHeight;
  gameArea.style.width = newWidth + 'px';
  gameArea.style.height = newHeight + 'px';
}

اکنون که عرض و ارتفاع منطقه بازی را تنظیم کرده اید، باید با قرار دادن یک حاشیه منفی در بالا که نصف ارتفاع و در سمت چپ است که نصف عرض است، چیزها را در مرکز قرار دهید. به یاد داشته باشید که CSS در حال حاضر گوشه سمت چپ بالای gameArea div را دقیقاً در مرکز پنجره قرار داده است، بنابراین ناحیه بازی را در پنجره مرکز می‌کند:

gameArea.style.marginTop = (-newHeight / 2) + 'px';
gameArea.style.marginLeft = (-newWidth / 2) + 'px';

همچنین می خواهید اندازه فونت را به طور خودکار تنظیم کنید. اگر همه عناصر فرزند را دارید که از em استفاده می کنند، می توانید به سادگی ویژگی fontSize CSS بلوک gameArea div را روی مقداری تنظیم کنید که با اندازه آن تعیین می شود.

gameArea.style.fontSize = (newWidth / 400) + 'em';

در نهایت، می‌خواهید ابعاد طراحی بوم را با عرض و ارتفاع جدید مطابقت دهید. توجه داشته باشید که بقیه کد بازی باید ابعاد موتور بازی را از ابعاد طراحی بوم جدا نگه دارد تا برای وضوح بوم پویا در نظر گرفته شود.

var gameCanvas = document.getElementById('gameCanvas');
gameCanvas.width = newWidth;
gameCanvas.height = newHeight;

بنابراین تابع تغییر اندازه تکمیل شده ممکن است چیزی شبیه به این باشد:

function resizeGame() {
    var gameArea = document.getElementById('gameArea');
    var widthToHeight = 4 / 3;
    var newWidth = window.innerWidth;
    var newHeight = window.innerHeight;
    var newWidthToHeight = newWidth / newHeight;
    
    if (newWidthToHeight > widthToHeight) {
        newWidth = newHeight * widthToHeight;
        gameArea.style.height = newHeight + 'px';
        gameArea.style.width = newWidth + 'px';
    } else {
        newHeight = newWidth / widthToHeight;
        gameArea.style.width = newWidth + 'px';
        gameArea.style.height = newHeight + 'px';
    }
    
    gameArea.style.marginTop = (-newHeight / 2) + 'px';
    gameArea.style.marginLeft = (-newWidth / 2) + 'px';
    
    var gameCanvas = document.getElementById('gameCanvas');
    gameCanvas.width = newWidth;
    gameCanvas.height = newHeight;
}

اکنون، می‌خواهید هر زمان که اندازه پنجره تغییر می‌کند یا در مورد دستگاه‌های تلفن همراه، جهت صفحه نمایش تغییر می‌کند، این تنظیمات به‌طور خودکار انجام شود. این رویدادها را با فراخوانی تابع resizeGame() به این صورت مدیریت کنید:

window.addEventListener('resize', resizeGame, false);
window.addEventListener('orientationchange', resizeGame, false);

اگر اندازه پنجره خیلی زیاد است یا جهت صفحه نمایش عمودی است، عرض 100٪ پنجره را می سازید و اگر اندازه پنجره خیلی عریض است یا جهت صفحه نمایش افقی است، ارتفاع 100٪ پنجره را می سازید. ابعاد باقیمانده با توجه به نسبت ابعاد از پیش تعیین شده عرض به ارتفاع اندازه گیری می شود.

خلاصه

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