Friday, June 28, 2013

IV. The Slider and the Ball - Using the past learning


So here's what we need
[import to your game and name it "ball"]

[import to your game and name it "slider"]


Now let's declare the position and the texture of the two files..

Texture2D ball,slider;
Vector2 sliderPosition, ballPosition;
float bounceNumber = 0; //get the number of bounces made by the intersection or collision of slider and ball
float directionx, directiony; //the direction of the ball
Vector2 ballVelocity= Vector2.Zero; // the velocity of the ball
float speed= 5f; // the speed of the ball

At loadcontent..
ball = Content.Load<Texture2D>("ball");
slider= Content.Load<Texture2D>("slider");
sliderPosition = new Vector2(GraphicsDevice.Viewport.Width/2 - slider.Width /2,GraphicsDevice.Viewport.Height - 50);
ballPosition= new Vector2(sliderPosition.X , sliderPosition.Y - ball.Height);
directionx = 1; //if direction is 1 move right; if direction is -1 move left
directiony = -1;  // move down ; 1 move up

We used the viewport which is the size of the gamescreen..
slider.Width = is the width of the slider texture..
we set the ball position at the top of the slider..


Go to your draw method and add the following lines
REMOVE THE LINES WE USED TO DRAW THE OTHER TEXTURE..

  spriteBatch.Draw(ball, ballPosition , Color.White);
  spriteBatch.Draw(slider, sliderPosition, Color.White);

Now what we want to do is to edit the logical gates and updates of the input handling , so instead of updating the texturePosition , replace it with sliderPosition..
 (delete the following lines)

 if (currentKeyboardState.IsKeyDown(Keys.Down) && oldKeyboardState.IsKeyDown(Keys.Down))
            {
                texturePosition.Y += 10;
            }
            if (currentKeyboardState.IsKeyDown(Keys.Up) && oldKeyboardState.IsKeyDown(Keys.Up))
{
                texturePosition.Y -= 10;
}

We only want to update the x position of the slider.. so remove those..

and edit the following if statements FROM

   if (currentKeyboardState.IsKeyDown(Keys.Right) && oldKeyboardState.IsKeyDown(Keys.Right))
            {
                texturePosition.X += 10;
            }
            if (currentKeyboardState.IsKeyDown(Keys.Left) && oldKeyboardState.IsKeyDown(Keys.Left))
            {
                texturePosition.X -= 10;
            }
TO

  if (currentKeyboardState.IsKeyDown(Keys.Right) && oldKeyboardState.IsKeyDown(Keys.Right))
            {
                sliderPosition.X += 10;
            }
            if (currentKeyboardState.IsKeyDown(Keys.Left) && oldKeyboardState.IsKeyDown(Keys.Left))
            {
                sliderPosition.X -= 10;
            }
Run the game and move the slider..

now let's make the ball move..
so at the top of your class, declare the ff:
bool isGameStart = false;
bool playerIsDead= false;

isGameStart is the value which we are going to check if we want to start the game..
now add this line at your update..

    if (currentKeyboardState.IsKeyUp(Keys.Space) && oldKeyboardState.IsKeyDown(Keys.Space))
   {
              if (!isGameStart){
              isGameStart = true;
             }
    }

So if the Space Button is pressed, start the game..

To make the ball move..
add a new method, we'll call it updateBall
   private void updateBall()
        {
        }
In this method we are going to update the game if and only if isGameStart is equal to TRUE..
So in the update method add this line.

if (isGameStart)
{
      updateBall();
}

Now, we want to disable the controls of the slider or paddle if the playerIsDead is equal to TRUE..
so we will wrap the controls inside a new if statement..
  if (!playerIsDead)

            {                if (currentKeyboardState.IsKeyDown(Keys.Right) && oldKeyboardState.IsKeyDown(Keys.Right))                {                    sliderPosition.X += 10;                }                if (currentKeyboardState.IsKeyDown(Keys.Left) && oldKeyboardState.IsKeyDown(Keys.Left))                {                    sliderPosition.X -= 10;                }            }

This will allow the game to disable the controls in slider when ,the player is dead.
Now going to the updateball..

How are we going to update the direction of the ball?
We will not use physics here, since i want you to learn about collisions..
So to change the direction of the ball.. we need to compare the position of the ball against the bounds or ends of the screen..



[Click the picture for more information]

   private void updateBall()
        {
            if (ballPosition.X > 0 && ballPosition.X <= ball.Width / 4)
            {
                directionx = 1;
            }
//  IF THE POSITION OF THE BALL IS GREATER THAN ZERO AND IS THE POSITION OF THE //   BALL IS LESS THAN OR EQUAL TO THE BALL WIDTH /4... Change direction to RIGHT

            if (ballPosition.X >= GraphicsDevice.Viewport.Width - ball.Width)
            {
                directionx = -1;
            }
//IF THE POSITION OF THE BALL IS GREATER THAN END OF RIGHT SCREEN - BALL WIDTH, CHANGE DIRECTION TO LEFT..WE SUBTRACT THE BALL WIDTH TO FIND THE POINT WHERE AT BALL IS AT THE END OF THE RIGHT SCREEN..
            if (ballPosition.Y > 0 && ballPosition.Y <= ball .Height /4)
            {
                directiony = 1;
            }
//SAME LOGIC APPLIES ON GETTING Y , IF THE POSITION OF THE BALL INTERSECTS WITH THE SLIDER POSITION, MOVE UP
            if (ballPosition.Y+ ball.Height > sliderPosition .Y 
                && ballPosition .Y < sliderPosition .Y + slider .Height /6
                && ballPosition .X > sliderPosition .X 
                && ballPosition .X < sliderPosition .X + slider .Width )
            {
                if (directiony == 1)
                {
                    bounceNumber += 1;
//FIRST CHECK IF THE DIRECTION IS GOING DOWN , AND SINCE THE BALL INTERSECTED WITH THE SLIDER, add 1 to bounceNumber
                }
                directiony = -1;  
            }
//IF THE POSITION OF THE BALL GET PASS THROUGH THE END OF THE SCREEN, KILL PLAYER (LOL)
            if (ballPosition.Y > GraphicsDevice.Viewport.Height)
            {
                playerIsDead = true;
            }
//IF BOUNCE NUMBER IS GREATER TO 10 , INCREASE THE SPEED OF THE BALL
            if (bounceNumber > 10)
            {
                speed = 10;
            }
//GET THE DIRECTION AND MULTIPLY TO SPEED, THEN SAVE TO BALL VELOCITY
            ballVelocity .X = directionx *speed;
            ballVelocity.Y = directiony * speed ;
// ADD VELOCITY TO POSITION
            ballPosition.Y += ballVelocity.Y;
            ballPosition.X += ballVelocity.X;
    }

We're almost done, what we are gonna do is  to display the score where score is the number of bounces, if playerisdead .. Draw a game over message.. So to do that, go to the draw method..

add the following lines
spriteBatch.DrawString(font,"Score:" + bounceNumber.ToString(), Vector2.Zero, Color.White);
  if (playerIsDead)
      spriteBatch.DrawString(font, "Game Over", new Vector2(GraphicsDevice.Viewport.Width / 2 -          font.MeasureString("Game Over").X / 2,
            GraphicsDevice.Viewport.Height / 2), Color.Red);

YOU'LL NOTICE THAT THE X POSITION OF THE GAME OVER SCREEN IS THE SCREEN WIDTH /2 , TO DRAW IT ON THE CENTER.. SUBTRACT THE LENGTH/2 OF THE STRING GAME OVER TO THE WIDTH /2 OF THE SCREEN ..

NOW AT THE BOTTOM OF SPRITEBATCH.BEGIN(), LET'S DRAW A BACK GROUND
To do that, we need a texture..
So declare this variable at the top of the class.
Texture2D backGround;
In the load content 
backGround = Content.Load<Texture2D>("background")
and finally add it on the draw method..

spriteBatch.Draw(backGround, Vector2.Zero, Color.White);


Don't forget to download and import the background texture into your content
[name this background]

The draw method will look like this..

 GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(backGround, Vector2.Zero, Color.White); //draw this first , so it will be drawn at the deepest                position (LOL)
 spriteBatch.Draw(ball, ballPosition, Color.White); // at the top of background
 spriteBatch.Draw(slider, sliderPosition, Color.White); // at the top of background and ball
 spriteBatch.DrawString(font,"Score:" + bounceNumber.ToString(), Vector2.Zero, Color.White);
  if (playerIsDead)
            spriteBatch.DrawString(font, "Game Over", new Vector2(GraphicsDevice.Viewport.Width / 2 -                font.MeasureString("Game Over").X / 2,  GraphicsDevice.Viewport.Height / 2), Color.Red);
 spriteBatch.End();



SOURCE CODE

 public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D texture;
        Vector2 texturePosition = Vector2.Zero;
        KeyboardState currentKeyboardState, oldKeyboardState;
        SpriteFont font;
        Texture2D ball, slider, backGround;
        Vector2 sliderPosition, ballPosition;
        bool playerIsDead = false;
        bool isGameStart = false;
        float directionx, directiony;
        Vector2 ballVelocity = Vector2.Zero;
        float speed = 5f;
        int bounceNumber = 0;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

        }

        protected override void Initialize()
        {


            base.Initialize();
        }


        protected override void LoadContent()
        {

            spriteBatch = new SpriteBatch(GraphicsDevice);
            texture = Content.Load<Texture2D>("test");
            texturePosition = new Vector2(100, 100);
            font = Content.Load<SpriteFont>("font");
            ball = Content.Load<Texture2D>("ball");
            slider = Content.Load<Texture2D>("slider");
            backGround = Content.Load<Texture2D>("background");
            sliderPosition = new Vector2(GraphicsDevice.Viewport.Width / 2 - slider.Width / 2, GraphicsDevice.Viewport.Height - 50);
            ballPosition = new Vector2(sliderPosition.X, sliderPosition.Y - ball.Height);
           
            directionx = 1;
            directiony = -1;
        }
        protected override void UnloadContent()
        {

        }
        protected override void Update(GameTime gameTime)
        {
            currentKeyboardState = Keyboard.GetState();
            if (!playerIsDead)
            {
                if (currentKeyboardState.IsKeyDown(Keys.Right) && oldKeyboardState.IsKeyDown(Keys.Right))
                {
                    sliderPosition.X += 10;
                }
                if (currentKeyboardState.IsKeyDown(Keys.Left) && oldKeyboardState.IsKeyDown(Keys.Left))
                {
                    sliderPosition.X -= 10;
                }
            }
            if (currentKeyboardState.IsKeyUp(Keys.Space) && oldKeyboardState.IsKeyDown(Keys.Space))
            {
                if (!isGameStart) isGameStart = true;
            }
            if (isGameStart)
            {
                updateBall();
            }
            oldKeyboardState = currentKeyboardState;
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            spriteBatch.Draw(backGround, Vector2.Zero, Color.White); //draw this first , so it will be drawn at the deepest                position (LOL)
            spriteBatch.Draw(ball, ballPosition, Color.White); // at the top of background
            spriteBatch.Draw(slider, sliderPosition, Color.White); // at the top of background and ball
            spriteBatch.DrawString(font, "Score:" + bounceNumber.ToString(), Vector2.Zero, Color.White);
            if (playerIsDead)
                spriteBatch.DrawString(font, "Game Over", new Vector2(GraphicsDevice.Viewport.Width / 2 - font.MeasureString("Game Over").X / 2, GraphicsDevice.Viewport.Height / 2), Color.Red);
            spriteBatch.End();
            base.Draw(gameTime);
        }
        private void updateBall()
        {
            if (ballPosition.X > 0 && ballPosition.X <= ball.Width / 4)
            {
                directionx = 1;
            }
            if (ballPosition.X >= GraphicsDevice.Viewport.Width - ball.Width)
            {
                directionx = -1;
            }
            if (ballPosition.Y > 0 && ballPosition.Y <= ball .Height /4)
            {
                directiony = 1;
            }
            if (ballPosition.Y+ ball.Height > sliderPosition .Y 
                && ballPosition .Y < sliderPosition .Y + slider .Height /6
                && ballPosition .X > sliderPosition .X 
                && ballPosition .X < sliderPosition .X + slider .Width )
            {
                if (directiony == 1)
                {
                    bounceNumber += 1;
                }
                directiony = -1;
                
            }
            if (ballPosition.Y > GraphicsDevice.Viewport.Height)
            {
                playerIsDead = true;
            }
            if (bounceNumber > 10)
            {
                speed = 10;
            }
            ballVelocity .X = directionx *speed;
            ballVelocity.Y = directiony * speed ;
            ballPosition.Y += ballVelocity.Y;
            ballPosition.X += ballVelocity.X;
        }
    }