共用方式為


Bizzy Bees Step 4: Making things move (XNA Walkthrough)

This is part of a walkthrough series on creating a game (Bizzy Bees) in XNA

Overview
Step 1: Setting the stage (projects and assets)
Step 2: Drawing the scene
Step 3: Adding flowers
Step 4: Making things move
Step 5: Adding some bees to the mix
Step 6: User interaction
Step 7: Rounding it up

Animating objects in XNA is extremely simple.  To move something we just change the position of the objects in the update method. To resize an object we can add a variable for scale that we can update in the update method and then we use that variable in the draw method etc.

If you want to do more complex animation like a bee flapping it’s wings or an object exploding you would use a spritemap with different images depicting different stages of the animation and advance the frame each time.  If you want to animate a bee flipping it’s wings you can make this look pretty convincingly by using two images (one with wings up and one with wings down and then toggle between them every 4 frames or so)

Animating the flowers

In our case, we want the flowers to move downwards at a steady pace.

1. Add a new membervariable to the Column class called Velocity (we’ll make this public so we can modify it easily later, you’ll see why). 
The 0.4 here is how many pixels the flowers will move downwards per frame.

         public float Velocity = 0.4f;

2. Add a new method to the Column class called Update where we move all the flowers downwards by changing the Y position

  public void Update()
        {
            foreach (Flower f in flowers)
            {
                f.Y += Velocity;
            }
        }

3. Finally, call the columns Update method from the Update method in the Game1 class so that it gets called for each frame

  foreach (Column c in columns)
                {
                    c.Update();
                }

What happens if you take too long to draw?

If you have payed attention you now know that we call Draw and Update 30 times a second, so what would happen if we suddenly take more than our allotted time when we draw or something?

Well, what will happen is that by default XNA will drop draws if it can’t complete the whole Update/Draw cycle in time, so that it can still keep a steady pace.  In this case that would mean that sometimes the flowers would move 0.8px in one go.
In the Game1 Update and Draw functions though you get a parameter GameTime that you can use if you need to do timebased stuff like updating a clock or something.  However, usually for simple games like this one, unless you have a really complex 3D world that you are dealing with, you can get away with a lot of things and still keep the Update/Draw cycle.

Back to our game. If you have followed along your flowers should be moving now, but there are two big problems

badmovebadmove2

First off, we don’t do anything to add new flowers when the flowers are dropping down, and secondly the flowers will just keep moving forever, even off the screen.  What really should happen is that the game should be finito when the flowers reach the bottom.

Game Over

Ok, let’s fix the 2nd problem first.

1. Add a new member variable to the Game1 class

         bool gameOver = false;

2. In the Update method in the Game1 class change the column update loop to check if the flowers reached the bottom and set the gameOver flag if they have

  if (!gameOver)
            {
                foreach (Column c in columns)
                {
                    c.Update();
                    if (c.ReachedBottom)
                    {
                        gameOver = true;
                        break;
                    }
                }
            }

3. In the column class add a constant for columnBottom and a property called ReachedBottom that checks if the first flower reached the bottom

         const int columnBottom = 620; public bool ReachedBottom { get { if (flowers.Count != 0 && flowers[0].Y >= columnBottom) return true; else
                    return false; } }

Now the updates will stop, but nothing else will really happen so we need to print out an endgame message when the game is over

Change the code for the Draw method in Game1 so that it looks like this

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


            spriteBatch.Begin();
            spriteBatch.Draw(backgroundTexture, Vector2.Zero, Color.White);

            if (!gameOver)
            {
                foreach (Column c in columns)
                    c.Draw();
            }
            else
            {
                spriteBatch.DrawString(largeFont, "GAME OVER", new Vector2(150, 400), Color.Red);
            }
            
            spriteBatch.Draw(foregroundTexture, Vector2.Zero, Color.White);
            DrawHUD();
            spriteBatch.End();

            base.Draw(gameTime);
        }

When the game is over we now draw a Game Over message instead of drawing the columns, which is pretty neat.

Creating a flower factory

Ok, so we fixed that, now let’s fix the code so we keep filling up the columns with new flowers as we go along.

In the Column.Update method add the following code to add new flowers when the topmost flower has passed the starting point

             if (flowers.Count == 0 || flowers[flowers.Count - 1].Y > columnTop) AddRandomFlower(x, columnTop - flowerDeltaY);

Now you should have a fully functioning flower factory and a way to end the game, but no way to win it.  don’t worry we’ll get there…

movingflowers

next time we’ll add in the bees to make the game a bit more complete