Animasi masih dapat dengan sempurna dipisah antara logika dan rendering. Keadaan abstrak data animasi akan menjadi informasi yang diperlukan untuk API grafik Anda untuk membuat animasi.
Dalam game 2D misalnya, itu bisa berupa area persegi panjang yang menandai area yang menampilkan bagian sprite sheet Anda saat ini yang perlu digambar (bila Anda memiliki sheet yang terdiri dari katakanlah 30 gambar 80x80 yang berisi berbagai langkah karakter Anda melompat, duduk, bergerak dll.) Ini juga bisa berupa data apa pun yang tidak Anda perlukan untuk render, tetapi mungkin untuk mengelola status animasi itu sendiri, seperti waktu yang tersisa hingga langkah animasi saat ini berakhir atau nama animasi ("berjalan", "berdiri" dll) Semua itu dapat diwakili dengan cara apa pun yang Anda inginkan. Itu bagian logika.
Di bagian rendering, Anda cukup melakukannya seperti biasa, dapatkan persegi panjang itu dari model Anda dan gunakan renderer Anda untuk benar-benar melakukan panggilan ke API grafik.
Dalam kode (menggunakan sintaks C ++ di sini):
class Sprite //Model
{
private:
Rectangle subrect;
Vector2f position;
//etc.
public:
Rectangle GetSubrect()
{
return subrect;
}
//etc.
};
class AnimatedSprite : public Sprite, public Updatable //arbitrary interface for classes that need to change their state on a regular basis
{
AnimationController animation_controller;
//etc.
public:
void Update()
{
animation_controller.Update(); //Good OOP design ;) It will take control of changing animations in time etc. for you
this.SetSubrect(animation_controller.GetCurrentAnimation().GetRect());
}
//etc.
};
Itu datanya. Perender Anda akan mengambil data itu dan menggambarnya. Karena Sprite normal dan animasi digambar dengan cara yang sama, Anda dapat menggunakan polimorf di sini!
class Renderer
{
//etc.
public:
void Draw(const Sprite &spr)
{
graphics_api_pointer->Draw(spr.GetAllTheDataThatINeed());
}
};
TMV:
Saya datang dengan contoh lain. Katakanlah Anda memiliki RPG. Model Anda yang mewakili peta dunia, misalnya, mungkin perlu menyimpan posisi karakter di dunia sebagai koordinat petak di peta. Namun, ketika Anda memindahkan karakter, mereka berjalan beberapa piksel sekaligus ke alun-alun berikutnya. Apakah Anda menyimpan posisi "antar ubin" ini di objek animasi? Bagaimana Anda memperbarui model ketika karakter akhirnya "tiba" di koordinat ubin berikutnya di peta?
Peta dunia tidak tahu tentang posisi pemain secara langsung (tidak memiliki Vector2f atau sesuatu seperti itu yang secara langsung menyimpan posisi pemain =, melainkan memiliki referensi langsung ke objek pemain itu sendiri, yang pada gilirannya berasal dari AnimatedSprite sehingga Anda bisa meneruskannya ke renderer dengan mudah, dan mendapatkan semua data yang diperlukan darinya.
Secara umum, tilemap Anda seharusnya tidak dapat melakukan semuanya - Saya memiliki kelas "TileMap" yang menangani pengelolaan semua ubin, dan mungkin juga melakukan deteksi tabrakan antara objek yang saya serahkan ke sana dan ubin di peta. Kemudian, saya akan memiliki kelas "RPGMap" lainnya, atau bagaimanapun Anda ingin menyebutnya, yang memiliki referensi ke tilemap Anda dan referensi ke pemain dan membuat Pembaruan aktual () panggilan ke pemain Anda dan ke Anda tilemap.
Bagaimana Anda ingin memperbarui model ketika pemain bergerak tergantung pada apa yang ingin Anda lakukan.
Apakah pemain Anda diperbolehkan bergerak di antara ubin secara terpisah (gaya Zelda)? Cukup tangani input dan pindahkan pemain sesuai setiap frame. Atau Anda ingin pemain menekan "kanan" dan karakter Anda secara otomatis memindahkan satu ubin ke kanan? Biarkan kelas RPGMap Anda menginterpolasi posisi pemain sampai tiba di tujuannya dan sementara itu mengunci semua penanganan input gerakan-kunci.
Either way, jika Anda ingin membuatnya lebih mudah pada diri Anda sendiri, semua model Anda akan memiliki metode Pembaruan () jika mereka benar-benar memerlukan beberapa logika untuk memperbarui diri mereka sendiri (bukan hanya mengubah nilai variabel) - Anda tidak memberikan controller dalam pola MVC seperti itu, Anda hanya memindahkan kode dari "satu langkah di atas" (controller) ke model, dan semua controller tidak memanggil metode Update () dari model (Controller dalam kasus kami akan menjadi RPGMap). Anda masih dapat dengan mudah menukar kode logika - Anda bisa langsung mengubah kode kelas atau jika Anda memerlukan perilaku yang sama sekali berbeda, Anda hanya dapat berasal dari kelas model dan hanya mengganti metode Pembaruan ().
Pendekatan itu mengurangi pemanggilan metode dan banyak hal seperti itu - yang dulunya merupakan salah satu kelemahan utama dari pola MVC murni (Anda akhirnya memanggil GetThis () GetThat () sangat sering) - itu membuat kode lebih lama dan lebih sedikit lebih sulit untuk dibaca dan juga lebih lambat - meskipun itu mungkin ditangani oleh kompiler Anda yang mengoptimalkan banyak hal seperti itu.