我有很多不同的课程。但是,它们都保证具有某些方法,例如render()和activate()。
我的目标是能够将它们全部存储在一个大清单中。目前我有一个名为Container的大类,我做这样的事情来存储我拥有的许多对象。
class Container{
public:
BUTTON * buttons;
int buttons_len;
DRAW_AREA * draw_areas;
int draw_areas_len;
Container(){
// constructor
}
void render(){
for( int i = 0; i < buttons_len; i++ )
buttons[i].render();
for( int i = 0; i < draw_areas_len; i++ )
draw_areas[i].render();
}
};
这个问题是,每次我想添加一个新的数据类型时,我都要修改多个区域,将来会变得难以处理。这是一个很好的方法吗?
我已经研究过使用模板,从我看到的,我不能在同一个列表中存储具有不同“模板变量”的类。
编辑:忘了提到渲染函数可以是不同的渲染函数。
编辑2:
我得到了我想要的工作。不确定“好代码”有多好,
以下是一个例子:
// abstract class
class Base{
public:
virtual void render() = 0;
};
class Button : public Base{
public:
int y;
Button(){
y = 10;
}
void render(){
std::cout << "BUTTONS " << y << "\n";
}
};
class Draw_Area : public Base{
public:
int x;
Draw_Area(){
x = 5;
}
void render(){
std::cout << "DRAW AREA " << x << "\n";
}
void extra(){
std::cout << "extra draw_area\n" << x << "\n";
}
};
int main( int argc, char * * argv ){
Base * test_1 = new Button();
test_1->render();
Base * test_2 = new Draw_Area();
test_2->render();
Base * * test = new Base*[4];
test[0] = new Button();
test[1] = new Button();
test[2] = new Draw_Area();
test[3] = new Button();
test[0]->render();
test[1]->render();
test[2]->render();
test[3]->render();
return 0;
}
感谢您的帮助!我必须处理的主要两个问题是创建一个抽象类来避免对象切片,并将指针存储到类而不是列表中的对象本身。
答案 0 :(得分:-1)
我有一个使用现代OpenGL的Game-Shader Engine。该项目有许多组件集成在一起。使用的一件事是一系列Manager Class
对象,它们本身都是Singleton对象:
我无法向您展示完整的类,但我将展示包含所有派生单例类型的Singleton基类的枚举:
class Singleton {
public:
// Number Of Items In Enum Type Must Match The Number
// Of Items And Order Of Items Stored In s_aSingletons
enum SingletonType {
TYPE_LOGGER = 0, // MUST BE FIRST!
TYPE_SETTINGS,
TYPE_ENGINE,
TYPE_ANIMATION_MANAGER,
TYPE_SHADER_MANAGER,
TYPE_ASSET_STORAGE,
TYPE_AUDIO_MANAGER,
TYPE_FONT_MANAGER,
TYPE_BATCH_MANAGER,
}; // Type;
// More code below
}; // Singleton
这些是我们在应用程序或游戏的生命周期中只需要一个实例的对象。
现在关于你的例子和问题,上面列表中与你想要达到的目标相关的重要性是:
我们可以忽略其他人,因为我们并不担心Audio
,Fonts
,Animations
,Game Settings
,The Main Game Engine
和{{ 1}}虽然它们是通过上面列出的一些对象使用的。
上面的3以这样的方式集成,即Logger
类将保存要呈现的所有对象的容器。 AssetStorage
还包含其他重要的东西,如加载的纹理,字体,音频文件,gui控件精灵,模型等。AssetStorage
类的目的是它充当负责的数据库用于管理这些对象的所有内存。
发送要呈现的所有顶点数据是AssetStorage
的责任,这是基于优先级队列的工作,其中优先级队列由哪个BatchManager's
最充分或具有{ {1}}该优先级基于Batch
。当highest priority
准备发送顶点数据(如属性和制服,矩阵等)时,它会查看Z-Depth
以查看要应用于准备渲染顶点的Shader技术,然后它设置了属性和制服。
这是一只非常复杂的野兽;这也不是唯一的方法,因为有其他方法,特别是当你开始渲染3D Terrains并且你必须构建一个场景图,BSP,体素,行进立方体等。
如果您想了解有关上述技术的更多信息,可以访问Marek Knows并关注他的OpenGL视频教程系列。然而,上面描述的方法正在使用Modern OpenGL,你必须遵循他早期使用Deprecated - Legacy OpenGL 1.0的系列,因为他就是如何设置他的网站。
我能做的是向您展示BatchManager
标题文件中的一小段摘录,以便您可以看到此类&#34;商店&#34;的容器和方法。和&#34;管理&#34;游戏对象的记忆或者#34;资产&#34;。
<强> AssetStorage.h 强>
ShaderManager
我还可以向您展示Asset Storage's
&amp;的声明。 #ifndef ASSET_STORAGE_H
#define ASSET_STORAGE_H
#include "Singleton.h"
#include "CommonStructs.h"
namespace vmk {
class BaseMko;
class GuiElement;
enum GuiType;
struct Texture {
bool hasAlphaChannel;
bool generateMipMap;
bool wrapRepeat;
unsigned uWidth;
unsigned uHeight;
TextureInfo::FilterQuality filterQuality;
std::vector<unsigned char> vPixelData;
Texture( TextureInfo::FilterQuality filterQualityIn, bool generateMipMapIn, bool wrapRepeatIn ) :
hasAlphaChannel( false ),
generateMipMap( generateMipMapIn ),
wrapRepeat( wrapRepeatIn ),
uWidth( 0 ),
uHeight( 0 ),
filterQuality( filterQualityIn )
{}
}; // Texture
class AssetStorage sealed : public Singleton {
private:
typedef std::unordered_map<std::string, std::shared_ptr<BaseMko>> MapMkoAssets;
typedef std::unordered_map<std::string, TextureInfo> MapTextureInfos;
typedef std::unordered_map<std::string, std::shared_ptr<GuiElement>> MapGuiAssets;
MapMkoAssets m_mkoAssets;
MapTextureInfos m_textureInfos;
MapGuiAssets m_guiScreenAssets;
MapGuiAssets m_guiRenderableAssets;
std::vector<std::string> m_vGuiForRemoval;
public:
AssetStorage();
virtual ~AssetStorage();
static AssetStorage* const get();
// Mko Objects
BaseMko* getMko( const std::string& strId ) const;
void add( BaseMko* pMko );
bool removeMko( const std::string& strId, bool removeTexture = false );
void showLoadedMkoObjects() const;
// Texture Objects
TextureInfo getTextureInfo( const std::string& strFilename ) const;
TextureInfo add( const Texture& texture, const std::string& strFilename );
bool removeTextureInfo( const std::string& strFilename );
bool removeTextureInfo( unsigned uTextureId );
void showLoadedTextureInfo() const;
// Gui Objects
GuiElement* getGuiElement( const std::string& strId, GuiType type ) const;
void add( GuiElement* pGui, GuiType type );
bool removeGuiElement( const std::string& strId, bool removeTextures = false );
template<typename T>
bool removeGuiElement( T* pGui, bool removeTextures = false );
void markGuiForRemoval( const std::string& strId );
void cleanOrphanedGuiObjects();
void showLoadedGuiObjects() const;
private:
AssetStorage( const AssetStorage& c ); // Not Implemented
AssetStorage& operator=( const AssetStorage& c ); // Not Implemented
// Gui Objects
GuiElement* getGuiElement( const std::string& strId, const MapGuiAssets& guiMap ) const;
void add( GuiElement* pGui, MapGuiAssets& guiMap );
bool removeGuiElement( const std::string& strId, MapGuiAssets& guiMap, bool removeTextures );
}; // AssetStorage
} // namespace vmk
#endif // ASSET_STORAGE_H
个类,但我无法向您展示 实施 。
<强> BatchManager.h 强>
BatchManager
<强> ShaderManager.h 强>
ShaderManager
正如您所看到的,这是一个非常复杂的对象系统,您提出的问题是一个非常广泛的问题,可以根据您的需要以多种方式完成。我刚刚提出这个问题,以展示一个人如何实现这一目标的概念。
与上面的代码片段一样,您可以看到#ifndef BATCH_MANAGER_H
#define BATCH_MANAGER_H
#include "Singleton.h"
#include "CommonStructs.h"
namespace vmk {
class Batch;
class BatchManager sealed : public Singleton {
private:
std::vector<std::shared_ptr<Batch>> m_vBatches;
unsigned m_uNumBatches;
unsigned m_uMaxNumVerticesPerBatch;
public:
BatchManager( unsigned uNumBatches, unsigned uNumVerticesPerBatch );
virtual ~BatchManager();
static BatchManager* const get();
void render( const std::vector<GuiVertex>& vVertices, const BatchConfig& config, const std::string& strId );
void emptyAll();
private:
BatchManager( const BatchManager& c ); // Not Implemented
BatchManager& operator=( const BatchManager& c ); // Not Implemented
void emptyBatch( bool emptyAll, Batch* pBatchToEmpty );
//void renderBatch( const std::vector<GuiVertex>& vVertices, const BatchConfig& confg );
}; // BatchManager
} // namespace vmk
#endif // BATCH_MANAGER_H
类中的不同类型的容器,然后当您查看#ifndef SHADER_MANAGER_H
#define SHADER_MANAGER_H
#include "Singleton.h"
#include "ShaderProgramSettings.h"
namespace vmk {
class ShaderManager sealed : public Singleton {
private:
// Number Of Items In enum type Must Match The Number Of Items
// Stored In s_aShaders And In InfoProgram::aShaderIndex
enum ShaderType {
TYPE_VERTEX = 0,
TYPE_FRAGMENT,
}; // ShaderType
struct AttributeVariable{
unsigned uLocation;
AttributeType eType;
int iSize;
AttributeVariable( AttributeType eTypeIn, unsigned uLocationIn );
}; // AttributeVariable
struct UniformVariable{
unsigned uLocation;
UniformType eType;
UniformVariable( UniformType eTypeIn, unsigned uLocationIn );
}; // UniformVariable
typedef std::unordered_map<Attribute, AttributeVariable> MapAttributes;
typedef std::unordered_map<Uniform, UniformVariable> MapUniforms;
struct InfoProgram{
unsigned uId;
std::array<unsigned, 2> aShaderIndex;
MapAttributes mAttributes;
MapUniforms mUniforms;
InfoProgram();
}; // InfoProgram
struct InfoShader{
unsigned uId;
std::string strFilename;
InfoShader( int iOpenglSharedId, std::string strShaderFilename );
}; // InfoShader
typedef std::shared_ptr<InfoProgram> SharedInfoProgram;
typedef std::shared_ptr<InfoShader> SharedInfoShader;
typedef std::vector<SharedInfoProgram> VectorInfoPrograms;
typedef std::vector<SharedInfoShader> VectorInfoShaders;
VectorInfoPrograms m_vPrograms;
std::array<VectorInfoShaders, 2> m_avShaders;
Program m_eEnabledShaderProgram;
unsigned m_uActiveTextureNumber;
public:
ShaderManager();
virtual ~ShaderManager();
static ShaderManager* const get();
void create( ShaderProgramSettings& shaderProgramSettings );
void enable( Program eShaderProgram );
void enableAttribute( Attribute eShaderAttribute, unsigned strideBytes = 0, unsigned offsetBytes = 0, bool normalize = false ) const;
void disableAttribute( Attribute eShaderAttribute ) const;
void setAttribute( Attribute eShaderAttribute, const glm::vec4& v4Value ) const;
void setUniform( Uniform eShaderUniform, const glm::mat4& m4Matrix ) const;
void setUniform( Uniform eShaderUniform, const float fValue ) const;
void setUniform( Uniform eShaderUniform, unsigned uValue ) const;
void setUniform( Uniform eShaderUniform, bool bValue ) const;
void setTexture( unsigned uTextureNumber, Uniform eSamplerUniform, int iTextureId );
private:
ShaderManager( const ShaderManager& c ); // Not Implemented
ShaderManager& operator=( const ShaderManager& c ); // Not Implemented
unsigned initializeShader( ShaderType eType, const std::string& strShaderFilename );
void processAttributes( unsigned uInfoProgramId, Program eShaderProgram, std::vector<ShaderProgramSettings::AttributeInfo>& vAttributes, MapAttributes& mAttributes ) const;
void processUniforms( unsigned uInforProgramId, Program eShaderProgram, std::vector<ShaderProgramSettings::UniformInfo>& vUniforms, MapUniforms& mUniforms ) const;
template<typename T>
void setVertexAttribute( Attribute eShaderAttribute, const T* const pParam, bool bEnable, unsigned strideBytes, unsigned offsetBytes, bool normalize ) const;
void setVertexAttribute( AttributeVariable attrib, const void* const pVoid, bool bEnable, unsigned strideBytes, unsigned offsetBytes, bool normalize ) const;
void setVertexAttribute( AttributeVariable attrib, const float* p4Values, bool _x1_, unsigned _x2_, unsigned _x3_, bool _x4_ ) const;
}; // ShaderManager
#include "ShaderManager.inl"
} // namespace vmk
#endif // SHADER_MANAGER_H
类时,您可以看到原型的函数来渲染由AssetStorage
和BatchManager
以及render()
完成的顶点。
尝试拥有每一个&#34;对象&#34;是完全不明智的。有自己的&#34;渲染&#34;功能。每个对象只需要担心它的emptyBatch()
。 emptyAll()
应该由Attributes & Properties
负责使用这些类来了解何时最有效和时间通过GameEngine
渲染所述顶点然后应用适当的着色或颜色技术。
答案 1 :(得分:-2)
如果每个类都有一个render()
函数,而你想用一个命令调用所有这些函数,那么你可以这样做。
class outer
{
public:
outer(); // Constructor.
render();
private:
other_class1 in_class1;
other_class2 in_class2;
};
outer::render()
{
in_class1.render();
in_class2.render();
// For all other member classes.
}
然后,您可以调用外部类outer.render()
的render函数,该函数调用所有成员类的render()
函数。