Tuesday
Mar022010

Acid Rain: A Hero's Journey --Dream Build Play 2010 Entry

  I submitted my game into Microsoft's 2010 Dream Build Play competition today. Deadline is tomorrow March 3rd so i just made it in.

Watch it full screen at Youtube: Acid Rain  

Make sure you switch the video to 720p in the lower right of the video window.  It defaults to 360p which looks fuzzy.

Whew.  I'm going to take a little break from my game and catch up on stuff I have neglected. I hope to do some posts about the tools I used to make my game and I'd like to do a series of tutorials on spritebatch. Oh yeah and I need to get my taxes done. I'm not sure how long the judging lasts but since I know there is no way I'll hear anything back, my plan is to go ahead and playtest for another couple of weeks then submit my game for playtesting with Microsoft (ie. the Creator's Club website). If it passes that I'll submit for review and with any luck get it on the Indie Live Marketplace. The DBP contest gave me a focus point which forced me to cut things off and consolidate/finalize missions etc.

So here is my gameplay video for Acid Rain. It's not a trailer. That will take a lot more work. This is just my submission video for DBP. This is also too long for a trailer which should probably be under a minute.
Wednesday
Mar112009

Simple 2D Shadows Tutorial recognized

So this was a pleasant surprise.

My first XNA tutorial that I submitted to Ziggyware.com here and of course posted on this site here was recognized by Microsoft.

I know it's a small thing but it's those small things that encourage us to continue forging ahead.

Here is the link to MS's reference to my tutorial on 2D simple Shadows.  What I really like is I am categorized with other "Space Brains".

http://blogs.msdn.com/xna/archive/2009/03/10/creators-club-communiqu-21.aspx

Allan

Wednesday
Mar112009

Volcano Storm Update - Working on GamePlay

I'm finally posting an update video on my efforts with XNA.

This is about a month and a half of work after my last video.  What have I added/changed?  Pretty much everything.

I completely dumped the Tile System that I was using from Nick Gravelyn's video tutorials series.  I just couldn't stand the look of the repetitive Tiles.  Perhaps it is my lack of artistic knowledge in creating seamless tiles that don't look so repetitive but after trying to create seamless tiles that don't look repetitive for months, I finally gave up.  Once my programming knowledge increased a little I was able to start toying with other terrain generation ideas.  I'm still using a bottom foundation of rocky grass tiles, however since my game structure is not constrained to tile size, there was no reason why I counldn't branch out on the tile concept.  My foundation tiles are now 510 X 510, created in ZBrush, rotated forward at 20 degrees and then screen captured as 510 X 510 Top Down tiles.  I have a bunch of game Objects that litter the foundation base.  All of these are created as 3D objects in ZBrush, tilted 20-45 degrees and randomly placed on my map.  This includes the mountains, Rocks, Trees, downed Trees, Volcano etc.  This helps break the repitition.  I also created a second layer of snowy landscape  Tiles that overlays the rocky grass layer.   I'm still vasilating on the look of the snowy ground layer.  I like the snow but it starts to make things look kind of busy. Perhaps too busy.  Since it's all randomly generated (except for the foundation rocky grass layer) I'm able to adjust the size of my map on the fly and the volume of stuff on the map.

I added a cloud layer that scales as you zoom in and out with the camera.  There are clouds that roll across the mountain range at all times and then there are higher clouds that only appear when you start to zoom out.  As you zoom out, I adjust the clouds transparency and scale so it looks like you are moving through the cloud layers.   My son said, "You need to adjust the sound so when you zoom out and are further away, your rock explosions and AcidRain Bursts are quieter."...so I did that....except for the thunder of course....because that's up where you are.   He said, "You need storm clouds."  So I added stormy clouds with lightning and thunder.  He reminded me that there is a delay between thunder sound and lightning.  OK.  That took a few days.  Then he said, what happens when the volcano rocks hit the trees.  I guess they should burn.  A week later and they burn.  And of course I needed burnt tree textures to replace the regular tree textures.

So now I have a look that I am moderately satisfied with.  Now the hard part....I need to make gameplay.

Thankfully I didn't neglect collision detection in my design so my player collides with the acidrain and the volcano rocks..  He also collides with the mountains and the volcano.  That collsion makes him slow and scale since he is climbing.  And of course I have to keep track of everything's depth.  Since the player walks behind some things and in front of others.  And he collides with certain higher rock formations.

Adding player health is the first step to gameplay once you have collision detection.  So I started working on a HUD.  Since my player is a vacationing mountain climber/hiker, I thought a rope would be appropriate for my health bar.  After several days trying to make a rope in ZBrush....(one that I could rotate and frey into strings and pieces)..in order to capture the frames I needed for a desintigrating rope/health bar, I integrated it into my game.  I added a rope exploding particle effect, code to tie the length of the rope to player health and a temperary text field just so I can make sure the rope length is actually tied to player health.  I showed this to my daughter and I said, "How do you like the health bar?"  She said, "Oh that...it looks ok."  See my guy is a vactioning mountain climber, so I thought a rope would be a good....  She said, "Oh that's a rope?" 

Ouch.  She got a good laugh out of that.
 
Allan

Friday
Feb062009

Simple 2D Shadows Extended XNA Tutorial

 
In this tutorial, I'll show you how to add simple 2D shadows to your 2D game. My original blog post demonstrated that you can create simple 2D Shadows that are realistic, with no additional textures, no new lines of code and no math.
At the end of the blog post, I theorized that you could extend the concept by having dynamic shadows that are repositioned based upon the sun. So I created a simple Sun Cycle to go along with my simple 2D shadows. You can download the source code with lots of comments at the bottom of this tutorial.

2dshadowssimple1

Inspired by other 2D shadow tutorials, I wanted to create a very simple method for adding shadows that I could understand, would add as little code as possible and would add no additional textures. One method I found involved simply using photoshop to make your textures black and transparent and then load those new textures into your game. But then you end up with two textures for every object, the real object and the blackened, transparent object (shadow). It occurred to me that spritebatch.draw will do exactly what this method did in photoshop. Thus you can do 2D shadows in your game without adding the shadow textures.

2dshadowssimple21Ultimately, all I do is redraw my existing texture, make it black and transparent, and reposition it based upon my arbitrary sun position. In order to create a sun cycle, I create variables out of my spritebatch.draw parameters that control position, color and layer depth.
I started with the default XNA 3.0 game template and just started adding code. The first thing I needed were variables to control my shadow. These variables are primarily used in the second spritebatch.draw where I redraw the canopy of my tree as a shadow. My textures are canopy and trunk. I keep them as separate pieces because if you shadow the trunk, it will appear to float over the ground. So I just want to shadow the canopy and leave the trunk flat and on the ground. My textures are designed to be sort of isometric in that they are tilted forward 45 degrees. This works for my little game project but the idea can be applied to any 2D perspective you might choose. I create a rectangle for the canopy so I have easy control over positioning both the canopy and it's shadow. I create variables for alpha and color because that's how I'm going to make my canopy texture black and transparent in the second spritebatch.draw. I create a couple of offsets so I can fine tune the shadow position. I have a variable for rotation, again, for positioning, and finally a boolean for sunCycle so I can have a little running demo.
  public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private Texture2D canopy;
        private Texture2D trunk;
        private Rectangle canopyRect;
        private byte shadowAlpha;
        private Color color;
        private int shadowOffsetX;
        private int shadowOffsetY;
        private float shadowRotation;
        private bool sunCycle = false;

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

canopy145

trunk145

 In my initialize method, I set the screen dimensions and name my little game window. Then I setup the starting values for my variables. I set alpha to 40 but you can play with this value depending on how dark you have your background. The darker your background, the darker you will want your shadow. The real magic of this concept is in the color command. Typically we would just use Color.White and that would make our texture opaque. Instead of saying Color.White, I use one of the overloads in Color. Amazingly, there are 9 overloads for Color. I use #8 which uses bytes to represent R, G, B, A. New Color(byte r, byte g, byte b, byte a). That’s Red, Green, Blue and Alpha. A byte is 0 - 255. Zero is black, 255 is white/opaque. So when you are saying Color.White, it’s the same as if you said New Color(255, 255, 255, 255). The Alpha is transparency which you can set on the fly for your texture. And here is the key... If you make r, g and b all equal Zero, you get black. Set your Alpha to 40. Thus you are saying redraw my texture in a different position, make it black and make it transparent down to 40 instead of fully opaque at 255. I then setup my shadow position variables, the offsets and rotation.
 protected override void Initialize()
        {
            //Set screen dimensions
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;
            graphics.IsFullScreen = false;
            graphics.ApplyChanges();
            Window.Title = "Simple 2D Shadows";
            
 
            //Set Shadow Start values.  These variables are used in the second spritebatch.draw in order to make our shadow.
            shadowAlpha = 40; // set transparency level, Adjust this depending on how dark your background is
            //I use the color variable to define the color of our canopy texture in the second draw of the canopy texture.
            //Using overload number 8 gives us color(byte r, byte g, byte b, byte a)
            //Remember a byte is 0 to 255. These values represent Red, Green, Blue and Alpha(transparency)
            //Setting r,g,b to 0 makes out texture black and then we can play with the alpha level to determine how transparent we
            //want our texture.  Make it darker for a darker background or adjust it based on game design.
            color = new Color(0, 0, 0, shadowAlpha); 
            shadowOffsetX = 0; // Shadow X Position offset, Use this to fine tune shadow position
            shadowOffsetY = 20; // Shadow y position offset, Use this to fine tune shadow position
            shadowRotation = -1f; //Shadow rotation starting position.  Use this to rotate the texture based upon sun position.
            
            base.Initialize();
        }

In my load content method, I load my textures and create a rectangle for my canopy texture. I set the width and height of the rectangle to the width and height of the texture. So my rectangle is the same size as my canopy texture.

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

            //Load canopy and trunk
            canopy = Content.Load(@"Canopy145");
            trunk = Content.Load(@"Trunk145");
            //create rectangle for canopy, sized to width and height of canopy texture
            canopyRect = new Rectangle(500, 200, canopy.Width, canopy.Height); 

            // TODO: use this.Content to load your game content here
        }

My update method is pretty simple. All I'm doing is checking to see if the user hits the space bar. If they do, I set the boolean sunCycle to true. It was originally set to false. I have another If then that checks to see if sunCycle is true. If it is true, then increment my rotation variable, shadowRotation, and then keep incrementing until shadowRotation is equal to 1f and set sunCycle to false. This stops the rotation.

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

            //Check if user hits spacebar and set sunCycle to true to start sun cycle
            if (Keyboard.GetState().IsKeyDown(Keys.Space) && sunCycle == false)
            {
                sunCycle = true;
            }

            //if suncycle is true (ie. you hit space bar), increment shadowRotation to rotate shadow texture 
            if (sunCycle)
            { 
                shadowRotation += .005f;

                if (shadowRotation >= 1f)  //stop shadowRotation when it is greater than 1.
                {
                    sunCycle = false;
                }
            }
          
            base.Update(gameTime);
        }

The draw method is where all of the real work gets done. First you'll notice I turned on SpriteSortMode.BackToFront in the spritebatch.begin. This allows me to sort my sprites from back to front on the screen in each draw statemnent. If you don't do this, your sprites will be drawn based upon the order of your spritebatch.draw commands. Personally, I like to control the ordering or layering of my sprites on the screen. Then I don't have to worry about the specific order of my draw commands. The first spritebatch.draw simply draws our canopy texture inside of the previously defined canopyRectangle. The source rectangle is null since it is unused. I set Color to white or opaque. No rotation. Origin is unused. No spriteeffects. Layer Depth is set to .2. This keeps the canopy on top of the trunk and shadow, or you could say it's closer to the camera or your face. 0 is in your face. 1 is the back of your screen.

In the second spritebatch.draw, we redraw the same canopy texture but change a number of parameters in the draw command. Our destination rectangle is the center bottom of the canopy rectangle with an offset variable for X and Y used for fine tuning the position of our shadow. Source rectangle is set to null since it's unused. The color variable gives us our magic. I set color to black (0, 0, 0, alpha) with alpha(transparency) set to 40. ShadowRotation is our float for rotation. Next is Origin. The rotate variable will rotate around the origin point. We could just use new vector(0,0) but the shadow rotation would then rotate around the top left corner of the rectangle. It works better if you set the origin to the center bottom of the rectangle so that becomes your rotation point. I set the rotation point or the origin at the center of the texture X and at the Bottom Y. We don't use scale. No spriteeffects. Layer Depth is below or under the canopy. This puts the transparent canopy under the regular canopy.

Finally we draw the trunk. Again, I use origin to find the center of the truck texture and then place the center of the trunk in the center of the canopy rectangle so it is nicely positioned. I offset the center point slightly, just to fine tune it's position.
 protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.SkyBlue);

            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None);

                        spriteBatch.Draw(canopy,
                           canopyRect,
                           null,
                           Color.White,
                           0f,
                           new Vector2(0f, 0f),
                           SpriteEffects.None, 0.2f);
                       
            spriteBatch.Draw(canopy,
                             new Vector2(canopyRect.Center.X + shadowOffsetX,
                             canopyRect.Bottom - shadowOffsetY),
                             null,
                             color,
                             shadowRotation,
                             new Vector2(canopy.Width / 2, canopy.Height),
                             1f,
                             SpriteEffects.None, 0.5f);
            
            spriteBatch.Draw(trunk, 
                            new Vector2(canopyRect.Center.X, canopyRect.Center.Y), 
                            null, 
                            Color.White, 
                            0f,
                            new Vector2(trunk.Width / 2, trunk.Height / 2 - 25), 
                            1f, 
                            SpriteEffects.None, 
                            0.5f);

            spriteBatch.End();

            base.Draw(gameTime);
        }

So there you have it. A simple 2D shadow that changes depending on where you position your sun. I think it looks pretty good. Now consider that if you kept your sun position the same throughout your game, you could eliminate all of the variables and just put your final values in your second spritebatch.draw command. By doing this, you would be adding 2D shadows with no additional textures, a simple copy of your already existing draw command (with changes to parameters you are passing) and no math.

Of if you're making some form of RPG, wouldn't it be cool to have a sun cycle with dynamic shadows all the while being mindful of the file size constraints required by Xbox 360 community game submission.
Download 2D Shadows Extended
Allan Chaney
Friday
Jan302009

Simple 2D Shadows in XNA

In this example, I'll show you how to add 2D shadows to your game with no new lines of code, no additional textures and no math.  It turns out everything you need is already contained in Spritbatch.Draw.

No Shadow                                                         Shadownotreeshadow1

runleft2



I was getting tired of trying to learn ZBrush, so I went back to programming my little game engine.  In the motto of why recreate the wheel, I started where I always do... at Google.  I quickly found two interesting takes on 2D shadow creation.  The first is recently posted source code found here from Catalin Zima, a Tech student in Romania.  I also found it when it showed up as a link  at Ziggyware.  If you don't have Ziggyware added to your RSS feeds, you should do that NOW!.  Some of the best educational tutorials have come out of that site.  They had a contest in 2008  and the articles were  mindblowing.  Here is the link to the winners for 2008.

All I can say is WOW! Catalin's example is amazing!  Unfortunately, I'm too early in my development to understand it.  It's not a tutorial, mind you, just source code.  To be honest when I ran the program, I wasn't entirely sure what I was looking at.  That's due to my limited skills, not Catalin's work.  But the bottom line is... it's over my head.  I could spend a few weeks trying to understand the code and implement it or I could keep searching.

My next hit pulled up this.  Very simple.  Just draw a shadow copy of your existing texture and place it in your code.  The problem I had with that is it means duplicating every texture where you want a shadow.  I already have capacity issues with my little game so adding shadow textures seemed extreme.  However this example gave me an idea.

What is a shadow really?  Yes you can find wikis with large brain shadow math/algorithms.  But I needed to keep things simple so I could understand it.  All a shadow really is is a copy of your existing game texture, darkened, partially transparent and offset according to sun position.  Well guess what?  Spritebatch.Draw controls all of that.

Player behind tree on top of tree shadow.

behindtree1I'll demonstrate with two examples.  A Tree and my animated Player character.  Remember.... no new lines of code, no new textures and no math.

In simplest form, all you have to do is make a copy of your spritebatch.draw statement and paste it underneath the one you are using to draw your tree.

I'm using overload #5 of the spritbatch.draw command.  An overload is just a variation or form.  Spritebatch.draw allows 7 different forms or variations.  The overload you choose determines the variables you need to pass to spritebatch.draw within the parenthesis.  So with overload #5, I have to pass the following.  SpriteBatch.Draw(Texture2D texture,  Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth)  This contains everything I need to make a shadow of my existing texture.  So here are my two commands.  I haven't added a "New" line of code.  All I've done is copied an exisitng line (spriteBatch.Draw) and then changed some of the variables.  I'm drawing the same tree twice but altering it in the second draw.

TreeTopRect = new Rectangle(500, 500, treeTop.Width, treeTop.Height);

This sets up the rectangle I'm going to place my treeTop texture in.  I place my texture in a rectangle in the first draw statement.  Then I use a different overload in the second draw statement, overload #6.  I use new Vector2(x, y) in overload #6 to offset the position of the rectangle that contains my treeTop texture.  I also change the color which includes transparency.  And I give it a little bit of rotation by setting rotation to .2f.  Also note that I change the layer depth so the tree shadow is always under the tree.  (You turn layer depth on on in your spriteBatch.Begin command by declaring SpriteSortMode.BackToFront).  This tells spritBatch.Draw to pay attention to the float values you set in layer depth.  If you don't use this feature, the order of sprites on the screen will be the order that you draw them.  Back being first and front being last.  My personal preference is to always have control of this feature as much as possible so I always turn it on. 

spriteBatch.Draw(treeTop, TreeTopRect, null, Color.White,
0f, new Vector2(0f, 0f), SpriteEffects.None, 0.2f);

spriteBatch.Draw(treeTop, new Vector2(TreeTopRect.X + 70,
TreeTopRect.Y - 20), null, new Color(0, 0, 0, 70), .2f,
new Vector2(0, 0), 1f, SpriteEffects.None, 0.5f);
 All I have done in my second spriteBatch.Draw is redraw the same texture...treeTop, offset the X and Y coordinates of it's position and make the source rectangle null because I don't use that.  Instead of saying Color.White, I use one of the overloads in Color.  Amazingly, there are 9 overloads for Color.  I use #8 which uses bytes to represent R, G, B, A.  New Color(byte r, byte g, byte b, byte a).  That's Red, Green, Blue and Alpha.  A byte is 0 - 255.  Zero is black, 255 is white.  So when you are saying Color.White, it's the same as if you said New Color(255, 255, 255, 255).  The  Alpha is transparency which you can set on the fly for your texture.  And here is the key....  If you make r, g and b all equal Zero, you get black.  Set your Alpha to 70.  Thus you are saying redraw my texture in a different position, make it black and make it transparent down to 70 instead of fully opaque at 255.  I also change the rotation float variable to .2f in order to rotate my shadow texture just a little relative to the sun's position.  And finally I set the layer depth so the shadow is always farther away from the camera or your face than the tree.  A layer depth of 1f is as far away as you can get and 0f is as close to you as you can get.  This allows you to position 2D sprites on the screen in an infinite number of layers, one on top of another.

Now to set this up, you would have already needed to declare

private Texture2D treeTop;  at the top of your code in the main class. 

Then you had to load treeTop with a texture in your Load Content method.  

treeTop = content.Load<Texture2D>(@"Tiles/canopy145"); 

You'll need your spriteBatch.Draw statements sandwiched in between spritebatch.begin and spritebatch.end in your main draw method as usual.

spriteBatch.Begin(SpriteBlendMode.AlphaBlend,SpriteSortMode.BackToFront, SaveStateMode.None, camera.Transform);

spriteBatch.Draw.....

spriteBatch.Draw....

spriteBatch.End();

I use a 2dCamera in my little game thus the camera.Transform but you don't need this for this example.

Now if you want to extend this, you could make color a variable and make your shadow x, y positions variables.  Then you could adjust your shadow position and transparency based upon wherever you want your sun.  If you want to go crazy, you could have a day night cycle and alter your shadow positions and transparency based upon the time of day.  That would be cool in an RPG.

In order to make color a variable, one way I have found that you can do it is to make color a Vector4.

float alpha = .2f;
color = new Color(new Vector4(0, 0, 0, alpha));
spriteBatch.Draw(treeTop, new Vector2(TreeTopRect.X + 70, TreeTopRect.Y - 20), null, color, .2f, new Vector2(0, 0),
1f, SpriteEffects.None, 0.5f);

Notice how I use the variable color in place of Color.White or New Color() in the second draw statement.  The only thing to keep in mind is when you make color a Vector4, you're now using floats instead of bytes.  So color is from 0 - 1.

You can apply the exact same logic to a player character.  The added benefit is your X, Y offsets for your shadows all stay the same for every direction you draw your character, thus your shadows appear consistant as you turn your character.  Here is a video of my character running and circling.  I increased the alpha to 80 so the video would show the shadow better.  I offset the player rectangle X +10 and Y - 5 on every player animation.  So all player animations have the same offset.  This places my Sun somewhere in the Southwestern sky.  It's easier to see the shadows if you watch the video in HD.