Bu öneri sunmaya gerçekten özgü değildir, ancak işleri büyük ölçüde ayrı tutan bir sistem bulmaya yardımcı olmalıdır. Öncelikle 'GameObject' verilerini konum bilgisinden ayrı tutmaya çalışın.
Basit XYZ konum bilgisinin o kadar basit olmayabileceğini belirtmekte fayda var. Bir fizik motoru kullanıyorsanız, o zaman konum verilerini 3. taraf motorunda saklayabilirsiniz. Ya aralarında senkronize olmanız gerekir (ki bu çok fazla anlamsız bellek kopyalaması gerektirir) ya da bilgileri doğrudan motordan sorgulamanız gerekir. Ancak tüm nesneler fiziğe ihtiyaç duymaz, bazıları yerine sabitlenir, böylece basit bir yüzdürme takımı orada iyi çalışır. Bazıları başka nesnelere bile bağlı olabilir, bu yüzden onların konumları aslında başka bir konumun kaymasıdır. Gelişmiş bir kurulumda, yalnızca GPU'da depolanan konum, bilgisayar tarafında gerekli olan tek zaman, komut dosyası, depolama ve ağ çoğaltması içindir. Dolayısıyla, konumsal verileriniz için birkaç olası seçeneğiniz olacaktır. Burada miras kullanımı mantıklı.
Konumuna sahip olan bir nesneden ziyade, bu nesnenin kendisinin bir dizin oluşturma veri yapısına sahip olması gerekir. Örneğin, bir 'Seviye' bir Octree veya belki bir fizik motoru 'sahne' olabilir. Oluşturmak istediğinizde (veya bir görüntü oluşturma sahnesi oluştururken), özel yapınızı kamera tarafından görülebilen nesneler için sorgularsınız.
Bu aynı zamanda iyi bellek yönetimi verilmesine yardımcı olur. Bu şekilde, aslında bir alanda bulunmayan bir nesnenin, 0.0 kordonu veya bir bölgedeki en son olduğu zaman sahip olduğu kodları döndürmekten daha mantıklı bir pozisyonu bile yoktur.
Koordinatları artık nesnede tutmazsanız, object.getX () yerine level.getX (object) olur. Bununla ilgili sorun, seviyedeki nesneye bakmak muhtemelen yavaş bir işlem olacaktır, çünkü tüm nesnelerine bakmak ve sorgunuzla eşleşmek zorunda kalır.
Bundan kaçınmak için muhtemelen özel bir 'link' sınıfı oluşturacağım. Bir seviye ve bir nesne arasında bağlanan. Ben buna "Yer" diyorum. Bu, xyz koordinatlarını, aynı zamanda seviyenin tanıtıcısını ve nesnenin tanıtıcısını içerir. Bu link sınıfı, spacial yapı / seviyede depolanacak ve nesnenin kendisine zayıf bir referansı olacaktır (eğer seviye / konum tahrip edilmişse, refrence öğesinin null olarak güncellenmesi gereken nesneler. Nesne 'kendi', eğer bir seviye silinirse, özel indeks yapısı, içerdiği yerler ve Nesneleri de öyle.
typedef std::tuple<Level, Object, PositionXYZ> Location;
Şimdi konum bilgisi sadece bir yerde saklanır. Nesne, Spacial endeksleme yapısı, oluşturucu vb. Arasında çoğaltılmaz.
Octrees gibi geniş veri yapılarının çoğu zaman depoladıkları nesnelerin koordinatlarına sahip olmaları gerekmez. Buradaki konum, yapının içindeki düğümlerin göreceli konumunda depolanır (hızlı arama süreleri için doğruluktan ödün veren bir tür benzer kayıplı sıkıştırma olarak düşünülebilir). Octree'deki konum nesnesi ile sorgu yapıldıktan sonra gerçek koordinatlar içinde bulunur.
Veya nesne konumlarınızı yönetmek için bir fizik motoru kullanıyorsanız ya da ikisi arasındaki bir karışımı kullanıyorsanız, Konum sınıfı tüm kodunuzu bir yerde tutarken şeffaf bir şekilde kullanmalıdır.
Diğer bir avantaj, şimdi seviyenin pozisyonu ve referansı aynı yerde depolanır. Object.TeleportTo (other_object) öğesini uygulayabilir ve düzeyler arasında çalışmasını sağlayabilirsiniz. Benzer şekilde AI yolu bulma, farklı bir bölgedeki bir şeyi takip edebilir.
İşleme ile ilgili olarak. Renderiniz, Konum ile benzer bir şekilde bağlanabilir. Dışında orada render özel şeyler olurdu. Muhtemelen bu yapı içinde saklamak için 'Nesne' veya 'Seviye' ihtiyacınız yoktur. Nesne, renk toplama veya üstünde bir hitbar oluşturma gibi bir şey yapmaya çalışıyorsanız veya bunun gibi bir şey yapmayı deniyorsanız faydalı olabilir; aksi takdirde, işleyici yalnızca kafes ve benzeriyle ilgilenir. RenderableStuff bir Mesh olacaktır, ayrıca sınırlayıcı kutulara sahip olabilir.
typedef std::pair<RenderableStuff, PositionXYZ> RenderThing;
renderer.render(level, camera);
renderer: object = level.getVisibleObjects(camera);
level: physics.getObjectsInArea(physics.getCameraFrustrum(camera));
for(object in objects) {
//This could be depth sorted, meshes could be broken up and sorted by material for batch rendering or whatever
rendering_que.addObjectToRender(object);
}
Bunu her karede yapmanız gerekmeyebilir, kameranın gösterdiğinden daha büyük bir alan almanızı sağlayabilirsiniz. Önbellekleyin, sınırlayıcı kutu içeri girip girmediğini görmek için nesne hareketlerini izleyin, kamera hareketini izleyin. Ancak, kıyaslamadan bu tür şeylerle uğraşmaya başlama.
Siz fizik motorunun kendisi de benzer bir soyutlamaya sahip olabilir, çünkü Nesne verilerine de ihtiyaç duymaz, sadece çarpışma ağı ve fizik özellikleri.
Tüm temel nesne verilerinizin içereceği, nesnenin kullandığı ağın adı olacaktır. Oyun motoru daha sonra devam edebilir ve nesne sınıfınıza bir dizi render özel bir şey (renderleme API'nize özel olabilecek, yani DirectX - OpenGL gibi) yüklemeden hangi formatta yüklenirse yükleyin.
Ayrıca farklı bileşenleri ayrı tutar. Bu, fizik motorunuzu değiştirmek gibi şeyleri yapmayı kolaylaştırır, çünkü bu şeyler çoğunlukla tek bir yerde bulunur. Aynı zamanda iç içe geçmeyi çok daha kolaylaştırır. Fizik sorguları gibi şeyleri gerçek sahte nesnelerin kurulumuna gerek kalmadan test edebilirsiniz çünkü ihtiyacınız olan tek şey Konum sınıfıdır. Ayrıca işleri daha kolay hale getirebilirsiniz. Bunları optimize etmek için hangi sınıflar ve tek konumlar üzerinde hangi sorguları yapmanız gerektiğini daha açık bir şekilde ortaya koymaktadır (örneğin, yukarıdaki seviye.getVisibleObject, kamera çok fazla hareket etmediğinde bir şeyleri önbelleğe alabileceğiniz yer olurdu).
m_renderable
. Bu şekilde, mantığınızı daha iyi ayırabilirsiniz. Renderable "arabirimini" aynı zamanda fiziği, AI ve ne de olsa genel nesneler üzerinde zorlamayın. Bundan sonra rendeble'ları ayrı ayrı yönetebilirsiniz. Bir şeyleri daha da fazla çözmek için OpenGL işlev çağrıları üzerinden bir soyutlama katmanına ihtiyacınız var. Bu nedenle, iyi bir motorun, çeşitli cana yakın uygulamalarının içinde herhangi bir GL API çağrısı yapmasını beklemeyin. Mikro cevizde.