[D3D9] Resizing sprites

Started by
5 comments, last by Sangman 12 years, 8 months ago
Me and a few others are working on a school project, a 2D platforming game. We were using GDI+ at first but the rendering became way too slow eventually and now I've been trying to rewrite the renderer to make use of Direct3D9. I'll post the renderer class below (it's not that big), I'm sure there are still some errors in here but for now all I want to know is if and how I can resize sprites.



public class Renderer {
private Control renderWindow;
private Device device;

public Renderer(Control renderWindow, bool Windowed) {
this.renderWindow = renderWindow;


// Initialize a Direct3D 'device' that we can use to render our scene
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.BackBufferHeight = this.renderWindow.ClientSize.Height;
presentParams.BackBufferWidth = this.renderWindow.ClientSize.Width;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.EnableAutoDepthStencil = true;
device = new Device(new Direct3D(), 0, DeviceType.Hardware, renderWindow.Handle, CreateFlags.HardwareVertexProcessing, presentParams);

}

/// <summary>
/// Get the renderer device
/// </summary>
public Device Device {
get {
return device;
}
}

public void Render(bool gameShown, bool menuShown, Level currentLevel, WTDLib.Global.Menu.Menu activeMenu, ImageDictionary imagedict, ViewCamera viewcam) {
// Clear drawing area
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, BackColor, 1.0f, 0);

device.BeginScene();
Sprite sprite = new Sprite(device);
if (gameShown) {
sprite.Begin(SpriteFlags.AlphaBlend);
foreach (GameObject go in currentLevel) {
// fix positio,:
int y = go.Y;
// manually flip the imagelocations (translatetransform is no longer present)
int half = renderWindow.Height / 2;
half -= 30;
if (y < half) {
int difference = half - y;
y = half + difference;
}
else {
int difference = y - half;
y = half - difference;
}
if (go is WTDLib.Global.Surface) {
y -= 34;
}

// set position and transformations and such

// get the texture out of the gameobject:
sprite.Draw(imagedict[go.Id.ToString()], go.SrcRect, null, new Vector3(go.X + viewcam.XOffset, y, 0), Color.White);
}
sprite.End();
}

else if (menuShown) {
SlimDX.Direct3D9.Font font = new SlimDX.Direct3D9.Font(device, new System.Drawing.Font(FontFamily.GenericSansSerif, 20));
sprite.Begin(SpriteFlags.AlphaBlend);
foreach(MenuElement element in activeMenu) {
if (element is MenuButton) {
MenuButton button = (MenuButton)element;
//font.DrawString(sprite, button.Text, new Rectangle(button.X, button.Y, button.Width, button.Height), DrawTextFormat.Left, new Color4(1f, 0, 0, 0));
font.DrawString(sprite, button.Text, button.X, button.Y, button.Brush.Color);
}

else if (element is MenuText) {
MenuText text = (MenuText)element;
font = new SlimDX.Direct3D9.Font(device, text.Font);
font.DrawString(sprite, text.Text, text.X, text.Y, text.Brush.Color);
}
}
sprite.End();
font.Dispose();
}


device.EndScene(); // end drawing 3D)scene
device.Present(); // flip back- & frontbuffer --> show 3D scene

// now dispose the sprites
sprite.Dispose();
}
}


Every texture shows up fine, but none of them have the width or height that I want. In GDI+ you could specify a bitmap to have certain values for that but it doesn't seem like this is possible with sprites? Am I gonna have to resize the actual files I'm loading? I've spent all day on this and can't find anything on the internet on how to solve this so some help would be very appreciated. :)


edit: Oh forgot to mention, I have tried out the Matrix.Scaling methods but that one doesn't quite give me what I want.. It's hard to explain :/ It looks like it doesn't just make the sprite bigger, but also the distance between sprites and such.
Advertisement
Ok figured out what I did wrong - apparently scaling a sprite does not only scale its width and height but also its coordinates. So first I had to translate it to (0,0), then scale them and then translate them back to their original positions.

Ok figured out what I did wrong - apparently scaling a sprite does not only scale its width and height but also its coordinates. So first I had to translate it to (0,0), then scale them and then translate them back to their original positions.


Hi Would you please share the code - scaling of the sprite? I am also facing the same issue.
Before you render your sprites, you usually transform the world coordinates. This is how you move objects and this is where you can scale the X, Y, and Z coordinates (World Space). You could also manually scale your object by locking the vertex buffer and reposition the vertices (Model Space).


Just keep in mind that, if you're using a pixel shader, scaling the X, Y and Z independently needs to be handled in your lighting calculations and can get costly depending on what else you're calculating.


Dj

Before you render your sprites, you usually transform the world coordinates.



Yeah I tried doing that but couldn't get it to work, so I just worked with "world coordinates" for game logic and then altered em to whatever the corresponding device coordinates would be manually in my renderer.

The project's deadline was 2 months ago btw, it pleases me to say we passed it with a pretty high grade and I learned at least a few things about programming games.

[quote name='Sangman' timestamp='1304276025' post='4805144']
Ok figured out what I did wrong - apparently scaling a sprite does not only scale its width and height but also its coordinates. So first I had to translate it to (0,0), then scale them and then translate them back to their original positions.


Hi Would you please share the code - scaling of the sprite? I am also facing the same issue.
[/quote]

Multiple ways to go about that I suppose but here you go. I cut a bit of code out of it to stick to the main issue here, there was some other stuff I had to do to properly draw objects but I guess that depends on how you code things. The identation is a bit bricked but should be readable :P




try {

Sprite sprite = new Sprite(device);
sprite.Begin(SpriteFlags.AlphaBlend);

// fix scaling
// srcrect width and height = width and height of the actual sprite on disk
// width and height of gameobject itself = width and height in the game world
int width = gameobject.SrcRect.Width;
int height = gameobject.SrcRect.Height;
float scaleX = (float)gameobject.Width / (float)width;
float scaleY = (float)gameobject.Height / (float)height;

// first: translate to 0, 0, 0 (this wasn't for a 3D game so Z-coordinate should just be 0)
// second: scale
// third: translate back to original position but with a "reversed" Y
Matrix transformation = Matrix.Translation(0f, 0f, 0f);
transformation *= Matrix.Scaling(scaleX, scaleY, 0f);
transformation *= Matrix.Translation(gameobject.X, gameobject.Y, 0);
sprite.Transform = transformation;

sprite.Draw(gameobject.Texture, gameobject.SrcRect, Color.White);

}
catch (Exception e) {
Console.WriteLine("Render failed "+e.Message);
continue;
}


// clean sprite
sprite.End();
sprite.Dispose();
Good to hear you got a great grade and learned something but I don't want you to learn the wrong thing. Yes, there are several ways to handle scaling I suppose, but the proper way should be in the transforms of World Space. They are order dependant, meaning- they should be multiplied in a certain order -> Scale, Pitch, Yaw, Position, etc... Now that takes care of the positioning and scaling of all the sprites as a whole. If you want to scale and position each sprite specifically you'll need to manually create quads instead of sprite batching. This way you can lock the vertex buffer and edit each vertex, it's a lot more flexible. There is some hardware that support "sprite size" but in my past experience I've never seen any cohesion between hardware types that support sprites, they all handle them differently. I usually create my own quad which gives me complete control. Then render with a triangle list.
I didn't even use a VertexBuffer... all I did was draw textures as sprites (using a certain srcrect). :P Guess there's more to learn.

This topic is closed to new replies.

Advertisement