2011-07-14 88 views
0

我在做一個2D基於圖塊的遊戲,我試圖讓我的磚結構的微小使用位字段和字節在瓦結構中的值:如何定義2D瓦片遊戲的瓦片結構?

struct Tile 
{ 
    // 3 bytes (24 bits) 
BYTE i : 8; // Texture index (0-255) 
BYTE p : 1; // Passable (0-1) 
BYTE x : 7; // Texture x (0-127) 
BYTE y : 7; // Texture y (0-127) 
BYTE v : 1; // Visible (0-1) 
}; 

所以,如果我有一個2D 1024x1024瓦片陣列,然後它只有3mb的內存,當我從HD保存/加載。

但現在我需要動畫瓷磚,所以我需要像額外的數據,

struct Tile 
{ 
#define TILE_NORMAL  0 
#define TILE_ANIMATED 1 
    BYTE tile_type; 

    // 3 bytes (24 bits) 
    BYTE i : 8; // Texture index (0-255) 
BYTE p : 1; // Passable (0-1) 
BYTE x : 7; // Texture x (0-127) 
BYTE y : 7; // Texture y (0-127) 
BYTE v : 1; // Visible (0-1) 

    // For animated tiles 
    BYTE frame; 
    BYTE maxFrame; 
    float frameTime; 
}; 

在每個瓦片,並且由於2D陣列是定義像:

平鋪瓦片[X] [ Y];

即使只有很小比例的圖塊被動畫化,每個圖塊的大小仍將爲10個字節左右。我想存儲一個二維指針數組,然後每個指向一個普通的瓷磚或動畫的,但這將意味着每個指針是4個字節,並指向至少4-10個字節。

+2

你是否爲8MB內存的遊戲男孩編程?你確定這是一個瓶頸嗎? – orlp

+0

那麼gameboy怎麼做呢,我記得口袋妖怪有一些靜態和其他動畫的海量地圖 – Kaije

+0

@Kaije:他們曾經一次只加載一個子集,足以填滿幾個屏幕。此外,只有幾種瓷磚(可能每個瓷磚一個字節),並且地圖也不是那麼大。 IIRC,來自塞爾達鏈接的覺醒的地圖是512x512,整個ROM裝入幾百千字節。 –

回答

-1

你可以讓結構成爲一個聯合?例如(和請原諒任何語法錯誤,我不記得確切的語法):

struct Tile 
{ 
#define TILE_NORMAL  0 
#define TILE_ANIMATED 1 
    BYTE tile_type; 

    // 3 bytes (24 bits) 
    BYTE i : 8; // Texture index (0-255) 
    BYTE p : 1; // Passable (0-1) 
    BYTE v : 1; // Visible (0-1) 
    BYTE x : 7; // Texture x (0-127) 
    BYTE y : 7; // Texture y (0-127) 

    union 
    { 
     struct AnimatedTileData 
     { 
      // For animated tiles 
      BYTE frame; 
      BYTE maxFrame; 
      float frameTime; 
     }; 

     struct NoData 
     { 
     }; 
    }; 
}; 

因此,在這種方式,你有一個額外的字節來表示它是否爲動畫與否。如果它沒有動畫,那麼將使用'NoData',不會增加開銷。如果瓦片是動畫的,那麼將爲動畫相關數據添加6個開銷字節。

+0

但是,聯合將始終佔用最大數據類型的內存,無論是否使用。沒有這個保存。 – bcsanches

+0

Bah!你是對的。我沒有意識到工會以這種方式工作。抱歉。 –

3

如果您想節省內存,請勿將動畫數據存儲在瓷磚本身中。相反,你可以在你的遊戲程序定義一個單獨的結構,如:

struct AnimationSequence 
{ 
    BYTE first; 
    BYTE current; 
    BYTE frames[]; 
    float frametime; 
} 

則你可以定義這樣的一些代表每種類型的瓷磚的數組,動畫,以及它如何動畫。然後,在您的動畫計時器中,循環訪問該陣列,對照屏幕上的圖塊進行檢查,並根據需要重新繪製它們。

爲了節省更多內存,您可能需要考慮的另一件事是而不是在瓦片數據中存儲X/Y座標值。我假設你的X/Y字節代表了瓷磚在屏幕上繪製的位置,或類似的東西。您可以嘗試將座標值附加到遊戲的視圖窗口中的自己的數組中,而不是粘貼到自己的圖塊上,這樣您只需將一個視圖窗口值爲瓦片即可作爲查找列表,以便在繪製它們時到屏幕上,而不是整個地圖的價值。

+0

存儲在tile中的x和y是紋理位置,我有一個大的精靈表,它是1024x1024像素,上面有32x32的平鋪圖像,以獲得紋理「矩形」,我喜歡:rect。left =(tile.x * TILE_WIDTH),rect.right = rect.left + TILE_WIDTH。然後將其繪製到屏幕上。實際的圖塊被兩個for循環定位,使x和y遞增32。 – Kaije

+0

但是,您已經有了tile.index,它告訴你同樣的事情,所以X和Y是多餘的。 (tile.index%32)* 32會給出精靈表中tile的X像素位置,math.floor(tile.index/32)* 32會給你Y像素位置。您可以在繪製時即時計算這些位置(這可能會使處理速度稍慢),或者您可以一次計算這些位置並將它們保存在查找列表數組中。 (假設tile.index代表精靈表中的一個特定的矩形或對象;儘管我沒有看到最大255的可能性,所以我可能是錯的。) –

+0

瓦片索引是紋理索引,我做了說我有一個1024x1024紋理,但實際上它們在數組中很多,所以每個圖塊上的紋理ID是它們用於渲染的紋理,如Draw(紋理[tile.i],&rect); – Kaije