Sebagai contoh, saya memiliki kelas Game dan itu membuat int
yang melacak kehidupan pemain. Saya memiliki persyaratan
if ( mLives < 1 ) {
// Do some work.
}
Namun kondisi ini terus menyala dan pekerjaan dilakukan berulang kali. Misalnya, saya ingin mengatur timer untuk keluar dari game dalam 5 detik. Saat ini, ia akan terus menyetelnya menjadi 5 detik setiap frame dan permainan tidak pernah berakhir.
Ini hanyalah satu contoh, dan saya memiliki masalah yang sama di beberapa area permainan saya. Saya ingin memeriksa beberapa kondisi dan kemudian melakukan sesuatu sekali dan hanya sekali, dan kemudian tidak memeriksa atau melakukan kode dalam pernyataan if lagi. Beberapa solusi yang mungkin terlintas dalam pikiran adalah memiliki bool
untuk setiap kondisi dan mengatur bool
kapan kondisi menyala. Namun dalam praktiknya hal ini menjadi sangat berantakan dalam menangani banyak hal bools
, karena harus disimpan sebagai bidang kelas, atau secara statis dalam metode itu sendiri.
Apa solusi yang tepat untuk ini (bukan untuk contoh saya, tetapi untuk domain masalah)? Bagaimana Anda melakukan ini dalam permainan?
Jawaban:
Saya pikir Anda dapat menyelesaikan masalah ini hanya dengan menggunakan kontrol yang lebih hati-hati atas jalur kode yang mungkin Anda miliki. Misalnya, dalam kasus di mana Anda memeriksa apakah jumlah nyawa pemain telah turun di bawah satu, mengapa tidak memeriksa hanya ketika pemain kehilangan nyawa, bukan setiap frame?
Ini, pada gilirannya, mengasumsikan bahwa
subtractPlayerLife
hanya akan dipanggil pada kesempatan tertentu, yang mungkin akan dihasilkan dari kondisi bahwa Anda harus memeriksa setiap frame (tabrakan, mungkin).Dengan mengontrol dengan hati-hati bagaimana kode Anda dieksekusi, Anda dapat menghindari solusi berantakan seperti boolean statis dan juga mengurangi sedikit demi sedikit pada seberapa banyak kode dieksekusi dalam satu frame.
Jika ada sesuatu yang sepertinya tidak mungkin untuk diperbaiki, dan Anda benar-benar hanya perlu memeriksa sekali, maka nyatakan (seperti a
enum
) atau boolean statis adalah cara yang harus dilakukan. Untuk menghindari menyatakan statika sendiri, Anda dapat menggunakan trik berikut:yang akan membuat kode berikut:
cetak
something
dansomething else
hanya sekali. Itu tidak menghasilkan kode berpenampilan terbaik, tetapi berhasil. Saya juga cukup yakin ada cara untuk memperbaikinya, mungkin dengan lebih baik memastikan nama variabel yang unik. Ini#define
hanya akan bekerja sekali selama runtime. Tidak ada cara untuk mengatur ulang, dan tidak ada cara untuk menyimpannya.Terlepas dari triknya, saya sangat menyarankan lebih baik mengendalikan aliran kode Anda terlebih dahulu, dan menggunakan ini
#define
sebagai upaya terakhir, atau hanya untuk tujuan debug.sumber
Ini terdengar seperti kasus klasik dalam menggunakan pola keadaan. Di satu negara Anda memeriksa kondisi Anda untuk hidup <1. Jika kondisi itu menjadi kenyataan, Anda beralih ke kondisi penundaan. Status penundaan ini menunggu durasi yang ditentukan dan kemudian transisi ke status keluar Anda.
Dalam pendekatan yang paling sepele:
Anda bisa mempertimbangkan menggunakan kelas Negara bersama dengan StateManager / StateMachine untuk menangani perubahan / mendorong / transisi antar negara daripada pernyataan switch.
Anda dapat membuat solusi manajemen negara Anda secanggih yang Anda inginkan, termasuk beberapa status aktif, status induk aktif tunggal dengan banyak status anak aktif menggunakan beberapa hierarki, dll. Gunakan apa yang masuk akal bagi Anda untuk saat ini tentu saja, tetapi saya benar-benar berpikir bahwa solusi pola keadaan akan membuat kode Anda jauh lebih dapat digunakan kembali dan lebih mudah untuk mempertahankan dan mengikuti.
sumber
Jika Anda khawatir tentang kinerja, kinerja pemeriksaan beberapa kali biasanya tidak signifikan; juga karena memiliki kondisi bool.
Jika Anda tertarik pada sesuatu yang lain, Anda dapat menggunakan sesuatu yang mirip dengan pola desain nol untuk menyelesaikan masalah ini.
Dalam hal ini, mari kita asumsikan Anda ingin memanggil metode
foo
jika pemain tidak memiliki nyawa yang tersisa. Anda akan mengimplementasikan ini sebagai dua kelas, satu yang memanggilfoo
, dan satu yang tidak melakukan apa-apa. Ayo panggil merekaDoNothing
danCallFoo
suka:Ini sedikit contoh "mentah"; poin kuncinya adalah:
FooClass
yang dapatDoNothing
atauCallFoo
. Ini bisa berupa kelas dasar, kelas abstrak, atau antarmuka.execute
metode kelas itu.DoNothing
instance).CallFoo
instance).Ini pada dasarnya seperti campuran strategi dan pola nol.
sumber
if
cek keFooClass
instance itu sendiri, jadi itu hanya dieksekusi sekali, dan ditto untuk instantiatingCallFoo
.