বড় স্ক্রিনের জন্য ডিজাইন

এই গাইডে, আপনি শিখবেন কীভাবে আপনার গেমকে বিভিন্ন Android ফর্ম ফ্যাক্টর জুড়ে কাজ করার জন্য উপযুক্ত করে তুলবেন।

শুরু করার আগে, বড় স্ক্রিনের সাইজ পরিবর্তন করার সুবিধা সম্পর্কে পড়ুন। Android-এ আধুনিক গেমগুলি সিস্টেম কম্প্যাটিবিলিটি লেয়ারের উপর নির্ভর না করে সমস্ত স্ক্রিন সাইজের সাথে মানানসই হওয়া উচিত। এইভাবে, আপনার গেম কীভাবে দেখানো হবে তার উপর আপনার সর্বদা নিয়ন্ত্রণ থাকে এবং আপনার গেমটি একটি প্রিমিয়াম প্লেয়ার অভিজ্ঞতা প্রদান করে, এমনকি XR বা এমন ডিভাইসের মতো ফর্ম ফ্যাক্টরেও যেখানে স্ক্রিন ঘোরানো যায় না।

এটি করতে, নিম্নলিখিত টাস্ক সম্পূর্ণ করুন:

  1. সিস্টেম লেটারবক্সিং বন্ধ করুন এবং আপনার নিজস্ব ইন-ইঞ্জিন লেটারবক্সিং প্রয়োগ করুন।
  2. লেটারবক্স করা জায়গাটি ব্যবহারযোগ্য ও থিমের সাথে মানানসই করে তুলুন।
  3. আপনার গেমের স্কেল ২১:৯ থেকে ১:১ এবং ৯:২১-এ পরিবর্তন করার জন্য ডিজাইন সংক্রান্ত প্রয়োজনীয়তা পূরণ করুন।

টেস্ট করার জন্য কমান্ড

আপনার গেম তৈরি ও টেস্ট করার সময়, আপনার গেম কোনও লেটারবক্স রেন্ডার করে কিনা তা যাচাই করুন। এছাড়াও, আপনার গেমটি পোর্ট্রেট এবং ল্যান্ডস্কেপ ওরিয়েন্টেশনে ফোর্স করা উচিত, কারণ টিভি এবং গাড়ির ডিসপ্লের মতো ডিভাইসগুলি তাদের ডিফল্ট ল্যান্ডস্কেপ বা পোর্ট্রেট ওরিয়েন্টেশন থেকে ঘুরতে পারে না।

আপনার গেম ইঞ্জিন সিস্টেম লেটারবক্সিং ব্যবহার করছে কিনা তা চেক করতে, adb shell cmd window set-letterbox-style কমান্ড ব্যবহার করুন। যেমন, নিম্নলিখিত কমান্ড সিস্টেম লেটারবক্সকে উজ্জ্বল সবুজ করে তোলে এবং আপনার গেমে একটি কর্নার রেডিয়াস যোগ করে, যার ফলে আপনার গেম অপারেটিং সিস্টেমের কম্প্যাটিবিলিটি মোডে ফিরে গেলে তা স্পষ্ট হয়ে যায়:

adb shell "cmd window set-letterbox-style --backgroundType solid_color --backgroundColor '#00FF00' --cornerRadius 30 --isEducationEnabled false"

টেস্ট করার জন্য ওরিয়েন্টেশন জোর করে সেট করতে, adb shell cmd window user-rotation lock ব্যবহার করুন। এটি আপনাকে সিমুলেট করতে সাহায্য করে যে আপনার গেমটি এমন একটি ডিভাইসে কীভাবে আচরণ করে যা ওরিয়েন্টেশনের জন্য অ্যাপ ওভাররাইডকে সম্মান করে না, বা ব্যবহারকারীরা XR বা পিসি-র মতো ডিভাইসে কী দেখেন তা বুঝতে সাহায্য করে যেখানে উইন্ডোগুলি ডিভাইসের ওরিয়েন্টেশন নির্বিশেষে পোর্ট্রেট বা ল্যান্ডস্কেপে প্রদর্শিত হতে পারে।

প্রথমে, আপনার ডিভাইসকে এমন একটি অবস্থায় রাখুন যেখানে আপনি অ্যাপের ওরিয়েন্টেশন ওভাররাইড করতে পারবেন:

adb shell cmd window set-ignore-orientation-request true
adb shell cmd window fixed-to-user-rotation enabled

এরপর, আপনার গেম ল্যান্ডস্কেপ মোডে পরিবর্তন করে টেস্ট করুন:

adb shell cmd window user-rotation lock 1

তারপর আপনার গেম পোর্ট্রেট মোডে পরিবর্তন করে টেস্ট করুন:

adb shell cmd window user-rotation lock 0

রিবুট করে বা নিম্নলিখিত কমান্ড রান করে আপনার ডিভাইস OEM কনফিগারেশনে রিসেট করুন:

adb shell cmd window reset-letterbox-style
adb shell cmd window fixed-to-user-rotation default
adb shell cmd window user-rotation free
adb shell cmd window set-ignore-orientation-request reset

সিস্টেম লেটারবক্সিং কেন বন্ধ করবেন?

সিস্টেম সবসময় সিস্টেম লেটারবক্সিং নিয়ন্ত্রণ করে। স্ক্রিনের সাইজ শনাক্ত করে এবং ডিসপ্লে এরিয়া নিজে ম্যানেজ করে, আপনি ড্রপড ইনপুটের মতো সমস্যা কমাতে পারেন, যা ইনপুট আপনার গেম এরিয়া থেকে বেরিয়ে গেলে ঘটে। এছাড়াও, আপনার গেমের কন্টেন্ট স্ক্রিনের মাঝখানে স্থির থাকলেও, আপনি গেমপ্লে নয় এমন এলিমেন্ট স্ক্রিনের প্রান্ত পর্যন্ত বাড়িয়ে নিতে পারেন। সিস্টেম কম্প্যাটিবিলিটি মোড কোনও গেমকে উপলভ্য করতে পারে, তবে গেম ডেভেলপার হিসেবে আপনার গেমকে প্লেয়ারদের জন্য দুর্দান্ত করে তোলার দায়িত্ব আপনারই।

ফোন, ফোল্ডেবল, ট্যাবলেট ও ল্যাপটপের ডিসপ্লের ছবি, যেখানে অ্যাক্টিভ উইন্ডো হাইলাইট করা আছে।
ছবি ১. ফোন, ফোল্ডেবল, ট্যাবলেট ও ল্যাপটপ ফর্ম ফ্যাক্টর।

লেটারবক্স স্যাম্পেল প্রয়োগ

বেশিরভাগ গেম ইঞ্জিন আপনাকে স্ক্রিনে ক্যামেরা রেন্ডার করার উপর নিয়ন্ত্রণ দেয়। আপনার নিজস্ব লেটারবক্সিং প্রয়োগ করতে, রেন্ডার করা অংশের অ্যাস্পেক্ট রেশিও পরিমাপ করুন এবং অব্যবহৃত অংশের জন্য আপনার ক্লিপিং রেকট্যাঙ্গেল অ্যাডজাস্ট করুন, যাতে সিস্টেমকে আপনার গেম লেটারবক্স করতে না হয়। নিম্নলিখিত স্যাম্পেল একটি ক্যামেরাকে বাউন্ডেড অ্যাস্পেক্ট রেশিওতে রেন্ডার করার জন্য সীমাবদ্ধ করে, যেখানে UI ক্যামেরা বা পাসকে সম্পূর্ণ লজিক্যাল স্ক্রিন সাইজে প্রসারিত করার অনুমতি দেয়:

Unity

[SerializeField]
private float minAspectRatio = 4f / 3f;

[SerializeField]
private float maxAspectRatio = 21f / 9f;

private Camera _camera;

private void Awake()
{
    _camera = GetComponent<Camera>();
}

public void MaintainAspectRatio()
{
    int viewWidth = Screen.width;
    int viewHeight = Screen.height;

    // 1. Calculate screen aspect ratio
    float scaleScreen = viewWidth / (float)viewHeight;
    Rect rect = _camera.pixelRect;

    // 2. Scale to the fullest of the lower between width or height
    if (scaleScreen > maxAspectRatio)
    {
        // use height, lock width to max at aspect scale
        rect.width = viewHeight * maxAspectRatio;
        rect.height = viewHeight;
    }
    else if (scaleScreen < minAspectRatio)
    {
        // use width, lock height to min at aspect scale
        rect.width = viewWidth;
        rect.height = viewWidth / minAspectRatio;
    }
    else
    {
        // within allowed aspect ratio range, use full screen
        rect.width = viewWidth;
        rect.height = viewHeight;
    }

    rect.x = Mathf.Floor((viewWidth - rect.width) * 0.5f);
    rect.y = Mathf.Floor((viewHeight - rect.height) * 0.5f);

    Debug.Log("camera view width = " + rect.width +
        " height = " + rect.height +
        " x = " + rect.x +
        " y = " + rect.y);

    // 3. Commit the new size to the camera so that it takes effect
    _camera.pixelRect = rect;
}

C++ (Vulkan)

/**
 * @brief Calculates a bounded-aspect-ratio gameplay viewport and scissor
 * rectangle and records them directly into a Vulkan command buffer.
 *
 * @note Requires `VK_DYNAMIC_STATE_VIEWPORT` and `VK_DYNAMIC_STATE_SCISSOR` to
 * be enabled on the bound graphics `VkPipeline`.
 *
 * @param command_buffer   Active `VkCommandBuffer` in the recording state.
 * @param window_width     Full physical window or swapchain width in pixels.
 * @param window_height    Full physical window or swapchain height in pixels.
 * @param min_aspect_ratio Minimum allowed aspect ratio (`width / height`).
 * @param max_aspect_ratio Maximum allowed aspect ratio (`width / height`).
 */
void MaintainAspectRatio(VkCommandBuffer command_buffer, uint32_t window_width,
                         uint32_t window_height, float min_aspect_ratio,
                         float max_aspect_ratio) {
  if (command_buffer == VK_NULL_HANDLE || window_width == 0 ||
      window_height == 0 || min_aspect_ratio <= 0.0f ||
      max_aspect_ratio < min_aspect_ratio) {
    return;
  }

  // 1. Calculate screen aspect ratio.
  const float view_width = static_cast<float>(window_width);
  const float view_height = static_cast<float>(window_height);
  const float scale_screen = view_width / view_height;

  // 2. Scale to the fullest of the lower between width or height.
  float rect_width = view_width;
  float rect_height = view_height;
  if (scale_screen > max_aspect_ratio) {
    // Use height, lock width to max at aspect scale (pillarbox).
    rect_width = std::floor(view_height * max_aspect_ratio);
    rect_height = view_height;
  } else if (scale_screen < min_aspect_ratio) {
    // Use width, lock height to min at aspect scale (letterbox).
    rect_width = view_width;
    rect_height = std::floor(view_width / min_aspect_ratio);
  } else {
    // Within allowed aspect ratio range, use full screen.
    rect_width = view_width;
    rect_height = view_height;
  }

  const float rect_x = std::floor((view_width - rect_width) * 0.5f);
  const float rect_y = std::floor((view_height - rect_height) * 0.5f);

  // 3. Commit the new viewport and scissor to the command buffer so that
  // subsequent gameplay draw calls are transformed and clipped to this region.
  const VkViewport viewport = {
      .x = rect_x,
      .y = rect_y,
      .width = rect_width,
      .height = rect_height,
      .minDepth = 0.0f,
      .maxDepth = 1.0f,
  };
  const VkRect2D scissor = {
      .offset =
          {
              .x = static_cast<int32_t>(rect_x),
              .y = static_cast<int32_t>(rect_y),
          },
      .extent =
          {
              .width = static_cast<uint32_t>(rect_width),
              .height = static_cast<uint32_t>(rect_height),
          },
  };

  vkCmdSetViewport(command_buffer, 0, 1, &viewport);
  vkCmdSetScissor(command_buffer, 0, 1, &scissor);
}

Unity-তে ধাপে ধাপে ওয়াকথ্রু পেতে, বড় স্ক্রিন ও ফোল্ডেবল ডিভাইসের জন্য Unity গেম অপ্টিমাইজ করা কোডল্যাব দেখুন।

বড় ও ছোট স্ক্রিনের সাইজ ম্যানেজ করা

ফোন এবং ফোল্ডেবল ডিভাইসের বাইরের ডিসপ্লের মতো ছোট স্ক্রিনে, সেরা ব্যবহারকারীর অভিজ্ঞতা পোর্ট্রেট- বা ল্যান্ডস্কেপ-লক করা গেম হতে পারে। ট্যাবলেট, Chromebook, গাড়ির ডিসপ্লে বা ফোল্ডেবল ডিভাইসের ইনার ডিসপ্লের মতো স্ক্রিন যত বড় হয়, ডিভাইস ঘোরানো তত কম কাম্য বা অসম্ভব হয়ে পড়ে। তবে, বড় ফিজিক্যাল ডিসপ্লেতে অফ-অ্যাক্সিস অ্যাস্পেক্ট রেশিওতে গেম খেলা যায়।

প্লেয়ারদের সেরা অভিজ্ঞতা দিতে, রানটাইমে স্ক্রিনের সাইজ শনাক্ত করুন এবং প্রয়োজন হলে স্ক্রিন ঘোরানো সীমিত করুন, তবে স্ক্রিনের সাইজ বাড়ার সাথে সাথে প্লেয়ারদের আরও বেশি ফ্লেক্সিবিলিটি দিন। Android আদর্শ কাট-অফ sw600dp হিসেবে বিবেচনা করে, যা হল ৬০০ ডেনসিটি-ইন্ডিপেন্ডেন্ট পিক্সেলের (600dp) সবচেয়ে ছোট প্রস্থ। এটি WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND-এর সাথে সম্পর্কিত। মাল্টি-ডিসপ্লে কনফিগারেশনে উপলভ্য স্ক্রিন সাইজ যাচাই করতে computeMaximumWindowMetrics ব্যবহার করুন।

আপনার গেমে এটি কাজ করাতে, আপনার ম্যানিফেস্টে সব ওরিয়েন্টেশন কাজ করান এবং তারপর onCreate() ও onConfigurationChanged(), দুটিতেই সবচেয়ে ছোট প্রস্থ মূল্যায়ন করুন এবং ওরিয়েন্টেশন লক যথাযথভাবে সেট করুন:

  1. আপনার ম্যানিফেস্টে স্ট্যাটিক ওরিয়েন্টেশন লক সরিয়ে দিন এবং কনফিগারেশন পরিবর্তন ম্যানেজ করার বিষয়টি ঘোষণা করুন:

    <activity
        android:name=".MainActivity"
        android:resizeableActivity="true"
        android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|density|keyboard|keyboardHidden" />
    
  2. প্রয়োজনীয় ইমপোর্ট যোগ করুন:

    import android.content.pm.ActivityInfo
    import android.content.res.Configuration
    import android.os.Bundle
    import androidx.activity.enableEdgeToEdge
    import androidx.window.core.layout.WindowSizeClass
    import androidx.window.layout.WindowMetricsCalculator
    import kotlin.math.min
    
  3. onCreate ও onConfigurationChanged, দুটিই হ্যান্ডেল করুন:

    override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge()
        super.onCreate(savedInstanceState)
        applyAdaptiveOrientationPolicy()
        // ...
    }
    
    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        applyAdaptiveOrientationPolicy()
        // ...
    }
    
  4. সবচেয়ে ছোট স্ক্রিনের প্রস্থের উপর ভিত্তি করে অনুরোধ করা ওরিয়েন্টেশন আপডেট করুন, কমপ্যাক্ট স্ক্রিনগুলি আপনার গেমের পছন্দের ডিজাইন ওরিয়েন্টেশনে লক করুন:

    private fun applyAdaptiveOrientationPolicy() {
        // compute the smallest screen bound in dp
        val maxMetrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
        val minDimensionPx = min(maxMetrics.bounds.width(), maxMetrics.bounds.height())
        val displaySmallestWidthDp = minDimensionPx / maxMetrics.density
    
        val targetOrientation = if (displaySmallestWidthDp >= WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) {
            // Large display (>= 600dp): allow free rotation in any orientation
            ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
        } else {
            // Compact display (< 600dp): lock to your game's preferred orientation
            // (use SCREEN_ORIENTATION_SENSOR_LANDSCAPE for landscape-first games)
            ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
        }
    
        // Guard against redundant setter calls to avoid configuration change loops
        if (requestedOrientation != targetOrientation) {
            requestedOrientation = targetOrientation
        }
    }
    

সাধারণ সমস্যাগুলি এড়িয়ে ডিজাইন করুন

বিভিন্ন ধরনের অ্যাস্পেক্ট রেশিও ও ওরিয়েন্টেশন সাপোর্ট করলে, আপনার প্লেয়াররা সবচেয়ে ভালো ব্যবহারকারীর অভিজ্ঞতা পাবেন। ফোনের মতো নয়, বড় ডিসপ্লে প্রায়ই ল্যান্ডস্কেপ বা পোর্ট্রেট ওরিয়েন্টেশনে ফিক্স করা থাকে এবং কিছু ক্ষেত্রে স্ক্রিন প্রায় বর্গাকার হয়। এইসব বড় ডিভাইসে, আপনার গেম খেলার সময় প্লেয়াররা প্রায়ই মাল্টিটাস্ক করেন। স্ক্রিন স্পেসের ব্যবহার সর্বাধিক করে, আপনি আরও বেশি প্লেয়ারকে আরও ঘন ঘন এবং দীর্ঘ প্লে সেশনের জন্য এনগেজ করতে পারবেন।

নিম্নলিখিত বিভাগগুলি এমন সমাধান প্রদান করে যা আপনার গেমটিকে ফোন ছাড়া অন্য স্ক্রিনে এম্বেড করা ফোন গেমের পরিবর্তে বিভিন্ন ফর্ম ফ্যাক্টর জুড়ে একটি প্রিমিয়াম অভিজ্ঞতার মতো অনুভব করায়।

অ্যাসপেক্ট-অ্যাওয়ার ক্যামেরা

3D গেমে, স্ক্রিন খুব লম্বা হলে, প্লেয়ারদের মনে হতে পারে যে তারা একটি সরু স্লিটের মাধ্যমে গেমটি দেখছেন এবং এটি খুব চওড়া হলে, প্লেয়াররা ডিজাইন করা ইন্টার‍্যাকশন মিস করতে পারেন। 2D গেমের মতো, আপনি "নিরাপদ এলাকা" সবসময় দৃশ্যমান রাখতে পারবেন। অ্যাক্টিভ অ্যাস্পেক্ট রেশিও কীভাবে ১৯২০x১০৮০-এর রেফারেন্স অ্যাস্পেক্ট রেশিওর সাথে তুলনা করে তার উপর ভিত্তি করে নিম্নলিখিত কোডটি একটি ক্যামেরাকে অনুভূমিক ফিল্ড অফ ভিউ এবং উল্লম্ব ফিল্ড অফ ভিউয়ের মধ্যে পরিবর্তন করে। এইভাবে, একজন ডিজাইনার 1080p ডিসপ্লের জন্য একটি গেম তৈরি করতে পারেন এবং জানতে পারেন যে সেই রেফারেন্স ফ্রেমের মধ্যে ডিজাইন করা সবকিছু দেখা যাবে:

Unity

[SerializeField]
private Camera _camera;

[SerializeField]
private float _referenceWidth = 1920f;

[SerializeField]
private float _referenceHeight = 1080f;

[SerializeField]
private float _referenceVerticalFov = 60f;

public float ReferenceAspectRatio => _referenceWidth / Mathf.Max(0.0001f, _referenceHeight);

private void Awake()
{
    if (_camera == null)
    {
        _camera = GetComponent<Camera>();
    }
}

// Built-in Render Pipeline callback. In URP, subscribe to
// RenderPipelineManager.beginCameraRendering or call UpdateFov() on resize.
private void OnPreCull()
{
    UpdateFov();
}

public void UpdateFov()
{
    if (_camera == null || _camera.orthographic)
    {
        return;
    }

    float referenceAspect = ReferenceAspectRatio;
    float currentAspect = _camera.aspect;
    if (currentAspect <= 0.0001f)
    {
        return;
    }

    float targetVerticalFov;

    if (currentAspect >= referenceAspect)
    {
        // Viewport is wider than (or equal to) the reference safe area
        targetVerticalFov = _referenceVerticalFov;
    }
    else
    {
        // Viewport is skinnier than the reference safe area
        float referenceHorizontalFov = Camera.VerticalToHorizontalFieldOfView(_referenceVerticalFov, referenceAspect);
        targetVerticalFov = Camera.HorizontalToVerticalFieldOfView(referenceHorizontalFov, currentAspect);
        targetVerticalFov = Mathf.Clamp(targetVerticalFov, 1f, 179f);
    }

    if (!Mathf.Approximately(_camera.fieldOfView, targetVerticalFov))
    {
        _camera.fieldOfView = targetVerticalFov;
    }
}

C++ (Vulkan)

/**
 * @brief Calculates an aspect-aware Vulkan perspective projection matrix using
 * GLM that keeps a reference safe area (e.g., 1920x1080) visible across
 * aspect ratios.
 *
 * @note Uses `glm::perspectiveZO` for Vulkan's `[0, 1]` depth range and
 * inverts `projection[1][1]` for Vulkan's top-left (`+Y` down) clip space.
 *
 * @param viewport_width         Active gameplay viewport width in pixels.
 * @param viewport_height        Active gameplay viewport height in pixels.
 * @param reference_width        Authored safe-area reference width in pixels.
 * @param reference_height       Authored safe-area reference height in pixels.
 * @param reference_vertical_fov Authored vertical FOV in degrees (e.g., 60.0f).
 * @param near_plane             Near clipping plane distance (`zNear > 0.0f`).
 * @param far_plane              Far clipping plane distance (`zFar > zNear`).
 * @return Aspect-aware `glm::mat4` perspective projection matrix for Vulkan.
 */
glm::mat4 CalculateAspectAwareProjectionMatrix(
    float viewport_width, float viewport_height, float reference_width = 1920.0f,
    float reference_height = 1080.0f, float reference_vertical_fov = 60.0f,
    float near_plane = 0.1f, float far_plane = 100.0f) {
  if (viewport_width <= 0.0001f || viewport_height <= 0.0001f) {
    return glm::mat4(1.0f);
  }

  // 1. Compare the active viewport aspect ratio against the reference safe
  // area.
  const float reference_aspect =
      reference_width / std::max(0.0001f, reference_height);
  const float current_aspect = viewport_width / viewport_height;

  float target_vertical_fov_rad = glm::radians(reference_vertical_fov);

  if (current_aspect >= reference_aspect) {
    // Viewport is wider than (or equal to) the reference safe area (Hor+).
    target_vertical_fov_rad = glm::radians(reference_vertical_fov);
  } else {
    // Viewport is skinnier than the reference safe area (Vert+):
    // Convert reference vertical FOV -> reference horizontal FOV -> new
    // vertical FOV at current_aspect so the safe area is never cropped.
    const float tan_half_horiz =
        std::tan(target_vertical_fov_rad * 0.5f) * reference_aspect;
    target_vertical_fov_rad = 2.0f * std::atan(tan_half_horiz / current_aspect);
    target_vertical_fov_rad = std::clamp(
        target_vertical_fov_rad, glm::radians(1.0f), glm::radians(179.0f));
  }

  // 2. Build the Vulkan [0, 1] depth perspective matrix and flip +Y clip space.
  glm::mat4 projection = glm::perspectiveZO(
      target_vertical_fov_rad, current_aspect, near_plane, far_plane);
  projection[1][1] *= -1.0f;
  return projection;
}

সম্পূর্ণ ইন্টার‍্যাক্টিভ লেটারবক্স

কিছু গেমের ডিজাইন অনুযায়ী খেলার জায়গা নির্দিষ্ট থাকে, যা প্রায়ই জনরা-ভিত্তিক ডিজাইন বিবেচনার সাথে মেলে, যেমন ভার্টিক্যাল শুট-'এম-আপের নির্দিষ্ট ফিল্ড বা রেট্রো অ্যাস্থেটিকের জন্য ব্যবহৃত ফ্লিপ-স্ক্রিন স্ক্রলিং।

এইসব গেমের জন্য, গেমপ্লে এরিয়া ফিট করার জন্য স্কেল করুন যাতে গেমের একটি অক্ষ সবসময় গেমপ্লে এরিয়া পূরণ করার জন্য সর্বাধিক করা হয়। আপনার গেমের আপেক্ষিক অ্যাস্পেক্ট রেশিও এবং ডিসপ্লে বাউন্ডের উপর ভিত্তি করে কোন অক্ষটি সর্বাধিক করা হয়েছে তা পরিবর্তন হতে পারে।

স্ক্রিনের নিরাপদ প্রান্ত পর্যন্ত HUD এবং UI এলিমেন্ট অ্যাঙ্কর করুন: কাটআউট এড়িয়ে চলুন, তবে ভার্চুয়াল কন্ট্রোল, হেল্থ বার এবং মিনিম্যাপের মতো ইন্টার‍্যাক্টিভ এলিমেন্ট গেমপ্লে এরিয়া থেকে যতটা সম্ভব দূরে রাখুন। এইভাবে, গেমের ইন্টার‍্যাক্টিভ অংশটি পুরো স্ক্রিন ব্যবহার করে এবং ট্যাবলেট ও ফোল্ডেবলের মতো ফর্ম ফ্যাক্টরে প্লেয়াররা আঙুল অতিরিক্ত না বাড়িয়েই আরামে আপনার গেম খেলতে পারেন।

সবশেষে, লেটারবক্সের জায়গাটি উপযুক্ত থিম বা ডাইজেটিক করুন। স্ক্রিনে দেখানো প্যালেট বা টাইল সেটের সাথে ম্যাচ করে এমন বর্ডার, বোর্ড বা রেট্রো গেমের জন্য ভার্চুয়াল টেবিল বা স্ক্রিন অথবা এক্সটেন্ডেড মিনিম্যাপ ও আলঙ্কারিক ভিজ্যুয়াল ব্যবহার করার কথা বিবেচনা করুন।

নিচের উদাহরণে, বেশিরভাগ অ্যাস্পেক্ট রেশিওর জন্য গেমটি ফুল সাইজে রেন্ডার করা হয়। অ্যাস্পেক্ট রেশিও 4:3-এর থেকে কম হলে, এটি থিম্যাটিক কালার করা স্কাইবক্স রেন্ডার করে এবং স্ক্রিনের প্রান্তে কন্ট্রোলের মতো UI এলিমেন্ট প্লেস করা চালিয়ে যায়:

সাইড-স্ক্রলিং ফরেস্ট গেমটি একটি প্রশস্ত ল্যান্ডস্কেপ উইন্ডোতে ফুল-ব্লিড হিসেবে রেন্ডার করা হয়েছে, যার কোণে টাচ কন্ট্রোল রয়েছে।
ছবি ২. স্ট্যান্ডার্ড ওয়াইড অ্যাস্পেক্ট রেশিওতে গেম ফুল সাইজে রেন্ডার করা।
৪:৩-এর চেয়ে সরু উইন্ডোতে সাইড-স্ক্রলিং ফরেস্ট গেম, যেখানে থিমযুক্ত হলুদ পাতার লেটারবক্স বার দেখানো হচ্ছে এবং টাচ কন্ট্রোল স্ক্রিনের বাইরের প্রান্তে অ্যাঙ্কর করা আছে।
ছবি ৩. ৪:৩-এর থেকে কম অ্যাস্পেক্ট রেশিওতে গেম খেললে, স্ক্রিনের প্রান্তে UI কন্ট্রোল অ্যাঙ্কর করা সহ থিমযুক্ত স্কাইবক্স রেন্ডার করা হয়।

যুদ্ধের কুয়াশা

অনেক গেম ডেভেলপাররা চিন্তিত যে প্লেয়াররা অত্যন্ত উল্লম্ব বা অনুভূমিক অ্যাস্পেক্ট রেশিও থেকে একটি অন্যায্য সুবিধা পেতে পারে। যেমন, মাল্টিপ্লেয়ার অনলাইন যুদ্ধক্ষেত্রের (MOBA) মতো প্রতিযোগিতামূলক গেমের কোনও প্লেয়ার প্রতিপক্ষের লেনের গভীর ভিউ পেতে খুব ভার্টিক্যাল স্ক্রিন ব্যবহার করতে পারেন।

টপ-ডাউন স্ট্র্যাটেজি ও সিমুলেশন গেমের জন্য, ফগ অফ ওয়ার রেন্ডার করার কথা বিবেচনা করুন:

  • প্লেয়ার দেখতে না পাওয়া পর্যন্ত জিওমেট্রি রেন্ডার করবেন না।
  • কোনও ডাইনামিক এলিমেন্ট ছাড়াই, প্লেয়ারের চরিত্র সক্রিয়ভাবে দেখতে পায় না এমন জ্যামিতি আবছা হিসেবে রেন্ডার করুন।
  • শুধুমাত্র প্রতিপক্ষ, সংগ্রহযোগ্য আইটেম এবং অন্যান্য ডাইনামিক অবজেক্ট রেন্ডার করুন যা প্লেয়ার চরিত্রটি ডাইজেটিক্যালি সক্রিয়ভাবে দেখতে পারে।

আপনি যদি এই টেকনিকের সাথে সম্পূর্ণ ইন্ট্যার‍্যাক্টিভ লেটারবক্স এবং স্ক্রিনের একদম ধার পর্যন্ত UI রেন্ডার করার সুবিধা যোগ করেন, তাহলে প্লেয়াররা এমন অভিজ্ঞতা পাবেন যা একইসাথে পরিমার্জিত এবং উদ্দেশ্যপূর্ণ বলে মনে হবে। এর জন্য আপনাকে লেভেল স্ট্রাকচার বা টিম ব্যালেন্স নতুন করে ডিজাইন করতে হবে না।

এই গেমটি বড় স্ক্রিনে খেলার সময় ফগ অফ ওয়ার না থাকলে ম্যাপের এমন কিছু অংশ দেখা যায় যা প্লেয়ারের দেখার কথা নয়:

ছোট স্ক্রিনে টপ-ডাউন আরপিজি যেখানে স্যার বাগড্রয়েডকে পেডেস্টালে রাখা উজ্জ্বল তরবারির কাছে ঢাল ও লণ্ঠন ধরে থাকতে দেখা যাচ্ছে, সাথে আছে নদীর উপর ব্রিজ ও মাইনকার্ট ট্র্যাক।
ছবি ৪. ছোট স্ক্রিনে আসল ক্যামেরা ভিউ।
একটি বড় স্ক্রিনে একই টপ-ডাউন আরপিজি ম্যাপের বড় করা ভিউ, যেখানে একটি অন্ধকূপের ঘরের ভিতরে একটি গোলেম এবং গুপ্তধনের বাক্স এবং নদীর ওপারে গবলিন দেখা যাচ্ছে।
ছবি ৫. বড় করে দেখানো ভিউতে ম্যাপের এমন অংশ দেখা যাচ্ছে যা প্লেয়ারের দেখার কথা নয়।

'ফগ অফ ওয়ার' রেন্ডার করে এবং শত্রু ও আইটেমের মতো ডায়নামিক এলিমেন্ট লুকিয়ে, আপনি গেমের জন্য উপলভ্য সম্পূর্ণ ফ্রেম ব্যবহার করার সময় গেমের ন্যায্যতা বজায় রাখেন:

ছোট স্ক্রিনে টপ-ডাউন আরপিজি, যেখানে প্লেয়ারের চারপাশে অ্যাক্টিভ এরিয়া দেখানো হচ্ছে।
ছবি ৬. প্লেয়ার চরিত্রের চারপাশে অ্যাক্টিভ দৃশ্যমান এলাকা।
উপর থেকে নিচে আরপিজি ম্যাপের বড় করা ভিউ যেখানে দূরের ভূখণ্ড আবছা এবং প্লেয়ারের দৃষ্টিসীমার বাইরে থাকা শত্রু ও আইটেম লুকানো থাকে।
ছবি ৭. যুদ্ধক্ষেত্রের কুয়াশাচ্ছন্ন পরিবেশের কারণে দূরের ভূখণ্ড অস্পষ্ট এবং ডায়নামিক এলিমেন্টগুলি লুকানো অবস্থায় দেখা যাচ্ছে।

ফেড-আউট জিওমেট্রি

অনেক গেম, বিশেষ করে টার্ন-ভিত্তিক স্ট্র্যাটেজি স্পেসে, পূর্ববর্তী বিভাগে বর্ণিত যুদ্ধের কুয়াশার মতো একটি কৌশল ব্যবহার করে এবং জ্যামিতি রেন্ডার করে না যা প্লেয়ার আবিষ্কার করেনি বা প্লেয়ার একটি নির্দিষ্ট সেটপিস চলাকালীন ইন্টার‍্যাক্ট করতে পারে না।

ফিল্ড অফ ভিউ বড় করলে যদি আপনার সেট বা সিনেমাটিকের এমন অংশ দেখা যায় যা প্লেয়ারের দেখা উচিত নয়, তাহলে দৃশ্যের নির্দিষ্ট অংশ পরিষ্কারভাবে ডিজাইন করা উপায়ে মাস্ক করলে, স্থির বর্ডার ছাড়াই লেটারবক্সের মতো একই ধরনের এফেক্ট পাওয়া যায়।

নিচের উদাহরণে, গেমটি আরও বড় অ্যাস্পেক্ট রেশিওতে প্রসারিত করলে দুর্গের দেয়ালের বাইরে জম্বির দল দেখা যায়:

দুর্গের দেওয়ালের মধ্যে Bugdroid ও মেকা হ্যামস্টারের আইসোমেট্রিক ট্যাকটিক্যাল RPG ভিউ।
ছবি ৮. আরও সংকীর্ণ অ্যাস্পেক্ট রেশিওতে দুর্গের দেওয়ালের মধ্যে খেলার জায়গা।
এক্সপ্যান্ড করা আইসোমেট্রিক ট্যাকটিক্যাল আরপিজি ভিউ, যেখানে দুর্গের নিচের গেটের বাইরে শত্রুদের একটি দল অপেক্ষা করছে।
ছবি ৯. আরও বড় অ্যাস্পেক্ট রেশিওতে দুর্গের দেওয়ালের বাইরে জম্বির দল দেখা যাচ্ছে।

পরিবর্তে, আপনি বর্তমান খেলার এলাকার সীমার বাইরে লেভেল জ্যামিতি রেন্ডার করা বাদ দিতে পারেন:

দুর্গের দেওয়ালের মধ্যে Bugdroid ও মেকা হ্যামস্টারের আইসোমেট্রিক ট্যাকটিক্যাল RPG ভিউ।
ছবি ১০. দুর্গের দেওয়ালের মধ্যে খেলার জায়গা।
বর্ধিত আইসোমেট্রিক ট্যাকটিক্যাল RPG ভিউ যেখানে লেভেল জিওমেট্রি এবং দুর্গের দেওয়ালের বাইরের শত্রুদের বাদ দেওয়া হয়েছে।
ছবি ১১. আরও বড় অ্যাস্পেক্ট রেশিও যেখানে বর্তমান প্লে এরিয়ার বাইরে লেভেল জিওমেট্রি রেন্ডার করা হয় না।

ডাইজেটিক বাউন্ডারি

ইমারসিভ 3D গেমে, যেখানে ফিল্ড অফ ভিউ বড় করলে ফার্স্ট- বা থার্ড-পার্সন মাল্টিপ্লেয়ার গেমে প্রতিযোগিতামূলক সুবিধা পাওয়া যায় অথবা ফিক্সড সেট-ভিত্তিক গেমের অননুমোদিত এলাকা দেখা যায়, সেখানে ফিল্ড অফ ভিউ সীমিত করার জন্য আয়তাকার লেটারবক্সের উপর নির্ভর না করে গেমে ডাইজেটিক এলিমেন্ট যোগ করার কথা বিবেচনা করুন। উদাহরণের মধ্যে রয়েছে:

  • গাড়ি বা প্লেনের মতো কোনও গাড়ির ভেতরের ককপিট
  • হেলমেটের ভিতরের অংশ
  • একটি ভিনয়েট যা প্লেয়ারের দৃষ্টির প্রান্ত নির্দেশ করে

UI এবং HUD এলিমেন্ট এখনও স্ক্রিনের প্রান্ত পর্যন্ত প্রসারিত করা উচিত বা ডাইজেটিক সীমানায় অন্তর্ভুক্ত করা উচিত এবং সেগুলিকে ডাইনামিক করা আদর্শ। এইসব ডাইজেটিক এলিমেন্ট সেইসব প্লেয়ারদেরও সাহায্য করতে পারে যারা মোশন সিকনেস অনুভব করেন—বিশেষ করে XR ফর্ম ফ্যাক্টরে—নতুন অ্যাস্পেক্ট রেশিওর জটিলতা কমানোর পাশাপাশি অ্যাক্সেসিবিলিটি সংক্রান্ত সহায়তা প্রদান করে।

ইন্টার‍্যাক্টিভ নয় এমন স্ট্যাটিক দৃশ্যের মধ্যে কোনও সারফেসে গেম রেন্ডার করা এড়িয়ে চলুন। যদিও এই পদ্ধতিটি লেটারবক্স এবং পিলারবক্সের জন্য কালো বার রেন্ডার করার চেয়ে ভাল, খেলোয়াড়রা দ্রুত স্ট্যাটিক বর্ডার লক্ষ্য করে এবং তাদের প্রিয় গেমগুলি ফোন-সাইজের প্যাচ অফ স্ক্রিনে রেন্ডার করলে তারা হতাশ হতে পারে।

এই উদাহরণে, স্ট্যান্ডার্ড ফোন স্ক্রিনের জন্য ডিজাইন করা একটি গেম সিমুলেটেড টেলিভিশনের মধ্যে স্কিউমর্ফিক গেমপ্যাড সহ রেন্ডার করা হয় যাতে ফোল্ডেবল ডিভাইসের ইনার ডিসপ্লেতে সাধারণত দেখা যায় এমন আরও বর্গাকার অ্যাস্পেক্ট রেশিওতে মানানসই হয়:

ফোরগ্রাউন্ডে স্কিউমর্ফিক গেমপ্যাড সহ সিমুলেটেড CRT টেলিভিশন ফ্রেমের মধ্যে রেন্ডার করা 3D মেজ গেম।
ছবি ১২. একটি স্কিউমর্ফিক গেমপ্যাড সহ একটি স্ট্যাটিক সিমুলেটেড টেলিভিশন ফ্রেমের ভিতরে গেমটি রেন্ডার করা হয়েছে।

কিছু 3D গেমের ক্ষেত্রে প্রতিযোগিতামূলক ন্যায্যতা বা ডিজাইন সংক্রান্ত বিবেচনার জন্য ফিল্ড অফ ভিউ সীমিত করার প্রয়োজন হতে পারে। ককপিট, হেলমেট বা অন্য কোনও ডাইজেটিক মেটাফর ব্যবহার করে ফিল্ড অফ ভিউ সীমাবদ্ধ করা কালো বারের থেকে ভালো:

একটি গোলাকার হ্যামস্টার-বল ককপিটের ভিতর থেকে ফার্স্ট-পার্সন 3D মেজ ভিউ, যার উপরে একটি মিনিম্যাপ এবং নিচে টাচ কন্ট্রোল রয়েছে।
ছবি ১৩. ডাইজেটিক স্ফেরিক্যাল ককপিট ফ্রেম ফিল্ড অফ ভিউকে সীমাবদ্ধ করে, যখন HUD এবং কন্ট্রোল স্ক্রিনের প্রান্তে অ্যাঙ্কর করা হয়।

অতিরিক্ত রিসোর্স