首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >体素游戏

体素游戏
EN

Code Review用户
提问于 2011-11-30 18:21:05
回答 1查看 403关注 0票数 6

我开始了一个业余爱好项目,这是我在C语言中做的第一件事,目的是让别人看到我。我已经练习了一段时间,但实际上我是个初学者,我还没有用C/C++编写过真正的软件。

我想知道从我的代码中什么是好的,什么是错误的,为什么,如果它是清晰的/可读的,你能告诉我的一切都会很好。我从来没有向任何人展示过我的代码,我也不知道我是否做得很好,或者它不会更糟--后者是我认为最有可能的。所以我想知道有C/C++经验的人的原因,以及你认为我可以改进/删除什么,等等。

这段代码是我刚刚开始的,关于“我的世界”-like游戏中的一个小体素系统。

基本想法是:

  1. 拥有一个体素类型数组
  2. 能够将规则分配给体素类型(例如要调用的函数/脚本)。不知何故?)
  3. 每个体素都有一系列与游戏相关的状态。状态数据主要是照明和能见度值。
  4. 能够根据需要保存和加载状态数据。

等等。我有很多想法,但我仍然很少写一些代码,我想知道其他人的意见在继续之前,所以我可以改进这个项目,而不是必须修复它以后。

这是项目文件的链接(只有一个.h和一个.cpp,刚刚开始)在谷歌代码

下面是.h的一些内容,这样您就可以在不打开链接的情况下给自己一个想法:

代码语言:javascript
复制
typedef struct _GVOXEL_RULE
{
        GVOXELRULE_ID   nRuleID;
        INT32                   nRuleValue; // this value is left for use by the rule function, not needed right now
} GVOXEL_RULE;

// here I'm planning to store the description of the voxel types
typedef struct _GVOXEL_DATA
{
        GVOXEL_TYPE             nVoxelType;     
        dword                   nRuleCount;
        GVOXEL_RULE*    pVoxelRules; // I'm thinking this should be separated to a "voxel rule manager" class or something similar
        dword                   nVoxelCount; // store here the amount of voxels applying this reference (so we stop looking when the limit is reached)
} GVOXEL_DATA;

typedef struct _GVOXEL_STATE_1_0
{
        GVOXEL_ID       nVoxelID;       // This id will be equal to the voxel index which may be handy
        GVOXEL_TYPE     nVoxelType;     // This number will reference the table with voxel descriptions
        word            nMetadata;      // This was described below.
        byte            nLightX;        // This stores how much light (from 0 to 255) is receiving the face pointing to +X 
        byte            nLightXN;       // Same from below but for -X face
        byte            nLightY;        // etc.
        byte            nLightYN;       // etc..
        byte            nLightZ;        // etc...
        byte            nLightZN;       // 
} GVOXEL_STATE_1_0, GVOXEL_STATE;

typedef struct _GVOXELCHUNK_DATA_1_0 // 
{
    volatile long       nRefCount; // <-- This gives me the chills
    dword               nChunkID;           // some chunk ID that makes sense in some other reference table. or not.
    dword               nWidth;             // size of the array in the X dimension
    dword               nHeight;            // size of the array in the Y dimension
    dword               nDepth;             // size of the array in the Z dimension
    GVOXEL_STATE_1_0*   pVoxelStateList;    // The count of voxel states will be nWidth*nHeight*nDepth
    dword               nExtendedDataSize;  // size of optional data, if found in the file, to be loaded to the "pExtendedData" pointer.
    void*               pExtendedData;      // If bExtendedData is 0, this variable should be set to 0 (null).
} GVOXELCHUNK_DATA_1_0, GVOXELCHUNK_DATA;

void gvCreateChunkData10( GVOXELCHUNK_DATA_1_0** ppChunkData );
void gvAcquireChunkData10( GVOXELCHUNK_DATA_1_0* pChunkData );
void gvFreeChunkData10( GVOXELCHUNK_DATA_1_0** ppChunkData );

#define gvCreateChunkData               gvCreateChunkData10 
#define gvFreeChunkData                 gvFreeChunkData10       
#define gvAcquireChunkData              gvAcquireChunkData10

// wchar_t* pFilename: Name of the source file to load chunk data from
// dword *nMaxChunks: if ppChunkData is NULL, the function returns here the number of chunks in the file. else stores the
// GVOXELCHUNK_DATA** ppChunkData: 
INT32 gvLoadChunkFromFileW( wchar_t* pFilename, dword *inout_nMaxChunks, GVOXELCHUNK_DATA** ppChunkData );
//
INT32 gvSaveChunkToFileW( wchar_t* pFilename, dword nChunkCount, GVOXELCHUNK_DATA** ppChunkData );
#ifdef _TODO
INT32 gvLoadChunkFromFileA( char* pFilename, dword nMaxChunks, GVOXELCHUNK_DATA** ppChunkData );
INT32 gvSaveChunkToFileA( char* pFilename, dword nChunkCount, GVOXELCHUNK_DATA** ppChunkData );
#endif

#define gvLoadChunkFromFile     gvLoadChunkFromFileW
#define gvSaveChunkToFile       gvSaveChunkToFileW  
EN

回答 1

Code Review用户

回答已采纳

发布于 2011-12-02 14:46:49

设计

看起来你有一个设计,但是并不是所有的代码都是可见的。不管怎么说,我对你真正想要做的模特儿有些模糊,所以让我们来看看。

  1. 体素实例的三维数组:这是你的实际世界状态,明白了。
  2. nVoxelType .某个类型数组的索引没有显示?好吧,我们显然需要在体素实例和它的类型之间建立某种连接,不管实现方式如何。
  3. 现在,体素类型需要哪些属性?您将显示一系列规则,但尚不清楚它们如何与类型交互。如果你打算每条规则都代表像用镐砍7型的体素,或者烧到3型的体素,我不确定线性数组会把它切掉。

如果你试着画一个游戏事件的草图,它可能有助于澄清一些事情:从坐标到体素实例很容易,但是一旦你有了它,你会对它做些什么呢?

Implementation

您说您可能需要C而不是C++,但是您可以在这两种语言中使用类似的多态性,所以设计交互仍然比选择语言更重要。

例如:C++

代码语言:javascript
复制
class VoxelType
{
public:
    // common interface for all types
    virtual void hitMeWithAPickaxe(Voxel *self) = 0;
    virtual void setFireToMe(Voxel *self) = 0;
};

class DirtVoxelType: public VoxelType
{
public:
    // specific implementation for this type
    void hitMeWithAPickaxe(Voxel *self);
    virtual void setFireToMe(Voxel *self);
};

或用C语:

代码语言:javascript
复制
struct VoxelType {
    int type;
    void (*hitMeWithAPickaxe)(struct Voxel *self);
    void (*setFireToMe)(struct Voxel *self);
};

void hitDirtWithAPickaxe(struct Voxel *);
void setFireToDirt(struct Voxel *);

struct VoxelType VoxelTypeArray[] = {
  { DirtType, hitDirtWithAPickaxe, setFireToDirt },
  ...
};

显然,您也可以使用这两种语言中久经考验的大量切换/用例声明--关键是C或C++的选择不是设计背后的驱动力,而是实现背后的驱动力。

volatile long nRefCount; // <-- This gives me the chills,我不怪你--即使你已经知道你的游戏会被多线程化,我也看不出这有什么用。要么预先设计并发和同步,然后正确地完成它,要么完全忽略它,准备在某个线程确实不够好的情况下稍后再做一些重新设计工作。

风格

以增加主观性的近似顺序

#define gvSaveChunkToFile gvSaveChunkToFileW是怎么回事?这是为了方便一些跨平台的东西以后,还是你只是从其他地方复制它?它是丑陋和潜在的混乱,所以我会删除它,除非它增加了一些真正有价值的东西,我在这里看不到。

同样,对于所有的GVOXEL_STATE_1_0, GVOXEL_STATE内容--除非您真的计划在运行时拥有和处理多个不兼容版本的相同结构(这听起来很可怕),否则您可以将任何向后兼容逻辑隔离到(反)序列化层,并删除主代码中的重复名称。

您正在使用很多(我认为是)特定于平台的类型,以防您在意。也许bytedword等在该平台上是惯用的,所以有很大的一致性好处,但我不清楚它们相对于标准类型(如charint8_tuint8_t )还有什么优势。

主观上,我不太喜欢这里使用的匈牙利符号:您只是在复制类型,而没有添加任何语义信息。

最后,在主观上,我不喜欢ALL_UPPER_CASE类型的名称或_LEADING_UNDERSCORE_UPPER_CASE符号,它们与__RESERVED_NAMES非常接近,看起来很难看。我也不认为需要对每个结构进行类型标注;struct VoxelState *而不是GVOXEL_STATE_1_0 *似乎更清晰、更容易阅读

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/6419

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档