二维图形的使用(1)

------------------------------------------------------------------------------

原文作者:lovedday

原文地址:点击打开链接

------------------------------------------------------------------------------

贴片与地图

二维游戏的核心绘制技术就是所谓的贴片技术(tiling),在进行贴图的过程中,用较小的像素矩形分组(小位图称之为贴片)构造一个较大的场景,贴片的绘制过程称为映射。

如下图所示,左边4个编号的小图像就是贴片,中间一个加了编号的栅格代表了绘制贴片的布局(按编号顺序进行描绘的方式)。对于每个栅格单元,开始绘制编号各自代表的贴片,直到整个场景被绘制完。这个栅格就是地图,当栅格被绘制完成后,便得到右边的图像。

 

在DirectX中使用贴片

渲染小型矩形纹理映射的多边形并不困难,它可以非常完美地表现出贴片。要想实现它,可以通过一个特殊的D3DX对象ID3DXSprite。ID3DXSprite对象惟一的工作就是使用所指定的具体纹理,将矩形多边形绘制到屏幕上。当然,给出的纹理将被包含在贴片中。

来看看DirectX SDK文档提供的ID3DXSprite类的简要信息:

The ID3DXSprite interface provides a set of methods that simplify the process of drawing sprites using Microsoft Direct3D.

ID3DXSprite Members

MethodDescription
ID3DXSprite::BeginPrepares a device for drawing sprites.
ID3DXSprite::DrawAdds a sprite to the list of batched sprites.
ID3DXSprite::EndCalls ID3DXSprite::Flush and restores the device state to how it was before ID3DXSprite::Begin was called.
ID3DXSprite::FlushForces all batched sprites to be submitted to the device. Device states remain as they were after the last call to ID3DXSprite::Begin. The list of batched sprites is then cleared.
ID3DXSprite::GetDeviceRetrieves the device associated with the sprite object.
ID3DXSprite::GetTransformGets the sprite transform.
ID3DXSprite::OnLostDeviceUse this method to release all references to video memory resources and delete all stateblocks. This method should be called whenever a device is lost or before resetting a device.
ID3DXSprite::OnResetDeviceUse this method to re-acquire resources and save initial state.
ID3DXSprite::SetTransformSets the sprite transform.
ID3DXSprite::SetWorldViewLHSets the left-handed world-view transform for a sprite. A call to this method is required before billboarding or sorting sprites.
ID3DXSprite::SetWorldViewRHSets the right-handed world-view transform for a sprite. A call to this method is required before billboarding or sorting sprites.
Remarks

The ID3DXSprite interface is obtained by calling the D3DXCreateSprite function.

The application typically first calls ID3DXSprite::Begin, which allows control over the device render state, alpha blending, and sprite transformation and sorting. Then for each sprite to be displayed, call ID3DXSprite::Draw. ID3DXSprite::Draw can be called repeatedly to store any number of sprites. To display the batched sprites to the device, call ID3DXSprite::End or ID3DXSprite::Flush.

The LPD3DXSPRITE type is defined as a pointer to the ID3DXSprite interface.

typedef interface ID3DXSprite ID3DXSprite;
typedef interface ID3DXSprite *LPD3DXSPRITE;

在Direct3D中使用贴片,首先要实例化一个ID3DXSprite对象,使用D3DXCreateSprite功能函数对它进行初始化。

Creates a sprite object which is associated with a particular device. Sprite objects are used to draw 2D images to the screen.

HRESULT D3DXCreateSprite(
  LPDIRECT3DDEVICE9 pDevice,
  LPD3DXSPRITE * ppSprite
);
Parameters
pDevice
[in] Pointer to an IDirect3DDevice9 interface, the device to be associated with the sprite.
ppSprite
[out] Address of a pointer to an ID3DXSprite interface. This interface allows the user to access sprite functions.
Return Values

If the function succeeds, the return value is S_OK. If the function fails, the return value can be one of the following: D3DERR_INVALIDCALL, E_OUTOFMEMORY.

Remarks

This interface can be used to draw two dimensional images in screen space of the associated device.

绘制贴片可以调用ID3DXSprite::Draw函数。

Adds a sprite to the list of batched sprites.

HRESULT Draw(
  LPDIRECT3DTEXTURE9 pTexture,
  CONST RECT * pSrcRect,
  CONST D3DXVECTOR3 * pCenter,
  CONST D3DXVECTOR3 * pPosition,
  D3DCOLOR Color
);
Parameters
pTexture
[in] Pointer to an IDirect3DTexture9 interface that represents the sprite texture.
pSrcRect
[in] Pointer to a RECT structure that indicates the portion of the source texture to use for the sprite. If this parameter is NULL, then the entire source image is used for the sprite.
pCenter
[in] Pointer to a D3DXVECTOR3 vector that identifies the center of the sprite. If this argument is NULL, the point (0,0,0) is used, which is the upper-left corner.
pPosition
[in] Pointer to a D3DXVECTOR3 vector that identifies the position of the sprite. If this argument is NULL, the point (0,0,0) is used, which is the upper-left corner.
Color
[in] D3DCOLOR type. The color and alpha channels are modulated by this value. A value of 0xFFFFFFFF maintains the original source color and alpha data. Use the D3DCOLOR_RGBA macro to help generate this color.
Return Values

If the method succeeds, the return value is S_OK. If the method fails, the return value can be one of the following: D3DERR_INVALIDCALL, D3DXERR_INVALIDDATA.

Remarks

To scale, rotate, or translate a sprite, call ID3DXSprite::SetTransform with a matrix that contains the scale, rotate, and translate (SRT) values, before calling ID3DXSprite::Draw. For information about setting SRT values in a matrix, see Matrix Transforms.

使用Draw函数的技巧就是构造一个源矩形的RECT结构以及贴片纹理的坐标。比如,有一个256 x 256像素大小的纹理,它包含了64个贴片(每个贴片为32 x 32像素大小),排列布置为8行8列,如下图所示:

如果需要对要绘制的贴片进行旋转、缩放、平移等操作,则需要在调用Draw之前调用SetTransform进行设置。

Sets the sprite transform.

HRESULT SetTransform(
  CONST D3DXMATRIX * pTransform
);
Parameters
pTransform
[in] Pointer to a D3DXMATRIX that contains a transform of the sprite from the original world space. Use this transform to scale, rotate, or transform the sprite.
Return Values

If the method succeeds, the return value is S_OK. If the method fails, the following value will be returned.

D3DERR_INVALIDCALL

 

构造处理贴片的类

贴片类的代码以创建游戏内核中编写的游戏内核代码为基础。

来看看TILE类的定义:

//=========================================================================================
// This class encapsulate 2D graphics tile draw.
//=========================================================================================
typedef  class  TILE
{
private :
    GRAPHICS_PTR    _graphics;          
// parent graphics
        
    
long             _num_textures;       // number of textures
    TEXTURE_PTR     _textures;           // TEXTURE array

    
long *           _tile_widths;        // tile width array
     long *           _tile_heights;       // tile height array
     long *           _tile_columns;       // number of tile columns in texture

public :
    TILE();
    ~TILE();

    
// functions to create and free the tile interface
    BOOL create(GRAPHICS_PTR graphics,  long  num_textures);
    
void  free();

    
// functions to load and free a single texture
    
    BOOL load_texture(
long  texture_index,  const   char * texture_filename,
                      
short  tile_width = 0,  short  tile_height = 0,
                      D3DCOLOR transparent = 0,
                      D3DFORMAT format = D3DFMT_A1R5G5B5);

    
void  free_texture( long  texture_index);

    
// functions to retrieve tile dimensions and number of tiles in a texture
     long  get_tile_width( long  texture_index);
    
long  get_tile_height( long  texture_index);
    
long  get_tile_number( long  texture_index);

    
// enable or disable transparent blitting
    BOOL set_transparent(BOOL enabled = TRUE);

    
// draw a single tile at specified location
    BOOL draw_tile( long  texture_index,  long  tile_index,
                   
long  screen_x,  long  screen_y,
                   D3DCOLOR color = 0xFFFFFFFF,
                   
float  x_scale = 1.0f,  float  y_scale = 1.0f);
} *TILE_PTR;


构造函数初始化数据,析构函数释放已分配的内存:
 

//----------------------------------------------------------------------------------
// Constructor, zero member data.
//----------------------------------------------------------------------------------
TILE::TILE()
{
    memset(
this , 0,  sizeof (* this ));
}

//----------------------------------------------------------------------------------
// Destructor, free allocated resource.
//----------------------------------------------------------------------------------
TILE::~TILE()
{
    free();
}

//----------------------------------------------------------------------------------
// Free allocated resource.
//----------------------------------------------------------------------------------
void  TILE::free()
{
    _graphics = NULL;

    
// free all tetxures
     if (_num_textures)
    {
        
for ( short  i = 0; i < _num_textures; i++)
            _textures[i].free();
    }

    delete[] _textures;
    _textures = NULL;
    
    
// free width, height, and column arrays.
    delete[] _tile_widths;
    delete[] _tile_heights;
    delete[] _tile_columns;

    _tile_widths = _tile_heights = _tile_columns = NULL;

    _num_textures = 0;
}


create函数分配TEXTURE对象数组以便在其中存储贴片,请确保给该函数传递一个预先初始化好的GRAPHICS对象。
 

//----------------------------------------------------------------------------------
// Allocate memory.
//----------------------------------------------------------------------------------
BOOL TILE::create(GRAPHICS_PTR graphics,  long  num_textures)
{
    
// free in case of existing data
    free();

    
// error checking
     if ((_graphics = graphics) == NULL)
        
return  FALSE;

    
if ((_num_textures = num_textures) == 0)
        
return  FALSE;

    
// allocate texture objects
     if ((_textures =  new  TEXTURE[_num_textures]) == NULL)
        
return  FALSE;

    
// allocate width, height, and column count arrays
    _tile_widths  =  new   long [_num_textures];
    _tile_heights = 
new   long [_num_textures];
    _tile_columns = 
new   long [_num_textures];

    
return  TRUE;
}


load_texture负责将一个纹理加载到指定的纹理数组中。例如,如果创建TILE对象使用了5个纹理,可以指定从0-4的任何元素去加载一个纹 理。所有的纹理都是通过它们在纹理数组中的索引来进行引用的。当加载一个纹理文件时,必须指定存储在纹理上的贴片的大小(以像素计),那些贴片将被装配到 纹理上,从左到右从上到下,第一个贴片从纹理左上角的像素开始。

如果想使用透明位块传送,最后的两个参数将会非常有用。将transparent参数设置为一个有效的D3DCOLOR数值(使用 D3DCOLOR_RGBA或其他类似的宏,请确保使用alpha值255),而且让format保留它的默认设置D3DFMT_A1R5G5B5,或者从Direect3D提供的可用格式列表中指定一个。

//----------------------------------------------------------------------------------
// Load texture from file.
//----------------------------------------------------------------------------------
BOOL TILE::load_texture( long  texture_index,  const   char * texture_filename,
                        
short  tile_width,  short  tile_height, 
                        D3DCOLOR transparent, D3DFORMAT format)
{
    
// error checking
     if (texture_index >= _num_textures || _textures == NULL || texture_filename == NULL)
        
return  FALSE;

    
// free older texture resource
    free_texture(texture_index);

    
// load the texture
     if (! _textures[texture_index].load(_graphics, texture_filename, transparent, format))
        
return  FALSE;

    
// store width value (get width of texture if no tile_width was specified).
     if (tile_width == 0)
        _tile_widths[texture_index] = _textures[texture_index].get_width();
    
else
        _tile_widths[texture_index] = tile_width;

    
// store height value (get height of texture if no tile_height was specified).
     if (tile_height == 0)
        _tile_heights[texture_index] = _textures[texture_index].get_height();
    
else
        _tile_heights[texture_index] = tile_height;

    
// Calculate how many columns of tiles there are in the texture.
    // This is used to speed up calculations when drawing tiles.                                                         
    _tile_columns[texture_index] = _textures[texture_index].get_width() / _tile_widths[texture_index];

    
return  TRUE;
}


释放特定的纹理资源可以调用free_texture函数。
 

//----------------------------------------------------------------------------------
// Free specified texture.
//----------------------------------------------------------------------------------
void  TILE::free_texture( long  texture_index)
{
    
// error checking
     if (texture_index >= _num_textures || _textures == NULL)
        
return ;

    
// free a single texture resource
    _textures[texture_index].free();
}


使用get_tile_width,get_tile_height,get_tile_number来分别获得指定纹理贴片的宽度、高度、贴片总数。
 

//----------------------------------------------------------------------------------
// Return tile width.
//----------------------------------------------------------------------------------
long  TILE::get_tile_width( long  texture_index)
{
    
// error checking
     if (texture_index >= _num_textures || _tile_widths == NULL)
        
return  0;

    
return  _tile_widths[texture_index];
}

//----------------------------------------------------------------------------------
// Return tile height.
//----------------------------------------------------------------------------------
long  TILE::get_tile_height( long  texture_index)
{
    
// error checking
     if (texture_index >= _num_textures || _tile_widths == NULL)
        
return  0;

    
return  _tile_heights[texture_index];
}

//----------------------------------------------------------------------------------
// Return number of tiles.
//----------------------------------------------------------------------------------
long  TILE::get_tile_number( long  texture_index)
{
    
// error checking
     if (texture_index >= _num_textures || _textures == NULL || 
       _tile_columns == NULL || _tile_widths == NULL || _tile_heights == NULL)
    {
       
return  0;
    }

    
return  _tile_columns[texture_index] * (_textures[texture_index].get_height() / _tile_heights[texture_index]);
}


使用set_transparent来启用或禁用alpha测试,这意味着当启动时,被加载的带有适当透明色彩及颜色格式的纹理将使用透明位块传送。默认情况下,enabled被设置为TRUE。
 

//----------------------------------------------------------------------------------
// Enable or disable alpha testing.
//----------------------------------------------------------------------------------
BOOL TILE::set_transparent(BOOL enabled)
{
    
// error checking
     if (_graphics == NULL)
        
return  FALSE;

    
return  _graphics->enable_alpha_testing(enabled);
}


绘制贴片使用draw_tile方法:
 

//----------------------------------------------------------------------------------
// Draw tile.
//----------------------------------------------------------------------------------
BOOL TILE::draw_tile( long  texture_index,  long  tile_index, 
                     
long  screen_x,  long  screen_y, 
                     D3DCOLOR color, 
                     
float  x_scale,  float  y_scale)
{
    
// error checking
     if (_graphics == NULL || _textures == NULL || texture_index >= _num_textures)
        
return  FALSE;

    
// calculate the source tile coordinates from texture
     long  src_x = (tile_index % _tile_columns[texture_index]) * _tile_widths[texture_index];
    
long  src_y = (tile_index / _tile_columns[texture_index]) * _tile_heights[texture_index];

    
return  _textures[texture_index].blit(screen_x ,screen_y, src_x, src_y,
        _tile_widths[texture_index], _tile_heights[texture_index], x_scale, y_scale, color);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值