2D游戏中可定制的玩家头像

时间:2008-12-31 08:29:36

标签: java 3d 2d

如何在我的游戏中使用该功能,玩家可以通过该功能改变他们的发型,外观,衣服样式等等,因此每当他们穿着不同的衣服时,他们的化身就会随之更新。

我应该:

  • 让我的设计师创造所有可能的盔甲,发型和面部组合作为精灵(这可能是很多工作)。

  • 当玩家在游戏介绍过程中选择他们应该看起来的样子时,我的代码会自动创建这个精灵,以及头盔/护甲与该精灵的所有可能组合。然后每当他们选择一些不同的护甲时,就会加载该护甲/外观组合的精灵。

  • 是否可以将角色的精灵分为几个部分,如脸部,衬衫,牛仔裤,鞋子,并具有每个部分的像素尺寸。然后,每当玩家改变他的头盔时,我们使用像素尺寸将头盔图像放在其脸部图像通常所在的位置。 (我正在使用Java来构建这个游戏)

  • 这在2D中是不可能的,我应该使用3D吗?

  • 还有其他方法吗?

请指教。

5 个答案:

答案 0 :(得分:2)

要考虑的一个主要因素是动画。如果角色有带肩垫的盔甲,那些肩垫可能需要与他的躯干一起移动。同样地,如果他穿着靴子,那些必须遵循与裸脚一样的周期。

基本上,您的设计师需要的是Sprite Sheet,让您的艺术家可以看到基本角色的所有可能的动画帧。然后让他们根据这些床单创建自定义发型,靴子,盔甲等。是的,它做了很多工作,但在大多数情况下,元素需要少量的重绘;靴子是我唯一可以看到的,因为他们改变了多个动画帧,所以我需要做很多工作来重新创建。尽管如此,请尽可能减少所需数量。

在您积累了元素库后,您可以开始作弊。回收相同的发型并在Photoshop中或直接在角色创建者中使用滑块的游戏中调整其颜色。

为了确保游戏中的良好性能,最后一步是将所有不同元素的精灵表拼接成单个精灵表,然后将其拆分并存储在精灵缓冲区中。

答案 1 :(得分: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())。

答案 2 :(得分:1)

我选择procedural generation解决方案(#2)。只要不产生限制量的精灵,就会产生太长时间。也许在获得每个项目时进行生成,以降低负载。

答案 3 :(得分: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的纹理。纹理管理器的相关部分就是这些。纹理管理器实际上通过检查颜色读取是否为纯白色(RGB(ff,ff,ff))来模拟alpha通道 - loadFile代码以每像素24位BMP文件的速度运行:

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;          
}

这实际上是我在业余时间偶尔开发的一个小型Jump'nRun。它使用了gluOrtho2D()模式,顺便说一句。如果您留下与您联系的方式,我会根据您的需要将来源发送给您。

答案 4 :(得分:0)

较早的2D游戏,如暗黑破坏神和Ultima Online使用精灵合成技术来做到这一点。您可以从那些较旧的2D等距游戏中搜索艺术品,看看他们是如何做到的。