Controlling Players and Characters(14)

Controlling Players and Characters(14)

 

The cTextWindow Class
 

To get things rolling, take a look at the following cTextWindow class definition:

#include <stdlib.h>
#include "core_common.h"
#include "core_graphics.h"

typedef 
class  cTextWindow
{
private :
    typedef 
struct  sVertex
    {
        
float  x, y, z;       // coordinates in screen space
         float  rhw;      
        D3DCOLOR diffuse;   
    } *sVertexPtr;

    
#define  WINDOW_FVF  (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

    ID3DXFont*                  m_font;
    IDirect3DVertexBuffer9*     m_vb;   
// vertex buffer for window text    

    
char *           m_text;              // text to display
    D3DCOLOR        m_text_color;        // color to draw text

    
long             m_x_pos, m_y_pos;    // window coordinates
     long             m_width, m_height;   // window dimensions

    
bool             m_draw_target;       // flag to draw bubble pointer

public :
    cTextWindow()
    {
        memset(
this , 0,  sizeof (* this ));

        m_text_color = 0xFFFFFFFF;
    }

    ~cTextWindow()
    {
        free();
    }

    
void  create(ID3DXFont* font)
    {
        free();

        m_font = font;            

        create_vertex_buffer(&m_vb, 11, 
sizeof (sVertex), WINDOW_FVF);        
    }

    
void  free()
    {
        release_com(m_vb);
        delete[] m_text;
    }

    
void  set_text(pcstr text, D3DCOLOR text_color)
    {
        delete[] m_text;

        m_text = strdup(text);
        m_text_color = text_color;
    }      

    
long  get_height()
    {
        
return  m_height;
    }

    
void  move( long  x_pos,  long  y_pos,  long  width,  long  height,
              
long  target_x,  long  target_y,
              D3DCOLOR back_color, D3DCOLOR outline_color);

    
void  render(pcstr text, D3DCOLOR text_color);
} *cTextWindowPtr;

Remember that the text window uses a vertex buffer to contain a
couple of rectangles (with two triangles defined per rectangle). The vertex buffer uses
only transformed vertices that are assigned a diffuse color (white for the larger rectangle
in the back and your color of choice for the smaller rectangle in the front). Each
vertex is stored within the preceding sVertex structure
(and matching vertex descriptor).

 

cTextWindow::move


The biggest of the bunch, cTextWindow::Move has the job of constructing the vertex buffer
used to render the window (and supporting pointer, if needed). The function takes
as arguments the position to place the window (screen coordinates), the dimensions
(in pixels), a pair of coordinates at which to point the text-bubble pointer, and a
color to use for the smaller frontmost window.

void  cTextWindow::move( long  x_pos,  long  y_pos,  long  width,  long  height,
                       
long  target_x,  long  target_y,
                       D3DCOLOR back_color, D3DCOLOR outline_color)
{
    m_x_pos = x_pos;
    m_y_pos = y_pos;
    m_width = width;

    
// calculate height if needed
     if ((m_height = height) == 0)
    {
        RECT rect;

        rect.left   = x_pos;
        rect.top    = 0;
        rect.right  = x_pos + width - 12;
        rect.bottom = 1;

        
int  text_height = m_font->DrawText(NULL, m_text, -1, &rect, DT_CALCRECT | DT_WORDBREAK, 0xFFFFFFFF);
        m_height = text_height + 12;
    }

    sVertex verts[11];

    
// initialize vertex data
     for ( long  i = 0; i < 11; i++)
    {
        verts[i].z       = 0.0f;
        verts[i].rhw     = 1.0f;
        verts[i].diffuse = outline_color;
    }

    
// setup outline

    verts[0].x = (
float ) m_x_pos;
    verts[0].y = (
float ) m_y_pos;

    verts[1].x = (
float ) (m_x_pos + m_width);
    verts[1].y = (
float ) m_y_pos;

    verts[2].x = (
float ) m_x_pos;
    verts[2].y = (
float ) m_y_pos + m_height;

    verts[3].x = (
float ) (m_x_pos + m_width);
    verts[3].y = (
float ) (m_y_pos + m_height);

    
// setup text window

    verts[4].x       = (
float ) m_x_pos + 2.0f;
    verts[4].y       = (
float ) m_y_pos + 2.0f;
    verts[4].diffuse = back_color;

    verts[5].x       = (
float ) m_x_pos + m_width - 2.0f;
    verts[5].y       = (
float ) m_y_pos + 2.0f;
    verts[5].diffuse = back_color;

    verts[6].x       = (
float ) m_x_pos + 2.0f;
    verts[6].y       = (
float ) m_y_pos + m_height + 2.0f;
    verts[6].diffuse = back_color;

    verts[7].x       = (
float ) m_x_pos + m_width - 2.0f;
    verts[7].y       = (
float ) m_y_pos + m_height - 2.0f;
    verts[7].diffuse = back_color;

    
// setup the target position
     if (target_x != -1 && target_y != -1)
    {
        m_draw_target = 
true ;

        
if (target_y < m_y_pos)
        {
            verts[8].x = (
float ) target_x;
            verts[8].y = (
float ) target_y;

            verts[9].x = (
float ) (m_x_pos + m_width/2 + 10);
            verts[9].y = (
float ) m_y_pos;

            verts[10].x = (
float ) (m_x_pos + m_width/2 - 10);
            verts[10].y = (
float ) m_y_pos;
        }
        
else
        {
            verts[8].x = (
float ) (m_x_pos + m_width/2 - 10);
            verts[8].y = (
float ) (m_y_pos + m_height);

            verts[9].x = (
float ) (m_x_pos + m_width/2 + 10);
            verts[9].y = (
float ) (m_y_pos + m_height);

            verts[10].x = (
float ) target_x;
            verts[10].y = (
float ) target_y;
        }
    }
    
else
        m_draw_target = 
false ;

    fill_in_vertex_buffer(m_vb, 0, 11, &verts);
}   

Using the previously stored position and dimensions, the windows are constructed
as shown in Figure 16.7.

Controlling Players and Characters(14)_第1张图片

 

cTextWindow::render

Render merely sets the required rendering states and
draws the required polygons that form the pointer and text window. Then it draws
the text string (if the window height is greater than 12, which is the size of the
border used to surround the smaller frontmost window).

void  cTextWindow::render(pcstr text, D3DCOLOR text_color)
{
    
if (m_font == NULL)
        
return ;

    g_d3d_device->SetTexture(0, NULL);
    disable_zbuffer();

    render_vertex_buffer(m_vb, 0, 2, D3DPT_TRIANGLESTRIP);
    render_vertex_buffer(m_vb, 4, 2, D3DPT_TRIANGLESTRIP);

    
if (m_draw_target)
        render_vertex_buffer(m_vb, 8, 1, D3DPT_TRIANGLELIST);

    
if (m_height > 12)
    {
        
if (text == NULL)
            draw_font(m_font, m_text, m_x_pos+6, m_y_pos+6, m_width-12, m_height-12, m_text_color, DT_WORDBREAK);
        
else
            draw_font(m_font, text, m_x_pos+6, m_y_pos+6, m_width-12, m_height-12, text_color, DT_WORDBREAK);
    }
}

Render takes two optional arguments. The first argument, Text, overrides the class’s
text that was already set using the SetText function. Overriding the text to draw is
great for dynamically updating what needs to be shown. The second argument,
Color, specifies the color you want to use to draw the text to the display.


你可能感兴趣的:(Controlling Players and Characters(14))