2008-12-31 84 views
3

我如何在我的遊戲中擁有該功能,玩家可以通過該功能改變他們的髮型,外觀,服裝風格等,並且每當他們穿着不同的服裝頭像時用它更新。2D遊戲中的可自定義球員頭像

我應該:

  • 有我的設計師創造的鎧甲,髮型所有可能的組合,並面臨着與小精靈(這可能是大量的工作)。

  • 當玩家在遊戲介紹中選擇他們應該看起來的樣子時,我的代碼會自動創建這個精靈,並且所有可能的頭盔/盔甲與該精靈的組合。然後每次他們選擇一些不同的裝甲時,加載該裝甲/外觀組合的精靈。

  • 是否有可能將角色的精靈分成組件,如臉部,襯衫,牛仔褲,鞋子,並且每個組件都有像素尺寸。然後,例如,當玩家更換他的頭盔時,我們使用像素尺寸將頭盔圖像放置在其通常的臉部圖像的位置。 (我使用Java來構建這個遊戲)

  • 這在2D中是不可能的,我應該使用3D來做到這一點?

  • 其他方法?

請指教。

回答

1

3D沒有必要爲這一點,但畫家算法是常見的3D世界可能恕我直言,爲您節省一些工作:

畫家算法通過先繪製最遠處的物體,然後使用對象透支靠近相機。在你的情況下,它會生成你的精靈的緩衝區,將其繪製到緩衝區,找到下一個依賴的精靈部分(即裝甲或什麼),繪製,找到下一個依賴精靈部分(即特殊這是裝甲上的標誌),等等。當沒有更多的依賴部分時,將完整生成的精靈繪製到用戶所看到的顯示中。

組合部分應該有一個alpha通道(RGBA而不是RGB),這樣你只能將alpha值設置爲你選擇的值的部分組合起來。如果你無論如何都不能這麼做,只需堅持一種RGB組合,你會認爲它是透明的。

使用3D可能使您更容易組合部分,而且您甚至不必使用屏幕外緩衝區或寫入像素組合代碼。另一方面,如果你不知道它,你需要學習一點3D。 :-)

編輯回答評論:

的結合部會有些這樣的工作(在C++,Java將是非常相似的 - 請注意,我並沒有通過編譯運行下面的代碼) :

// 
// @param dependant_textures is a vector of textures where 
// texture n+1 depends on texture n. 
// @param combimed_tex is the output of all textures combined 
void Sprite::combineTextures (vector<Texture> const& dependant_textures, 
           Texture& combined_tex) { 
    vector<Texture>::iterator iter = dependant_textures.begin(); 
    combined_tex = *iter; 

    if (dependant_textures.size() > 1) 
    for (iter++; iter != dependant_textures.end(); iter++) { 
     Texture& current_tex = *iter; 

     // Go through each pixel, painting: 
     for (unsigned char pixel_index = 0; 
      pixel_index < current_tex.numPixels(); pixel_index++) { 
      // Assuming that Texture had a method to export the raw pixel data 
      // as an array of chars - to illustrate, check Alpha value: 
      int const BYTESPERPIXEL = 4; // RGBA 
      if (!current_tex.getRawData()[pixel_index * BYTESPERPIXEL + 3]) 
       for (int copied_bytes = 0; copied_bytes < 3; copied_bytes++) 
       { 
       int index = pixel_index * BYTESPERPIXEL + copied_bytes; 
       combined_tex.getRawData()[index] = 
        current_tex.getRawData()[index]; 
       }    
     } 
    } 
} 

要回答你的3D解決方案的問題,你會簡單地劃各自的紋理矩形(這將有alpha通道)超過對方。您可以將系統設置爲以正交模式顯示(對於OpenGL:gluOrtho2D())。

+0

謝謝。你能告訴我在2D中做什麼的方法(如果有的話),以及是否可以將3D僅用於玩家精靈,其餘的用2D? – 2008-12-31 08:55:21

+0

對於結合3D和2D:這當然是可能的,但比它的價值更大的破壞力。不過,在正交模式下使用3D框架本質上是2D的。 – mstrobl 2008-12-31 09:31:25

+0

非常感謝:)。上面給出的用於組合2D和3D的代碼(即3D用於字符和2D用於其他所有內容),還是用2D來完成所有代碼? 謝謝aain! – 2008-12-31 09:40:15

1

我想用procedural generation解決方案(#2)。只要不會產生有限的精靈數量,這樣就會產生太長的時間。也許是在獲得每個物品時進行生成,以降低負載。

2

要考慮的一個主要因素是動畫。如果角色有護肩護甲,那麼肩膊可能需要隨着他的軀幹移動。同樣,如果他穿着靴子,那麼他們必須遵循與赤腳一樣的週期。

基本上,您的設計師需要的是Sprite Sheet,它可以讓您的藝術家爲您的基本角色看到所有可能的動畫幀。然後讓他們根據這些牀單製作定製的髮型,靴子,盔甲等。是的,它有很多工作,但在大多數情況下,這些元素將需要最少量的重繪;靴子是我能看到的唯一一件事情,因爲它們改變了多個動畫幀,所以真的需要大量工作來重新創建。儘管如此,儘可能地減少所需的數量。

在您積累了元素庫後,您可能會開始作弊。回收相同的髮型,並在Photoshop中或使用角色創建器中的滑塊直接在遊戲中調整其顏色。

爲確保遊戲性能良好,最後一步是將所有不同元素的精靈表平鋪到一個精靈表中,然後將其分割並存儲在精靈緩衝區中。

0

由於我在評論中被要求提供3D方式,以下是一些,這是我前段時間寫的一些代碼的摘錄。它是OpenGL和C++。

每個精靈都會被要求自己繪製。使用適配器模式,我會組合精靈 - 也就是說,將會有精靈會持有兩個或更多精靈,它們具有(0,0)相對位置,一個精靈具有包含所有這些「子」精靈的真實位置。

void Sprite::display (void) const 
{ 
    glBindTexture(GL_TEXTURE_2D, tex_id_); 
    Display::drawTranspRect(model_->getPosition().x + draw_dimensions_[0]/2.0f, 
     model_->getPosition().y + draw_dimensions_[1]/2.0f, 
     draw_dimensions_[0]/2.0f, draw_dimensions_[1]/2.0f); 
} 

void Display::drawTranspRect (float x, float y, float x_len, float y_len) 
{ 
    glPushMatrix(); 

    glEnable(GL_BLEND); 
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

    glColor4f(1.0, 1.0, 1.0, 1.0); 

    glBegin(GL_QUADS);   
    glTexCoord2f(0.0f, 0.0f); glVertex3f(x - x_len, y - y_len, Z); 
    glTexCoord2f(1.0f, 0.0f); glVertex3f(x + x_len, y - y_len, Z); 
    glTexCoord2f(1.0f, 1.0f); glVertex3f(x + x_len, y + y_len, Z); 
    glTexCoord2f(0.0f, 1.0f); glVertex3f(x - x_len, y + y_len, Z); 
    glEnd(); 

    glDisable(GL_BLEND); 
    glPopMatrix(); 
} 

tex_id_是標識哪個紋理用於​​OpenGL的整數值。紋理管理器的相關部分就是這些。

TextureManager::texture_id 
TextureManager::createNewTexture (Texture const& tex) { 
    texture_id id; 
    glGenTextures(1, &id); 
    glBindTexture(GL_TEXTURE_2D, id); 

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);  
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  
    glTexImage2D(GL_TEXTURE_2D, 0, 4, tex.width_, tex.height_, 0, 
     GL_BGRA_EXT, GL_UNSIGNED_BYTE, tex.texture_); 

    return id; 
} 

void TextureManager::loadImage (FILE* f, Texture& dest) const { 
    fseek(f, 18, SEEK_SET); 
    signed int compression_method; 
    unsigned int const HEADER_SIZE = 54; 

    fread(&dest.width_, sizeof(unsigned int), 1, f); 
    fread(&dest.height_, sizeof(unsigned int), 1, f); 
    fseek(f, 28, SEEK_SET); 
    fread(&dest.bpp_, sizeof (unsigned short), 1, f); 
    fseek(f, 30, SEEK_SET); 
    fread(&compression_method, sizeof(unsigned int), 1, f); 

    // We add 4 channels, because we will manually set an alpha channel 
    // for the color white. 
    dest.size_ = dest.width_ * dest.height_ * dest.bpp_/8 * 4; 
    dest.texture_ = new unsigned char[dest.size_]; 
    unsigned char* buffer = new unsigned char[3 * dest.size_/4];  

    // Slurp in whole file and replace all white colors with green 
    // values and an alpha value of 0: 
    fseek(f, HEADER_SIZE, SEEK_SET);  
    fread (buffer, sizeof(unsigned char), 3 * dest.size_/4, f); 
    for (unsigned int count = 0; count < dest.width_ * dest.height_; count++) {  
    dest.texture_[0+count*4] = buffer[0+count*3]; 
    dest.texture_[1+count*4] = buffer[1+count*3]; 
    dest.texture_[2+count*4] = buffer[2+count*3]; 
    dest.texture_[3+count*4] = 0xff; 

    if (dest.texture_[0+count*4] == 0xff && 
     dest.texture_[1+count*4] == 0xff && 
     dest.texture_[2+count*4] == 0xff) { 
     dest.texture_[0+count*4] = 0x00; 
     dest.texture_[1+count*4] = 0xff; 
     dest.texture_[2+count*4] = 0x00; 
     dest.texture_[3+count*4] = 0x00; 
     dest.uses_alpha_ = true; 
    }     
    } 
    delete[] buffer;   
} 

:所述的loadFile代碼上每像素BMP文件24位操作 - 紋理管理器實際上通過檢查,以查看是否讀取的顏色爲純白色(的(FF,FF,FF)RGB)仿真alpha通道這實際上是我閒暇時偶爾開發的一個小Jump'nRun。它也使用gluOrtho2D()模式,順便說一句。如果您留下聯繫方式,我會將您的來源發送給您。

0

比如Diablo和Ultima Online等較早的2D遊戲使用sprite合成技術來完成此操作。您可以從那些較舊的2D等距遊戲中搜索藝術品,看看他們是如何做到的。