Archived

This topic is now archived and is closed to further replies.

User Interface

This topic is 5107 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''m making an FPS and I''m looking for the best way to display things such as the health of the player and the chat box etc. For things such as the chat box, health, and ammo, I''m thinking of using bitmaps or something similar. For the chat messages and fps and the score screen, I have no idea what to use. I don''t know how to display any 2D objects to the user, as I am using Direct3D 9.0, and if anyone has comments about how they do their user interface, I would appreciate seeing their replies. Thanks, Joshua Merchant

Share this post


Link to post
Share on other sites
You might want to try using textured quads to represent 2D stuff. i.e. set up rectangles that are unaffected by transformation or lighting stages, apply your bitmap to them and render away. This also allows you to use cool stuff like alpha transparency etc. Plus it''s faster than using DirectDraw (I think)

Share this post


Link to post
Share on other sites
I''m pretty sure he''s not using Direct Draw because he''s making a FPS .

Anyway, textured quads are the way to go. There are a few really good 2D D3D tutorials on this site, and most of them could be converted to OGL too (for which it probably already exists specific 2D tutorials).

Share this post


Link to post
Share on other sites
Yup, good ol'' texture quads are the best. I''m doing something similar and here''s my code (CBitmap class):


class CBitmap
{
public:
int m_x, m_y;
D3DCOLOR m_ColorKey;
bool m_AlwaysSolid;
LPDIRECT3DVERTEXBUFFER9 m_VB;
int m_Width, m_Height;
LPDIRECT3DTEXTURE9 m_Texture;
string m_strFileName;
bool m_bInitialized;
void Init();
public:
CBitmap();
CBitmap(char* strFileName);
CBitmap(char* strFileName, D3DCOLOR ColorKey);
CBitmap(char* strFileName, D3DCOLOR ColorKey, int x, int y);
~CBitmap();
void LoadNewFile(char* strFileName);
void Render();
void ReloadVerts();
};


using namespace std;
LPDIRECT3D9 extern g_pD3D;
LPDIRECT3DDEVICE9 extern g_pd3dDevice;
int extern DEVICEWIDTH;
int extern DEVICEHEIGHT;
int g_DeviceWidth = DEVICEWIDTH;
int g_DeviceHeight = DEVICEHEIGHT;

struct BITMAPVERTEX
{
D3DXVECTOR4 position;
FLOAT tu, tv;
};
#define D3DFVF_BITMAPVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)

CBitmap::CBitmap()
{
m_VB = NULL;
m_Texture = NULL;
m_Width = m_Height = m_x = m_y = m_ColorKey = m_AlwaysSolid = NULL;
m_strFileName = "";
}
CBitmap::CBitmap(char* strFileName)
{
m_VB = NULL;
m_Texture = NULL;
m_Width = m_Height = m_x = m_y = m_ColorKey = m_AlwaysSolid = NULL;
m_strFileName = strFileName;
}
CBitmap::CBitmap(char* strFileName, D3DCOLOR ColorKey)
{
m_VB = NULL;
m_Texture = NULL;
m_Width = m_Height = m_x = m_y = m_AlwaysSolid = NULL;
m_ColorKey = ColorKey;
m_strFileName = strFileName;
}
CBitmap::CBitmap(char* strFileName, D3DCOLOR ColorKey, int x, int y)
{
m_VB = NULL;
m_Texture = NULL;
m_Width = m_Height = m_AlwaysSolid = NULL;
m_x = x;
m_y = y;
m_ColorKey = ColorKey;
m_strFileName = strFileName;
}
CBitmap::~CBitmap()
{
SAFE_RELEASE(m_Texture);
SAFE_RELEASE(m_VB);
SAFE_RELEASE(m_Texture);
}
void CBitmap::Init()
{
HBITMAP hBitmap;
BITMAP Bitmap;
hBitmap = (HBITMAP)LoadImage(NULL, m_strFileName.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if(hBitmap == NULL)
{
return;
}
GetObject(hBitmap, sizeof(BITMAP), &Bitmap);
DeleteObject(hBitmap);
m_Width = Bitmap.bmWidth;
m_Height = Bitmap.bmHeight;
SAFE_RELEASE(m_Texture);
D3DXCreateTextureFromFileEx(g_pd3dDevice, m_strFileName.c_str(), m_Width, m_Height, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, m_ColorKey, NULL, NULL, &m_Texture);
if(m_Texture == NULL)
{
return;
}
SAFE_RELEASE(m_VB)
g_pd3dDevice->CreateVertexBuffer( 4*sizeof(BITMAPVERTEX), 0, D3DFVF_BITMAPVERTEX, D3DPOOL_MANAGED, &m_VB, NULL );
BITMAPVERTEX* pVertices;
m_VB->Lock( 0, 0, (void**)&pVertices, 0 );
pVertices[0].position = D3DXVECTOR4((float)(m_x), (float)(m_y), 0.0f, 1.0f);
pVertices[1].position = D3DXVECTOR4((float)(m_x + m_Width), (float)(m_y) , 0.0f, 1.0f);
pVertices[2].position = D3DXVECTOR4((float)(m_x), (float)(m_y + m_Height), 0.0f, 1.0f);
pVertices[3].position = D3DXVECTOR4((float)(m_x + m_Width), (float)(m_y + m_Height), 0.0f, 1.0f);
pVertices[0].tu = 0.0f;
pVertices[0].tv = 0.0f;
pVertices[1].tu = 1.0f;
pVertices[1].tv = 0.0f;
pVertices[2].tu = 0.0f;
pVertices[2].tv = 1.0f;
pVertices[3].tu = 1.0f;
pVertices[3].tv = 1.0f;
m_VB->Unlock();
m_bInitialized = true;
}
void CBitmap::Render()
{
if(!m_bInitialized)
{
Init();
}
DWORD prevfill;
g_pd3dDevice->GetRenderState( D3DRS_FILLMODE, &prevfill );
g_pd3dDevice->SetStreamSource( 0, m_VB, 0, sizeof(BITMAPVERTEX) );
g_pd3dDevice->SetFVF( D3DFVF_BITMAPVERTEX );
g_pd3dDevice->SetTexture(0, m_Texture);
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
if(m_AlwaysSolid)
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, prevfill );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, 4 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, 2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, 2 );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, 2 );
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}
void CBitmap::ReloadVerts()
{
if(!m_bInitialized)
return;
BITMAPVERTEX* pVertices;
m_VB->Lock( 0, 0, (void**)&pVertices, 0 );
pVertices[0].position = D3DXVECTOR4((float)(m_x), (float)(m_y), 0.0f, 1.0f);
pVertices[1].position = D3DXVECTOR4((float)(m_x + m_Width), (float)(m_y) , 0.0f, 1.0f);
pVertices[2].position = D3DXVECTOR4((float)(m_x), (float)(m_y + m_Height), 0.0f, 1.0f);
pVertices[3].position = D3DXVECTOR4((float)(m_x + m_Width), (float)(m_y + m_Height), 0.0f, 1.0f);
pVertices[0].tu = 0.0f;
pVertices[0].tv = 0.0f;
pVertices[1].tu = 1.0f;
pVertices[1].tv = 0.0f;
pVertices[2].tu = 0.0f;
pVertices[2].tv = 1.0f;
pVertices[3].tu = 1.0f;
pVertices[3].tv = 1.0f;
m_VB->Unlock();
}


Of course, if you''re using a lot of them, however, you should make the VB global, and write all of the bitmaps too it and not have a bunch of VBs and all...
Anyway, I used that class for displaying the gun at the bottom of the screen, the health, the inventory (when it''s displayed), as well as splash screens, etc.

Share this post


Link to post
Share on other sites
I would say to use the DirectX SDK''s built-in sprite and font classes. I''m not sure if they''re still included in DirectX 9, but the classes are:

LPD3DXSPRITE (ID3DXSprite) for drawing bitmaps
LPD3DXFONT (ID3DXFont) for drawing text

All you need to have to draw a bitmap is the texture, and all you need to draw text is the appropriate LOGFONT structure and a RECT to give a drawing rectangle.

Share this post


Link to post
Share on other sites
I''ve looked around this site and found articles on textured quads for 2d, and I''ve decided that I want to use those for my UI. I couldn''t find any tutorials showing doing text on textured quads, and I ask you where I would find a good one. I personally thought of an idea to do text- having a bitmap for each character, and then printing those ontop of the other "background" quads, but I think that this would be too framerate costly, as some things (like the numbers on the health indicator and the ingame timer) change quickly every frame; the built in font was too static, and I''d like to be able to have lots of control over my text. So I ask again, where can I find a tutorial on printing out text in D3D?

Thanks,
Joshua Merchant


EDIT:: Just in case that post was confusing, basically I want to know how to display text in D3D9 without using the built-in ID3DXFONT class. Is this possible? If so, where can I find a tutorial on how to do this?

[edited by - jtmerchant on December 17, 2003 10:11:36 PM]

Share this post


Link to post
Share on other sites
The way i do my interface rendering is as follows.

Render everything in the scene.
Disable the zbuffer.
Set the projection and view matrices to the identity matrix to setup a homogenous projection.
render some flat things (the top left of the screen is -1, 1, the center is 0,0 and the bottom right is 1, -1).
done.

Share this post


Link to post
Share on other sites
At the moment I have one texture that has the entire alphabet on it. When I want to create a text object I copy each letter I need from that texture to a new texture and render the entire word at once. It''s probably not the best way, but it''s all I could come up with so far.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Similar to cynicalpenguin, I write the entire alphabet to a texture during initialization. But when I draw the text, I lock the VB, and then for each character, I add 4 vertices, with the appropriate texture coordinates (which could be looked up from an array also created during initialization), until my VB is full. I unlock it, draw it, and then lock and continue adding more characters. I do this until the entire string has been rendered. If I''m not mistaken, I believe this is how DirectX''s font class works, and I can''t think of a faster method myself for dynamic text. Either way, unless you''re drawing massive amounts of text per frame, or working on a very old computer, drawing even one whole screenful of average sized text shouldn''t be a large issue. The only limitation is that it is harder to deal with formating text nicely. You''d need another texture for every different font face or style.

Share this post


Link to post
Share on other sites