Archive for the 'Windows Phone 7' category

SWFSheet – create sprite sheets from SWFs

[EDIT: Just released a beta of SWFSheet 1.1 here: http://www.bit-101.com/blog/?p=2948]
[EDIT: Version 1.1 final released: http://www.bit-101.com/blog/?p=2977]

SWFSheet is a program I created in most of a day back in late December. I finally polished it up this week and it’s now ready for release. The idea is to take an animation created in Flash, and generate a sprite sheet from it. A sprite sheet, for those of you who may not be familiar, is a single large bitmap containing several frames of an animation, usually layed out in a grid. These can be loaded in very efficiently by games, and each frame shown to recreate the animation.

I had the idea for this program while attempting to port some Flash stuff to the iPhone. And later while making other mobile games, I found that Flash was still the best tool to create animations. It has a powerful time line, easy to use drawing tools, tweens, 3D, and of course, powerful scripting with ActionScript. However, getting a nice looking Flash animation into a sprite sheet that could be used with cocos2d on the iPhone/iPad or with XNA for Windows Phone 7 was not so easy. I did it by hand a couple of times, and it wasn’t very fun. Thus, SWFSheet was born.

SWFSheet is an AIR application and has been tested on Windows and Mac. You create your SWF however you want. Flash CS5 or earlier, Flash Builder, or anything else that outputs a SWF. It doesn’t matter how it’s created. Then you load the SWF into SWFSheet.

swfsheet screenshot

Immediately, you’ll see the live loaded SWF running in the upper left panel. The program will then capture an image of the SWF on each frame for the number of frames you have specified (default 15) and arrange them in a grid on the bitmap. Once that is done, it will then animate this bitmap using the same techniques you would use to animate a sprite sheet in a real game. This is seen in the lower left panel. You can adjust how many frames you want to capture to make sure you get your whole animation and have it loop smoothly. And you can adjust the frame of exactly how much area is captured in each frame, to maximize space on the bitmap. If there is not enough space to capture all frames, you can choose a larger bitmap. After any changes, you need to click “Capture” to re-capture the frames based on the new settings.

Often when scripting animations, you will have various transformations or other changes happening in an onEnterFrame type of loop. This can sometimes cause a glitch, as the first frame is captured before the first enterFrame handler fires, and thus does not have the initial transformations applied. There is a “Skip first frame” checkbox which handles this situation. There are also options for smoothing, which may or may not make any difference in a specific animation, and for transparency. By default, a loaded in SWF will have a transparent background, but you can override this to make an opaque bitmap with any color background you want. And you can change the preview frame rate – of course this doesn’t change the bitmap at all, but can give you an idea what your animation will look like at your target frame rate.

Note that there are a limited number of sized of bitmaps. Sprite sheets can almost always take advantage of extra efficiency when created in power-of-two sized squares – 64×64, 128×128, 256×256, etc. Thus, these are the only choices. A future version may make possible custom sizes if enough people ask for it.

Here’s the AIR installer:

SWFSheet Installer

And here are some test files to get started with:

Test Files

Enjoy!

ps. Another tool you might be interested in is Mike Jones’ Sprite Sheet Maker, which is more geared to making sprite sheets from a series of separate image files. Similar outcome, different use cases, depending on what kind of input you are starting from.

76 responses so far

Good bye 2010

As usual, it’s time to make my year end post. I’ll keep it relatively brief.

A few changes this year. This spring, I got kind of fed up with Apple, their control-happy policies, and the general direction they are heading. After 3 years of being 100% Mac, I switched back to Windows. It is an action that I not only do not regret the tiniest bit, but as Apple continues to evolve in the same direction, I’m happier than ever that I switched when I did. This is not to say that I’ve abandoned all iOS development and have thrown away my Mac. I still own two Apple computers. Both are plugged in and booted up and ready for action at all time. I have an iPhone, and iPad, an iPod Touch and a 5G iPod. They aren’t going anywhere. But the machine I open up in the morning and use all day long is my Sony Vaio, and I’m very happy with it. I’m not shoving it down your throat. If you’re happy with Apple, far be it from me to try to change your mind. I’m OK, you’re OK, right?

Around the same time I switched back to Windows, I also came into the ownership of a Google Nexus One. It took a while to really get used to it, as it’s definitely not the polished experience that the iPhone is. But I forced myself to stick with it for a week or so and really started to love it. From my viewpoint, the main difference was that it was MY phone, not Steve Jobs’. I could do pretty much whatever I wanted with it. Change the lock screen, change the task switcher, add memory, change the battery, put my icons where I want them, install unsigned apps, have live gadgets on the home screen, etc. etc. Once I got used to it, the iPhone just seemed unbearably sterile. Unfortunately, the model I had was a T-Mobile version, so I couldn’t get 3G on it with my AT&T sim. I suffered with Edge for a several months, but finally the wifi connection and even the Edge connection started getting really flaky. One day in September, just couldn’t connect to anything, so it was back to the iPhone.

Coming back to the iPhone, I have to admit, I really did appreciate the slickness of the UI. But I didn’t fall back in love with it. To be honest, I knew it was only a stopgap until the new Windows Phones came out. I got a Samsung Focus as soon as they came out and I absolutely love it. It is without a doubt the best phone I’ve owned. Note – it’s far from perfect. It’s a v1 product and it shows in many ways. But regardless of all that, there is so much RIGHT about what Microsoft did with it. I’m really excited to see where it goes in the coming years. I don’t expect it to overtake or even match Android or iOS any time in the near future, if at all, and I don’t really care. As long as I can continue to own one and see it improve, I’m a happy camper.

As for mobile development, I didn’t do much at all most of the year. But this autumn and winter I worked on one major and one minor iOS projects at Infrared5. After being away from Objective-C for so long, it was pretty bizarre trying to get back into it. It took a couple of days before it stopped feeling like I was typing with my toes, but eventually I got back in the groove. I played with Android dev briefly, but never really dove into it that much. But in October, I got my hands dirty with Windows Phone dev, with both XNA and Silverlight, and it has blown me away. I might even say it’s revitalized me as a developer. For a large part of the year I was on a very tough, frustrating project. It wore me down quite a bit. But with Visual Studio and C#, it’s like starting from scratch – in a good way! All the excitement without the learning curve. After many years of Flash development, writing ActionScript is almost second nature to me. But after just a couple of months in Visual Studio, I feel like I’m more at home with C# than I ever was with ActionScript. It’s a very, very similar language. If you took AS3 and removed all the little things that annoy or distract you and pull you out of the “flow” of coding, and replaced them with a whole bunch of little things that just work exactly the way you would expect them to, you’d have C#. And if you took Flash Builder and … no, that’s just not going to work. There’s no comparing Eclipse to Visual Studio.

Speaking of IDEs, after working in VS for a few months, and then going back to XCode… it really dawned on me just how bizarre an IDE that really is. I’m really trying not to bash any particular technology, but I can’t help feeling like XCode was designed on an anti-matter planet in an alternate universe by some bizarre aliens on really strong acid. I’m not even talking about the language – just the IDE. I sometimes find it hard to believe that it was created by and for programmers. I know it’s not “wrong”, just different. Most IDEs are relatively similar, like most western human languages are pretty similar. I may not speak Spanish, but I can see it and read the words even if I don’t know their meaning, and can catch a bit of a hint of what’s being said. Same with most IDEs – you can quickly find your way around them for the most part. But diving into XCode is like being dropped in an Asian or Middle Eastern country where everything just looks like random scratchings or scribbles to your unfamiliar eye. That’s what XCode is like – just a completely foreign programming paradigm. Again, not saying it’s bad or wrong. You live with it long enough and you become fluent in it. But boy is it different.

Also in the summer I got into Processing quite a bit. Far more than I ever had before. I’ve kind of drifted from it again, but it was a great experience. I’m sure I’ll drift back around to it again before long. This largely came about from my conference session for 2010, “Programming Art”, in which I covered a bunch of different tools and languages for creating algorithmic and generative art, including Context Free Art, Structure Synth, Processing, the Hype Framework, and others. I also really enjoyed getting my head around Structure Synth, and got a bit revived on it just recently with the newly released integrated raytracer. Fun stuff!

On a personal basis, it was a year of health. I ran over 1000 miles, lost a good deal of weight, and reverted the trend of my blood sugar and blood pressure, which were edging into borderline problem areas. I think I also did more travelling this year than I have in any previous years, with trips to San Francisco, Minneapolis, Kortrijk Belgium, Toronto, Japan, back to San Francisco, and Edmonton.

Well so much for keeping in brief. In summary, it was a year of trying new things and going back to old things, learning new platforms and languages. Going forward, I don’t think it’s possible, at least not for me, to be a “Flash Developer”, or an “iPhone Developer” or be stuck in any single platform. Now more than ever, there is just too much diversity and you have to have a foot in every camp. If someone needs a game or an app these days, they can’t really just release a single version of it. They’re going to need an iPhone version, and Android version, eventually a Windows Phone version, and some kind of web presence with it. Are you going to just ask for one slice of that pie? Are they going to farm out their app to 4-5 different shops, one for each platform? As a company at the very least, you need to be able to do it all. Ideally as a developer as well, you need to be able to do as many of those as possible. I know that’s where Adobe is trying to be strong with the iPhone and Android packagers for Flash. I’m still not convinced those are the solutions for most projects though. Native will always win.

As for 2011, I assume the fist good chunk of the year I’ll be doing a lot more WP7 dev. And since the XNA codebase is 99% the same for WP7, Windows, and XBox games, I look forward to releasing some stuff for Windows desktop and XBox as well. I’m sure I’ll also play with the new Mac App Store stuff, and more iOS stuff too. The WP7 game I’m working on now will definitely need an iOS port. But who knows where I’ll go from there?

8 responses so far

PaceCalc for Windows Phone 7

Nov 25 2010 Published by under Silverlight, Uncategorized, Windows Phone 7

As many of you know, I’ve been running for the last year and few months, and completed a few races here and there. One of the first things you start to focus on when you sign up for your first race is your pace and predicted finish time. It’s a simple calculation of pace = time / distance. You might be thinking, “wait, speed is distance / time”, but runners usually measure pace in minutes per mile or kilometer, rather than kilometers or miles per hour. So if you know the length of your race and how fast you can run, you can predict when you’ll come in. Or if you have a goal for when you want to come in, you can calculate how fast you need run to meet that goal. Last, and probably least, if you know how fast you’ll be going and how long you’ll be running, you can predict how far you will go.

There are pace calculators all over the web, but none yet for Windows Phone 7. So I figured it would be a fun project to create one. It would give me a real world reason to use some of what I’ve been learning about Silverlight too. On the outset, it looked really simple. Three text boxes for time, distance, and pace, and three buttons. The toughest part was all the time conversion and formatting. I decided to break up the text boxes for time into separate ones for hours minutes and seconds. I added some preset distance buttons and a toggle for miles or kilometers. Here’s the final result:

I’m really impressed with Silverlight. I’ve done enough Flex work so that this was quite simple. Flex has never really grown on me, but I find I’m actually starting to like Silverlight. It feels much more robust and mature and well thought out than Flex.

Anyway, the whole app took just a few hours to code. I started it when I got home from work on Tuesday and it was done before I went to bed. Wednesday morning I made up a crappy icon, took a screenshot and submitted it to the WP7 marketplace. Wednesday evening I got an email saying it was approved and the next morning (today) it was live and available for download. After having waits of up to 3 weeks for iOS app store approval, this blew my mind. Of course, the MS marketplace is young and lower traffic and will feel its own stress points as it grows. But I’m willing to bet that it remains a much more streamlined experience. Developers, developers, developers! Right?

I think this app will continue to be a great way for me to learn more about Silverlight and tweak things. I already worked a bit on input validation. When you enter an input field, a keyboard comes up just like on other devices. I had made it so that a telephone numeric keyboard comes up since you only enter numbers there. But there are still invalid characters that one could enter, such as “,+=#”, space, or “.” in the time fields. So I just did an update that restricts those characters and limits the number fields to two digits. I also started working on better layout using a few grids in key spots. I may even experiment with changing it to a panorama control, adding another page for maybe calculating splits (where you’d have to be at each mile or kilometer to be on track for your goal time), or other useful info.

Long and short of it, I’m having fun. The app is free by the way, so it’s totally for fun and learning, and of course because I find it a useful app personally. I’m also forming an idea for another game. Having fun is fun!

10 responses so far

Falling Balls for Windows Phone 7 is Live!

Nov 23 2010 Published by under Windows Phone 7

When I decided to learn Windows Phone 7 programming, deciding what to code up was a no-brainer. Falling Balls! I got most of the game done before I had a device. Then got a loaner from Microsoft and shortly thereafter got my own Samsung Focus. I love the phone. Really grows on you. Anyway, with a device, I was able to wrap up the accelerometer code and tweak the game play and such and get the thing ready to go. It took a bit of study to find out all the stuff you need for submission – name, description, keywords, various sized icons, screenshots, etc. But finally got it all wrapped up and pushed the button on Sunday night.

This afternoon, just two days later, I got an email saying the game was ready for download. It took a few more hours for it to appear in the store, but it’s now live, just about 48 hours from submission. That was really refreshing!

When you submit a WP7 app, you have the option to allow a trial download. Microsoft highly recommends this. There are APIs to test whether or not the app is running as a trial or full version, so you can enable / disable various parts of the game. There is also a very simple call you can make that will take the user straight to your app’s page in the marketplace so they can buy the full version. Microsoft did an absolutely amazing job on this workflow. Compare that to the iOS platform where it is forbidden to have any “demo” or “trial” versions of apps or have any part of any UI disabled, and the complexity of making “light” and “full” versions of apps, or implementing in-app purchases. For WP7 it’s one method call to see if you’re in trial mode, conditionals wherever you want to disable stuff, and one call to send them off to buy your app. Brilliantly simple.

So Falling Balls WP7 is largely identical to the iOS version, with an easy mode, a medium mode and a hard mode where the balls come from both directions. The trial gives you easy mode. For 99 cents, you get the other two. We’ll see how that goes. No ads at this time, but I might look into that later. The platform isn’t as big this time, so I don’t expect to make a ton of money, but hopefully it’ll do something.

If you have the Zune software installed, this should take you right to the app: http://social.zune.net/redirect?type=phoneApp&id=b81b9cef-78f5-df11-9264-00237de2db9e. Otherwise, just search the marketplace.

The first review is in already: 5 stars, “So much fun!!! Love it”. 🙂

8 responses so far

Learning XNA 3.0

Oct 12 2010 Published by under Windows Phone 7

Since there are no XNA 4.0 books out there yet (lots due for release in the next 2 months though) I picked up a 3.0 one. This one had some really great reviews and just into Chapter 3, I’m really impressed.

Thus far, I don’t think I’ve seen any major differences between what the book describes (3.0) and what I’m using (4.0). I’m sure some will crop up, but I’m not worried.

Despite the fact that I honestly think this is a great book, part of my reason for posting this is to try out this new Amazon feature, where I can embed the first chunk of a book right in this post. They’re actually kind enough to let you read the first three chapters here, which rocks pretty solidly. (I suggest you go full screen with it.)

Of course, if you are willing to wait, the 4.0 version of the book is due out in December, and will contain WP7 specific content:

3 responses so far

More Windows Phone 7 Development Resources

Oct 05 2010 Published by under Windows Phone 7

Windows Phone 7 Jump Start Training 12 videos with close to 10 hours of hands on training. I’ve gone through the first two. Very accessible so far.

Programming Windows Phone 7 by Charles Petzold. This guy has been writing Windows programming books since day one. This is a free preview version of his new WP7 book.

C# Yellow Book by Rob Miles, one of the trainers in the Jump Start series above. The basics on C Sharp.

Channel 9 The MSDN developer portal. All kinds of Win Dev stuff including WP7.

XNA Creators Club Hard core XNA dev. Tons and tons of tutorials, articles, sample code, etc. Plus forums, and peer game review kind of stuff.

Comments are off for this post

Windows Phone 7 in 7: Getting Started with Windows Phone 7

Oct 01 2010 Published by under Windows Phone 7

A useful tutorial for getting up and running with Windows Phone 7.

Full disclosure: I was invited to embed this video by Unruly Media, who is working directly with Microsoft, and I may make a few cents per view. However, I wouldn’t be posting it here just for the money if I didn’t think the content wasn’t worth viewing.

One response so far

Drawing Primitives in XNA Game Studio 4.0

Sep 25 2010 Published by under Uncategorized, Windows Phone 7

So I’m working on porting Falling Balls over to Windows Phone 7. I have the animated stick figure, the motion code, the blood spatter, and sound effects all working. I’ll eventually need a real device to get the accelerometer stuff working, but in the meantime, I moved onto drawing the balls. In the game, I need to be able to make circles of arbitrary, random sizes. I looked into doing this with textures, starting with a circle bitmap and scaling it up or down, but we all know what happens when you start scaling bitmaps. Although it was a worthy experiment, it came out about as crappy as I expected it would. What I really needed was a way to dynamically draw a primitive circle.

In Flash, we all know how easy it is to draw a circle:

graphics.drawCircle(c, y, radius)

In Objective-C, I had to use some Core Graphics stuff, which, while a bit verbose (like all Objective-C), was eventually pretty straightforward. XNA, on the other hand, was really designed more for drawing textures, i.e. bitmaps. Once you get into drawing primitives like lines and circles, you need to code a lot closer to the metal. It took digging through a bunch of samples and forum and blog posts, but I think I finally distilled the core actions necessary to draw primitives.

On a side note, I think one of the reasons that people (at least seem to) like my tutorials, books, etc. is that I do distil things down to that base level needed to understand it. I personally find it difficult to find a lot of tutorials on the web that do that. For example, the primitive drawing sample code I learned most of this from gives you a class with hundreds of lines of code wrapping all the primitive drawing functions, and tells you to use this class. It’s great, I guess, if you just want some code that you can drag into your project and use, but it doesn’t explain much at all about what’s happening and why, other than a few one line comments. And there’s a whole lot of extra stuff going on there to make it flexible and reusable – good code, but it adds to the complexity if all you’re trying to do is learn what’s going on.

Drawing a Line

First let’s just draw a line. The first and most important concept you need to grasp is that all the primitive drawing stuff is really working with DirectX 3D drawing code. So even if you just want to draw a 2D line, you’re actually drawing a 3D line where all the points are at 0 in the z dimension. This also means we have to set up a viewport into our 3D scene, but we’ll want to do this so that it winds up just being a 2D scene and everything rendered at a z position of 0 will have a 1 to 1 ratio with the pixels of the screen when it is rendered. In other words, if I draw a line from 0, 0, 0, to 100, 100, 0 in the 3D space, it will draw that line from 0, 0 to 100, 100 on my screen.

We’ll also need to define vertex and pixel shaders on the graphics device. Scared yet? Yeah, so was I, until I realized that there are shortcuts for all this stuff. You still have to do it all, but it just takes a few lines of code that you don’t really need to fully understand. Of course, if  you want to understand it, by all means, dig in and learn more. But most of that is really only important when you start doing more complex 3D rendering. For drawing primitives in 2D, you really just need to know what to tell the system to make it work.

OK, first of all, create a new project in VS 2010 Express for Windows Phone. You can make it a WP7 project, Windows desktop, or XBox project, it doesn’t really matter, but I’ll be going with WP7.

This should give you your standard base class with Initialize, LoadContent, UnloadContent, Update, and Draw methods. We’ll need two class properties here, so add these in right away:

BasicEffect basicEffect;
VertexPositionColor[] vertices;

The basicEffect is where we set up our drawing properties – the viewport, how things are rendered, the shaders, etc. The vertices is an array of points. Actually, we’ll use the VertexPositionColor data type, which enapsulates a 3D vertex with a color.

Now, jump down to the Initialize method. Here’s where we set up the basicEffect and create a couple of points to draw a line.

protected override void Initialize()
{
    basicEffect = new BasicEffect(graphics.GraphicsDevice);
    basicEffect.VertexColorEnabled = true;
    basicEffect.Projection = Matrix.CreateOrthographicOffCenter
       (0, graphics.GraphicsDevice.Viewport.Width,     // left, right
        graphics.GraphicsDevice.Viewport.Height, 0,    // bottom, top
        0, 1);                                         // near, far plane

    vertices = new VertexPositionColor[2];
    vertices[0].Position = new Vector3(100, 100, 0);
    vertices[0].Color = Color.Black;
    vertices[1].Position = new Vector3(200, 200, 0);
    vertices[1].Color = Color.Black;

    base.Initialize();
}

First we create a new BasicEffect, passing in the graphics device. We tell it that we want to use colored vertices, so each point can have its own color assigned. Then we create our projection. This is what I was talking about making the 3D world look like a simple 2D plane. The Matrix.CreateOrthographicOffCenter function takes care of this for us. We pass it in the left, right, top and bottom coordinates of the area we want to look at, and a near and far plane. For this we use the coords of our physical screen, and 0 and 1 for the planes. Whew! That part is done. See, not so scary.

Then we create two colored vertices. One is at 100, 100 on x, y and the other at 200, 200. Both have a z index of 0 and a color of black. And that’s all we have to do to initialize. Now onto the Draw method.

Despite how scary I may have made it sound, you only need to write two lines of code to draw a line between these two points.

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.CornflowerBlue);

    basicEffect.CurrentTechnique.Passes[0].Apply();
    graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vertices, 0, 1);

    base.Draw(gameTime);
}

The first line (after clearing the screen) tells the basicEffect to apply whatever techniques it already has set up for drawing. This sets up the vertex and pixel shaders, etc. Do I have any idea what’s really going on there? Only vaguely. But if you leave that line out, You’ll get a run time error telling you that you need to define vertex and pixel shaders. So you better do it.

The next line is where the drawing happens. We call the DrawUserPrimitives method, telling it first what type of vertices we are using: VertexPositionColor. We pass this in the type of primitive we are are drawing. This can be a line list, line strip, triangle strip, or triangle fan. These should be familiar to you if you’ve dabbled at all in OpenGL or DirectX or even AS3’s advanced drawing API stuff in Flash Player 10. A line list is just that, a list of lines. The data in the vertices array is interpreted as pairs of points. It will draw a line between each pair. Then we pass the array of vertices itself, where to start drawing (0 means the first element in the array), and how many primitives to draw. Here we say 1, since we are drawing 1 line. A common mistake might be to pass in 2, thinking there are two poitns, but it’s the number of primitives, not the number of vertices.

Anyway, if you have that all right, you should be able to run this in the simulator and see a line on the screen. Yippee! An interesting point is that because each vertex has a color, you can get an automatic line gradient just by changing the color of one of the vertices. Try it:

vertices = new VertexPositionColor[2];
vertices[0].Position = new Vector3(100, 100, 0);
vertices[0].Color = Color.Black;
vertices[1].Position = new Vector3(200, 200, 0);
vertices[1].Color = Color.Red;

Neat, eh?

Drawing Multiple Lines

Now what about drawing more than one line? First, lets add a couple more vertices…

vertices = new VertexPositionColor[4];
vertices[0].Position = new Vector3(100, 100, 0);
vertices[0].Color = Color.Black;
vertices[1].Position = new Vector3(200, 100, 0);
vertices[1].Color = Color.Red;
vertices[2].Position = new Vector3(200, 200, 0);
vertices[2].Color = Color.Black;
vertices[3].Position = new Vector3(100, 200, 0);
vertices[3].Color = Color.Red;

Note that in the first line we specify that the array will have four elements.

Now in the Draw method, lets tell it we are drawing 2 primitives this time:

graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vertices, 0, 2);

Again, this is the tricky part. Remember that a line list takes the vertex array as a list of pairs of elements. So it looks at the first two vertices and draws a line between them. Then it takes the next two and draws a line between them. We have four vertices, so that’s two lines.

If we want to draw a continuous line between all the points, we should use a LineStrip. This takes the first vertex as the starting point, much like a moveTo in AS3, and each additional vertex will function as a lineTo. In this case, your number of primitives will be one less than the total number of points. We have four points, so that’s three lines.

graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, vertices, 0, 3);

If you want to draw a line back to the starting point, you’d have add another point to the array, with the same coords as the first one, and add one more primitive.

Drawing a Circle

There is no built in circle drawing function, so we have to roll our own. Luckily circles roll pretty well. (oh…..)

I’m not going to explain the trig here. If you don’t get it, go out and buy a few copies of my book. 😉 First we make the points:

vertices = new VertexPositionColor[100];
for (int i = 0; i < 99; i++)
{
    float angle = (float)(i / 100.0 * Math.PI * 2);
    vertices&#91;i&#93;.Position = new Vector3(200 + (float)Math.Cos(angle) * 100, 200 + (float)Math.Sin(angle) * 100, 0);
    vertices&#91;i&#93;.Color = Color.Black;
}
vertices&#91;99&#93; = vertices&#91;0&#93;;&#91;/csharp&#93;

Our circle will have 100 points. Its center will be 200, 200, and its radius will be 100. We use some trig to go around from 0 to just under PI * 2 and create 99 vertices around (0 to 98). Vertex 99 will be the same as the starting point so that the circle is closed.

In Draw, we just need to up the number of primitives to 99. Remember, with LineStrip, the number of primitives is one less than the number of vertices.

&#91;csharp&#93;graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, vertices, 0, 99);

There you go, a perfect circle. I’m sure it’s very obvious to you how to turn this into a reusable function, so I’ll leave that up to you, now that you know the basics. You probably know enough to make a DrawLine, DrawCircle, DrawRect, and maybe even a DrawCurve function.

Also note that the circle looks a bit rough. There doesn’t appear to be any antialiasing on it. I’m guessing that if you dig around in BasicEffect you might find something that makes it look prettier. Also, as far as I know, there is no built in way to change the line width. If you need something a bit more visually robust, check out this post:

http://blogs.msdn.com/b/manders/archive/2007/01/07/lines-2d-thick-rounded-line-segments-for-xna-programs.aspx

21 responses so far

Gravity Tutorial – Windows Phone 7 Version – Part III

Sep 20 2010 Published by under Windows Phone 7

If you’re not up to speed, make sure you go back and read Part I and Part II of this tutorial.

A Few Fixes

Before we go into user interaction, I wanted to make a few changes to yesterday’s code. We had a variable called ballSize which was set to 40, the circumference of the ball image. The actual position of the ball was the top left corner of the graphic, as that’s how textures are drawn. So in checking if it had hit any of the walls, I was checking for position.X < 0 on the left and position.X + ballSize > width on the right. I’m changing that up a bit here now. The position will actually be the center of the ball. To do this, I changed ballSize to radius and set it to 20. This allows the wall collision code to become:

if (position.X + radius > width)
{
    position.X = width - radius;
    velocity.X *= bounce;
}
else if (position.X < radius)
{
    position.X = radius;
    velocity.X *= bounce;
}
if (position.Y + radius > height)
{
    position.Y = height - radius;
    velocity.Y *= bounce;
}
else if (position.Y < radius)
{
    position.Y = radius;
    velocity.Y *= bounce;
}&#91;/csharp&#93;

which is more like what it should be. Now we just need to force the ball to be drawn so that its center is on position x, y, instead of its top left. To do that, I made another Vector2 called centerOffset and set that to -21, -21. This is because although the ball itself is 40 pixels across, the graphic is actually 42x42 to allow a bit of space for antialiasing or whatever. Now, when we draw the ball in the Draw method, instead of drawing it at position, we draw it at position + centerOffset. This puts the center of the ball on the position point.

&#91;csharp&#93;spriteBatch.Draw(ball, position + centerOffset, Color.White);&#91;/csharp&#93;

<strong>Getting Touchy</strong>

OK, now we deal with the touch screen and finding out when and where the user might have touched it. I'm not sure the following is the BEST way of handling this, but it certainly works. Basically, we need to get a list of all the active touch points. I believe XNA lets you have a total of four at any one time. These come in as a TouchCollection by calling GetState() on an object called the TouchPanel, like so:

[csharp]TouchCollection touchCollection = TouchPanel.GetState();

Now we can do a foreach loop through this collection. Each object in it will be a TouchLocation, which has a State, which can be Pressed, Released, Moved, or Invalid. A TouchLocation also has a Position property, which is simply a Vector2. So, what we can do is the following:

– If Pressed, check the distance of the touch to the position of the ball. If it’s within a certain range, set a variable called dragging to true and set position to the touch position.

– If Released, just set dragging to false.

– If Moved, set position to the touch position, but also see how much the touch has moved since the last time around and use this to set the velocity. More on that soon.

Here’s what that chunk of code looks like:

TouchCollection touchCollection = TouchPanel.GetState();
foreach (TouchLocation tl in touchCollection)
{
    if (tl.State == TouchLocationState.Pressed)
    {
        if (Vector2.Distance(tl.Position, position) < radius * 2)
        {
            dragging = true;
            position = tl.Position;
        }
        else
        {
            dragging = false;
        }
    }
    else if (tl.State == TouchLocationState.Released)
    {
        dragging = false;
    }
    else if (dragging && tl.State == TouchLocationState.Moved)
    {
        velocity = (tl.Position - position) / elapsed;
        position = tl.Position;
    }
}&#91;/csharp&#93;

For the Pressed state, we check: if (Vector2.Distance(tl.Position, position) < radius * 2), checking if the distance between the two points is less than radius * 2. Technically, this should just check if it's less than radius. If I were doing a traditional mouse based game, that's what I would do. But on a touch screen, it's hard to be very precise with a finger, so I'm allowing some leeway on how close the finger has to be to the center of the ball. This is something that I would probably want to test on an actual device and come up with a better number based on real world testing.

A few things to note about the Moved state: of course, we only want to change the position and velocity if we are actually dragging, so we check that right off. Then we subtract the current touch position with the previous ball position. That's how far it's moved since the last frame. We divide that by the elapsed time to convert it from pixels per frame to pixels per second. Then we are safe to assign the touch position to the ball position.

Finally, if dragging is false after all those checks, just carry on with the existing motion code that we wrote yesterday.

But if dragging is true, we just skip over all that stuff and allow the touch to dictate the location of the ball. Again, this is all covered in my ActionScript Animation book and previous tutorials. Not going to beat a dead horse. We just wrap all the motion code in a  if (!dragging) statement and be done with it.

So there you have it. The ball bounces around, and you can pick it up and toss it too. I guess that for the time being, I'm going to skip over the accelerometer code, because you really need to have a device to test that. Anyway, here is the entire code for today's post:

&#91;csharp&#93;using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

namespace GravityTutorial
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D ball;
        Vector2 position;
        Vector2 velocity;
        Vector2 centerOffset;
        float radius = 20;
        float gravity = 500;
        float bounce = -0.9f;
        Boolean dragging;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            // Frame rate is 30 fps by default for Windows Phone.
            TargetElapsedTime = TimeSpan.FromTicks(333333);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            ball = Content.Load<Texture2D>("ball");
            position.X = 100;
            position.Y = 100;
            velocity.X = 150;
            velocity.Y = 175;
            centerOffset.X = -21;
            centerOffset.Y = -21;
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

            TouchCollection touchCollection = TouchPanel.GetState();
            foreach (TouchLocation tl in touchCollection)
            {
                if (tl.State == TouchLocationState.Pressed)
                {
                    if (Vector2.Distance(tl.Position, position) < radius * 2)
                    {
                        dragging = true;
                        position = tl.Position;
                    }
                    else
                    {
                        dragging = false;
                    }
                }
                else if (tl.State == TouchLocationState.Released)
                {
                    dragging = false;
                }
                else if (dragging && tl.State == TouchLocationState.Moved)
                {
                    velocity = (tl.Position - position) / elapsed;
                    position = tl.Position;
                }
            }

            if (!dragging)
            {
                float width = graphics.GraphicsDevice.Viewport.Width;
                float height = graphics.GraphicsDevice.Viewport.Height;

                velocity.Y += gravity * elapsed;
                position += velocity * elapsed;

                if (position.X + radius > width)
                {
                    position.X = width - radius;
                    velocity.X *= bounce;
                }
                else if (position.X < radius)
                {
                    position.X = radius;
                    velocity.X *= bounce;
                }
                if (position.Y + radius > height)
                {
                    position.Y = height - radius;
                    velocity.Y *= bounce;
                }
                else if (position.Y < radius)
                {
                    position.Y = radius;
                    velocity.Y *= bounce;
                }
            }
            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(ball, position + centerOffset, Color.White);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

5 responses so far

Gravity Tutorial – Windows Phone 7 Version – Part II

Sep 19 2010 Published by under Windows Phone 7

Assuming you’ve gone through Part I, you now have a ball showing up at location 100, 100 on the simulator screen. Now let’s get it moving. Here’s the plan: we’ll set up another Vector2 for velocity, and add that to position on each frame, then check to see if we’ve hit any walls and bounce off them.

We’ll jump ahead hear and add a few more variables that we’ll eventually need, just so they’ll be there. Again, right with the rest of the class variables:

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D ball;
        Vector2 position;
        Vector2 velocity;
        float ballSize = 40;
        float gravity = 500;
        float bounce = -1.0f;

We can initialize the floats as we create them, and in LoadContent, we’ll initialize the velocity.

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    ball = Content.Load<Texture2D>("ball");
    position.X = 100;
    position.Y = 100;
    velocity.X = 150;
    velocity.Y = 175;
}

Note that the velocity values may seem high if you’re using to doing things on a pixels-per-frame basis. Here, we’ll be multiplying by the elapsed time that has passed since the last frame, so we’re really taking pixels-per-second here. This is also why the gravity value is so high.

Now we need to simply add the velocity to the position and check the boundaries. If you’ve read my AS3 Animation book, this should be old hat to you. In fact, if you’ve done any programmatic animation, this should be all very familiar, so I’m not going to go through it line by line, just touch the highlights. This code goes, of course, in the Update method.


protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

float width = graphics.GraphicsDevice.Viewport.Width;
float height = graphics.GraphicsDevice.Viewport.Height;

float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
velocity.Y += gravity * elapsed;
position += velocity * elapsed;

if (position.X + ballSize > width)
{
position.X = width – ballSize;
velocity.X *= bounce;
}
else if (position.X < 0) { position.X = 0; velocity.X *= bounce; } if (position.Y + ballSize > height)
{
position.Y = height – ballSize;
velocity.Y *= bounce;
}
else if (position.Y < 0) { position.Y = 0; velocity.Y *= bounce; } base.Update(gameTime); }[/csharp] First we get the width and height of the screen. It's a bit convoluted, but there it is. As an aside, if Objective-C likes long-winded property and method names, C Sharp seems to like digging into sub-objects to get at deeply nested properties. That violates a principle or two, but we'll let it slide. Next we get the elapsed time since the last Update call. Update is passed a GameTime object. We can go diving into that to get the elapsed time in seconds and multiply the velocity by that before adding it to the position. From there, it's all basic motion code. Add gravity to velocity, velocity to position, check the left, right, top, and bottom edges, reset position if the ball has gone past any of them, and reverse the velocity on the specified axis. And there we have it. A bouncing ball. No interaction with touches or accelerometer yet, but this should be enough to get you started. I'll try to add more features to this in the next day or two.

One response so far

Older posts »