Sign in to follow this  
sauronette

Rendering a cute 2D scrolling map inside a window

Recommended Posts

sauronette    122
Hi Everyone, I am a relative noobie to game programming (especially Direct X) and I wanted to ask a couple of specific questions that I am sure some genius here readily knows. I have read alot of the tutorials on creating a 2D tiling engine (non isometric) just 32 x 32px tiling, but I can't figure out a couple of details with the implementation. I want to basically do something very simple at first to learn: Example... 1. Create an array [x][y] and fill it with stuff to represent bitmaps "1111111111111111" "1 2 1" "1 222 1" "11 222 11111111 "11 111111111111" "1111111111111111" 2. Set up a loop to read in all the elements to the array so we can look at individual array elements to see what's in there. 3. Set up Direct X and get ready to Render 4. Here's where I fall down the stairs. I do not understand how you get the cute graphic tiles INSIDE c++ or how you translate the ASCII array into graphics? In the end, I know that you render the scene by writing to the Direct X back buffer and the Blit it, but getting to that point makes me scratch my head. 5. The tutorial "Tile Engine Gold" is a perfect example of what I want to do, but the graphics files and map are in something called ".dat" files, and a ".map" file. So I can't see inside those to really really look at the code and how it's done. Does anyone have a full example of a little piece of code that lets you scroll around a 2d Tiled map in a window? Thanks!

Share this post


Link to post
Share on other sites
TANSTAAFL    1160
Oh, boy.


Well, you seem to at least have something of a clue as far as what you'd like to do, and I'm quite happy you didn't make a "I'd like to make a MMORPG just like Everquest but different!" post as your first post.

RE: #4:

Typically, you'd load a bitmap or bitmaps for your tiles.

You might have multiple tiles on a bitmap, but for now, I'll suggest having one bitmap==one tile.

In DirectX, you would put these bitmaps onto surfaces/textures(depending on your rendering method).

Your tiles can be stored in an array, and the values in your map array would be indices into the array of tiles. Although, since you are using the character ' '(space) for empty, and '1' and '2' for tiles, you may need a translation layer in between to convert the value into an index into your tile array.

As far as scrolling is concerned, the only thing that change is where tile (0,0) is drawn, and rerender.


Share this post


Link to post
Share on other sites
sauronette    122
Hehe, no, I have been working non-stop for about 3 months doing this. It is way too complex to think about mastering something like that just starting out. I can't even get a bitmap on the screen yet.

But I do wish to get the bare bones help in getting to the point where I have a window that has a map inside it and I can design a big map and move a character around it (2D) I want an excuse to create cute potions and treasure in photoshop and scroll around with it (This means layers... i know i know.. later) I will settle for a floor tile and a wall for now. Maybe just a floor :)


I would actually use something like this..

"11111111111111"
"1.....3333...1"
"1.....3333...1"
"1..11111111111"


So, correct me if I am wrong, but here are the steps...

1. Define the Char for the array and read in the data to the array
map [x][y]

2. Load a bitmap image (I am assuming just using C stuff, like fopen?
and associate this bitmap with a variable? (This code is where I
need help)

3. Write some code that says... if 1, then use grass bitmap, if 3 use
wall bitmap, and so on... (need help here too)

4. Then write some code that makes Direct X write this array stuffed
full o' bitmaps to the surface. (need help here too)

[Edited by - sauronette on March 15, 2006 6:57:10 PM]

Share this post


Link to post
Share on other sites
TANSTAAFL    1160
Okay, let's take a step back and assess:

Thus far, you have established a platform of Windows(implicit with DirectX), and C++ as your language.

Next question: Direct3D or DirectDraw for rendering?

Also, if this is in a window, is DirectX even necessary at all, or would GDI suffice? If DirectDraw was the plan, then SDL becomes an option.

Share this post


Link to post
Share on other sites
sauronette    122
Yes, I am using C++, and Windows, and DirectX 9.0
That entails using Direct3D for rendering. Don't wanna use GDI or DirectDraw.
Here is my code thus far. I have my window nice and spiffy, and have extracted the rendering part into a function called RenderFrame() where I begin the scene, clear the buffer, and then go! go! go!

The biggest issue for me is where do I put the map array, and how does it fit into the game loop? I suppose I put the definition in WinMain.h, and also load the bitmap there also after parsing the array structure, and then do a for loop in the RenderFrame() function to output to the surface?

Here's my code so far...

WINMAIN.cpp

#include "stdafx.h"
#include "WinMain.h"

#define WINDOW_TITLE "Sauronette's spiffy 2D tile map"
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define WINDOWED TRUE

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;
HWND g_hWnd;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_CUNIT ) );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_CUNIT ) );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_EX_TOPMOST, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, GetWindowLong( g_hWnd, GWL_style ), FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}

// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}
TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );

return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 0 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 0 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{
g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 100 ), 1.0f, 0 );
g_pD3DDevice->BeginScene();

// Render the frame

g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}
ValidateRect( hWnd, 0 );
return 0;
case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}
return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}

Share this post


Link to post
Share on other sites
TANSTAAFL    1160
Suggested locations for things:
(look for /*TODO: blah blah*/)

#include "stdafx.h"
#include "WinMain.h"
/*TODO: additional includes*/

#define WINDOW_TITLE "Sauronette's spiffy 2D tile map"
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define WINDOWED TRUE

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;
HWND g_hWnd;
/*TODO: additional variables*/

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_CUNIT ) );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_CUNIT ) );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_EX_TOPMOST, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, GetWindowLong( g_hWnd, GWL_style ), FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}

/*TODO: additional setup*/

// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}
TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );

/*TODO: additional cleanup*/

return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 0 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 0 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{
g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 100 ), 1.0f, 0 );
g_pD3DDevice->BeginScene();

// Render the frame

g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}
ValidateRect( hWnd, 0 );
return 0;
case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}
return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}




Overview of what you need to do:

You are going to need a bitmap or bitmaps.

You are going to need to load this into an IDirect3DTexture9. I suggest doing this through the function D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx. The header for these functions are "D3dx9tex.h", so you'll need to add that to your list of includes.

You will need to set up a vertex type. You'll need to configure the device for that vertex type and set some rendering states and perhaps some texture stage states. You'll need to turn off lighting(I think).

When drawing, you'll need to set up vertices, and draw them.

Yes, it is a lot to do.

Things to add in specific TODO areas:

/*TODO: additional includes*/
An include for D3dx9tex.h

/*TODO: additional variables*/
A custom vertex structure
your map array declaration

/*TODO: additional setup*/
Setting up your map array
Setting up your D3Ddevice's FVF, turning off lighting, and any rendering values for the device
Loading the texture or textures(D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx)

/*TODO: additional cleanup*/
Releasing texture(s), similar to what you are already doing with other Direct3D object.

// Render the frame
selecting the texture(s) you want to draw(SetTexture)
setting up the vertices
drawing the polygons(DrawPrimitiveUP)

Share this post


Link to post
Share on other sites
sauronette    122
Thanks so much for taking the time to look at my code and give me some excellent hints on how to proceed. Being the curious girl that I am it's important for me to understand how and why I am using this. Basically what I am doing is making Direct3D render two triangles that end up being a block/square? and then laying a texture on top of this block.

So logically we have this->

MapArray[x][y] This holds the number of tiles in the map, x,y pointing to
a certain tile at the intersection of this vertex.

But, on some other logical layer, i.e. the vertex buffer, or the place that holds the vertexs.. there will have to be some kind of pointer to this... perhaps another array?

So logically this occurs

MapArray[x][y] points to another place that holds [x+y+, x+y-, x-y-, x-y+)
the four coordinates to draw our box. Once the box is drawn we then put a
texture on top of that.

Perhaps I am looking at this in overkill. Is this basically what is happening? Is it possible that we don't have to draw two triangles at all, but can just go ahead and draw a box? Would that be simpler? I think these questions lead up to how to declare the custom vertex structure and make the map array sync with it.

You guys probably know a much simpler way of looking at it! Lemme know!

Share this post


Link to post
Share on other sites
sauronette    122
Hi there! So far so good. I have almost all the sections completed that you gave me hints for... But my primitive doesn't render. I saw speckled dots at first, and now after more tweeking a black window. (boo hoo) :~( I wanted to set up and render a few simple triangles before tackling the next issue...i.e associating the character array with a bitmap and then associating that with a vertex and then making that blit to the screen.

Does anyone see anything standing out in the code below that would cause rendering to fail... also is there any code in here that is completely non-essential for 2D style tile stuff?


#include "stdafx.h"
#include "WinMain.h"

#define WINDOW_TITLE "Improved DirectX Initialization"
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z;
DWORD color;
};

CUSTOMVERTEX vertices[] =
{
{-10.0f, -10.0f, 10.0f, D3DCOLOR_XRGB( 255, 255, 255 )}, // Bottom left vertex
{ 0.0f, 10.0f, 10.0f, D3DCOLOR_XRGB( 255, 255, 255 )}, // Top vertex
{ 10.0f, 10.0f, 10.0f, D3DCOLOR_XRGB( 255, 255, 255 )} // Bottom right vertex
};


//your map array declaration
char map[12][12] = {
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}};




int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_CUNIT ) );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_CUNIT ) );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_EX_TOPMOST, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, GetWindowLong( g_hWnd, GWL_style ), FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}


/*TODO: additional setup*/
// Setting up your map array
// Setting up your D3Ddevice's FVF, turning off lighting, and any rendering values for the device

// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return 0;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return 0;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();


// Loading the texture or textures(D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx) - DONE
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/tile.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return 0;
}


// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}
TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );

/*TODO: additional cleanup*/
// Releasing texture(s), similar to what you are already doing with other Direct3D object. - DONE
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 0 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 0 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{
g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 100 ), 1.0f, 0 );
g_pD3DDevice->BeginScene();


// Render the frame
// selecting the texture(s) you want to draw(SetTexture)
// setting up the vertices
// drawing the polygons(DrawPrimitiveUP)

g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pD3DDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 1, vertices, sizeof( CUSTOMVERTEX ) );


g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}
ValidateRect( hWnd, 0 );
return 0;
case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}
return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}



[Edited by - sauronette on March 20, 2006 8:15:18 PM]

Share this post


Link to post
Share on other sites
Ratterbox    157
You need to actually change your custom vertex structure to include the rhw, your FVF is D3DFVF_XYZRHW so you should have

struct CUSTOMVERTEX {
float x, y, z, rhw;
DWORD color;
};

so then set all rhw to 1.0f when you define your quads.

Share this post


Link to post
Share on other sites
sauronette    122
yeppie. Tried that already. Used the code from the direct x SDK. Still no triangle for me.



struct CUSTOMVERTEX
{
float x, y, z, rhw;
DWORD color;
};

CUSTOMVERTEX vertices[] =
{
{-10.0f, -10.0f, 10.0f, 1.0f }, // Bottom left vertex
{ 0.0f, 10.0f, 10.0f, 1.0f }, // Top vertex
{ 10.0f, 10.0f, 10.0f, 1.0f } // Bottom right vertex
};

Share this post


Link to post
Share on other sites
Ratterbox    157
Ok, I have tried your code and I have made a version that will show a single textured quad. I had to change some of the initalization stuff just to make it compile because I dont have your WinMain.h file. Also your using SetStreamSource so you should be using DrawPrimitive not DrawPrimitiveUP because that is used of Unprocessed vertices.


//#include "stdafx.h"
#undef UNICODE

#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#define WINDOW_TITLE "Improved DirectX Initialization"
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW | D3DFVF_TEX1

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z, rhw;
float u, v;
};

CUSTOMVERTEX vertices[] =
{
{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
{ 100.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f},
{ 0.0f, 100.0f, 0.0f, 1.0f, 0.0, 1.0f},
{ 100.0f, 100.0f, 0.0f, 1.0f, 1.0f, 1.0f}
};


//your map array declaration
char map[12][12] = {
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL BuildPresentationParameters();
void RenderFrame();

#define SAFE_RELEASE(a) if((a)){(a)->Release();(a)=NULL;}



int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, IDI_WINLOGO);
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance,IDI_WINLOGO );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}


/*TODO: additional setup*/
// Setting up your map array
// Setting up your D3Ddevice's FVF, turning off lighting, and any rendering values for the device

// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice->CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return 0;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return 0;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();


// Loading the texture or textures(D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx) - DONE
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "..\\engine_data\\grass.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return 0;
}


// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}
TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );

/*TODO: additional cleanup*/
// Releasing texture(s), similar to what you are already doing with other Direct3D object. - DONE
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 640 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 480 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{
g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 100 ), 1.0f, 0 );
g_pD3DDevice->BeginScene();


// Render the frame
// selecting the texture(s) you want to draw(SetTexture)
// setting up the vertices
// drawing the polygons(DrawPrimitiveUP)

g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pD3DDevice->SetTexture(0, g_pTexture);
g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);


g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}
ValidateRect( hWnd, 0 );
return 0;
case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}
return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}





If you have MSN then you can add me to your contacts list if you have any more questions. my email is ratterbox@gmail.com

EDIT

PS - also on a side note WS_EX_TOPMOST is an Extended window style so you use it with CreateWindowEx and it would be the first parameter.

[Edited by - Ratterbox on March 17, 2006 10:21:18 PM]

Share this post


Link to post
Share on other sites
sauronette    122
Hey, thanks a bunch. This helps me a bunch. The tile texture loads and a polygon is rendered. The only thing I don't understand is that you said the vertex's you created rendered a quad... but I only see a triangle in the upper left with the texture applied? Should I see a box?

Share this post


Link to post
Share on other sites
Ratterbox    157
yes you should see a quad, or atleast on my system you do. post your exact code again and we can help you. :)

EDIT - Sorry its my mistake. when you create the vertex buffer make sure its 4*sizeof(CUSTOMVERTEX) and not 3. I forgot to change it in my post. Sorry.

Share this post


Link to post
Share on other sites
sauronette    122
Yes, I found this. It works perfectly. Thanks a ton to both you guys for your help. The next thing I need to do is set up world coordinates (which I did with my map char array).

My next question is about where to place the loop to render our players view of the tiles. Do we do it between beginscene() and endscene() or should this tileset view be built inside an arry with all the vertexs and textures and then the whole CUSTOMVERTEX thingy transferred to the Device? I am kinda just talking this out to myself. Please comment if my logic is bad..

I am assuming these next steps:

1. Do a loop to go through the map[x][y] array and test the characters
i.e If it's a "2" then we need the wall texture, if it's a "1" then we need a floor texture.. so there is a texture loop component to the loop.

2. Also in this process I suppose the number of subscripts in the array will be translated to a vertex grid... i.e. map[128][128] will end up with 4 vertexs per array subscript and then will be transferred to the Direct3D device at the appropriate time.

4. One other thing, is that even though we have a big array with our map filled in with vertexs and the appropriate texture, we have a SCREEN VIEW (screen coordinates) in addition to WORLD VIEW (the entire map) Does there have to be a SEPARATE arry for the screen coordinates? or do we do some math on the map itself to derive them? The screen view is actually the part we send to the renderer. The map view is our pool of map data.. screen view is just our window into it. This screen view would then tie into MOVEMENT. After this is written, we hook this up to directinput and arrow keys and voila we have a scolly map.

5. There is a question about how to deal with map boundaries.

If you guys could, just give me hint where the loops should be in the code. Perhaps you could just comment here and there in the code? That would be super quick. Please don't write any code for me. I wanna figure it out by myself. Just need a few hints.

I think after I get this working good, I am going to abstract it into a framework! and use classes and functions for initialization and stuff!

Thanks bunches!



STDAFX.H

#pragma once

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#define SAFE_RELEASE(x) if( x ) { (x)-&gt;Release(); (x) = NULL; }
#define SAFE_DELETE(x) if( x ) { delete(x); (x) = NULL; }
#define SAFE_DELETE_ARRAY(x) if( x ) { delete [] (x); (x) = NULL; }
#define MSG_RETURN(x,s) if (!(x)) { MessageBox( 0, s, 0, 0 ); return FALSE; }
#define RETURN(x) if (!(x)) { return FALSE; }

// Windows Header Files:
#include &lt;windows.h&gt;

// C RunTime Header Files
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;malloc.h&gt;
#include &lt;memory.h&gt;
#include &lt;tchar.h&gt;

// DirectX Header Files
#include &lt;d3d9.h&gt;
#include &lt;d3dx9.h&gt;

/*TODO: additional includes*/
//An include for D3dx9tex.h - DONE
#include &lt;d3dx9tex.h&gt;
#include &lt;d3d9types.h&gt;










WINMAIN.CPP
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW | D3DFVF_TEX1

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z, rhw;
float u, v;
};

CUSTOMVERTEX vertices[] =
{
{ 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f},
{ 32.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f},
{ 0.0f, 32.0f, 0.0f, 1.0f, 0.0, 1.0f},
{ 32.0f, 32.0f, 0.0f, 1.0f, 1.0f, 1.0f}

};


//your map array declaration
char map[12][12] = {
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL BuildPresentationParameters();
void RenderFrame();


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, IDI_WINLOGO);
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance,IDI_WINLOGO );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9-&gt;GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9-&gt;GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9-&gt;CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}


/*TODO: additional setup*/
// Setting up your map array
// Setting up your D3Ddevice's FVF, turning off lighting, and any rendering values for the device

// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice-&gt;CreateVertexBuffer( 4*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return 0;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB-&gt;Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return 0;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB-&gt;Unlock();


// Loading the texture or textures(D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx) - DONE
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/tile.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return 0;
}


// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}

TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );

/*TODO: additional cleanup*/
// Releasing texture(s), similar to what you are already doing with other Direct3D object. - DONE
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9-&gt;CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9-&gt;CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9-&gt;CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 640 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 480 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{
g_pD3DDevice-&gt;Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0 );
g_pD3DDevice-&gt;BeginScene();


// Render the tile
g_pD3DDevice-&gt;SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pD3DDevice-&gt;SetFVF( D3DFVF_CUSTOMVERTEX );
g_pD3DDevice-&gt;SetTexture(0, g_pTexture);
g_pD3DDevice-&gt;DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);


g_pD3DDevice-&gt;EndScene();
g_pD3DDevice-&gt;Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;

case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}

ValidateRect( hWnd, 0 );
return 0;

case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}

return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}





[Edited by - sauronette on March 20, 2006 8:28:45 PM]

Share this post


Link to post
Share on other sites
evillive2    779
please use the
[ source] [ /source]
tags around your source code (no spaces inside the brackets). It will make it much easier for the rest of us to read the thread and help out.

Share this post


Link to post
Share on other sites
TANSTAAFL    1160
Unless something fundamental has changed (and the rest of the fellows here can help with that), the expensive operation is changing the texture, so minimize the number of times you do that by drawing all of the "1"s first, and then the "2"s, only switching textures in between. Other than that, yes, this drawing is all done between the beginscene/endscene.

Share this post


Link to post
Share on other sites
sauronette    122
Thanks evillive for the [ source] tip. Will include it going foward. Thanks TANSTAAFL for the hint on where the code is rendered. One other hint I need is how you tie the correlation of the map contents (the array of 1's 2's, etc) to the texture. Is it simply...

(psuedocode)

if (map[x][y] == "1")
{
then texture = "wall.bmp"
}
else if (map[x][y] == "2")
then texture = "floor.bmp"
}

Would you make another array and store the textures in? or do all of this on the fly. My instinct tells me, that you make a big loop, and based upon the key pressed you make some adjustments to the map coordinates which in turn alters the screen coordinates and then based up that you look through those values in the array, make the vertex calculations and grab the textures and then render the new view based upon which arrow is pressed. Is this logic correct?



Share this post


Link to post
Share on other sites
TANSTAAFL    1160
zeroth suggestion: make your vertex buffer large enough to store the vertices for the entire map. i'm also going to suggest that you (for now, this is not a permanent thing) to go to triangle lists rather than triangle strip. you will then need six vertices for each square (two will have repeats) in your map, and because you have a 12x12 map, you'll need 864 vertices in your VB. (later on, you'll move to using an index buffer as well, reducing the total number of vertices to 13x13 or 169, and you'll wind up with 6 indices per tile instead)

first suggestion: have the image desired for a tile represented by a number, 0 for floor, 1 for wall. make it zero based rather than 1 based as you currently have it.

second suggestion: group vertices by what texture they use, and keep track of which vertex a particular group starts with, how many vertices/polys are in that group, etc. you currently seem to have 100 floor tiles and 44 wall tiles, so have the first 600 vertices in your buffer deal with the floor tiles, and the last 264 vertices in your buffer deal with wall tiles.

third suggestion: have an array of pointers to textures, so that you can simply reference them by the same value in your map (because you will be doing suggestion 1, and the value in the map will correspond to the texture in the array)

Share this post


Link to post
Share on other sites
sauronette    122
Thanks for the suggestions. I have went back and after some welcome to amateur hour multi-hour coding of individual array elements to find out how directX renders vertex data, I have consolidated the vertex data in the CUSTOMVERTEX area and used TriangleList as you suggested. Here is the updated code. I can now render two boxes instead of one! Yay for me. Of course looping this is another matter entirely. Not to mention hooking this up to the map array. For some reason now... my texture is out to lunch when I went over to triangle list.



[source}
#include <stdafx.h>


#undef UNICODE

#define WINDOW_TITLE "Improved DirectX Initialization"
#define WINDOW_WIDTH 1024
#define WINDOW_HEIGHT 768
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW | D3DFVF_TEX1

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z, rhw;
float u, v;
};

CUSTOMVERTEX vertices[] =
{
{ 0.0f, 0.0f, 0.0f },
{ 32.0f, 0.0f, 0.0f },
{ 0.0f, 32.0f, 0.0f },

{ 32.0f, 32.0f, 0.0f },
{ 0.0f, 32.0f, 0.0f },
{ 32.0f, 0.0f, 0.0f },

{ 32.0f, 0.0f, 0.0f },
{ 64.0f, 0.0f, 0.0f },
{ 32.0f, 32.0f, 0.0f },

{ 64.0f, 32.0f, 0.0f },
{ 32.0f, 32.0f, 0.0f },
{ 64.0f, 0.0f, 0.0f }


};

//your map array declaration
char map[12][12] = {
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL BuildPresentationParameters();
void RenderFrame();


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, IDI_WINLOGO);
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance,IDI_WINLOGO );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}


/*TODO: additional setup*/
// Setting up your map array

int ScreenX; // Where are we currently on the screen?
int ScreenY;
int WhereX; // Where are we currently rendering on the map?
int WhereY;


WhereY = 0;
WhereX = 0;
ScreenY = 0;
ScreenX = 0;


// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice->CreateVertexBuffer( 12*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return 0;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return 0;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();


// Loading the texture or textures(D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx) - DONE
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/tile.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return 0;
}


// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}

TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 640 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 480 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{
g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0 );
g_pD3DDevice->BeginScene();

// This mucks with the Texture when used
g_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

// Render the tile
// Setup the Stream Source
g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

// Apply the Texture
//g_pD3DDevice->SetTexture(0, g_pTexture);

// Draw the vertex buffer
g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 4);


g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;

case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}

ValidateRect( hWnd, 0 );
return 0;

case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}

return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}







[Edited by - sauronette on March 22, 2006 6:56:04 PM]

Share this post


Link to post
Share on other sites
MButchers    123
As a side note, an optimization you could do ( if you are doing pure 2D and your map always fills the screen!) is to disable Z comparisons and dont clear the Color Buffer and Depth Buffer by removind the following line

g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0 );

Hope its help

Mark

Share this post


Link to post
Share on other sites
sauronette    122
Yes, this helps also. Thanks. I will file this trick away for later when I spruce up my engine. If anyone has a moment, could they look at the code below. Welcome to amateur hour folks. Basically I am now in the midst of setting up my tile map. I decide to learn first how to make a loop to paint out two triangles to make a square and then how to blit out multiples of these.

The Y loop and storing a big map into an array and then only showing part of it eludes my knuckle dragging intellect at the moment. But this simple way blits out 10 cute tiles.

When I converted over from to TRIANGLE LIST from STRIP I lost my texture. I had a texture shaped like a small square floor tile, but now when I use it it just shows grey. Do i have to make a triangle shaped texture now for these? If so, that's a total pain, and doesn't seem practical.

I am guessing that I am going to apply the texture across two triangles, thereby covering the quad with the texture. Any hints would be great.

Thanks!





STDAFX.H


#pragma once

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers

#define SAFE_RELEASE(x) if( x ) { (x)->Release(); (x) = NULL; }
#define SAFE_DELETE(x) if( x ) { delete(x); (x) = NULL; }
#define SAFE_DELETE_ARRAY(x) if( x ) { delete [] (x); (x) = NULL; }
#define MSG_RETURN(x,s) if (!(x)) { MessageBox( 0, s, 0, 0 ); return FALSE; }
#define RETURN(x) if (!(x)) { return FALSE; }

// Windows Header Files:
#include <windows.h>

// C RunTime Header Files
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

// DirectX Header Files
#include <d3d9.h>
#include <d3dx9.h>

/*TODO: additional includes*/
//An include for D3dx9tex.h - DONE
#include <d3dx9tex.h>
#include <d3d9types.h>
[/source}










WINMAIN.CPP


#include <stdafx.h>


#undef UNICODE

#define WINDOW_TITLE "Improved DirectX Initialization"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW | D3DFVF_TEX1

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z, rhw;
float u, v;
};

CUSTOMVERTEX vertices[60];


//your map array declaration
char map[12][12] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL BuildPresentationParameters();
void RenderFrame();


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, IDI_WINLOGO);
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance,IDI_WINLOGO );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED)
? WS_OVERLAPPEDWINDOW : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}

int mapX = 0; // map X coordinate
int mapY = 0; // map Y coordinate


float x = 0.0; // vertex x coordinate
float y = 0.0; // vertex y coordinate

int e = 0; // array element

// Set up the Map Array
// Our goal is to take our map world coordinates and transform each x/y element
// into 2 triangles (6 vertexes) and store them into the vertex buffer structure
// Next step will be to include the map[x][y] array into this loop and test for
// the ascii contents and then incorporate a texture based upon what we find inside
// the map[x][y] array



for ( mapX = 0; mapX < 10; ) // We need 6 vertex points per quad
{


// TRIANGLE 1 - upper part of quad
// vertex 1
vertices[e].x = x;
vertices[e].y = y;

e++;

// vertex 2
vertices[e].x = x + 32;
vertices[e].y = y;

e++;

// vertex 3
vertices[e].x = x;
vertices[e].y = y + 32;

e++;

// vertex 4
vertices[e].x = x + 32;
vertices[e].y = y + 32;

e++;

// vertex 2
vertices[e].x = x;
vertices[e].y = y + 32;

e++;

// vertex 3
vertices[e].x = x + 32;
vertices[e].y = y;

e++;

x += 32;

mapX += 1;
}




// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice->CreateVertexBuffer( e*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return 0;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return 0;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();


// Loading the texture or textures(D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx) - DONE
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/tile.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return 0;
}


// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}

TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 640 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 480 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{
g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0 );
g_pD3DDevice->BeginScene();

// This mucks with the Texture when used
g_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

// Render the tile
// Setup the Stream Source
g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

// Apply the Texture
//g_pD3DDevice->SetTexture(0, g_pTexture);

// Draw the vertex buffer
g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 20);


g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;

case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}

ValidateRect( hWnd, 0 );
return 0;

case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}

return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}

[/source}


Share this post


Link to post
Share on other sites
sauronette    122
Hello All! Well, I have an update in that I have gotten the first pass of my 2D map rendering loop finished. With this beginning thingy I am able to change some parameters and make it render out a grid of triangles.

The next hint I would like to ask for, is how to set this up to make it put a texture on top of each tile? I have a texture set up in this code, but when I turn it on, it just puts a grey blob across the entire span of triangles. I have a nice beveled floor tile that is 32px x 32px that I would like to put on top of each quad. Can someone show me how?

TANSTAAFL's suggestion above about grouping the tiles based on map value is perfect. I probably need some pseudocode help with declaring the array of pointers to the textures...

Perhaps TANSTAAFL, you mean something like this:

if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/tile.bmp", &g_pTexture ) ) )
{

Use this Interface above and load all the texture based upon an element in an array? i.e:

char textureArray[2];

textureArray[0] = *g_pTexture1 // Pointer to wall tile
textureArray[1] = *g_pTexture2 // Pointer to floor tile

I am guessing that the reason you wanted me to use triangle list instead of strip is that with list we can render triangles not next to each other, and this allows us to separate wall tiles and floor tiles, etc. So, we instead will render in layers.. the floor, the walls, the door, then the potions, the treasure, the player, the monsters, etc.

Onward and upward.






#include <stdafx.h>


#undef UNICODE

#define WINDOW_TITLE "2D Scrolling Engine"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW | D3DFVF_TEX1

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z, rhw;
float u, v;
};

CUSTOMVERTEX vertices[864];


// map array declaration
// A nice cozy room with walls all around except
// for an open door at the bottom left.

char map[12][12] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL BuildPresentationParameters();
void RenderFrame();


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, IDI_WINLOGO);
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance,IDI_WINLOGO );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}

int mapX = 0; // map X coordinate
int mapY = 0; // map Y coordinate


float x = 0.0; // vertex x coordinate
float y = 0.0; // vertex y coordinate

int e = 0; // array element

// Set up the Map Array
// Our goal is to take our map world coordinates and transform each x/y element
// into 2 triangles (6 vertexes) and store them into the vertex buffer structure
// Next step will be to include the map[x][y] array into this loop and test for
// the ascii contents and then incorporate a texture based upon what we find inside
// the map[x][y] array

while ( mapY < 12 )
{

while ( mapX < 12 ) // We need 6 vertex points per quad
{


// TRIANGLE 1 - upper part of quad
// vertex 1
vertices[e].x = x;
vertices[e].y = y;

e++;

// vertex 2
vertices[e].x = x + 32;
vertices[e].y = y;

e++;

// vertex 3
vertices[e].x = x;
vertices[e].y = y + 32;

e++;

// vertex 4
vertices[e].x = x + 32;
vertices[e].y = y + 32;

e++;

// vertex 2
vertices[e].x = x;
vertices[e].y = y + 32;

e++;

// vertex 3
vertices[e].x = x + 32;
vertices[e].y = y;

e++;

x += 32;

mapX += 1;
}

mapY += 1;
mapX = 0;

x = 0;
y += 32;
}


// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice->CreateVertexBuffer( e*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return 0;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return 0;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();


// Loading the texture or textures(D3DXCreateTextureFromFile or D3DXCreateTextureFromFileEx) - DONE
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/tile.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return 0;
}


// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}

TranslateMessage( &msg );
DispatchMessage ( &msg );
}
else
{
RenderFrame();
}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 640 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 480 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{

// Shoot out the lights
g_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

// Toggle this on and off to check on triangle rendering
g_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

// Render the tile
// Setup the Stream Source
g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

// Set Texture
// g_pD3DDevice->SetTexture(0, g_pTexture);


g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0 );
g_pD3DDevice->BeginScene();


// Draw the vertex buffer
g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 288);


g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;

case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}

ValidateRect( hWnd, 0 );
return 0;

case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}

return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}













[Edited by - sauronette on March 24, 2006 3:30:01 PM]

Share this post


Link to post
Share on other sites
sauronette    122
Okay! I have converted over the map rendering loops to utilize the 2D array to test if we are encountering a '1' (wall), or '0' (floor) tile. Upon these decisions I would load a specific texture and then render those textures?

I know I said I didn't want code help, but I am currently at the end of my rope and need a major hint. I can't figure out how to make the 32x32 px texture I created from the file sit upon the two rendered triangles (quad) The texture just covers all the triangles. i am not even sure I am doing this correctly. I am able to render 12 x 12 tiles (864) vertices, but I am wondering how to express the loop more elegantly and add make it render the proper texture per tile?

Thanks everyone...








#include <stdafx.h>


#undef UNICODE

#define WINDOW_TITLE "2D Scrolling Engine - Stacey Yates"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW | D3DFVF_TEX1

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z, rhw, color, u, v;
};

CUSTOMVERTEX vertices[864];


// map array declaration
// A nice cozy room with walls all around except
// for an open door at the bottom left.


int map[12][12] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL BuildPresentationParameters();
void RenderFrame();


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, IDI_WINLOGO);
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance,IDI_WINLOGO );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}



// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}

TranslateMessage( &msg );
DispatchMessage ( &msg );
}

else
{
RenderFrame();

}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 640 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 480 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


return TRUE;
}


// Function to Render the Current Frame
void RenderFrame()
{

int mapX = 0; // map X coordinate
int mapY = 0; // map Y coordinate


float x = 0.0; // vertex x coordinate
float y = 0.0; // vertex y coordinate

int e = 0; // array element

// Set up the Map Array
for ( mapY = 0; mapY < 12; )
{
for ( mapX = 0; mapX < 12; )
{

if ( map[mapX][mapY] == 1 )
{
// texture = wall
// create 2 triangles to form a quad
// render

vertices[e].x = x;
vertices[e].y = y;


e++;

// vertex 2
vertices[e].x = x + 32;
vertices[e].y = y;

e++;

// vertex 3
vertices[e].x = x;
vertices[e].y = y + 32;

e++;

// vertex 4
vertices[e].x = x + 32;
vertices[e].y = y + 32;

e++;

// vertex 2
vertices[e].x = x;
vertices[e].y = y + 32;


e++;

// vertex 3
vertices[e].x = x + 32;
vertices[e].y = y;

e++;

}

if ( map[mapX][mapY] == 0 )
{

// create vertices
// render

vertices[e].x = x;
vertices[e].y = y;

e++;

// vertex 2
vertices[e].x = x + 32;
vertices[e].y = y;


e++;

// vertex 3
vertices[e].x = x;
vertices[e].y = y + 32;

e++;

// vertex 4
vertices[e].x = x + 32;
vertices[e].y = y + 32;

e++;

// vertex 2
vertices[e].x = x;
vertices[e].y = y + 32;

e++;

// vertex 3
vertices[e].x = x + 32;
vertices[e].y = y;


e++;

// Load texture for Floor
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/tile.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return;
}

}


x += 32;
mapX += 1;
}

mapY += 1;
x = 0;
y += 32;
}


// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice->CreateVertexBuffer( e*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();

g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0 );
g_pD3DDevice->BeginScene();

// Shoot out the lights
g_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

// Toggle this on and off to check on triangle rendering
//g_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

// Render the tile
// Setup the Stream Source
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );

g_pD3DDevice->SetTexture(0, g_pTexture);

// Draw the vertex buffer
g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 288);

g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;

case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}

ValidateRect( hWnd, 0 );
return 0;

case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}

return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}



Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Hint: You need to set the U and V values in your vertices.

Share this post


Link to post
Share on other sites
sauronette    122
Thanks anonymous. You just opened up the world for me :) I knew that u and v were texture coordinates, but I didn't know, that by default that the vertex buffer took care of transmitting these to the DrawPrimitive operation. DirectX was waiting for texture coordinates from me the whole time! :) It took a little while and some reading how to set up the texture coordinates. Now on the next step.... using that suggestion about setting up an array of pointers to textures and then stepping through the map and rendering the wall/floor, etc. And then to scrolling! And then smooth scrolling! And then broom-up, and onto sprites and layers.

Lots of work ahead. This direct X stuff is fun. Maddening, but the payoffs are great!. Here is the amateur hour code if anyone wants it. This renders a 12 x 12 textured quads.



#include <stdafx.h>


#undef UNICODE

#define WINDOW_TITLE "2D Scrolling Engine - straight outta Barad-dur"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOWED TRUE

// Set up the FVF
#define D3DFVF_CUSTOMVERTEX D3DFVF_XYZRHW | D3DFVF_TEX1

LPDIRECT3D9 g_pD3D9 = NULL;
LPDIRECT3DDEVICE9 g_pD3DDevice = NULL;
D3DDISPLAYMODE g_displayMode;
D3DPRESENT_PARAMETERS g_D3Dpp;

// make a pointer to where the Texture is
IDirect3DTexture9 *g_pTexture;

// make a pointer to the vertex buffer
IDirect3DVertexBuffer9 *g_pVB;

HWND g_hWnd;
/*TODO: additional variables*/

//A custom vertex structure
struct CUSTOMVERTEX
{
float x, y, z, rhw;
float u, v;
};


CUSTOMVERTEX vertices[864];


// map array declaration
// A nice cozy room with walls all around except
// for an open door at the bottom left.


int map[12][12] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1}};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
BOOL BuildPresentationParameters();
void RenderFrame();


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// Define the window
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, IDI_WINLOGO);
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = WINDOW_TITLE;
wcex.hIconSm = LoadIcon( hInstance,IDI_WINLOGO );

// Register the window
RegisterClassEx( &wcex );

// Create the window
g_hWnd = CreateWindow( WINDOW_TITLE, WINDOW_TITLE, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, hInstance, 0 );

// Adjust to actual desired size
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
AdjustWindowRect( &rect, (WINDOWED) ? WS_OVERLAPPEDWINDOW : WS_POPUP, FALSE );
SetWindowPos( g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE );

ShowWindow( g_hWnd, SW_SHOW );
UpdateWindow( g_hWnd );

// Create Direct3D Object
g_pD3D9 = Direct3DCreate9( D3D_SDK_VERSION );
if ( !g_pD3D9 )
{
MessageBox( 0, "Direct3DCreate9() - Failed", 0, 0 );
return 0;
}

// Get display mode
g_pD3D9->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &g_displayMode );

// Check for hardware T&L
D3DCAPS9 D3DCaps;
g_pD3D9->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &D3DCaps );
DWORD vertexProcessing = 0;
if ( D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
// Check for pure device
if ( D3DCaps.DevCaps & D3DDEVCAPS_PUREDEVICE )
{
vertexProcessing |= D3DCREATE_PUREDEVICE;
}
}
else
{
vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}

// Fill out the presentation parameters
if ( !BuildPresentationParameters() )
{
MessageBox( 0, "Unable to find a valid DepthStencil Format", 0, 0 );
SAFE_RELEASE( g_pD3D9 );
return 0;
}

// Create the device
if ( FAILED( g_pD3D9->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, vertexProcessing, &g_D3Dpp, &g_pD3DDevice ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "CreateDevice() - Failed", 0, 0 );
return 0;
}

int mapX = 0; // map X coordinate
int mapY = 0; // map Y coordinate


float x = 0.0; // vertex x coordinate
float y = 0.0; // vertex y coordinate

int e = 0; // array element

// Set up the Map Array
for ( mapY = 0; mapY < 12; )
{
for ( mapX = 0; mapX < 12; )
{


// texture = wall
// create 2 triangles to form a quad
// render

// vertex 1
vertices[e].x = x;
vertices[e].y = y;
vertices[e].u = 0.0f;
vertices[e].v = 0.0f;


e++;

// vertex 2
vertices[e].x = x + 32;
vertices[e].y = y;
vertices[e].u = 1.0f;
vertices[e].v = 0.0f;

e++;

// vertex 3
vertices[e].x = x;
vertices[e].y = y + 32;
vertices[e].u = 0.0f;
vertices[e].v = 1.0f;



e++;

// vertex 4
vertices[e].x = x + 32;
vertices[e].y = y + 32;
vertices[e].u = 1.0f;
vertices[e].v = 1.0f;


e++;

// vertex 2
vertices[e].x = x;
vertices[e].y = y + 32;
vertices[e].u = 0.0f;
vertices[e].v = 1.0f;


e++;

// vertex 3
vertices[e].x = x + 32;
vertices[e].y = y;
vertices[e].u = 1.0f;
vertices[e].v = 0.0f;

e++;


x += 32;
mapX += 1;
}

mapY += 1;
x = 0;
y += 32;
}


// Create our vertex buffer for rendering polygons at super speed
if( FAILED( g_pD3DDevice->CreateVertexBuffer( e*sizeof(CUSTOMVERTEX),0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Create Vertex Buffer - Failed", 0, 0 );
return 0;
}

// Fill the Vertex Buffer
void *pVertices;
if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
{
SAFE_RELEASE( g_pD3D9);
MessageBox( 0, "Can't fill Vertex Buffer - Failed", 0, 0 );
return 0;
}

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();


// Load texture for Floor
if ( FAILED( D3DXCreateTextureFromFile( g_pD3DDevice, "media/floor.bmp", &g_pTexture ) ) )
{
SAFE_RELEASE( g_pD3D9 );
MessageBox( 0, "Loading Texture - Failed", 0, 0 );
return 0;
}


// Main loop
MSG msg;
while ( 1 )
{
// Did we recieve a message?
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if ( msg.message == WM_QUIT)
{
break;
}

TranslateMessage( &msg );
DispatchMessage ( &msg );
}

else
{
RenderFrame();

}
}

// Give back resources
SAFE_RELEASE( g_pD3DDevice );
SAFE_RELEASE( g_pD3D9 );
SAFE_RELEASE( g_pTexture );


return 0;
}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
BuildPresentationParameters
Purpose:
Builds the D3DPRESENT_PARAMETERS structure using the current window size.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

BOOL BuildPresentationParameters()
{
ZeroMemory( &g_D3Dpp, sizeof(g_D3Dpp) );
D3DFORMAT adapterFormat = (WINDOWED) ? g_displayMode.Format : D3DFMT_X8R8G8B8;
if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24S8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
}
else if ( SUCCEEDED( g_pD3D9->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
{
g_D3Dpp.AutoDepthStencilFormat = D3DFMT_D16;
}
else
{
return false;
}

g_D3Dpp.BackBufferWidth = (WINDOWED) ? 640 : g_displayMode.Width;
g_D3Dpp.BackBufferHeight = (WINDOWED) ? 480 : g_displayMode.Height;
g_D3Dpp.BackBufferFormat = adapterFormat;
g_D3Dpp.BackBufferCount = 1;
g_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
g_D3Dpp.MultiSampleQuality = 0;
g_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
g_D3Dpp.hDeviceWindow = g_hWnd;
g_D3Dpp.Windowed = WINDOWED;
g_D3Dpp.EnableAutoDepthStencil = TRUE;
g_D3Dpp.FullScreen_RefreshRateInHz = (WINDOWED) ? 0 : g_displayMode.RefreshRate;
g_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


return TRUE;
}




// Function to Render the Current Frame
void RenderFrame()
{

g_pD3DDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0), 1.0f, 0 );
g_pD3DDevice->BeginScene();

// Shoot out the lights
g_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

// Toggle this on and off to check on triangle rendering
//g_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

// Render the tile
// Setup the Stream Source
g_pD3DDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pD3DDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );

g_pD3DDevice->SetTexture(0, g_pTexture);

// Draw the vertex buffer
g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 288);

g_pD3DDevice->EndScene();
g_pD3DDevice->Present( 0, 0, 0, 0 );

}

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Summary: Application event handler.
Parameters:
[in] hWnd - Unique handle to the window.
[in] message - Incoming message.
[in] wParam - Parameter of the message (unsigned int).
[in] lParam - Parameter of the message (long).
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;

case WM_PAINT:
if ( g_pD3DDevice )
{
RenderFrame();
}

ValidateRect( hWnd, 0 );
return 0;

case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostQuitMessage( 0 );
break;
}

return 0;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}






Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this