Jump to content
  • Advertisement
Sign in to follow this  

Best way to make a zooming 2D game

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

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

Recommended Posts

Hi, I'd like to make a 2D DirectX game that can zoom in and out in realtime. What's the best (i.e. most efficient) way of doing this? Please keep in mind that I'm still kind of new to DirectX. I assume there's some way of rendering a texture onto a texture, or a texture onto a surface, but I can't find the functions. ---UltimateWalrus

Share this post


Link to post
Share on other sites
Advertisement
OK, that makes sense.

What if I have thousands of sprites onscreen at once (e.g. drops of rain falling from the sky or bullets in a shooting game)? Won't I experience a performance drop then because of all of the thousands of polygons? Would it be more efficient to just draw a bunch of 2D textures onto another 2D texture/surface, and resize it? Or maybe, the most efficient way would be to scale and position each sprite individually?

I don't necessarily know any of this to be true; I'm just asking the questions in the hopes that somebody will elaborate on them.

EDIT: Also, I'm wondering if I'd be able to use capabilities like line drawing... but that's not as important.

Share this post


Link to post
Share on other sites
Quote:
Original post by UltimateWalrus
OK, that makes sense.

What if I have thousands of sprites onscreen at once (e.g. drops of rain falling from the sky or bullets in a shooting game)? Won't I experience a performance drop then because of all of the thousands of polygons? Would it be more efficient to just draw a bunch of 2D textures onto another 2D texture/surface, and resize it?


Probably not.

DirectDraw doesn't make use of 3D acceleration, while Direct3D does. Using Direct3D, and ID3DXSprite (a helper interface designed specifically to simplify drawing sprites), you can utilise the 3D acceleration on a graphics card.

D3DX also provides the ID3DXLine interface, which greatly simplifies line drawing.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sc4Freak
Probably not.

DirectDraw doesn't make use of 3D acceleration, while Direct3D does. Using Direct3D, and ID3DXSprite (a helper interface designed specifically to simplify drawing sprites), you can utilise the 3D acceleration on a graphics card.

D3DX also provides the ID3DXLine interface, which greatly simplifies line drawing.


OK, now I'm a little confused, so hopefully someone can clarify this for me.

I've been using Direct3D all along, not DirectDraw. When I use the ID3DXSprite::Draw function, I just give it 2D screen coordinates and it draws a 2D image for me. I'm a little sketchy on how this is implemented --- I'm guessing from the context of what you're saying that the graphics card actually draws it as a textured quad in 3D space?

If this is true, then is there a way to "move the camera around" even when all I've done is draw 2D sprites using ID3DXSPRITE? Or do I have to take a more "3D" approach and create a whole world, with vertices, polygons, etc.? If I did take this 3D approach, wouldn't there be distortion at the edges of the screen from the conical camera view? Is there a way to change the camera to just a flat projection?

The more struct and function names you can use to describe what you are saying, the better (remember I am still fairly new at this). :)

Share this post


Link to post
Share on other sites
First, look at D3DXMatrixOrtho* functions (I think that's what they are called), cause if you are developing a 2d game, you likely want to use Orthographic projection. To zoom in and out, change the resolution params you send to that function (it won't change real resolution, but it'll scale things for you, so that it looks zoomed).

When it comes to sprites.. You normally render them as textured quads yes. You CAN also use something called Point sprites, checkout codesampler.com for more details. Very nice for things like rain and particles, uses one vertex per sprite and one texture.

Share this post


Link to post
Share on other sites
I took a look at the D3DXMatrixOrtho functions. I think that I'm supposed to feed the matrix into the SetTransform function --- is that right?

I tried using the following function in a program in which sprites are being drawn with ID3DXSPRITE::Draw (nothing happened):


void ZoomPlayArea(float width, float height)
{
D3DXMATRIX matrix;
d3ddev->SetTransform(D3DTS_PROJECTION, D3DXMatrixOrthoRH(&matrix, width, height, -1000, 1000));
}




I wasn't sure what to put for the zn and zf values, so I tried to specify a broad range, -1000 to 1000.

Am I at least on the right track? Is there something I did wrong or something I still need to do? Am I supposed to use the D3DTS_PROJECTION type?

Share this post


Link to post
Share on other sites
You are correct, you are supposed to feed it to SetTransform.. Although, for znear, use a small value, such as 1. I'm not sure it's supposed to be a positive number, but it seems to be working for me anyway.


void ZoomPlayArea(float width, float height)
{
D3DXMATRIX matrix;
d3ddev->SetTransform(D3DTS_PROJECTION, D3DXMatrixOrthoRH(&matrix, width, height, 1, 1000));
}

/*
I tend to have something like this:
*/


void ZoomPlayArea(float zoom) // zoom may never be 0!
{
D3DXMATRIX matrix;
d3ddev->SetTransform(D3DTS_PROJECTION, D3DXMatrixOrthoRH(&matrix, m_width/zoom, m_height/zoom, 1, 1000));
// or:
// D3DXMatrixOrthoRH(&matrix, m_width - zoom * 0.1f, m_height - zoom * 0.1f, 1, 1000));
}



Which way you want depends completely on you.

Share this post


Link to post
Share on other sites
Ah shoot [sad]

If it works for you and not for me, then maybe there's a problem in the way I draw sprites, or initialize Direct3D... If you don't mind, could you take a look at it, and see if there's anything that needs to be changed?

When I draw a sprite, I do it like this:


if(d3ddev->BeginScene())
{
sprite_handler->Begin();
sprite_handler->Draw
(
texture,
NULL,
NULL,
NULL,
0.0,
&D3DXVECTOR2(x,y),
0xFFFFFFFF
);

sprite_handler->End();

d3ddev->EndScene();
}
d3ddev->Present(NULL,NULL,NULL,NULL);



And when I initialize Direct3D, I do it like this:


int Init_Direct3D(HWND hwnd, int width, int height, bool fullscreen)
{
//initialize Direct3D
d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (d3d == NULL)
{
MessageBox(hwnd, "Error initializing Direct3D", "Error", MB_OK);
return 0;
}

//set Direct3D presentation parameters
D3DDISPLAYMODE dm;
d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));

d3dpp.Windowed = (!fullscreen);
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.BackBufferFormat = dm.Format;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.hDeviceWindow = hwnd;

//Only needed for dialog boxes
d3dpp.Flags=D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;

//create Direct3D device
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);

if (d3ddev == NULL)
{
MessageBox(hwnd, "Error creating Direct3D device", "Error", MB_OK);
return 0;
}

//clear the backbuffer to black
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0);

//create pointer to the back buffer
d3ddev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);

D3DXCreateSprite(d3ddev, &sprite_handler);

return 1;
}



Or maybe, could you point me towards an example that shows how to do this?

Thanks!

Share this post


Link to post
Share on other sites
Again, checkout codesampler.com, LOTS of examples of just about everything.

I'm not sure, but I do believe ID3DXSprite thingy sets alot of render states and transform matrices, which can sometimes cause great headache.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!