Phát triển trò chơi cho mọi màn hình

Khi phát triển một trò chơi dành cho Android, quan trọng là bạn phải dự đoán được đa dạng các trải nghiệm có thể xảy ra với người chơi và duy trì tính thích ứng với nhu cầu tương tác của người chơi theo thời gian thực. Bằng cách hỗ trợ nhiều trải nghiệm người chơi, bạn làm tăng tính linh hoạt của lối chơi và giúp mở rộng phạm vi tiếp cận của trò chơi.

Có thể kể đến một số khác biệt cụ thể trong trải nghiệm của người chơi như sau:

  • Kiểu dáng thiết bị: Mặc dù điện thoại mang đến trải nghiệm thiết bị Android truyền thống, nhưng bạn vẫn có thể tương tác với trò chơi trên các loại thiết bị khác. Thiết bị ChromeOS có thể chạy vùng chứa Android hiển thị trò chơi của bạn. Máy tính bảng có thể chạy Android cũng hỗ trợ nhiều mức độ chân thực. Thiết bị Android TV hỗ trợ trải nghiệm phong phú và sống động hơn. Người chơi có thể mô phỏng môi trường nhiều cửa sổ bằng cách sử dụng công cụ tiện ích hiển thị. Và khi sử dụng thiết bị có thể gập lại, người chơi có thể thay đổi kích thước màn hình trong một phiên chơi.
  • Phương thức tương tác: Người chơi có thể cung cấp dữ liệu đầu vào bằng cách nhấn vào màn hình thiết bị, nhưng họ cũng có thể sử dụng chuột, bàn di chuột, bàn phím hoặc tay điều khiển. Ngoài ra, các công cụ tiện ích hiển thị và thiết bị có thể gập lại cũng cho phép người chơi trải nghiệm trò chơi của bạn trên màn hình lớn hơn, kéo dài các phiên chơi và tăng khả năng dùng được các giao diện phức tạp hơn.
  • Hỗ trợ phần cứng: Một số thiết bị chạy Android không có các phần cứng đặc biệt hơn thiết bị cầm tay thông thường, chẳng hạn như máy ảnh mặt sau, GPS và kết nối mạng. Trò chơi của bạn nên thích ứng với các phần cứng có sẵn và xử lý một cách linh hoạt những trường hợp không sử dụng được một số tính năng nào đó.

Bản hướng dẫn này trình bày các phương pháp hay nhất liên quan đến việc phát triển trò chơi cho nhiều loại màn hình cũng như nhiều loại hình tương tác của người dùng. Bản hướng dẫn này cũng đưa ra các đề xuất về việc thiết kế trò chơi và phát triển một chiến lược kiểm thử hiệu quả.

Các phương pháp hay nhất về thiết kế trò chơi

Khi lập kế hoạch về thiết kế và kiến trúc của trò chơi, hãy làm theo các phương pháp hay nhất được mô tả trong các phần sau đây.

Phản hồi các thay đổi về cấu hình theo cách thủ công

Khi phát hiện một thay đổi về cấu hình (chẳng hạn như thay đổi về kích thước màn hình, hướng màn hình hoặc phương thức nhập), theo mặc định, hệ thống sẽ khởi động lại hoạt động hiện tại. Để duy trì trạng thái trong ứng dụng hoặc trò chơi, theo mặc định, hoạt động này gọi onSaveInstanceState() trước khi khởi động lại và gọi onRestoreInstanceState() sau khi khởi động lại. Tuy nhiên, quá trình này yêu cầu hoạt động phải tải lại tất cả dịch vụ và tài nguyên liên quan. Để tìm hiểu thêm về hành vi mặc định này, hãy xem hướng dẫn về cách xử lý các thay đổi về cấu hình.

Một phiên chơi điển hình sẽ trải qua một số thay đổi về cấu hình. Nếu trò chơi của bạn cho phép hệ thống xử lý từng thay đổi đối với cấu hình, cảnh trò chơi của bạn sẽ bị hủy và khởi động lại nhiều lần, làm giảm hiệu suất của trò chơi. Vì lý do này, chúng tôi rất khuyến khích bạn tự xử lý những thay đổi về cấu hình này trong trò chơi.

Để tìm hiểu cách thêm logic thay đổi cấu hình này vào trò chơi, hãy xem phần về cách tạo trình xử lý thay đổi cấu hình tuỳ chỉnh.

Tạo cấu trúc linh hoạt

Để hỗ trợ thêm cho trò chơi của bạn trên nhiều thiết bị nhất có thể, hãy làm theo các phương pháp hay nhất sau:

  • Triển khai Android App Bundle thay vì từng APK. Android App Bundle cho phép bạn nhóm các cấu phần mềm thuộc nhiều độ phân giải và nhiều mô hình kiến trúc (chẳng hạn như x86, ARM) thành một cấu phần phần mềm duy nhất. Hơn thế, Android App Bundle còn hỗ trợ các hạn mức kích thước cao hơn cho trò chơi; mỗi tệp APK cơ sở có thể có kích thước lên tới 150 MB và ngay chính gói đó cũng có thể có kích thước nhiều gigabyte.
  • Thêm tính năng hỗ trợ cho kiến trúc x86. Bước này cải thiện hiệu suất của trò chơi trên các thiết bị không hỗ trợ ARM, vì giờ đây các thiết bị này có thể thực thi các hướng dẫn mà không cần phải dịch trước.

Thêm tính năng hỗ trợ cho Vulkan

Bằng việc hỗ trợ Vulkan, trò chơi của bạn có thể đạt được hiệu suất đồ hoạ cao hơn. Hầu hết thiết bị đều hỗ trợ API đồ hoạ này.

Tạo trình xử lý thay đổi cấu hình tuỳ chỉnh

Để khai báo các loại thay đổi cấu hình mà trò chơi của bạn tự xử lý, hãy thêm thuộc tính android:configChanges vào từng phần tử <activity> trong tệp kê khai đại diện cho một màn hình hoặc giao diện phức tạp.

Đoạn mã sau đây minh hoạ cách khai báo việc trò chơi của bạn có chú ý đến các thay đổi về kích thước màn hình, hướng màn hình và phương thức nhập:

<activity ...
    android:configChanges="screenSize|orientation|keyboard|keyboardHidden">
</activity>

Khi xảy ra thay đổi trong cấu hình đã khai báo, hệ thống sẽ gọi một phương thức khác onConfigurationChanged(). Trong phương thức này, hãy thêm logic để cập nhật giao diện người dùng của trò chơi:

Xử lý các thay đổi về cấu hình màn hình

Trò chơi của bạn xử lý các thay đổi về kích thước màn hình và hướng màn hình theo cách thủ công mỗi khi bạn đưa giá trị screenSizeorientation tương ứng vào thuộc tính android:configChanges. Bạn có thể sử dụng các giá trị mới này để cập nhật nội dung trong cảnh và khu vực nhập của người chơi Để nắm được hướng dẫn về cách thiết kế bố cục trò chơi sao cho cập nhật dễ dàng hơn, hãy xem hướng dẫn về cách hỗ trợ nhiều kích thước màn hình.

Trong quá trình triển khai onConfigurationChanged() cho trò chơi, hãy sử dụng đối tượng Configuration đã truyền vào và đối tượng Display của trình quản lý cửa sổ để xác định các giá trị cập nhật tương ứng cho kích thước màn hình và hướng màn hình.

Đoạn mã sau đây cho biết cách lấy kích thước và hướng màn hình đã cập nhật của trò chơi:

Kotlin

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()

    // Get general orientation; either Configuration.ORIENTATION_PORTRAIT or
    // Configuration.ORIENTATION_LANDSCAPE.
    val newScreenOrientation: Int = newConfig.orientation

    // Get general rotation; one of: ROTATION_0, ROTATION_90, ROTATION_180,
    // or ROTATION_270.
    val newScreenRotation: Int = windowManager.defaultDisplay.rotation
}

Java

@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);

    // Get general orientation; either Configuration.ORIENTATION_PORTRAIT or
    // Configuration.ORIENTATION_LANDSCAPE.
    int newScreenOrientation = newConfig.orientation;

    // Get general rotation; one of: ROTATION_0, ROTATION_90, ROTATION_180,
    // or ROTATION_270.
    int newScreenRotation = getWindowManager().getDefaultDisplay()
            .getRotation();
}

Hãy lưu ý rằng việc thay đổi tư thế của thiết bị có thể gập sẽ làm thay đổi cấu hình, ngay cả khi ứng dụng chạy ở chế độ toàn màn hình. Do đó, có thể ứng dụng của bạn sẽ phải xử lý các thay đổi về kích thước màn hình hoặc mật độ pixel nếu người dùng gấp hoặc mở thiết bị trong khi trò chơi đang chạy.

Chất lượng màn hình theo trò chơi

Các phần sau đây mô tả cách điều chỉnh phản ứng của trò chơi đối với các thay đổi về kích thước màn hình hoặc hướng màn hình, tuỳ thuộc vào chất lượng của trò chơi:

Chế độ toàn màn hình

Trên một số nền tảng, chẳng hạn như ChromeOS, các ứng dụng và trò chơi Android có thể được đặt trong cửa sổ và đổi kích thước theo mặc định. Nếu trò chơi của bạn luôn chạy ở chế độ toàn màn hình, bạn có thể đặt thuộc tính android:resizeableActivity thành false trong một trong các phần tử <activity>, như thể hiện trong đoạn mã sau đây:

<activity ...
    android:resizeableActivity="false">
</activity>

Bạn cũng có thể đặt thuộc tính android:resizeableActivity thành false để ngăn việc xảy ra các thay đổi về cấu hình dựa trên kích thước. Trừ phi trò chơi của bạn luôn chạy ở chế độ toàn màn hình, bạn chỉ nên thêm thuộc tính này làm bản sửa lỗi tạm thời cho mục đích kiểm thử.

Hướng màn hình

Nếu trò chơi của bạn phụ thuộc vào cảm biến của một thiết bị có hướng cụ thể, hãy chỉ định một giá trị cho android:screenOrientation trong hoạt động của trò chơi, như thể hiện trong đoạn mã sau đây. Chế độ cài đặt này giúp ngăn một cảnh trong trò chơi bị đảo ngược đột ngột.

<activity ...
    android:screenOrientation="landscape">
</activity>

Chất lượng màn hình theo thiết bị

Các phần sau mô tả cách xử lý các thay đổi về cấu hình theo màn hình, dựa trên một số yếu tố chất lượng cụ thể trên một số thiết bị.

Tỷ lệ khung hình

Có một số thiết bị hỗ trợ nhiều tỷ lệ khung hình. Ví dụ: các thiết bị có thể gập lại được thiết kế để hỗ trợ tỷ lệ khung hình 21:9 khi ở trạng thái gập. Để xử lý sự đa dạng về tỷ lệ khung hình này, hãy thực hiện ít nhất một trong những việc sau:

  • Nhắm đến Android 8.0 (API cấp 26) trở lên
  • Làm cho giao diện và trò chơi của bạn có thể đổi kích thước. Đặt android:resizeableActivity thành true trên những thiết bị chạy Android 7.0 (API cấp 24) trở lên.
  • Khai báo tỷ lệ khung hình tối đa được hỗ trợ. Trong thuộc tính <meta-data> liên kết với trò chơi của bạn, hãy đặt android.max_aspect thành 2.4, như thể hiện trong đoạn mã sau đây. Tuy nhiên, hãy lưu ý rằng việc tỷ lệ khung hình đó lớn hơn tỷ lệ khung hình mà bạn đã chỉ định có thể khiến trò chơi trông như hòm thư bên trong màn hình.

    <application>
    <meta-data android:name="android.max_aspect"
               android:value="2.4" />
    </application>
    

Nhiều hoạt động xuất hiện đồng thời

Có nhiều thiết bị hiện đại hỗ trợ đa dạng bố cục màn hình, có thể kể đến màn hình chia đôi, hình trong hình và khu vực hiển thị lớn. Khi sử dụng một trong các bố cục này, hệ thống có thể cho thấy nhiều hoạt động cùng một lúc.

Trên các thiết bị chạy Android 9 (API cấp 28) trở lên, bạn có thể tiếp tục mọi hoạt động hiển thị hàng đầu cùng một lúc. Tuy nhiên, để hành vi này hoạt động được, cả trò chơi của bạn và nhà sản xuất thiết bị gốc (OEM) đều phải chọn sử dụng chức năng này. Bạn có thể thêm tính năng hỗ trợ trong trò chơi bằng cách đặt android.allow_multiple_resumed_activities thành true trong tệp kê khai của trò chơi, như thể hiện trong đoạn mã sau:

<application>
    <meta-data android:name="android.allow_multiple_resumed_activities"
               android:value="true" />
</application>

Sau đó, bạn có thể kiểm thử trò chơi trên nhiều loại thiết bị để xem thiết bị nào có sự hỗ trợ cần thiết của OEM để tính năng tiếp tục nhiều hoạt động triển khai được đúng cách.

Để biết thêm thông tin về cách định cấu hình trò chơi sao cho trò chơi xuất hiện trong màn hình nhiều cửa sổ, hãy xem hướng dẫn về cách thêm tính năng hỗ trợ nhiều cửa sổ.

Xử lý nhiều loại mô hình tương tác

Trò chơi của bạn xử lý sự hiện diện của bàn phím và khả năng sử dụng bàn phím theo cách thủ công mỗi khi bạn đưa giá trị keyboardkeyboardHidden tương ứng vào thuộc tính android:configChanges. Bạn có thể sử dụng những giá trị mới này để cập nhật phương thức nhập chính của trò chơi.

Khi định cấu hình trò chơi để hỗ trợ nhiều loại dữ liệu người dùng nhập vào, hãy lưu ý những điều sau:

  • Phát hiện các phương thức nhập thay vì từng thiết bị riêng lẻ. Tư duy này giúp bạn dễ dàng cải thiện trải nghiệm của người chơi mà không cần tập trung quá nhiều vào thiết bị cụ thể của người chơi.
  • Đưa thuộc tính keyboardHidden vào danh sách các thay đổi cấu hình được xử lý thủ công. Nhờ vậy, trò chơi của bạn có thể theo dõi thời điểm một bàn phím được gắn vào thiết bị nhưng không sử dụng được.
  • Xác định các phương thức nhập hiện có. Để thực hiện việc này, hãy gọi getInputDeviceIds() khi khởi động trò chơi và sau mỗi lần thay đổi cấu hình.

    Thường thì bạn có thể xác định cách người chơi dự định tương tác với trò chơi dựa trên thiết bị đầu vào họ ưa dùng:

    • Người chơi thường dùng bàn phím hoặc tay điều khiển trò chơi để thực hiện các thao tác nhanh dùng nút.
    • Người chơi thường dùng màn hình cảm ứng hoặc bàn di chuột để thực hiện các cử chỉ phức tạp hơn.
    • Người chơi thường dùng chuột để thực hiện các thao tác nhập có độ chính xác cao hơn.

Các phần sau đây đưa ra các phương pháp hay nhất cho một số loại thiết bị đầu vào cụ thể.

Bàn phím

Khi tạo bố cục bàn phím cho trò chơi, hãy xem xét cách người chơi điều hướng trong một cảnh cụ thể cũng như cách họ tương tác với các chế độ cài đặt trong trò chơi của bạn.

Các phím WASD hoặc phím mũi tên thường dùng để điều khiển chuyển động của nhân vật. Bạn cũng nên gán một phím cụ thể cho mỗi hành động hoặc kỹ năng quan trọng mà một nhân vật điều khiển được có thể thực hiện trong trò chơi. Để tối đa hoá trải nghiệm của người chơi, hãy cân nhắc việc thêm tính năng hỗ trợ liên kết phím tuỳ chỉnh trong trò chơi.

Người chơi cũng có thể mở các trình đơn của trò chơi và di chuyển qua các trình đơn đó bằng cách sử dụng bàn phím. Phím Esc là một mục ánh xạ phổ biến để tạm dừng một cảnh và hiện trình đơn của trò chơi đó.

Để biết thêm thông tin về cách hỗ trợ nhập bằng bàn phím trong trò chơi, hãy xem hướng dẫn về cách hỗ trợ thao tác bằng bàn phím cũng như hướng dẫn về cách xử lý thao tác bằng bàn phím.

Tay điều khiển trò chơi

Để biết thêm thông tin về cách xử lý dữ liệu đầu vào của tay điều khiển trò chơi, hãy xem hướng dẫn về cách hỗ trợ tay điều khiển trò chơi.

Chuột hoặc bàn di chuột

Nếu trò chơi của bạn hỗ trợ người chơi nhập bằng chuột hoặc bàn di chuột, hãy lưu ý rằng người chơi còn tương tác với thiết bị theo những cách khác ngoài việc chơi trò chơi. Quan trọng là bạn cần lưu ý rằng khi yêu cầu chụp con trỏ, mọi hoạt động nhập của chuột đều được chuyển hướng đến trò chơi. Do đó, sau khi trò chơi có thông tin cần thiết, hãy nhả chụp con trỏ để người chơi lấy lại quyền kiểm soát tiêu chuẩn đối với thiết bị của họ.

Trên các thiết bị chạy Android 8.0 (API cấp 26) trở lên, bạn có thể sử dụng Mouse Capture API để hỗ trợ quá trình chụp con trỏ. Trong các trò chơi tương tác với phương thức nhập có độ chính xác cao, bạn có thể lấy toạ độ hiện tại của con trỏ bằng cách gọi getX()getY().

Để biết thêm thông tin về cách thêm tính năng hỗ trợ nhập liệu bằng chuột và bàn di chuột trong trò chơi, hãy xem hướng dẫn cách theo dõi chuyển động của con trỏ và điểm chạm cũng như hướng dẫn về cách xử lý cử chỉ nhiều điểm chạm.

Kiểm thử trò chơi

Trước khi phát hành trò chơi, hãy kiểm thử cách ứng dụng phản hồi các thay đổi về cấu hình bằng cách hoàn tất các bước được trình bày trong các phần sau đây.

Cập nhật kế hoạch kiểm thử

Khi xác thực chức năng của trò chơi, hãy xem xét các trường hợp kiểm thử sau đây:

  • Thu nhỏ và phóng to cửa sổ chứa trò chơi. (Không áp dụng nếu trò chơi của bạn luôn ở chế độ toàn màn hình).
  • Thay đổi kích thước màn hình.
  • Thay đổi hướng màn hình (Không áp dụng nếu trò chơi của bạn có hướng cố định.)
  • Kết nối và ngắt kết nối với thiết bị đầu vào, chẳng hạn như bàn phím và chuột.
  • Thực hiện thao tác tiếp tục nhiều hoạt động (nếu trò chơi của bạn có hỗ trợ tính năng này).

Ngoài ra, hãy xem xét việc cập nhật hệ thống quản lý chất lượng của trò chơi để bạn có thể tối ưu hoá cho thêm nhiều trải nghiệm người chơi.

Để biết các phương pháp hay nhất liên quan đến hoạt động kiểm thử trò chơi, hãy xem hướng dẫn Kiến thức cơ bản về hoạt động kiểm thử.

Sử dụng các công cụ kiểm thử và gỡ lỗi

Bạn có thể kiểm thử bằng nhiều công cụ mà nền tảng này hỗ trợ: