تصميم شاشات كبيرة

في هذا الدليل، ستتعرّف على كيفية تكييف لعبتك لتعمل على أشكال مختلفة من أجهزة Android.

قبل البدء، يُرجى الاطّلاع على مقالة إتاحة إمكانية تغيير حجم الشاشة الكبيرة. يجب أن تتوافق الألعاب الحديثة على Android مع جميع أحجام الشاشات بدون الاعتماد على طبقات توافق النظام. بهذه الطريقة، يمكنك دائمًا التحكّم في كيفية عرض لعبتك وتقديم تجربة متميّزة للاعبين، حتى على أشكال الأجهزة مثل الواقع الممتد أو الأجهزة التي لا يمكن تدوير شاشتها.

لإجراء ذلك، أكمِل المهام التالية:

  1. أوقِف ميزة "العرض على شاشة عريضة" التي يوفّرها النظام ونفِّذ ميزة "العرض على شاشة عريضة" الخاصة بك داخل محرّك اللعبة.
  2. اجعل منطقة letterbox قابلة للاستخدام ومناسبة من حيث الموضوع.
  3. يجب مراعاة اعتبارات التصميم اللازمة للسماح بتغيير حجم لعبتك من 21:9 إلى 1:1 وإلى 9:21.

أوامر للاختبار

عند إنشاء لعبتك واختبارها، تأكَّد من أنّ لعبتك تعرض أي أشرطة سوداء بنفسها. يجب أيضًا فرض الوضعَين العمودي والأفقي في لعبتك، لأنّ الأجهزة مثل أجهزة التلفزيون والشاشات داخل السيارة لا يمكن تدويرها من الوضع الأفقي أو العمودي التلقائي.

للتحقّق مما إذا كان محرّك اللعبة يستخدم ميزة "إضافة أشرطة سوداء" في النظام، استخدِم الأمر 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

يمكنك إعادة ضبط جهازك على إعدادات المصنّع الأصلي للجهاز من خلال إعادة تشغيله أو تنفيذ الأوامر التالية:

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

لماذا يجب إيقاف ميزة "إضافة أشرطة سوداء" على مستوى النظام؟

يتحكّم النظام دائمًا في ميزة "العرض على شاشة عريضة أفقيًا" التي يوفّرها النظام. من خلال رصد حجم الشاشة وإدارة مساحة العرض بنفسك، يمكنك الحدّ من المشاكل، مثل عدم رصد الإدخالات، التي تحدث عندما تخرج الإدخالات من مساحة اللعبة. يمكنك أيضًا توسيع العناصر غير المتعلّقة بأسلوب اللعب لتصل إلى حافة الشاشة، حتى إذا ظل محتوى اللعبة ثابتًا في المنتصف. يمكن أن تتيح أوضاع توافق النظام إمكانية تشغيل اللعبة، ولكن الأمر متروك لك كمطوّر ألعاب لجعل لعبتك رائعة للاعبين.

صور توضيحية لشاشات هاتف وجهاز قابل للطي وجهاز لوحي وكمبيوتر محمول تُبرز مناطق النوافذ النشطة
الشكل 1. الهواتف والأجهزة القابلة للطي والأجهزة اللوحية وأجهزة الكمبيوتر المحمول

نموذج تنفيذ Letterbox

تمنحك معظم محرّكات الألعاب إمكانية التحكّم في مكان عرض الكاميرا على الشاشة. لتنفيذ ميزة "العرض على شاشة عريضة"، قِس نسبة العرض إلى الارتفاع للمنطقة المعروضة واضبط مستطيل الاقتصاص للمنطقة غير المستخدَمة بدلاً من السماح للنظام بعرض لعبتك على شاشة عريضة. يحدّ النموذج التالي من عرض كاميرا واحدة بنسبة عرض إلى ارتفاع محدودة مع السماح لكاميرات واجهة المستخدم أو عمليات العرض بالتوسّع إلى حجم الشاشة المنطقي الكامل:

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، أي أصغر عرض يبلغ 600 بكسل مستقل الكثافة (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
        }
    }
    

التصميم حول المشاكل الشائعة

يوفّر دعم مجموعة من نِسب العرض إلى الارتفاع والاتجاهات للاعبين أفضل تجربة مستخدم ممكنة. على عكس الهواتف، غالبًا ما يتم تثبيت الشاشات الأكبر حجمًا في الاتجاه الأفقي أو العمودي، وفي بعض الحالات تكون الشاشة مربعة تقريبًا. على هذه الأجهزة الأكبر حجمًا، غالبًا ما يؤدي اللاعبون مهام متعددة أثناء تشغيل لعبتك. من خلال الاستفادة إلى أقصى حد من مساحة الشاشة، يمكنك جذب المزيد من اللاعبين بشكل متكرر ولفترات لعب أطول.

تقدّم الأقسام التالية حلولاً تجعل لعبتك تبدو وكأنّها تجربة متميّزة على جميع أشكال الأجهزة بدلاً من لعبة هاتف مضمّنة في شاشة غير شاشة الهاتف.

كاميرات تراعي نسبة العرض إلى الارتفاع

في الألعاب الثلاثية الأبعاد، إذا كانت الشاشة طويلة جدًا، قد يشعر اللاعبون بأنّهم يشاهدون اللعبة من خلال فتحة ضيقة، وإذا كانت عريضة جدًا، قد يفوّت اللاعبون التفاعلات المصمَّمة. كما هو الحال في الألعاب الثنائية الأبعاد، يمكنك إبقاء "منطقة آمنة" مرئية دائمًا. يقوم الكود التالي بتبديل الكاميرا بين مجال رؤية أفقي ومجال رؤية رأسي بناءً على كيفية مقارنة نسبة العرض إلى الارتفاع النشطة بنسبة العرض إلى الارتفاع المرجعية التي تبلغ 1920 × 1080. بهذه الطريقة، يمكن للمصمّم إنشاء لعبة لشاشة بدقة 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) وواجهة المستخدم على طول الحافة الآمنة للشاشة: تجنَّب الصور المقطوعة، ولكن ضَع العناصر التفاعلية، مثل عناصر التحكّم الافتراضية وأشرطة الصحة والخرائط المصغّرة، بعيدًا عن منطقة اللعب قدر الإمكان. بهذه الطريقة، يستخدم الجزء التفاعلي من اللعبة الشاشة بأكملها، ويمكن للاعبين على الأجهزة اللوحية والأجهزة القابلة للطي الاستمتاع باللعبة بشكل مريح دون الحاجة إلى تمديد أصابعهم بشكل مفرط.

أخيرًا، اجعل منطقة الشريط الأسود ذات مظهر مناسب أو متناسق مع اللعبة. يمكنك استخدام حدود تتطابق مع لوحة الألوان أو مجموعة المربّعات على الشاشة، أو طاولة أو شاشة افتراضية للألعاب اللوحية أو الكلاسيكية، أو خرائط مصغّرة موسّعة ومرئيات زخرفية.

في المثال التالي، يتم عرض اللعبة بالحجم الكامل لمعظم نِسب العرض إلى الارتفاع. عندما تكون نسبة العرض إلى الارتفاع أضيق من 4:3، يتم عرض صندوق سماء ملوّن حسب المظهر مع الاستمرار في وضع عناصر في واجهة المستخدم مثل عناصر التحكّم على حافة الشاشة:

لعبة غابة بالتمرير الجانبي تظهر بوضع ملء الشاشة في نافذة أفقية عريضة مع عناصر تحكّم باللمس في الزوايا
الشكل 2. يتم عرض اللعبة بالحجم الكامل بنسبة عرض إلى ارتفاع عريضة عادية.
لعبة غابة ذات تمرير جانبي في نافذة أضيق من نسبة 4:3، تعرض أشرطة سوداء لأوراق شجر صفراء مع عناصر تحكّم باللمس مثبّتة على حواف الشاشة الخارجية.
الشكل 3. لعبة بنسبة عرض إلى ارتفاع أقل من 4:3 تعرض صندوق سماء ذي طابع خاص مع عناصر تحكّم في واجهة المستخدم مثبّتة على حواف الشاشة

ضباب الحرب

يشعر العديد من مطوّري الألعاب بالقلق من أنّ اللاعبين قد يحصلون على مزايا غير عادلة من نِسب العرض إلى الارتفاع الرأسية أو الأفقية الكبيرة. على سبيل المثال، قد يستخدم لاعب في لعبة تنافسية مثل ألعاب ساحات المعارك المتعددة اللاعبين على الإنترنت (MOBA) شاشة عمودية للغاية للحصول على رؤية عميقة لمسار الخصم.

بالنسبة إلى ألعاب المحاكاة والاستراتيجية من الأعلى إلى الأسفل، ننصحك بعرض ضباب الحرب:

  • لا تعرض الأشكال الهندسية على الإطلاق حتى يتمكّن اللاعب من رؤيتها.
  • يتم عرض الأشكال الهندسية التي لا يمكن لشخصية اللاعب رؤيتها بشكل نشط على أنها معتمة، بدون أي عناصر ديناميكية.
  • اعرض فقط الخصوم والعناصر القابلة للجمع والعناصر الديناميكية الأخرى التي يمكن لشخصية اللاعب رؤيتها بشكل نشط.

إذا جمعت بين هذه الطريقة وشرائط letterbox التفاعلية بالكامل وعرضت واجهة المستخدم على حافة الشاشة، سيحصل اللاعب على تجربة تبدو متقنة ومقصودة بدون الحاجة إلى إعادة تصميم بنية المستوى أو توازن الفريق.

يؤدي توسيع هذه اللعبة لملء شاشة أكبر بدون ضباب الحرب إلى الكشف عن أجزاء من الخريطة لا ينبغي للاعب رؤيتها:

لعبة تقمّص أدوار من منظور علوي على شاشة صغيرة يظهر فيها Sir Bugdroid وهو يحمل درعًا وفانوسًا بالقرب من سيف متوهّج على قاعدة، وجسر فوق نهر، ومسارات لعربات المناجم.
الشكل 4. عرض الكاميرا الأصلي على شاشة أصغر
عرض موسّع لخريطة لعبة تقمّص الأدوار نفسها من الأعلى على شاشة كبيرة يظهر فيها غولم وصندوق كنز داخل غرفة في زنزانة وعفاريت على الجانب الآخر من النهر
الشكل 5. ويكشف العرض الموسّع عن أجزاء من الخريطة لا يُفترض أن يراها اللاعب.

من خلال عرض ضباب الحرب وإخفاء العناصر الديناميكية مثل الأعداء والعناصر، يمكنك الحفاظ على العدالة في اللعبة أثناء استخدام الإطار الكامل المتاح للعبة:

لعبة تقمّص أدوار من منظور علوي على شاشة صغيرة تعرض المنطقة النشطة حول اللاعب
الشكل 6. المنطقة المرئية النشطة حول شخصية اللاعب
عرض موسّع لخريطة لعبة تقمّص أدوار من الأعلى إلى الأسفل، حيث يتم تعتيم التضاريس البعيدة وإخفاء الأعداء والعناصر خارج خط رؤية اللاعب.
الشكل 7. عرض موسّع مع ضباب الحرب الذي يحجب التضاريس البعيدة ويخفي العناصر الديناميكية

تلاشي الشكل الهندسي

تستخدم العديد من الألعاب، خاصةً في مجال الألعاب الاستراتيجية القائمة على الأدوار، أسلوبًا مشابهًا لضباب الحرب الموضَّح في القسم السابق، ولا تعرض الأشكال الهندسية التي لم يكتشفها اللاعب أو التي لا يمكنه التفاعل معها أثناء مجموعة معيّنة من اللقطات.

إذا كان مجال الرؤية الموسّع سيكشف أجزاءً من المشهد أو اللقطة السينمائية التي لا ينبغي للاعب رؤيتها، فإنّ إخفاء أجزاء معيّنة من المشهد بطريقة مصمّمة بشكل واضح يحقّق التأثير العملي نفسه الذي يحقّقه الشريط الأسود بدون إدراك وجود حدود ثابتة.

في المثال التالي، يؤدي توسيع اللعبة إلى نسبة عرض إلى ارتفاع أكبر إلى الكشف عن حشد من الزومبي خارج جدران القلعة:

منظور متساوي القياس للعبة تقمّص أدوار تكتيكية يظهر فيه Bugdroid وMecha Hamster داخل جدران القلعة
الشكل 8. منطقة اللعب داخل جدران القلعة بنسبة عرض إلى ارتفاع أضيق
عرض موسّع متساوي القياس للعبة تقمّص أدوار تكتيكية يكشف عن حشد من الأعداء ينتظرون خارج بوابة القلعة السفلية.
الشكل 9: نسبة عرض إلى ارتفاع أكبر تكشف عن حشد من الزومبي خارج جدران القلعة

بدلاً من ذلك، يمكنك حذف هندسة المستوى التي تتجاوز حدود منطقة اللعب الحالية:

لقطة من منظور متساوي القياس لـ Bugdroid وMecha Hamster داخل جدران القلعة في لعبة تقمّص أدوار تكتيكية
الشكل 10: منطقة اللعب داخل أسوار القلعة
لقطة موسّعة من لعبة تقمّص أدوار تكتيكية بمنظور متساوي القياس، حيث تم حذف هندسة المستوى والأعداء خارج جدران القلعة.
الشكل 11: نسبة عرض إلى ارتفاع أكبر لا يتم فيها عرض هندسة المستوى خارج منطقة اللعب الحالية.

الحدود السردية

في الألعاب الثلاثية الأبعاد الغامرة التي يمكن أن يؤدي فيها مجال الرؤية الموسّع إلى ميزة تنافسية في الألعاب المتعدّدة اللاعبين من منظور الشخص الأول أو الثالث أو الكشف عن مناطق غير مصمَّمة في الألعاب ذات المجموعات الثابتة، ننصحك بإنشاء عناصر سردية في اللعبة لتحديد مجال الرؤية بدلاً من الاعتماد على شاشة عريضة مستطيلة. تشمل الأمثلة ما يلي:

  • المقصورة الداخلية لمركبة مثل سيارة أو طائرة
  • الجزء الداخلي من خوذة
  • تأثير تظليل يشير إلى حافة رؤية اللاعب

يجب أن تمتد عناصر واجهة المستخدم وشاشة العرض الرأسية إلى حافة الشاشة أو أن يتم دمجها في الحدود السردية، ومن الأفضل جعلها ديناميكية. يمكن أن تساعد هذه العناصر أيضًا اللاعبين الذين يعانون من دوار الحركة، خاصةً على أجهزة الواقع الممتد، ما يوفّر لهم وسيلة مساعدة في تسهيل الاستخدام، بالإضافة إلى المساعدة في تقليل تعقيد نِسب العرض إلى الارتفاع الجديدة.

تجنَّب عرض اللعبة على سطح داخل مشهد ثابت غير تفاعلي. على الرغم من أنّ هذا الأسلوب أفضل من عرض أشرطة سوداء في أعلى الشاشة وأسفلها أو على جانبيها، يلاحظ اللاعبون بسرعة الحدود الثابتة وقد يشعرون بالإحباط إذا تم عرض ألعابهم المفضّلة على جزء من الشاشة بحجم الهاتف على أجهزة غير الهواتف.

في هذا المثال، يتم عرض لعبة مصمَّمة لشاشة هاتف عادية داخل تلفزيون محاكى مع جهاز تحكّم في الألعاب يحاكي الواقع ليتناسب مع نسبة العرض إلى الارتفاع المربّعة الأكثر شيوعًا على الشاشات الداخلية للأجهزة القابلة للطي:

لعبة متاهة ثلاثية الأبعاد معروضة داخل إطار تلفزيون CRT محاكي مع جهاز تحكّم في الألعاب بتصميم واقعي في المقدّمة
الشكل 12: يتم عرض اللعبة داخل إطار تلفزيون ثابت يحاكي الواقع مع جهاز تحكّم في الألعاب يحاكي الواقع.

قد تحتاج بعض الألعاب الثلاثية الأبعاد إلى تقييد مجال الرؤية إما لتحقيق العدالة التنافسية أو لاعتبارات التصميم. يُفضَّل استخدام قمرة قيادة أو خوذة أو أي استعارة سردية أخرى لتقييد مجال الرؤية بدلاً من استخدام الأشرطة السوداء:

صورة ثلاثية الأبعاد من منظور الشخص الأول لمتاهة من داخل قمرة قيادة كروية تشبه كرة الهامستر، مع خريطة مصغّرة في الأعلى وعناصر تحكّم باللمس في الأسفل.
الشكل 13: إطار قمرة قيادة كروي يقيّد مجال الرؤية مع تثبيت شاشة عرض رأسية (HUD) وعناصر التحكّم على حواف الشاشة

مراجع إضافية