Şahsen draw fonksiyonunu Object sınıfının dışında tutmanızı tavsiye ederim. Hatta Nesnelerin konumunu / koordinatlarını Nesnenin kendisinden uzak tutmanızı öneririm.
Bu draw () yöntemi, OpenGL, OpenGL ES, Direct3D, bu API'lardaki sarma katmanınız veya bir motor API'sı gibi düşük düzeyli oluşturma API'sı ile ilgilenecektir. O zaman (örneğin OpenGL + OpenGL ES + Direct3D'yi desteklemek istiyorsanız) arasında geçiş yapmanız gerekebilir.
Bu GameObject, Mesh gibi görsel görünümüyle ilgili temel bilgileri veya gölgelendirici girdileri, animasyon durumu vb.Dahil olmak üzere daha büyük bir paket içermelidir.
Ayrıca esnek bir grafik boru hattı isteyeceksiniz. Nesneleri kameraya olan mesafelerine göre sipariş etmek isterseniz ne olur? Veya malzeme türleri. 'Seçili' bir nesneyi farklı bir renk çizmek isterseniz ne olur? Bir nesne üzerinde bir çizim işlevi çağırırken gerçekte soo yapmak yerine, işlemenin gerçekleştirilmesi için eylemlerin bir komut listesine koyarsa (iş parçacığı için gerekli olabilir) ne olur? Bu tür bir şeyi diğer sistemle yapabilirsiniz ama bu bir PITA.
Önerdiğim doğrudan çizim yapmak yerine, istediğiniz tüm nesneleri başka bir veri yapısına bağlarsınız. Bu bağlamanın gerçekten nesnelerin konumuna ve oluşturma bilgilerine referans olması gerekir.
Seviyeleriniz / parçalarınız / alanlarınız / haritalarınız / hub'larınız / tüm dünya / bir uzaysal indeks ne olursa olsun, bu nesneleri içerir ve bunları koordinat sorgularına dayalı olarak döndürür ve basit bir liste veya bir Octree gibi bir şey olabilir. Ayrıca, bir fizik sahnesi olarak 3. taraf bir fizik motoru tarafından uygulanan bir şey için bir sarıcı olabilir. "Kamera görünümündeki tüm nesneleri etraflarında fazladan bir alanla sorgula" veya her şeyi listenin tamamını kaplayabileceğiniz daha basit oyunlar için yapmanızı sağlar.
Özel Dizinlerin gerçek konumlandırma bilgilerini içermesi gerekmez. Nesneleri ağaç yapılarında diğer nesnelerin konumuna göre depolayarak çalışırlar. Bir nesnenin konumuna göre hızlı bir şekilde aranmasına izin veren bir tür kayıplı önbellek olarak düşünülebilirler. Gerçek X, Y, Z koordinatlarınızı çoğaltmanıza gerek yoktur. Tutmak istersen yapabileceğini söyledi
Aslında oyun nesnelerinizin kendi konum bilgilerini içermesi bile gerekmez. Örneğin, bir düzeye yerleştirilmemiş bir nesnenin x, y, z koordinatları olmamalı, bu hiç mantıklı değil. Bunu özel dizine ekleyebilirsiniz. Gerçek referansına göre nesnenin koordinatlarına bakmanız gerekiyorsa, nesne ile sahne grafiği arasında bir bağ kurmak istersiniz (sahne grafikleri, nesneleri koordinatlara göre döndürmek içindir, ancak nesnelere dayalı koordinatları döndürmede yavaştır) .
Seviyeye bir Nesne eklediğinizde. Aşağıdakileri yapacaktır:
1) Konum Yapısı Oluşturun:
class Location {
float x, y, z; // Or a special Coordinates class, or a vec3 or whatever.
SpacialIndex& spacialIndex; // Note this could be the area/level/map/whatever here
};
Bu aynı zamanda üçüncü taraf fizik motorlarındaki bir nesneye referans olabilir. Veya başka bir konuma referansla ofset koordinatları olabilir (bir izleme kamerası veya ekli bir nesne veya örnek için). Polimorfizmde, statik veya dinamik bir nesne olmasına bağlı olabilir. Koordinatlar güncellendiğinde burada uzaysal dizine bir referans tutarak uzaysal dizin de olabilir.
Dinamik bellek ayırma konusunda endişeleriniz varsa bir bellek havuzu kullanın.
2) Nesneniz, konumu ve sahne grafiği arasında bir bağlama / bağlantı.
typedef std::pair<Object, Location> SpacialBinding.
3) Bağlama, seviyenin içindeki boşluk indeksine uygun noktada eklenir.
Oluşturmaya hazırlanırken.
1) Kamerayı al (Sadece başka bir nesne olacak, ancak konumu oyuncuların karakterini izleyecek ve oluşturucunun özel bir referansı olacak, aslında hepsi gerçekten gerekli).
2) Kameranın SpacialBinding özelliğini edinin.
3) Boşluk dizinini ciltlemeden alın.
4) Kamera tarafından görülebilen (muhtemelen) nesneleri sorgulayın.
5A) Görsel bilgilerin işlenmesi gerekir. GPU'ya yüklenen dokular vb. Bu en iyi şekilde önceden (seviye yükünde olduğu gibi) yapılabilir, ancak belki de çalışma zamanında yapılabilir (açık bir dünya için, bir parçaya yaklaştığınızda bir şeyler yükleyebilirsiniz, ancak yine de önceden yapılması gerekir).
5B) İsteğe bağlı olarak önbelleğe alınmış bir oluşturma ağacı oluşturun, derinlik / malzeme sıralaması yapmak veya yakındaki nesneleri takip etmek istiyorsanız, daha sonra görülebilir. Aksi takdirde, oyun / performans gereksinimlerinize bağlı olacağı her zaman boşluk dizinini sorgulayabilirsiniz.
Oluşturucunuz büyük olasılıkla Nesne, koordinatlar arasında bağlantı kuracak bir RenderBinding nesnesine ihtiyaç duyacaktır.
class RenderBinding {
Object& object;
RenderInformation& renderInfo;
Location& location // This could just be a coordinates class.
}
Sonra render, sadece liste üzerinden çalıştırın.
Yukarıda referanslar kullandım ama akıllı işaretçiler, ham işaretçiler, nesne tutamakları vb.
DÜZENLE:
class Game {
weak_ptr<Camera> camera;
Level level1;
void init() {
Camera camera(75.0_deg, 1.025_ratio, 1000_meters);
auto template_player = loadObject("Player.json")
auto player = level1.addObject(move(player), Position(1.0, 2.0, 3.0));
level1.addObject(move(camera), getRelativePosition(player));
auto template_bad_guy = loadObject("BadGuy.json")
level1.addObject(template_bad_guy, {10, 10, 20});
level1.addObject(template_bad_guy, {10, 30, 20});
level1.addObject(move(template_bad_guy), {50, 30, 20});
}
void render() {
camera->getFrustrum();
auto level = camera->getLocation()->getLevel();
auto object = level.getVisible(camera);
for(object : objects) {
render(objects);
}
}
void render(Object& object) {
auto ri = object.getRenderInfo();
renderVBO(ri.getVBO());
}
Object loadObject(string file) {
Object object;
// Load file from disk and set the properties
// Upload mesh data, textures to GPU. Load shaders whatever.
object.setHitPoints(// values from file);
object.setRenderInfo(// data from 3D api);
}
}
class Level {
Octree octree;
vector<ObjectPtr> objects;
// NOTE: If your level is mesh based there might also be a BSP here. Or a hightmap for an openworld
// There could also be a physics scene here.
ObjectPtr addObject(Object&& object, Position& pos) {
Location location(pos, level, object);
objects.emplace_back(object);
object->setLocation(location)
return octree.addObject(location);
}
vector<Object> getVisible(Camera& camera) {
auto f = camera.getFtrustrum();
return octree.getObjectsInFrustrum(f);
}
void updatePosition(LocationPtr l) {
octree->updatePosition(l);
}
}
class Octree {
OctreeNode root_node;
ObjectPtr add(Location&& object) {
return root_node.add(location);
}
vector<ObjectPtr> getObjectsInRadius(const vec3& position, const float& radius) { // pass to root_node };
vector<ObjectPtr> getObjectsinFrustrum(const FrustrumShape frustrum;) {//...}
void updatePosition(LocationPtr* l) {
// Walk up from l.octree_node until you reach the new place
// Check if objects are colliding
// l.object.CollidedWith(other)
}
}
class Object {
Location location;
RenderInfo render_info;
Properties object_props;
Position getPosition() { return getLocation().position; }
Location getLocation() { return location; }
void collidedWith(ObjectPtr other) {
// if other.isPickup() && object.needs(other.pickupType()) pick it up, play sound whatever
}
}
class Location {
Position position;
LevelPtr level;
ObjectPtr object;
OctreeNote octree_node;
setPosition(Position position) {
position = position;
level.updatePosition(this);
}
}
class Position {
vec3 coordinates;
vec3 rotation;
}
class RenderInfo {
AnimationState anim;
}
class RenderInfo_OpenGL : public RenderInfo {
GLuint vbo_object;
GLuint texture_object;
GLuint shader_object;
}
class Camera: public Object {
Degrees fov;
Ratio aspect;
Meters draw_distance;
Frustrum getFrustrum() {
// Use above to make a skewed frustum box
}
}
İşleri birbirinden 'haberdar' hale getirmek için. Bu çarpışma tespiti. Muhtemelen Octree'de uygulanacaktır. Ana nesnenizde bir geri arama sağlamanız gerekir. Bu şey en iyi Bullet gibi uygun bir fizik motoru tarafından ele alınır. Bu durumda Octree yerine PhysicsScene ve Position yerine CollisionMesh.getPosition () gibi bir bağlantı ekleyin.