Игры с вокселями


Я начал проект хобби, которое будет первое, что я делаю в C, который предназначен, чтобы быть замеченными кем-то еще. Я тренировался некоторое время, но я на самом деле новичок, я никогда не писал реальные программы на C/C++ и еще.

Я хотел знать, что это нормально с мой код, что не так и почему, если понятно/читаемо, и все, что вы можете рассказать мне об этом было бы прекрасно. Я никогда не показывал мой код никого и я понятия не имею, если я делаю хорошо, или если он не может быть хуже-последнее, что я считаю наиболее вероятным. Поэтому я хотел бы знать причины, от людей с опытом работы с C/C++ и то, что вы считаете, что я могу улучшить/удалить и т. д.

Кода-то я только начал, о небольшой воксельная система для Майнкрафт-как игра.

Основная идея была бы:

  1. иметь различные типы вокселей
  2. чтобы иметь возможность назначать правила, типы вокселей (функции/скрипты называли.. почему-то?)
  3. чтобы иметь массив игры соответствующими государствами для каждого воксела. Данные состояния будут в основном освещение и значения видимости.
  4. чтобы иметь возможность сохранять и загружать данные по мере необходимости

и т. д... у меня много идей, но я до сих пор еле написал некоторый код, и я хотел бы знать чужие мнения, прежде чем продолжить, так что я могу улучшить проект, вместо того, чтобы исправить это позже.

Это ссылка на файлы проекта (только .H и A .cpp, она только началась) на гугл код

И вот некоторые из содержания .ч так что вы можете дать себе идею без открытия ссылки:

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  


446
6
задан 30 ноября 2011 в 06:11 Источник Поделиться
Комментарии
1 ответ

Дизайн

Похоже, у вас есть дизайн в виду, но это не всем видно из публикуемого кода.
Я вообще немного не о том, что ты пытаешься здесь модель, поэтому давайте шаг через него.


  1. 3Д массив экземпляров воксел: это реально твой мир, государство, получил его.

  2. nVoxelType является ... индекс в какой тип массива не показали? Ну, мы явно нужны некоторые связи между конструировании экземпляра и его типа, однако реализован

  3. теперь, какие свойства воксельного типа нужны? Вы показываете массив правил, но это не ясно, как они взаимодействуют с этим типом. Если ты думаешь, что в каждом правиле должны представлять собой что-то вроде нажмите воксельного типа 7 с киркой или поджечь воксельного типа 3, я не уверен, что линейный массив будет резать.

Это может прояснить многое, если попытаться рисование игровое событие: переход от координаты вокселя экземпляр легко, но после того, что вы собираетесь делать?

Реализация

Вы говорите, что вы, вероятно, хотите C вместо C++, но вы можете использовать подобный полиморфизм в с небольшим усилием, поэтому при проектировании взаимодействия является еще более важным, чем выбор языка.

Например. В C++

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:

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++ не является движущей силой дизайна, Дизайн является движущей силой реализации.

летучие длинные nRefCount; // <- Это дает мне озноб
Я не виню тебя - даже если вы уже знаете, ваша игра будет многопоточный, я не могу увидеть эту работу. Либо дизайн параллелизма и синхронизации в передней, и сделать это правильно, или опустить его и будьте готовы сделать некоторые ре-дизайн работать позже, если кто-нить не достаточно.

Стиль

В приблизительном порядке возрастания субъективности

Что случилось с #определить gvSaveChunkToFile gvSaveChunkToFileW вещи? Это предназначено, чтобы облегчить некоторые кросс-платформенные вещи позже, или просто скопировать его из других? ИМО это некрасиво и может привести к путанице, поэтому я удалить его, если он добавляет что-то действительно стоящее я не вижу здесь.

Аналогично со всеми GVOXEL_STATE_1_0, GVOXEL_STATE вещи - если вы действительно планируете иметь дело с несколько несовместимых версий одной и той же структуры во время выполнения (что звучит ужасно), вы можете выделить какой-либо обратной совместимости логику (де)сериализации слой и удалить повторяющиеся имена в основном коде.

Вы используете много (как я считаю) от платформы определения типов, в случае, если вы заботитесь. Может, байта, DWORD с и т. д. несколько идиоматических на этой платформе, так что есть большая согласованность пользу, но мне не ясно, какое преимущество они имеют более стандартные виды, как голец, int8_t или uint8_t.

Субъективно я не большой поклонник венгерской нотации здесь: ты просто имитирует тип и не добавив никакой смысловой информации.

И наконец, опять же субъективно, я не люблю ALL_UPPER_CASE введите имена или _LEADING_UNDERSCORE_UPPER_CASE символы, которые они получают в опасной близости к __отведенные_имена и, как правило, выглядят некрасиво.
Я тоже не вижу необходимости typedef для каждой структуры; структуры VoxelState * вместо GVOXEL_STATE_1_0 * кажется четким и легким для чтения

5
ответ дан 2 декабря 2011 в 02:12 Источник Поделиться