پشتیبانی از قابلیت تغییر اندازه صفحه نمایش بزرگ

گسترش از گوشی‌های هوشمند به فرم‌فاکتورهای مختلف با صفحه نمایش بزرگ، ملاحظاتی را در مورد نحوه مدیریت پنجره در بازی شما ایجاد می‌کند. در Googlebook ، ChromeOS و Google Play Games در رایانه شخصی ، بازی شما می‌تواند در حالت پنجره‌ای روی رابط اصلی دسکتاپ اجرا شود. در تبلت‌ها و دستگاه‌های تاشوی اندرویدی جدید که اندروید ۱۲L (سطح API 32) یا بالاتر با عرض صفحه نمایش > 600dp را اجرا می‌کنند، بازی شما می‌تواند در حالت تقسیم صفحه در کنار سایر برنامه‌ها اجرا شود، تغییر اندازه دهد و حتی در دستگاه‌های تاشو بین نمایشگر داخلی و خارجی جابجا شود که منجر به تغییر پیکربندی برای اندازه پنجره و در برخی دستگاه‌ها، جهت‌گیری می‌شود.

قابلیت تغییر اندازه با بازی‌های Unity

پیکربندی اولیه صفحه نمایش بزرگ

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

<android:resizeableActivity="true" or "false" />

اگر نمی‌توانید از قابلیت تغییر اندازه پشتیبانی کنید، مطمئن شوید که مانیفست بازی به صراحت حداقل و حداکثر نسبت ابعاد پشتیبانی شده را تعریف می‌کند:

<!-- Render full screen between 3:2 and 21:9 aspect ratio -->
<!-- Let the platform letterbox otherwise -->
<activity android:minAspectRatio="1.5">
<activity android:maxAspectRatio="2.33">

بازی‌های گوگل پلی روی کامپیوتر

برای بازی‌های گوگل پلی روی کامپیوتر، پلتفرم، قابلیت تغییر اندازه پنجره را با رعایت نسبت ابعاد مشخص‌شده مدیریت می‌کند. اندازه پنجره به‌طور خودکار روی ابعاد بهینه قفل می‌شود. اگر جهت اصلی شما افقی است، باید حداقل از نسبت ابعاد ۱۶:۹ و اگر بازی شما حالت عمودی است، از نسبت ابعاد ۹:۱۶ پشتیبانی کنید. برای بهترین تجربه، به‌طور صریح از نسبت‌های ابعاد ۲۱:۹، ۱۶:۱۰ و ۳:۲ برای یک بازی افقی پشتیبانی کنید. قابلیت تغییر اندازه پنجره در اینجا الزامی نیست، اما برای سازگاری با سایر فرم فاکتورها، داشتن آن همچنان خوب است.

برای اطلاعات بیشتر و بهترین شیوه‌ها، به پیکربندی گرافیک برای بازی‌های Google Play در رایانه شخصی مراجعه کنید.

صفحه نمایش‌های بزرگ

برای به حداکثر رساندن ناحیه قابل مشاهده برای بازی خود در حالت تمام صفحه در تبلت‌های صفحه بزرگ، دستگاه‌های تاشو، Googlebook، ChromeOS و نمایشگرهای متصل، از حالت فراگیر تمام صفحه پشتیبانی کنید و با تنظیم پرچم‌ها در decorView ، قابلیت مشاهده رابط کاربری سیستم یا از طریق API WindowInsetsCompat ، نوارهای سیستم را پنهان کنید. همچنین باید رویدادهای پیکربندی چرخش و تغییر اندازه را به طرز ماهرانه‌ای مدیریت کنید یا از وقوع آنها جلوگیری کنید.

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

شکل ۱. پنجره‌ی سازگاری پیکربندی.

در برخی دستگاه‌ها، وقتی بازیکن به پیکربندی پشتیبانی‌نشده‌ای منتقل می‌شود، ممکن است با گزینه‌ای برای بارگذاری مجدد بازی و ایجاد مجدد فعالیت برای بهترین تطابق با طرح‌بندی پنجره جدید مواجه شود که این امر تجربه بازی را مختل می‌کند. بازی خود را در پیکربندی‌های مختلف حالت چند پنجره‌ای (اندازه پنجره ۲/۳، ۱/۲، ۱/۳) آزمایش کنید و مطمئن شوید که هیچ عنصر گیم‌پلی یا رابط کاربری قطع یا غیرقابل دسترس نمی‌شود. علاوه بر این، نحوه واکنش بازی خود را به پیوستگی تاشو هنگام جابجایی بین صفحه داخلی و خارجی در دستگاه‌های تاشو آزمایش کنید. اگر مشکلی مشاهده کردید، به صراحت این رویدادهای پیکربندی را مدیریت کنید و پشتیبانی پیشرفته از تغییر اندازه صفحه نمایش بزرگ را اضافه کنید.

قابلیت تغییر اندازه پیشرفته برای صفحه نمایش بزرگ

شکل ۲. رابط‌های کاربری مختلف روی میز و حالت تاشو در حالت رومیزی.

برای خارج شدن از حالت سازگاری و جلوگیری از فعالیت‌های تفریحی، موارد زیر را انجام دهید:

  1. اکتیویتی اصلی خود را به صورت قابل تغییر اندازه تعریف کنید:

    <android:resizeableActivity="true" />
    
  2. برای دریافت تمام رویدادهای پیکربندی صفحه نمایش بزرگ، در ویژگی android:configChanges مربوط به عنصر <activity> در مانیفست بازی خود، پشتیبانی صریح از "orientation"، "screenSize"، "smallestScreenSize"، "screenLayout" و "density" را اعلام کنید:

    <android:configChanges="screenSize | smallestScreenSize | screenLayout | orientation | keyboard |
                            keyboardHidden | density" />
    
  3. تابع onConfigurationChanged() نادیده بگیرید و رویداد پیکربندی، شامل جهت فعلی، اندازه پنجره، عرض و ارتفاع را مدیریت کنید:

    کاتلین

    override fun onConfigurationChanged(newConfig: Configuration) {
       super.onConfigurationChanged(newConfig)
       val density: Float = resources.displayMetrics.density
       val newScreenWidthPixels =
    (newConfig.screenWidthDp * density).toInt()
       val newScreenHeightPixels =
    (newConfig.screenHeightDp * density).toInt()
    
       // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE
       val newScreenOrientation: Int = newConfig.orientation
    
       // ROTATION_0, ROTATION_90, ROTATION_180, or ROTATION_270
       val newScreenRotation: Int =
    windowManager.defaultDisplay.rotation
    }

    جاوا

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
       super.onConfigurationChanged(newConfig);
       float density = getResources().getDisplayMetrics().density;
       int newScreenWidthPixels = (int) (newConfig.screenWidthDp * density);
       int newScreenHeightPixels = (int) (newConfig.screenHeightDp * density);
    
       // Configuration.ORIENTATION_PORTRAIT or ORIENTATION_LANDSCAPE
       int newScreenOrientation = newConfig.orientation;
    
       // ROTATION_0, ROTATION_90, ROTATION_180, or ROTATION_270
       int newScreenRotation = getWindowManager().getDefaultDisplay()
               .getRotation();
    }

همچنین می‌توانید WindowManager برای بررسی چرخش فعلی دستگاه استفاده کنید. با استفاده از این فراداده، ابعاد پنجره جدید را بررسی کرده و آن را به اندازه کامل پنجره رندر کنید. این کار ممکن است در همه موارد به دلیل تفاوت نسبت ابعاد کار نکند، بنابراین به عنوان یک جایگزین، رابط کاربری بازی خود را با اندازه پنجره جدید هماهنگ کنید و محتوای اصلی گیم‌پلی خود را در کادر قرار دهید. اگر محدودیت‌های فنی یا طراحی مانع از هر یک از این رویکردها می‌شود، کادربندی حروف درون موتور خود را برای حفظ نسبت ابعاد انجام دهید و در حالی که resizeableActivity = false را اعلام می‌کنید و از حالت پیکربندی اجتناب می‌کنید، به بهترین ابعاد ممکن مقیاس‌بندی کنید.

صرف نظر از رویکردی که انتخاب می‌کنید، بازی خود را در پیکربندی‌های مختلف (تاشو و باز کردن، تغییرات چرخش مختلف، حالت تقسیم صفحه) آزمایش کنید و مطمئن شوید که هیچ برش یا همپوشانی در عناصر رابط کاربری بازی، مشکلی در دسترسی به هدف لمسی یا مشکلات نسبت ابعاد که باعث کشیده شدن، فشرده شدن یا تحریف بازی می‌شود، وجود ندارد.

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

حالت چند پنجره‌ای

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

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

هیچ تضمینی وجود ندارد که برنامه هنگام قرار گرفتن در حالت چند پنجره‌ای، فوکوس را دوباره به دست آورد. بنابراین، اگر از هر یک از رویدادهای وضعیت برنامه برای مکث بازی خود استفاده می‌کنید، برای از سرگیری بازی به رویداد کسب فوکوس ( onWindowFocusChanged() با مقدار focus برابر با true) تکیه نکنید. در عوض، از سایر کنترل‌کننده‌های رویداد یا کنترل‌کننده‌های تغییر وضعیت مانند onConfigurationChanged() یا onResume() استفاده کنید. توجه داشته باشید که همیشه می‌توانید از متد isInMultiWindowMode() برای تشخیص اینکه آیا فعالیت فعلی در حالت چند پنجره‌ای اجرا می‌شود یا خیر، استفاده کنید.

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

گزینه اول با استفاده از ویژگی‌های خاص در تگ <layout> در مانیفست اندروید شما کار می‌کند. ویژگی‌های defaultHeight و defaultWidth ابعاد اولیه را کنترل می‌کنند. همچنین به ویژگی‌های minHeight و minWidth توجه داشته باشید تا از تغییر اندازه پنجره بازی توسط بازیکنان به ابعادی که شما پشتیبانی نمی‌کنید، جلوگیری کنید. در نهایت، ویژگی gravity وجود دارد که تعیین می‌کند پنجره هنگام اجرا در کجای صفحه نمایش ظاهر شود. در اینجا یک مثال از تگ layout با استفاده از این ویژگی‌ها آورده شده است:

<layout android:defaultHeight="500dp"
        android:defaultWidth="600dp"
        android:gravity="top|end"
        android:minHeight="450dp"
        android:minWidth="300dp" />

گزینه دوم برای تنظیم اندازه پنجره از طریق استفاده از مرزهای راه‌اندازی پویا عمل می‌کند. با استفاده از setLaunchBounds(Rect)⁠⁠ ، می‌توانید ابعاد پنجره شروع را تعریف کنید. اگر یک مستطیل خالی مشخص شود، فعالیت در حالت حداکثر شروع می‌شود.

علاوه بر این، اگر از موتورهای بازی Unity یا Unreal استفاده می‌کنید، مطمئن شوید که از نسخه‌های جدید (Unity 2019.4.40 و Unreal 5.3 یا جدیدتر) استفاده می‌کنید که پشتیبانی خوبی از حالت چند پنجره‌ای ارائه می‌دهند.

پشتیبانی از وضعیت بدن تاشو

از کتابخانه طرح‌بندی Jetpack WindowManager برای پشتیبانی از حالت‌های تاشو، مانند حالت رومیزی، استفاده کنید تا غوطه‌وری و تعامل بازیکن را افزایش دهید:

شکل ۳. بازی در حالت رومیزی با نمای اصلی در قسمت عمودی نمایشگر، و کنترل‌ها در قسمت افقی.

کاتلین

fun isTableTopPosture(foldFeature : FoldingFeature?) : Boolean {
    contract { returns(true) implies (foldFeature != null) }
    return foldFeature?.state == FoldingFeature.State.HALF_OPENED &&
            foldFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
}

جاوا

boolean isTableTopPosture(FoldingFeature foldFeature) {
    return (foldFeature != null) &&
           (foldFeature.getState() == FoldingFeature.State.HALF_OPENED) &&
           (foldFeature.getOrientation() == FoldingFeature.Orientation.HORIZONTAL);
}