This is something I’m pretty excited about. The xna3way gang is proud to announce:
The Community Games (using XNA Game Studio) DVD Project!
This project is a showcase of work being done by people in the developer community using XNA Game Studio Express or Game Studio 2.0. It doesn’t matter if you are a professional developer, hobbyist or student. As long as your game is complete and playable, and you don’t mind sharing the source code then there’s room for you on the disk(s).
This is a living project, so there aren’t any hard deadlines. Once enough projects are submitted to fill the first DVD, an image will be made and then work will begin on the second disk, etc… The disks will be available for download as images and will also be distributed on physical media (details pending.)
The great thing about this project is that there is no cost to be included. The only requirements are as follows:
The game must be complete: playable and winnable. We aren’t looking for toolkits or libraries.
All source code must be included.
No stolen resources (this includes art, music, fonts, etc.) If you didn’t make it, you need permission to distribute it.
No offensive, obscene or pornographic content. Keep it clean. No drugs, racism or sex.
A lot of people will see these games. If you’re looking for a good way to get your game in the hands of a lot of people, for free, don’t miss this opportunity.
Stay tuned for more information!
For now, if you have questions about this project, contact me via this blog. I’ll post a URL soon with more info and a mechanism for submitting your games.
(For those of you wondering about Treehouse Troubles, yes it will be making an appearance on the first DVD.)
NOTE: This project is not affiliated with Microsoft or the XNA product team.
Well… Buttnumbing Code-a-thon II was a lot of fun and generally regarded as a success. We continue to work on our game, Treehouse Troubles and it should be finished in the next month or so. Georgie had to bow out this time around due to a family emergency, but we pressed on in his absence. Fortunately the ZMan was able to step in and help out with some hilarious voice-overs and George did come through for us in a big way with some much needed art assets. It was a lot of fun and I can’t wait to do it again next year.
Stay tuned to the next blog post for a very special announcement.
That’s the sad reality. We all got together in January, worked our asses off, fell a little short of our goal and then went our separate ways. The plan was to keep chugging along, but work, new babies, upcoming babies, Reality Check Games, moving and the need for sleep kept us from ever coming back to it.
I can’t promise that we’ll ever get back to Gejach, or Paradox. Too many exciting new ideas have come up and been forgotten since then, but still we’ve all kept in touch, and we’ve all been playing with new technologies and allowing greatness to percolate in the backs of our tiny little rat brains.
I’ve been playing more and more with TorqueX lately and I’m really impressed with how it’s shaping up, The TorqueX Builder (TXB) is a thing of beauty and makes parts of the process really painless. I’ve also been beta-testing some of their tutorials, which have helped my ramp up time, a lot! (I highly recommend the tutorials. Very well written.)
So anyway, I’ve just about convinced my buddy George to give TorqueX a try (he says.. “I’m just the artist” but we know that’s a load of crap.) Jason is hot on it again, so assuming no RC planes fly by (and blizzard doesn’t release another WoW expansion) we should be able to keep his interest long enough to crank something out, even if its just a rough prototype.
So Butt-numbing Code-athon 2 (aka my birthday) is coming up in a few months, and this time I think we’re gonna do it in Seattle. I dunno yet for sure. Maybe Portland. The plan is to work on (the beginnings of) a dungeon crawl. More on this and BnCa2 later.
Well, we went. We coded. We had a blast, celebrated a birthday,drank a ton of Woodchuck (well, I slowly sipped a couple of Woodchucks, but that’s just how I roll), played a mighty game of WoW: the Card game that will be recorded in the annals of history, but did we finish a game in a weekend? Umm..no.
No beating around the bush here. It was difficult, we gave it a run for the money and what we made we are dang proud of, but it’s not a game. Yet. We walked away from that weekend so excited by what we had started that we just have to finish it. We are like men possessed. Well, Jason and Chris are like men possessed, I came back from that weekend and slept. A lot.
Now though, I feel like I’m regaining my strength. I’m prepping my mind to re-enter the beauty that is our framework and work mighty wondrous things.
First though, I thought I would share a little teaser of the game intro. I mean who cares about gameplay, check out this snazzy title screen. MMMM…..good (although don’t get attached to that name, I think that’s still up in the air….)
For those of you who can’t see the embedded video, you can watch the video here).
[Yeah, I got the video working…enjoy! Hopefully there will be more videos and art assets to follow soon…]
Well, I said that I had my strength back, but I hear the call of some other projects right now that want to borrow a little of that strength. I do however to go through some of the artwork I made that weekend and post various samples to wet your whistle with. Once I get that finished, I need to huddle close with my co-conspirators and figure out what gameplay element we each will be focusing on next. I’m hoping they don’t say coffee runs again, I swear guys I can code! Geesh, mistakenly recode the .NET type framework one time and you’re fetching coffee and beef jerky all night long….
Well, we’ve done a METRIC CRAP TON of coding this weekend (and George doing art until this evening before joining the rest of the code monkeys). There will definitely be learning experiences we take away from this. For example, I definitely underestimated the amount of effort to write a framework for us from the ground up. However, it is mostly behind us now so we are starting to make good progress on game play. That’s another post for another time though.
I was _very_ skeptical that we would get this done this weekend until quite recently. However, things are really starting to come together. The game won’t be completely finished (it won’t include particle effects and the like and some of the other publish). We’re making good enough progress though that we have decided to pull an all-nighter tonight (the night before George and I fly back to the Northwest).
We haven’t made as many videos as I would have liked. Truth be told, I gave up like a fat, pimpled high school loser trying to get laid before flying off to college (without having to fork over cash before the “transaction” that is). First day we had some great conversations about game play and the trade-offs we were making but weren’t running the camera at the time. So, you may just have to settle for posts now (although I can at least prepare some of the first videos we did if you are all curious). I know I’m a geek (okay, borderline nerd), but I’m fairly excited about this all-nighter. I’ve never really done the all-night coding thing with friends, let alone stopping in the middle of it for a 3am Denny’s run. It should be a blast (no comments from the peanut-gallery about the fat guy being excited about the late night Denny’s trip, okay? M’kay?!?!?).
Well I’m burning precious coding time, so I must be getting back.
Say the word aloud. Feel it reverberate in your skull like the force-feedback of an Xbox 360 controller in your hand.
So, what is Gejach? The short answer is that it’s a space shooter. Think of it at the transgenerational love child of Geometry Wars Evolved and Yars Revenge. Gameplay is deliciously simple, with a control schema reminscent of the two stick action of Geometry Wars combined with some of the basic “use your enemies defense as your offense” elements of Yars Revenge. It’s quite possibly the best of both worlds.
The premiseÂ
We’re developing for multiplayer first, with single play AI if time permits. Objective Numero Uno was to have a working, playable, winnable game by Monday 1/8/07. We determined that we could get multiplayer done faster than single player combined with enemy AI.
The Controls
The control schema is kept simple so it works equally well on the 360 as on Windows simply by designing for a wired 360 controller. Button mashing is eliminated in favor of smooth stick control for moving and firing (ala Geometry Wars, ala Robotron 2084.) Harvesting and the SuperWeapon (fueld by harvesting, ala Yars Revenge) is handled by the two triggers.
The Gameplay
You are the lone pilot and commander of your planetary defense system. Your mission is twofold. First, protect your planet from attackers by engaging and destroyer them in space combat. Your planet has a basic energy shield which is gradually weakened as it is attacked (or harvested) by your opponents. Simply playing defensive is not enough to win the game. Destruction of your opponents homeworld is the only way to ensure the peaceful existence of your species.
To this end, a superweapon was created. Unfortunately your world is not powerful enough to fuel the weapon and the planetary shield. It falls upon you to not only guard your home planet and engage attackers, but to also steal energy from your enemies defenses in order to power your superweapon.
Unfortunately, being energy based, your superweapon has its limitations. While it’s strong enough to destroy a planet with a single burst, if the ray is intercepted by the planetary shielding the energy is harmlessly dispersed across the grid. You must aim your shot to get through the holes in the shield created by your primary ship weapons. Sounds easy enough, right?Â
Keep in mind your enemy will be doing the exact same thing. In addition to your enemies, certain other obstacles may be in your way. One of these obstacles is asteroids. Big, bouncy asteroids. To help you, the ruling council of your planet has decided to teleport ship & weapon enhancements to you. Unfortunately their aim isn’t so good and these enhancements tend to end up floating space where anyone can grab them.
So how do I steal energy?
This is accomplished by skimming the energy shield of the opposing world while pressing the Left Trigger. Energy is transferred to the ship where it can be used for a superweapon blast or carried back to the player’s homeworld to augment the planetary defense system.
Okay, the site is working again with Firefox. It turns out that it wasn’t a CSS issue. The issue was with some code formatting done by WordPress.
WordPress adds padding (using <p> tags) around content to get a nice content layout that isn’t too crowded. While it accounts for HTML elements like TABLE and the like, it doesn’t currently account for the OBJECT element (at least the version of the code base this site is running on). Because of this, when I used the OBJECT tag for my embedded video in the tutorial, it broke all the layout because it added a </p> tag after the object tag and before all the parameters.
So to fix it, I had to pop in to the PHP code and add OBJECT| to some of the RegEx expressions for the padding function. Yuck! I can’t believe I had to edit PHP code to fix it. Then again, the code was right there, so I could edit it just fine even though it was a bug in the product. So that’s pretty cool . A huge thanks go out to the Support Forums for WordPress where I found the solution right away since others have had the problem as well.
I also made some corrections to the various images we were adding in order to make the site XHTML compliant again. So, long story short, the site works again in Firefox and we are XHTML compliant as well.
Thanks to Ben and others, I’m now aware that the stylesheet is now broken for FireFox. It’s my own fault since I spent some time expanding the width of the site last night and adding the styles for the code. Apparently this broke it in FireFox.
Why didn’t I test it? Well, to be honest, I uninstalled FireFox as soon as I started using the latest IE .
So, time to re-install it and try to get this stylesheet working again. Apologies to all you FireFox users (since the code and tutorial obviously look like utter crap to you).
Welcome to my first tutorial here on Xna3Way.com. No, this is not another “how to create a Sprite” tutorial. I figure you can get those types of topics either from the help file or from the wealth of other tutorials that are already out there on the net. My goal in my set of tutorials is to cover topics that you might not see elsewhere. I’ll be covering all sorts of cool topics from Sprite Animation Frameworks, to Flocking algorithms, to board game AI, and many others. Basically, wherever the prevailing winds decide to take me. I warn you now though that I’m a stickler for well-designed code. So if you are looking for truly craptastic code that you can copy-and-paste and spend days trying to get work, you definitely won’t find it here. Wait, you _aren’t_ looking for that you say? I didn’t think so . Well then, read on.
In this tutorial, we will discuss building a Sprite Animation framework that you can use to do all sorts of cool and complex animations of sprites. The framework we will implement is very simple. At the same time, it also enables some pretty complex behaviors via animation composition. So enough of me “blowing smoke where the sun don’t shine,” let’s get down to business y’all.
The End Product
For those of you that are as impatient as I am when it comes to tutorials, let’s just skip to the end and see what we will be building in this tutorial. Here is a video that shows the animation framework in action (for those of you who can’t see the embedded video player below, you can watch the video here).
This is what we will be building in this tutorial.
Our Goals
Let’s talk a little about the goals that we are wanting to achieve with this framework we will be building.
First of all, it should be simple to add animations to a Sprite. Not only that, but the individual animations should be small and easy to maintain. If animations are bulky, it becomes a pain to use them. And we don’t want that, do we? By making the individual animations very small and atomic, we can build more complex animations by bundling up smaller animations together. This compositional model for animations becomes very powerful, as we’ll see below.
Sprites
Since a Sprite Animation framework would largely be useless without a Sprite class to animate, we might as well start there. The main definition of a sprite is split among two classes, the Sprite class and the SpriteParameters class. The Sprite is the heart of our system. The SpriteParameters class defines the “essence” of a sprite like the Position, Tint, Scale, etc. By splitting this information out into its own class, it becomes easier to animate it by simply requesting the various animations to modify a SpriteParameters instance to reflect its animation results. Here’s what they look like:
The SpriteParameters class is pretty straight forward. Let’s look at the code:
1: class SpriteParameters : ICloneable
2: {
3: //
4: // Fields
5: //
6: publicbool IsVisible = true;
7: public Vector2 Origin = Vector2.Zero;
8: public Vector2 Position;
9: publicfloat Rotation;
10: publicfloat Scale;
11: public Color Tint;
12:
13: //
14: // Constructors
15: //
16: public SpriteParameters()
17: : this(Vector2.Zero, Color.White, 0, 1) { }
18: public SpriteParameters(Vector2 position, Color tint, float rotation, float scale)
The first thing you might notice is that I’m not using properties in this class. There’s a good reason for this. I don’t believe in using language features just because you “should” use them. It all depends on the situation. In this case, SpriteParameters is a very simple data structure that has no behavior. Because of this, I believe there is no reason to encapsulate the fields at this time. If at a later date I need to add behavior to this class, I can refactor the public fields into properties then.
The implementation of ICloneable is merely a convenience. This way, when we need to create a new instance of SpriteParameters, we can simply clone the existing one defined for the Sprite that we are bound to. We will leverage this Clone() method in the AnimationManager class, which we’ll take a look at in the next section.
Finally there is the heart of our system, the Sprite. Most of the Sprite class is pretty self explanatory. Let’s take a look:
1: class Sprite
2: {
3: //
4: // Fields
5: //
6: private AnimationManager animationManager;
7: private SpriteBatch batch;
8: private ContentManager contentManager;
9: private Texture2D image;
10: private SpriteParameters parameters;
11:
12: //
13: // Constructors
14: //
15: public Sprite(GraphicsDevice graphicsDevice, ContentManager contentManager, Vector2 position, string assetName)
16: {
17: this.contentManager = contentManager;
18: this.image = contentManager.Load(assetName);
19:
20: this.parameters = new SpriteParameters();
21: this.parameters.Position = position;
22:
23: this.animationManager = new AnimationManager(this);
24: this.batch = new SpriteBatch(graphicsDevice);
25: }
26:
27: //
28: // Properties
29: //
30: public AnimationManager Animations
31: {
32: get { returnthis.animationManager; }
33: }
34:
35: public Texture2D Image
36: {
37: get { returnthis.image; }
38: }
39:
40: public SpriteParameters Parameters
41: {
42: get { returnthis.parameters; }
43: set { this.parameters = value; }
44: }
You can see this first part of our Sprite class is pretty simple. The largest part of the Sprite class is our Draw method (which really isn’t all that large as you’ll see:
You can see here that we get the SpriteParameters that we use to draw our sprite from our actual animation framework. The main interface into our new animation framework is our AnimationManager. We’ll take a look at that in the next section. As you can see, the interface into our animation framework is very small and very simple. Remember, that is one of our goals.
Since we haven’t hit any of the “meat” yet, I will go ahead and move on to our Animation framework . MOVING ALONG!!!
AnimationManager
Sprites are the heart of our system, that’s true. But Sprites our only a part of the larger picture. To animate our Sprites, we need the framework that will do the actual animation. This is achieved through a simple AnimationManager that will manage all the various animations that are attached to a sprite. The interface to our AnimationManager is pretty small. Let’s take a look.
So, what are animations? As you can see, they run the gamut. The key is that they are each small, and do purely atomic animations. This gives us the power of writing complex animations by composing many smaller animations together rather than creating a seperate animation for every possible combination we could have.
You may also notice that the power of the system is done through composition, not through inheritance. This is intentional. When you inherit one class from another, that newly inherited class is now tightly coupled to its parent. We want to reduce this coupling. If we used inheritance for our different animation types, we would be introducing unnecessary coupling into our system that could limit the number of behaviors we could build (or at least make them less atomic and harder to maintain). We will take a deeper look at the various animations later. For now, lets dig into our AnimationManager, the interface into our animation system.
The “brain” of our animation system is the AnimationManager. While it’s the “brain” of our system, it’s not really all that complicated itself (I know, I’m sure you’re sick and tired of me saying “it’s simple” and “it’s not complicated” already). Let’s look at the code for it.
1: public SpriteParameters Animate(GameTime gameTime)
Here we process the first animation that we have attached. It is not a foreach of all our animations. When animations are attached, they are processed sequentially (one after the other). This means that the second attached animation won’t process until the first one is finsihed. If you need several animations to run at a single time, that is what the CompositeAnimation is for (as we’ll see in “Putting it all together” below). Once the animation is finished, we remove it from the list of animations that are currently attached to the Sprite. We know an animation is finished because it has marked itself as finished. This means that the concept of a “finished” animation is completely up to the discretion of the animation itself.
1: // Auto adjust location if we are rotating.
2: // This will force a rotation around the center of the image rather than the top left
3: if (animatedParameters.Rotation > 0)
4: {
5: Vector2 center = new Vector2(boundSprite.Image.Width / 2,
6: boundSprite.Image.Height / 2);
7:
8: animatedParameters.Origin = center;
9: animatedParameters.Position += center;
10: }
I admit, this part is kind of a “hack.” When rotating a Sprite in the draw method of a SpriteBatch in XNA, the rotation will actually occur around the Position specified, unless an Origin is specified. So, to get the image to rotate around it’s center, we need to specify the center of the image as the Origin of the image. This has an unintended consequence (well, “intended” if you are fmiliar with the XNA Framework). This consequence is that the Position specified in the draw method is assumed to be the position of the Origin on the screen. So, to have the Position still be the upper left of the image in our parameter stack, we need to offset the Position to the center of the image.
After we have accounted for the rotation of our Sprite, we simply return the animatedParameters that we have modified as part of our animation:
1:
2: return animatedParameters;
3: }
4: }
And that’s all there is for our AnimationManager. Not very interesting in of itself until you consider the various animations that we have implemented as part of our animations framework. So what do the animations shown above in the UML diagram actually do?
SpriteAnimations
The animations above are acutally not all that special. What do they do? Well, let’s discuss.
TimedAnimation - This animation accepts as a parameter another animation that should run for a specified amount of time. Therefore, if I want the AutoRotateAnimation to run for only two seconds, I can create a TimedAnimation that lasts for two seconds and is passed the AutoRotateAnimation (or any other animation) to run during that timeframe.
CompositeAnimation - This allows many animations to run at the same time. By default, animations are sequential. If I add two animations to a Sprite via AddAnimation(), the second one added won’t run until the first one is finished. CompositeAnimation is the way to get around this. Since CompositeAnimation is just a SpriteAnimation, an instance of it can be passed to DelayedAnimation like any other type of Animation.
RotateAnimation - With RotateAnimation, you can specify the “speed” of the rotation (how many seconds it takes to rotate completely around a single time) you wish for a specified Sprite to have. As it exists now, it will auto rotate forever (which is why I’m currently using it below on the windowsSprite in combination with the TimedAnimation to prevent it from lasting forever).
PathAnimation - This animation accepts two parameters: the speed at which to progress between waypoints, and an array of waypoints to animate to. In the TitleScreen.cs file, I’m only ever using a single waypoint. However, I could pass in three, five, seven, or however many waypoints as I wish and this animation would process from it’s original position to every single waypoint specified in the animation. You could very easily imagine this animation being used as output from an A* algorithm for pathfinding in NPCs and the like.
BlinkAnimation - This animation will “blink” a Sprite at a specified frequency.
InvisibleAnimation - If you want a Sprite to “disappear,” this is the way to go. InvisibleAnimation will set the IsVisible property of a Sprite to false every time through the animation loop. By its own definition, an InvisibleAnimation will never actually finish. If you want the Sprite to only be invisible for a specified amount of time, use this animation in combination with a TimedAnimation.
Although we won’t take a look at the code for all of these animations (you can go grab the code zip file for that), we will discuss the implementation for a couple of them. Let’s go ahead and start with the BlinkAnimation.
As mentioned above, the BlinkAnimation will “blink” a Sprite at a specified frequency. It’s pretty simple how this is done:
Yes, a good number of SpriteAnimations are acutally this simple. This is what I was talking about when I said that the compliexity of animations is derived from the composition of many smaller animations rather than complex individual animations. In the case of BlinkAnimation, each time through the Animate loop (calls to Animate) we subtract the elapsed time from the time we have been waiting. If we have reached the blink length, we toggle the visibility flag of our Sprite. This means that if I create a BlinkAnimation with the TimeSpan of two seconds, the Sprite will be visible for two seconds, invisible for two seconds, visible for two seconds, invisible for two seconds, and so on and so on.
How about the TimedAnimation?
1: class TimedAnimation : SpriteAnimation
2: {
3: //
4: // Fields
5: //
6: private SpriteAnimation animation;
7: private TimeSpan timeLeft;
8:
9: //
10: // Constructors
11: //
12: public TimedAnimation(TimeSpan length, SpriteAnimation animation)
All we do in TimedAnimation is wait for the specified amount of time, and then mark the animation complete. If the animation isn’t complete yet, we actually call the child animation that we are timing. If you want to see the implementation for the other animations that are part of this whole package, make sure to grab the code from the Downloads section below.
So, what are some examples of some other animations that you can build to augment this framework even more? Here’s a couple that I have implemented in my own games to get your mind thinking:
DelayedAnimation - This will wait a specified amount of time before kicking off another animation. For example: if I want the sprite to wait for five seconds and then disappear, I can create a DelayedAnimation of five seconds that then kicks off an InvisibleAnimation. This becomes even more powerful when combined with other animations like CompositeAnimation and SequentialAnimation to kick off entire chunks of animations.
SequentialAnimation - This takes a series of animations that will be executed sequentially. By default, you can do this by simply adding many animations to the Sprite via the AnimationManager. However, this allows you to create a block of animations that are managed together. With the combination of CompositeAnimation, DelayedAnimation, and TimedAnimation, it becomes a very powerful compositional tool to build complex animations out of simple ones.
ColorAnimation - Animates the color or “tint” of a sprite. Currently, this just sets the tint to a single color (I use it for my menu items and such to emphasize which option is currently chosen). You can probably imagine this being expanded though to allow cycling through the actual color wheel in order to achieve a slightly psychadelic effect.
PulsateAnimation - This will scale the sprite using a specified speed and scaling factor. This gives the effect of the Sprite “pulsating.” I have used this on my menu option sprites to help emphasize which menu option is chosen, although there are many other uses as well.
What animations can you think to add that would make this animation framework even cooler for your own use? Perhaps enhancing the PathAnimation to use Curves as well to allow curved paths? Perhaps a StretchAnimation that will stretch the sprite along a specified axis? It’s all up to you and your imagination .
Putting it all together
“How does this all fit together,” you might ask. Good question! When we create our sprites, we also add any animations that we want our sprites to have. It’s really as simple as creating a new animation and adding it to the AnimationManager bound to our Sprite.
Let’s say that I want a sprite to blink every two seconds. To accomplish this, all I need to do is attach a BlinkAnimation to our ActionManager via the Sprite instance. Like this:
18: windowsSprite = new Sprite(graphics.GraphicsDevice,
19: content,
20: new Vector2(600, 300),
21: ImageFiles.Windows);
22: windowsSprite.Animations.Add(
23: new TimedAnimation(TimeSpan.FromSeconds(4), new InvisibleAnimation()));
24: windowsSprite.Animations.Add(
25: new CompositeAnimation(
26: new RotateAnimation(TimeSpan.FromSeconds(1.5)),
27: new PathAnimation(400.0f,
28: new Vector2[] { new Vector2(20, 300), new Vector2(600, 300) })));
29: }
30: }
Let’s dig apart each one. mySampleGameSprite:
1: mySampleGameSprite = new Sprite(graphics.GraphicsDevice,
2: content,
3: new Vector2(200, -50),
4: ImageFiles.MySampleGame);
5: mySampleGameSprite.Animations.Add(
6: new PathAnimation(200.0f, new Vector2[] { new Vector2(200, 400), new Vector2(200, 200) }));
Here we are using a PathAnimation with two waypoints. This will start the sprite at [200, -50], and move it to [200, 400], followed by [200, 200], at a rate of 200 pixels per second.
1: xna3waySprite = new Sprite(graphics.GraphicsDevice,
This will simply blink the xna3way sprite every 0.4 seconds (400 milliseconds). Once again, pretty simple. The windows sprite is where it gets a bit complicated though. Let’s take a look:
1: windowsSprite = new Sprite(graphics.GraphicsDevice,
2: content,
3: new Vector2(600, 300),
4: ImageFiles.Windows);
5: windowsSprite.Animations.Add(
6: new TimedAnimation(TimeSpan.FromSeconds(4), new InvisibleAnimation()));
7: windowsSprite.Animations.Add(
8: new CompositeAnimation(
9: new RotateAnimation(TimeSpan.FromSeconds(1.5)),
10: new PathAnimation(400.0f,
11: new Vector2[] { new Vector2(20, 300), new Vector2(600, 300) })));
Here we have two animations in sequence. First, we make the Sprite invisible for four seconds using a TimedAnimation. Once that animation is finished, we use a CompositeAnimation to perform two different animations at the same time. First of all, we rotate the Sprite at a rate of one revolution every 1.5 seconds. Second of all, we make the windows image move to the left of the screen and back to the right using a PathAnmimation. Because we create the RotateAnimation and PathAnimation within a CompositeAnimation, the image will rotate _while_ it is navigating the path. This is a good example of the type of complex animation you can achieve by simply combining several smaller animations.
In Closing
Well that’s about it for now. I hope you all enjoyed the first tutorial here on Xna3Way.com. I hope that there will be many more like it. There are many subjects I wish to talk about including flocking algorithms, tactical AI, board game AI (Minimax / Negamax), etc. There is definitely no shortage of topics to be discussed (although I’ll freely admit that I’m a slacker, so who knows how many of these subjects will wind up getting tutorials written about them). If you have any questions regarding this tutorial, feel free to contact me at jolson88 AT yahoo DOT com.
So until we meet again, remember, that’s how the cookie crumbles .
Downloads
Code. A zip file containing the project file and code for this tutorial.
You could assume this is because out of the three of us, I slack the most. I could argue that you were wrong and point out all of the things I’ve currently got going on, but it would just be a front. A cleverly thrown argument to confuse and mislead you from the truth. You see, I am the king slacker.
Sure, I might be running an XNA community site. I might be uber active in the MSDN XNA forums. I might be getting interviewed by Rory and responding to tons of fan mail (”We love you George W. Clingerman from XNADevelopment.com!” Just remember girls, I’m married so NO I won’t be making 2D love with you). I might be raising a family of three rambunctious boys. It might be the Christmas season and we might be doing things like decorating the house, getting a Christmas tree and doing secret Christmas shopping. I might have an application in beta at work. I might be working on some secret projects that I can’t even talk about here. I might be doing all of those things and just not have enough time to post….but I’d be lying.
Truth is, I’m a procrastinator and a slacker. Laziness is an art form I’ve become to lazy to perfect.
So yeah, I’m lazy and now I writing about this upcoming trip excitement last. Serves me right.
So what do I envision for this trip? I see the rise and fall of empires, I see epic romance, I see friendships forged in the dwarven fires of old broken asunder by the hounds of hell. I see Jason and I needing another blanket on the flight. I see a heckuva a lot of fun with the potential of something superbly wonderful potentially being spawned from the guaranteed chaos of the three of us being in the same earthly location.
We have no idea what we’re going to make. We’ve never worked on a project together. We’ve never even hung out as a group before. We have no idea if we’ll even get it done.
What we do know is that we love XNA. We love coding. We love making games. We know how to make games and we sure as hell know how to have a good time.
So whether the game ends up being that ashtray/plate/bowl/paperweight pottery item thingy we made for our mom in Art Class in high school or it ends up being the next World of Warcraft (*snicker*), we’re going to have a blast doing it, I wouldn’t want to be doing it with any other guys and only good fun and great memories will come out of this trip…