Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Nota
Topik ini adalah bagian dari Membuat game Universal Windows Platform (UWP) sederhana dengan seri tutorial DirectX. Topik di tautan tersebut mengatur konteks untuk seri.
Game ini sekarang memiliki jendela, telah mendaftarkan beberapa penanganan aktivitas, dan telah memuat aset secara asinkron. Topik ini menjelaskan penggunaan status game, cara mengelola status permainan kunci tertentu, dan cara membuat perulangan pembaruan untuk mesin game. Kemudian kita akan mempelajari tentang alur antarmuka pengguna dan, akhirnya, memahami lebih lanjut tentang penanganan aktivitas yang diperlukan untuk game UWP.
Status permainan yang digunakan untuk mengelola alur permainan
Kami memanfaatkan status permainan untuk mengelola alur permainan.
Ketika Simple3DGameDX permainan contoh dijalankan untuk pertama kalinya pada komputer, permainan berada dalam keadaan di mana belum ada yang dimulai. Ketika permainan dijalankan pada kali berikutnya, permainan dapat berada dalam salah satu keadaan ini.
- Tidak ada permainan yang dimulai, atau permainan berada di antara level (skor tinggi adalah nol).
- Loop permainan sedang berjalan, dan berada di tengah level.
- Perulangan permainan tidak berjalan karena permainan telah selesai (skor tinggi memiliki nilai bukan nol).
Game Anda dapat memiliki status sebanyak yang dibutuhkan. Tapi ingatlah bahwa itu dapat dihentikan kapan saja. Dan ketika dimulai kembali, pengguna mengharapkannya dilanjutkan dalam keadaan saat dihentikan.
Manajemen status game
Jadi, selama inisialisasi game, Anda harus mendukung permainan cold-starting serta memulai kembali permainan setelah menghentikannya dalam penerbangan. Sampel
Sebagai respons terhadap peristiwa penangguhan, gameplay ditangguhkan, tetapi sumber daya game masih dalam memori. Demikian juga, peristiwa resume ditangani untuk memastikan bahwa permainan sampel melanjutkan dari kondisi saat ditangguhkan atau dihentikan. Tergantung pada statusnya, opsi yang berbeda disajikan kepada pemain.
- Jika permainan dilanjutkan di tengah level, permainan akan tampak sebagai dijeda, dan overlay menawarkan opsi untuk melanjutkan.
- Jika permainan dilanjutkan dalam keadaan di mana permainan selesai, maka itu menampilkan skor tinggi dan opsi untuk memainkan permainan baru.
- Terakhir, jika permainan dilanjutkan sebelum level dimulai, maka overlay menyajikan opsi mulai kepada pengguna.
Contoh permainan tidak membedakan apakah permainan dimulai dari keadaan dingin, diluncurkan untuk pertama kali tanpa peristiwa penangguhan, atau melanjutkan dari status yang ditangguhkan. Ini adalah desain yang tepat untuk aplikasi UWP apa pun.
Dalam sampel ini, inisialisasi status permainan terjadi di GameMain::InitializeGameState (kerangka metode tersebut ditampilkan di bagian berikutnya).
Berikut adalah diagram alur untuk membantu Anda memvisualisasikan alur. Ini mencakup inisialisasi dan perulangan pembaruan.
- Inisialisasi dimulai pada simpul Mulai ketika Anda memeriksa status permainan saat ini. Untuk kode game, lihat GameMain::InitializeGameState di bagian berikutnya.
- Untuk informasi selengkapnya tentang siklus pembaruan, buka Pembaruan mesin game. Untuk kode game, buka GameMain::Update.
Metode GameMain::InitializeGameState
Metode GameMain::InitializeGameState dipanggil secara tidak langsung melalui konstruktor kelas GameMain, yang merupakan hasil dari pembuatan instance GameMain dalam App::Load.
GameMain::GameMain(std::shared_ptr<DX::DeviceResources> const& deviceResources) : ...
{
m_deviceResources->RegisterDeviceNotify(this);
...
ConstructInBackground();
}
winrt::fire_and_forget GameMain::ConstructInBackground()
{
...
m_renderer->FinalizeCreateGameDeviceResources();
InitializeGameState();
...
}
void GameMain::InitializeGameState()
{
// Set up the initial state machine for handling Game playing state.
if (m_game->GameActive() && m_game->LevelActive())
{
// The last time the game terminated it was in the middle
// of a level.
// We are waiting for the user to continue the game.
...
}
else if (!m_game->GameActive() && (m_game->HighScore().totalHits > 0))
{
// The last time the game terminated the game had been completed.
// Show the high score.
// We are waiting for the user to acknowledge the high score and start a new game.
// The level resources for the first level will be loaded later.
...
}
else
{
// This is either the first time the game has run or
// the last time the game terminated the level was completed.
// We are waiting for the user to begin the next level.
...
}
m_uiControl->ShowGameInfoOverlay();
}
Memperbarui mesin game
Metode App::Run memanggil GameMain::Run. Di dalam GameMain::Run terdapat mesin status dasar untuk menangani semua aksi mayor yang dapat dilakukan pengguna. Tingkat tertinggi dari mesin status ini berkaitan dengan pemuatan game, memainkan level tertentu, atau melanjutkan level setelah game dijeda (oleh sistem atau oleh pengguna).
Dalam permainan sampel, ada 3 status utama (diwakili oleh enum UpdateEngineState) yang dapat digunakan game.
- UpdateEngineState::WaitingForResources. Perulangan permainan sedang berulang, tidak dapat bertransisi sampai sumber daya, khususnya sumber daya grafis, tersedia. Ketika tugas pemuatan sumber daya asinkron selesai, kami memperbarui status ke UpdateEngineState::ResourcesLoaded. Ini biasanya terjadi di antara level ketika level memuat ulang sumber daya baru dari disk, dari server game, atau dari backend cloud. Dalam permainan sampel, kami mensimulasikan perilaku ini, karena sampel tidak memerlukan sumber daya tambahan per tingkat pada saat itu.
- UpdateEngineState::WaitingForPress. Siklus permainan sedang berulang, menunggu input pengguna spesifik. Input ini adalah tindakan pemain untuk memuat game, memulai level, atau melanjutkan level. Kode contoh merujuk pada sub-keadaan ini melalui enumerasi PressResultState.
- UpdateEngineState::D ynamics. Perulangan permainan sedang berjalan saat pengguna bermain. Saat pengguna bermain, permainan memeriksa 3 kondisi di mana permainan dapat mengalami transisi.
- GameState::TimeExpired. Kedaluwarsa batas waktu untuk tahap.
- GameState::LevelComplete. Penyelesaian level oleh pemain.
- GameState::GameComplete. Penyelesaian semua level oleh pemain.
Permainan hanyalah mesin status yang berisi beberapa mesin status yang lebih kecil. Setiap status tertentu harus didefinisikan oleh kriteria yang sangat spesifik. Transisi dari satu status ke status lainnya harus didasarkan pada input pengguna diskrit, atau tindakan sistem (seperti pemuatan sumber daya grafis).
Saat merencanakan permainan, pertimbangkan untuk menggambar seluruh alur permainan untuk memastikan bahwa Anda telah mengatasi semua kemungkinan tindakan yang dapat dilakukan pengguna atau sistem. Gim bisa sangat rumit, jadi mesin status adalah alat yang ampuh untuk membantu Anda memvisualisasikan kompleksitas ini, dan membuatnya lebih mudah dikelola.
Mari kita lihat kode untuk perulangan pembaruan.
Metode GameMain::Update
Ini adalah struktur mesin status yang digunakan untuk memperbarui mesin game.
void GameMain::Update()
{
// The controller object has its own update loop.
m_controller->Update();
switch (m_updateState)
{
case UpdateEngineState::WaitingForResources:
...
break;
case UpdateEngineState::ResourcesLoaded:
...
break;
case UpdateEngineState::WaitingForPress:
if (m_controller->IsPressComplete())
{
...
}
break;
case UpdateEngineState::Dynamics:
if (m_controller->IsPauseRequested())
{
...
}
else
{
// When the player is playing, work is done by Simple3DGame::RunGame.
GameState runState = m_game->RunGame();
switch (runState)
{
case GameState::TimeExpired:
...
break;
case GameState::LevelComplete:
...
break;
case GameState::GameComplete:
...
break;
}
}
if (m_updateState == UpdateEngineState::WaitingForPress)
{
// Transitioning state, so enable waiting for the press event.
m_controller->WaitForPress(
m_renderer->GameInfoOverlayUpperLeft(),
m_renderer->GameInfoOverlayLowerRight());
}
if (m_updateState == UpdateEngineState::WaitingForResources)
{
// Transitioning state, so shut down the input controller
// until resources are loaded.
m_controller->Active(false);
}
break;
}
}
Memperbarui antarmuka pengguna
Kita perlu memberitahu pemain tentang keadaan sistem, dan memungkinkan keadaan permainan berubah tergantung pada tindakan pemain dan aturan yang menentukan permainan. Banyak game, termasuk permainan sampel ini, biasanya menggunakan elemen antarmuka pengguna (UI) untuk menyajikan info ini kepada pemain. UI berisi representasi status permainan dan info khusus permainan lainnya seperti skor, amunisi, atau jumlah peluang yang tersisa. UI juga disebut overlay karena dirender secara terpisah dari alur grafis utama, dan ditempatkan di atas proyeksi 3D.
Beberapa info UI juga disajikan sebagai heads-up display (HUD) untuk memungkinkan pengguna melihat info tersebut tanpa sepenuhnya melepas mata dari area gameplay utama. Dalam permainan sampel, kita membuat overlay ini dengan menggunakan API Direct2D. Atau, kita dapat membuat overlay ini menggunakan XAML, yang kita bahas dalam Memperluas contoh permainan.
Ada dua komponen untuk antarmuka pengguna.
- HUD yang berisi skor dan info tentang status gameplay saat ini.
- Bitmap jeda, yang merupakan persegi panjang hitam dengan teks yang ditumpangkan ketika permainan dijeda/ditangguhkan. Ini adalah overlay permainan. Kami membahasnya lebih lanjut di Menambahkan antarmuka pengguna.
Tidak mengherankan, overlay memiliki mesin status juga. Overlay bisa menampilkan pesan awal level atau pesan game-over. Ini pada dasarnya adalah kanvas tempat kita dapat menghasilkan info apa pun tentang status permainan yang ingin kita tampilkan kepada pemain saat permainan dijeda atau ditangguhkan.
Overlay yang dirender bisa menjadi salah satu dari enam layar ini, tergantung pada keadaan permainan.
- Layar kemajuan pemuatan sumber daya di awal permainan.
- Layar statistik permainan.
- Layar pesan tingkat mulai.
- Layar game-over ketika semua level selesai tanpa kehabisan waktu.
- Tampilan game over ketika waktu habis.
- Jeda layar menu.
Memisahkan antarmuka pengguna dari alur grafis game memungkinkan Anda mengerjakannya secara independen dari mesin rendering grafis game, dan mengurangi kompleksitas kode game Anda secara signifikan.
Berikut adalah cara permainan sampel mengatur mesin status overlay.
void GameMain::SetGameInfoOverlay(GameInfoOverlayState state)
{
m_gameInfoOverlayState = state;
switch (state)
{
case GameInfoOverlayState::Loading:
m_uiControl->SetGameLoading(m_loadingCount);
break;
case GameInfoOverlayState::GameStats:
...
break;
case GameInfoOverlayState::LevelStart:
...
break;
case GameInfoOverlayState::GameOverCompleted:
...
break;
case GameInfoOverlayState::GameOverExpired:
...
break;
case GameInfoOverlayState::Pause:
...
break;
}
}
Penanganan peristiwa
Seperti yang kita lihat di topik Definisikan kerangka kerja aplikasi UWP game, banyak metode kelas penyedia tampilan dari App mendaftarkan penangan kejadian. Metode ini perlu menangani peristiwa penting ini dengan benar sebelum kami menambahkan mekanika game atau memulai pengembangan grafis.
Penanganan peristiwa yang tepat yang dimaksud sangat mendasar untuk pengalaman aplikasi UWP. Karena aplikasi UWP dapat kapan saja diaktifkan, dinonaktifkan, diubah ukurannya, diciutkan, dilepaskan dari ciut, ditangguhkan, atau dilanjutkan kembali, game harus mendaftarkan diri pada kejadian ini sesegera mungkin, dan menanganinya dengan cara yang menjaga pengalaman tetap lancar dan dapat diprediksi bagi pemain.
Ini adalah penanganan aktivitas yang digunakan dalam sampel ini, dan peristiwa yang mereka tangani.
Pengendali acara | Deskripsi |
---|---|
Tidak Aktif | Menangani CoreApplicationView::Activated. Aplikasi game telah dibawa ke latar depan, sehingga jendela utama diaktifkan. |
OnDpiChanged | Menangani Graphics::Display::DisplayInformation::DpiChanged. DPI tampilan telah berubah dan game menyesuaikan sumber dayanya.
CatatanCoreWindow koordinat berada dalam piksel mandiri perangkat (DIP) untuk Direct2D. Akibatnya, Anda harus memberi tahu Direct2D tentang perubahan DPI untuk menampilkan aset atau primitif 2D dengan benar.
|
SaatOrientasiBerubah | Mengelola Graphics::Display::DisplayInformation::OrientationChanged. Orientasi tampilan berubah dan pemrosesan perlu diperbarui. |
OnDisplayContentsInvalidated | Mengelola Graphics::Display::DisplayInformation::DisplayContentsInvalidated. Tampilan memerlukan penggambaran ulang dan permainan Anda perlu digambar lagi. |
OnResuming | Menangani CoreApplication::Resuming. Aplikasi game memulihkan game dari status ditangguhkan. |
OnSuspending | Menangani CoreApplication::Menangguhkan. Aplikasi game menyimpan statusnya ke disk. Ini memiliki 5 detik untuk menyimpan status ke penyimpanan. |
KetikaVisibilitasBerubah | Mengatasi CoreWindow::VisibilityChanged. Aplikasi game telah mengubah visibilitas dan telah menjadi terlihat atau tidak terlihat ketika aplikasi lain menjadi terlihat. |
SaatAktivasiJendelaBerubah | Menangani CoreWindow::Activated. Jendela utama aplikasi game telah dinonaktifkan atau diaktifkan, sehingga harus menghapus fokus dan menjeda permainan, atau mendapatkan kembali fokus. Dalam kedua kasus tersebut, overlay menunjukkan bahwa permainan dijeda. |
SaatJendelaDitutup | Menangani CoreWindow::Closed. Aplikasi game menutup jendela utama dan menangguhkan permainan. |
OnWindowSizeChanged | Menangani CoreWindow::SizeChanged. Aplikasi game merealokasi sumber daya grafis dan overlay untuk mengakomodasi perubahan ukuran, lalu memperbarui target render. |
Langkah selanjutnya
Dalam topik ini, kita telah melihat bagaimana alur permainan secara keseluruhan dikelola menggunakan status permainan, dan bahwa game terdiri dari beberapa mesin status yang berbeda. Kami juga telah melihat cara memperbarui UI, dan mengelola penanganan aktivitas aplikasi utama. Sekarang kita siap untuk menyelami loop rendering, permainan, dan mekanismenya.
Anda dapat melalui topik yang tersisa yang mendokumen game ini dalam urutan apa pun.