|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionOK, first some disclaimers: this is my first "project" in C# and while I have some previous experience in graphics coding it has been in Direct3D using c++, where different issues are to be considered. I wrote this just as an exercise in C# and for almost exclusive purpose at posting at www.codeproject.com so if you are to use this somewhere else please mention this site. Now about code itself. I wanted to create a set of classes that will handle basic sprite manipulation, using nothing more than GDI+. I started with class
After some thought (and try-and-error approaches) I created following classes: Approach to creating an application using above mentioned classes should be like this: you create a form and drag Word about animated sprites: all animations are time stamped, so duration of animation sequence is the same no matter how often you update it. Meaning, if you have sprite animation composed of 10X6 = 60 frames and you set it's K, back to creating an app. I should really have created a user control based on public SpriteWorld.World myWorld=new SpriteWorld.World();
So now you have everything you need (class wise) and you should do the following: create some viewports, create some test objects and start timers. Your Form constructor should look like this: public Form1()
{
InitializeComponent();
//create two viewports, one default size and origin
myWorld.CreateViewport(pictureBox1,Background.Image);
//... the other somewhat smaller and showing different
// portion of "world"
myWorld.CreateViewport(View2,View2.CreateGraphics(),
new Point(145,25),
new Rectangle(30,30,120,120),
Background.Image);
//create some sprites
CreateTestObjects();
//main loop timer
timer.Start();
//animation loop timer
AnimationTimer.Start();
}
You create objects like this: private void CreateTestObjects()
{
//animated
myWorld.AddSprite(canvas1,new Point(20,60),new Point(0,59),30,true);
//also animated
myWorld.AddSprite(canvas1,new Point(175,60),new Point(0,59),60,true);
//static
myWorld.AddSprite(canvas1,new Point(80,50));
//static
myWorld.AddSprite(canvas1,new Point(70,80));
//start updating FPS monitor
FPStimer.Start();
//show some numbers
textBox3.Text=Convert.ToString(myWorld.Library.Item(1).oFPS);
textBox1.Text=Convert.ToString(myWorld.Library.Item(2).oFrame);
}
You also need to create timer callbacks: private void timer_Tick(object sender, System.EventArgs e)
{
//check if we need some rendering
myWorld.RenderingLoop();
}
private void AnimationTimer_Tick(object sender, System.EventArgs e)
{
//we animate sprites here
myWorld.UpdateAnimated();
}
Some painting override in case we minimize app. or draw some other window over it and it needs repainting:private void pictureBox1_Paint(object sender,
System.Windows.Forms.PaintEventArgs e)
{
//this is used only when we have some area that needs to be
// redrawn like when we start, or min. then restore app, or
// bring it to front from behind some other app
myWorld.RePaint(sender,e.Graphics, e.ClipRectangle);
}
Now, class For the end, word about clipping. It was probably the hardest thing to do. Consider the following picture:
Let's say that we got rendering request from sprite1 and sprite3, and we want to create one clip region. So we create a clip region (yellow outline) that contains both sprite1 and sprite3. But wait, if we draw background and only these two sprites, other sprites 2,4 and 5 will get also partially erased when we draw background in this clip. Clearly, we end up with much larger clip region and instead of drawing two sprites now we have to draw five. That is why I have created variable number of clips in If you are interested into the exact implementation of the above please look up the source code, as I do have a tendency to get long-winded and you may find it easier just to look it up yourself. I am aware of at least couple shortcomings right now, like I didn't correctly implement rendering in case you don't want to have background image, and sprite selection (used to move sprites around) doesn't check where does call comes from, so only first viewport works (it should be easy to fix it, every viewport has reference to it's parent, so you should be able to detect from where did call came from) etc. If you do find something useful feel free to use it, also if you have some improvements it would be nice if you let me know in a forum bellow or at: djurovic@nyc.rr.com
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||