I am trying to create a very basic sprite image.
First off i have an existing image (Width=100px, Height=100px).
I will be looping through this image betwee
An approach that can work is by allowing to place the sprite's frames anywhere in the bitmap (that way you can make them more compact) and accompany each bitmap with a(n xml) file that describes the location, size and origin of each frame AND has a listing of all the animations. Something like this:
<SpriteSheet>
<Frames>
<Frame id="0" location="20,40" size="64,64" origin="32,32" />
<Frame id="1" location="100,40" size="64,64" origin="32,32" />
<Frame id="2" location="164,40" size="64,64" origin="0,0" />
<Frame id="3" location="20,120" size="64,64" origin="32,32" />
</Frames>
<Animations>
<Animation name="walk left" >
<Keyframes>
<Keyframe frameId="0" duration="0:0:0.5" offset="-5,0" />
<Keyframe frameId="1" duration="0:0:0.5" offset="-5,0" />
<Keyframe frameId="2" duration="0:0:0.4" offset="-2,0" />
<Keyframe frameId="1" duration="0:0:0.5" offset="-5,0" />
</Keyframes>
</Animation>
<Animation name="walk right" >
<Keyframes>
<Keyframe frameId="5" duration="0:0:0.5" offset="5,0" />
<Keyframe frameId="6" duration="0:0:0.5" offset="5,0" />
<Keyframe frameId="2" duration="0:0:0.4" offset="2,0" />
<Keyframe frameId="6" duration="0:0:0.5" offset="5,0" />
</Keyframes>
</Animation>
</Animations>
</SpriteSheet>
This way you can re-use frames across animations (and so optimizing the bitmap sizes even more) and customize the animations by simply editing the XML file.
All you have to do is read the XML file, read the bitmap and when starting an animation: start a timer that ticks at a regular interval. When it ticks you calculate the correct Keyframe in the animation by adding the durations of the Keyframes one by one and stopping when the sum is more than the tick time; the current Keyframe should be used.
In the XML file above I added stuff such as an offset that allows you to modify the position of the sprite during the animation (you could even interpolate it so it moves smoothly)
All that is left is grabbing the correct frame out of the bitmap. As an optimization you could pre-process the bitmap when loading the XML file by grabbing the frames, keeping those as tiny bitmaps, and discarding the big bitmap. This might optimize memory when the bitmap is big and not fully covered in frames.
In other cases, you don't pre-process and just blit the frame.
For larger applications (more bitmaps/animations/frames) I recommend creating an app to create and edit the XML file. Another option might be to create a plugin for your favorite paint program (if possible)
There is a lot of information about 2D-sprites in the following MSDN article: Rendering 2D sprites
Those examples are based on Microsoft's XNA, which is a platform that can be used within Visual Studio to develop games for Windows, Windows Phone and XBOX 360.
For example, to draw a sprite, you can use the following C# code (example taken from the MSDN article, XBOX 360 specific code removed):
private Texture2D SpriteTexture;
private Rectangle TitleSafe;
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
SpriteTexture = Content.Load<Texture2D>("ship");
TitleSafe = GetTitleSafeArea(.8f);
}
protected Rectangle GetTitleSafeArea(float percent)
{
Rectangle retval = new Rectangle(
graphics.GraphicsDevice.Viewport.X,
graphics.GraphicsDevice.Viewport.Y,
graphics.GraphicsDevice.Viewport.Width,
graphics.GraphicsDevice.Viewport.Height);
return retval;
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
Vector2 pos = new Vector2(TitleSafe.Left, TitleSafe.Top);
spriteBatch.Draw(SpriteTexture, pos, Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
You need to call LoadContent()
to initialize it, then you need to call GetTitleSafeArea(100)
to get the safe draw area (in this case wich 100 percent), finally you can use the Draw
method. It accepts a parameter containing an instance of the GameTime
class, which is a Snapshot of the game timing state expressed in values that can be used by variable-step (real time) or fixed-step (game time) games.
Please let me know if that helps you.
Let me try with some pseudocode:
Bitmap originalImage; // that is your image of 100x100 pixels
Bitmap bigImage; // this is your 3000x3000 canvas
int xPut = 0;
int yPut = 0;
int maxHeight = 0;
while (someExitCondition)
{
Bitmap imagePiece = GetImagePieceAccordingToSomeParameters(originalImage);
if (xPut + imagePiece.Width > 3000)
{
xPut = 0;
yPut += maxHeight;
maxHeight = 0;
}
DrawPieceToCanvas(bigImage, xPut, yPut, imagePiece);
xPut += imagePiece.Width;
if (imagePiece.Height > maxHeight) maxHeight = imagePiece.Height;
// iterate until done
}
declare a variable at 3000, if you put in a picture of width 250 take that away from the variable, keep doing this, this also allows you to decide if there is enough space left on that line for your next picture by seeing if the number left is larger than the width of the next picture. every time you start on a new line set the variable back to 3k and start again. solved