XNA Creators Club Online
Page 1 of 1 (11 items)
Sort Posts: Previous Next

Ball Speed Bug

Last post 10/21/2009 6:42 AM by Beeny95. 10 replies.
  • 10/20/2009 6:13 PM

    Ball Speed Bug

    Hi XNA community.

    I have ran into a bug I just can't figure out. Basically I am making a breakout game, and whenever I add an extra block to the game, the ball travels faster. I have no idea why.
    Here is an outline of the porcess:
    1. Update In-Game State
    2. Update level_manager
    3. Update Blocks
    That said I don't understand what is causing the problem. Here is my code:

    In-Game State
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    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.Media; 
    using Microsoft.Xna.Framework.Net; 
    using Microsoft.Xna.Framework.Storage; 
    using System.IO; 
    using System.Diagnostics; 
    using System.Text; 
     
     
    namespace Pong 
        /// <summary> 
        /// This is a game component that implements IUpdateable. 
        /// </summary> 
        public class InGameState : Microsoft.Xna.Framework.DrawableGameComponent 
        { 
            #region Class Level Variables 
            // TODO: Add your calss level variables here 
            SpriteBatch spriteBatch; 
     
            SpriteFont score_font; 
     
            List<Paddle> paddle_list = new List<Paddle>(); 
            List<Ball> ball_list = new List<Ball>(); 
            List<Ball> lives_list = new List<Ball>(); 
     
            LevelManager level_manager; 
     
            bool paddle_colided; 
            bool block_colided; 
     
            public int current_level = 1; 
     
            int next_state; 
            #endregion 
     
            public InGameState(Game game) 
                : base(game) 
            { 
                // TODO: Construct any child components here 
            } 
     
            /// <summary> 
            /// Allows the game component to perform any initialization it needs to before starting 
            /// to run.  This is where it can query for any required services and load content. 
            /// </summary> 
            public override void Initialize() 
            { 
                // TODO: Add your initialization code here 
                level_manager = new LevelManager(this.current_level, 
                    Game.Content.Load<Texture2D>("Sprites//Block")); 
     
                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); 
     
                score_font = Game.Content.Load<SpriteFont>("Fonts//ScoreFont"); 
     
                // TODO: use this.Content to load your game content here 
                #region Add Paddles 
                // Add the paddles 
                paddle_list.Add(new Paddle( 
                    Game.Content.Load<Texture2D>("Sprites//paddle"), 
                    new Vector2(Game.Window.ClientBounds.Width, 680f), 
                    new Vector2(5f, 5f), 
                    3)); 
     
                // Initializes each paddle 
                foreach (Paddle p in paddle_list) 
                    p.Initialize(); 
                #endregion 
                #region Add Balls 
                // Adds the balls 
                ball_list.Add(new Ball( 
                    Game.Content.Load<Texture2D>("Sprites//ball"), 
                    new Vector2(Game.Window.ClientBounds.Width, Game.Window.ClientBounds.Height), 
                    new Vector2( -1f, 1f ))); 
     
                // Initializes teh balls 
                foreach (Ball b in ball_list) 
                    b.Initialize(); 
                #endregion 
                #region Add Lives 
                foreach (Paddle p in paddle_list) 
                { 
                    for (int i = 0; i < p.get_paddle_lives; ++i) 
                    { 
                        int offset = 10 + i * 20; 
                        lives_list.Add(new Ball( 
                            Game.Content.Load<Texture2D>("Sprites//ball"), 
                            new Vector2( offset, 35), 
                            Vector2.Zero)); 
                    } 
                } 
                #endregion 
            } 
     
            /// <summary> 
            /// Allows the game component to update itself. 
            /// </summary> 
            /// <param name="gameTime">Provides a snapshot of timing values.</param> 
            public override void Update(GameTime gameTime) 
            { 
                // TODO: Add your update code here 
                #region Paddle Collision Check 
                foreach (Paddle p in paddle_list) 
                { 
                    foreach (Ball b in ball_list) 
                    { 
                        if (p.get_paddle_rect.Intersects(b.get_ball_rect)) 
                            this.paddle_colided = true
     
                        else 
                            this.paddle_colided = false
                    } 
                } 
                #endregion 
                #region Block Collision Check 
                foreach (Block bl in level_manager.get_block_list) 
                { 
                    foreach (Ball ba in ball_list) 
                    { 
                        if (bl.get_block_rect.Intersects(ba.get_ball_rect)) 
                            this.block_colided = true
     
                        else 
                            this.block_colided = false
                    } 
                } 
                #endregion 
                #region Update Paddles 
                foreach (Paddle p in paddle_list) 
                { 
                    p.Update(gameTime, 
                        Game.Window.ClientBounds, 
                        Game.GraphicsDevice.Viewport); 
                } 
                #endregion 
                #region Updates Balls 
                foreach (Ball ba in ball_list) 
                { 
                    ba.Update(gameTime, 
                        Game.Window.ClientBounds, 
                        Game.GraphicsDevice.Viewport, 
                        this.paddle_colided, 
                        this.level_manager.get_block_list); 
                } 
                #endregion 
                #region Updtae Level 
                level_manager.Update(gameTime, Game.Window.ClientBounds); 
                #endregion 
                #region Update Lives 
                foreach (Ball b in ball_list) 
                { 
                    // TODO: Check if there are no more lives left and set state to game over 
                    if (b.get_minus_life) 
                    { 
                        this.lives_list.RemoveAt(lives_list.Count - 1); 
                    } 
                } 
                #endregion 
     
                base.Update(gameTime); 
            } 
     
            /// <summary> 
            /// This is called when the game should draw itself. 
            /// </summary> 
            /// <param name="gameTime">Provides a snapshot of timing values.</param> 
            public override void Draw(GameTime gameTime) 
            { 
                GraphicsDevice.Clear(Color.Black); 
     
                // TODO: Add your drawing code here 
                spriteBatch.Begin(); 
                #region Draw Paddles 
                foreach (Paddle p in paddle_list) 
                    p.Draw(gameTime, spriteBatch); 
                #endregion 
                #region Draw Balls 
                foreach (Ball b in ball_list) 
                    b.Draw(gameTime, spriteBatch, Color.White); 
                #endregion 
                #region Draw Level 
                level_manager.Draw(gameTime, spriteBatch); 
                #endregion 
                #region Draw Score 
                foreach (Paddle p in paddle_list) 
                    spriteBatch.DrawString( 
                        score_font, 
                        "Score: " + p.get_paddle_score, 
                        new Vector2( Game.GraphicsDevice.Viewport.Width - score_font.MeasureString("Score: " + p.get_paddle_score).X - 10f, 0), 
                        Color.LightGray); 
                #endregion 
                #region Draw Lives 
                foreach (Paddle p in paddle_list) 
                    spriteBatch.DrawString( 
                        score_font, 
                        "Lives:"
                        new Vector2(Game.GraphicsDevice.Viewport.X + 10f, 0), 
                        Color.LightGray); 
     
                foreach (Ball b in lives_list) 
                    b.Draw(gameTime, spriteBatch, Color.LightGray); 
                #endregion 
     
                spriteBatch.End(); 
     
                base.Draw(gameTime); 
            } 
     
            public int get_next_state 
            { 
                get 
                { 
                    return this.next_state; 
                } 
            } 
        } 

    LevelManager
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using Microsoft.Xna.Framework; 
    using Microsoft.Xna.Framework.Graphics; 
     
    namespace Pong 
        class LevelManager 
        { 
            // Class level variables 
            int current_level; 
     
            Texture2D block_sprite; 
     
            List<Block> block_list = new List<Block>(); 
            List<Vector2> level_handler = new List<Vector2>(); 
     
            // Constructor 
            public LevelManager(int t_currnet_level, 
                Texture2D t_block_sprite) 
            { 
                this.current_level = t_currnet_level; 
                this.block_sprite = t_block_sprite; 
     
                this.Initialize(); 
            } 
     
            public virtual void Initialize() 
            { 
                // TODO: Add your initialization logic here 
                #region Add Blocks 
                this.load_level_one(); 
     
                foreach (Vector2 v in level_handler) 
                { 
                    block_list.Add(new Block( 
                        this.block_sprite, 
                        1, 
                        (int)v.X, 
                        (int)v.Y)); 
                } 
                #endregion 
            } 
     
            public virtual void Update(GameTime gameTime, Rectangle clientBounds) 
            { 
                // TODO: Add your update logic here 
                foreach (Block bl in block_list) 
                { 
                    bl.Update(); 
                } 
            } 
     
            public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch) 
            { 
                // TODO: Add your drawing code here 
                foreach (Block bl in block_list) 
                { 
                    bl.Draw(gameTime, spriteBatch); 
                } 
            } 
     
            private void load_level_one() 
            { 
                this.level_handler.Add(new Vector2(7, 7)); 
                this.level_handler.Add(new Vector2(8, 5)); 
                this.level_handler.Add(new Vector2(9, 2)); 
                this.level_handler.Add(new Vector2(1, 7)); 
            } 
     
            public List<Block> get_block_list 
            { 
                get 
                { 
                    return this.block_list; 
                } 
            } 
        } 
     

    Ball
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using Microsoft.Xna.Framework; 
    using Microsoft.Xna.Framework.Graphics; 
     
    namespace Pong 
        class Ball 
        { 
            #region Class Level Variables 
            // Class level variables 
            Texture2D ball_sprite; 
     
            Vector2 ball_position; 
            Vector2 ball_velocity; 
     
            Vector2 ball_max_velocity; 
            Vector2 ball_min_velocity; 
     
            // Used for collision 
            Rectangle ball_rect; 
            bool minus_life; 
            #endregion 
     
            // Constructor 
            public Ball(Texture2D t_ball_sprite, 
                Vector2 t_ball_position, 
                Vector2 t_ball_velocity) 
            { 
                this.ball_sprite = t_ball_sprite; 
                this.ball_position = t_ball_position; 
                this.ball_velocity = t_ball_velocity; 
            } 
     
            public virtual void Initialize() 
            { 
                // TODO: Add your initialization logic here 
                this.ball_max_velocity = new Vector2(5f, 5f); 
                this.ball_min_velocity = new Vector2(-5f, -5f); 
     
                this.ball_position = new Vector2( 
                    (this.ball_position.X / 2) - (this.ball_sprite.Width / 2), 
                    (this.ball_position.Y / 2) - (this.ball_sprite.Height / 2)); 
     
                // Updates collision rect 
                this.ball_rect = new Rectangle( 
                    (int)this.ball_position.X, 
                    (int)this.ball_position.Y, 
                    this.ball_sprite.Width, 
                    this.ball_sprite.Height); 
     
                // Set minus_life 
                this.minus_life = false
            } 
     
            public virtual void Update( 
                GameTime gameTime, 
                Rectangle clientBounds, 
                Viewport screen_res, 
                bool paddle_colided, 
                List<Block> block_list) 
            { 
                #region Reset Minus Life 
                this.minus_life = false
                #endregion 
                #region Screen Collision 
                // Updates ball collision with window 
                if (this.ball_position.X < screen_res.X) 
                    this.ball_velocity.X *= -1; 
     
                if ((this.ball_position.X + this.ball_sprite.Width) > screen_res.Width) 
                    this.ball_velocity.X *= -1; 
     
                if (this.ball_position.Y < screen_res.Y) 
                    this.ball_velocity.Y *= -1; 
     
                if ((this.ball_position.Y/* + this.ball_sprite.Height*/) > screen_res.Height) 
                { 
                    this.ball_position = new Vector2( 
                        (screen_res.Width / 2) - (ball_sprite.Width / 2), 
                        (screen_res.Height / 2) - (ball_sprite.Height / 2)); 
     
                    minus_life = true
                } 
                #endregion 
                #region Collision Checks 
                if (paddle_colided) 
                    this.ball_velocity.Y *= -1; 
     
                foreach (Block bl in block_list) 
                { 
                    if( bl.get_block_rect.Intersects(this.ball_rect)) 
                    { 
                        // Updates ball collision with block 
                        if (this.ball_position.X < bl.get_block_rect.X + bl.get_block_rect.Width) 
                            this.ball_velocity.X *= -1; 
     
                        if (this.ball_position.X + this.ball_sprite.Width > bl.get_block_rect.X) 
                            this.ball_velocity.X *= -1; 
     
                        if (this.ball_position.Y < bl.get_block_rect.Y + bl.get_block_rect.Height) 
                            this.ball_velocity.Y *= -1; 
     
                        if (this.ball_position.Y + this.ball_sprite.Height > bl.get_block_rect.Y) 
                            this.ball_velocity.Y *= -1; 
                    } 
                } 
                #endregion 
                #region Ball Speed Clamp 
                // Updates balls max/min speed 
                if (this.ball_velocity.X > this.ball_max_velocity.X) 
                    this.ball_velocity.X = this.ball_max_velocity.X; 
     
                if (this.ball_velocity.Y > this.ball_max_velocity.Y) 
                    this.ball_velocity.Y = this.ball_max_velocity.Y; 
     
                if (this.ball_velocity.X < this.ball_min_velocity.X) 
                    this.ball_velocity.X = this.ball_min_velocity.X; 
     
                if (this.ball_velocity.Y < this.ball_min_velocity.Y) 
                    this.ball_velocity.Y = this.ball_min_velocity.Y; 
                #endregion 
                #region Add Velocity 
                // TODO: Add your update logic here 
                this.ball_position += this.ball_velocity; 
                #endregion 
                #region Update Rectangle 
                // Updates collision rect 
                this.ball_rect = new Rectangle( 
                    (int)this.ball_position.X, 
                    (int)this.ball_position.Y, 
                    this.ball_sprite.Width, 
                    this.ball_sprite.Height); 
                #endregion 
            } 
     
            public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch, Color ball_color) 
            { 
                // TODO: Add your drawing code here 
                spriteBatch.Draw( 
                    this.ball_sprite, 
                    this.ball_position, 
                    ball_color); 
            } 
     
            public Rectangle get_ball_rect 
            { 
                get 
                { 
                    return this.ball_rect; 
                } 
            } 
            public bool get_minus_life 
            { 
                get 
                { 
                    return this.minus_life; 
                } 
            } 
        } 
     

    Block
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using Microsoft.Xna.Framework; 
    using Microsoft.Xna.Framework.Graphics; 
     
    namespace Pong 
        class Block 
        { 
            #region Class Level Variables 
            // Class level variables 
            Texture2D block_sprite; 
     
            int block_type; 
            int row; 
            int column; 
     
            Vector2 block_position; 
     
            // Used for collision 
            Rectangle block_rect; 
            #endregion 
     
            // Constructor 
            public Block(Texture2D t_block_sprite, 
                int t_block_type, 
                int t_row, 
                int t_column) 
            { 
                this.block_sprite = t_block_sprite; 
                this.block_type = t_block_type; 
                this.row = t_row; 
                this.column = t_column; 
     
                this.Initialize(); 
            } 
     
            public virtual void Initialize() 
            { 
                // TODO: Add your initialization logic here 
                this.block_position.X = (this.block_sprite.Width * this.column) - this.block_sprite.Width; 
                this.block_position.Y = (this.block_sprite.Height * this.row) - this.block_sprite.Height; 
            } 
     
            public virtual void Update() 
            { 
                // Updates collision rect 
                this.block_rect = new Rectangle( 
                    (int)this.block_rect.X, 
                    (int)this.block_rect.Y, 
                    this.block_rect.Width, 
                    this.block_rect.Height); 
            } 
     
            public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch) 
            { 
                // TODO: Add your drawing code here 
                spriteBatch.Draw( 
                    this.block_sprite, 
                    this.block_position, 
                    Color.White); 
            } 
     
            public Rectangle get_block_rect 
            { 
                get 
                { 
                    return this.block_rect; 
                } 
            } 
        } 
     

    I hope you can help, many thanks for reading anyway.
    teK-Junkies: 'where one man's junk becomes another man's tek'
  • 10/20/2009 6:20 PM In reply to

    Re: Ball Speed Bug

    You are calling Ball.Update once for each block (see #region Update Balls). Why? That is what is causing your balls to speed up based on the number of blocks.

     

  • 10/20/2009 6:22 PM In reply to

    Re: Ball Speed Bug

    ahhhh, ok thanks. I will try and fix it.

    Many thanks (embarrased face), wish me luck

    [EDIT:] Im not sure how to do this tehn?
    teK-Junkies: 'where one man's junk becomes another man's tek'
  • 10/20/2009 6:23 PM In reply to

    Re: Ball Speed Bug

    Seems like you update the ball once for each block

                #region Updates Balls 
                foreach (Ball ba in ball_list) 
                { 
                    foreach(Block bl in level_manager.get_block_list) 
                    { 
                        ba.Update(gameTime, 
                            Game.Window.ClientBounds, 
                            Game.GraphicsDevice.Viewport, 
                            this.paddle_colided, 
                            this.block_colided, 
                            bl.get_block_rect); 
                    } 
                } 
                #endregion 

    I'm guesssing inside there you move the ball, so it moves once for each block...

    Play Kissy Poo - a game for 4 year olds on Xbox and windows
    The ZBuffer
    News and information for XNA
      Follow The Zman on twitter, Email me
        Please read the forum FAQs - Bug/Feature reporting
          Don't forget to mark good answers and good playtest feedback when you see it!!!
  • 10/20/2009 6:27 PM In reply to

    Re: Ball Speed Bug

    yeah your right, but how would i got about updating the ball speed once every update, and updating if the ball intersects the block once for every block every update?
    teK-Junkies: 'where one man's junk becomes another man's tek'
  • 10/20/2009 6:31 PM In reply to

    Re: Ball Speed Bug

    #region Updates Balls 
                foreach (Ball ba in ball_list) 
                { 
                    foreach(Block bl in level_manager.get_block_list) 
                    {
     
                        ba.Update(gameTime, 
                            Game.Window.ClientBounds, 
                            Game.GraphicsDevice.Viewport, 
                            this.paddle_colided, 
                            this.block_colided,
                            bl.get_block_rect,
                            level_manager.get_block_list); 
                    } 
                } 
                #endregion 


    Pass the blocks into the ball.Update and do the loop inside there, that way you can move the ball just once and check the collisions inside.
    Play Kissy Poo - a game for 4 year olds on Xbox and windows
    The ZBuffer
    News and information for XNA
      Follow The Zman on twitter, Email me
        Please read the forum FAQs - Bug/Feature reporting
          Don't forget to mark good answers and good playtest feedback when you see it!!!
  • 10/20/2009 6:33 PM In reply to

    Re: Ball Speed Bug

    Ahhh, smart. I'll do it now and see what happens.

    [EDIT:] I updated the first post with the new code. It appears that the ball doesn't react with the blocks. It also doesn't even run the if statements to check where about it hits the block. I put break points to test.
    teK-Junkies: 'where one man's junk becomes another man's tek'
  • 10/21/2009 5:18 AM In reply to

    Re: Ball Speed Bug

    My solution was an indication of what you might like to do, not a 100% solution.. there's no way I can give you all the code you need to make this work - something you just have to work out for yourself.

    Play Kissy Poo - a game for 4 year olds on Xbox and windows
    The ZBuffer
    News and information for XNA
      Follow The Zman on twitter, Email me
        Please read the forum FAQs - Bug/Feature reporting
          Don't forget to mark good answers and good playtest feedback when you see it!!!
  • 10/21/2009 5:24 AM In reply to

    Re: Ball Speed Bug

    You're updating the ball positions in Ball.Update, but your aren't updating the ball rectangles...

  • 10/21/2009 5:39 AM In reply to

    Re: Ball Speed Bug

    I do:

     // Updates collision rect  
                this.ball_rect = new Rectangle(  
                    (int)this.ball_position.X,  
                    (int)this.ball_position.Y,  
                    this.ball_sprite.Width,  
                    this.ball_sprite.Height);  

    teK-Junkies: 'where one man's junk becomes another man's tek'
  • 10/21/2009 6:42 AM In reply to

    Re: Ball Speed Bug

    Ok I figured it out. The block was updating it's rectangle X and Y on the rectangle X and Y.... Yeah so nothing changed.
    So I simply changed it to the X and Y positions. I didn't even notice, I must of been tired....

    Anyway here is what the block rectangle code in update is now:
            public virtual void Update()  
            {  
                // Updates collision rect  
                this.block_rect = new Rectangle(  
                    (int)this.block_position.X,  
                    (int)this.block_position.Y,  
                    this.block_sprite.Width,  
                    this.block_sprite.Height);  
            }  

    Which leaves me with the problem of bouncing the block. I had this problem before, but I think I may have a solution? How about creating 4 rectangles on the block. So they form a border. If it only intersects one, then bounce of appropriately depending on which one. If it hits a corner and hits 2, then reverse both directions?

    Well I will try it when I get home, it:s 7:45am and I have to go to school in 15 minutes D=
    teK-Junkies: 'where one man's junk becomes another man's tek'
Page 1 of 1 (11 items) Previous Next