Xbox LIVE Indie Games
Sort Discussions: Previous Discussion Next Discussion
Page 1 of 1 (4 posts)

Not understanding where to place initialize and update functions

Last post 4/6/2012 12:30 AM by OnekSoft Games. 3 replies.
  • 4/4/2012 9:34 PM

    Not understanding where to place initialize and update functions

    So I think I've got my game up and running within this framework, but I'm still a bit
     confused when it comes to getting the two to work together. I'm using Oneksoft's
     XNA basic starter kit, which thus far has worked great.I'm also using a lot of code from
     a pong tutorial
    , which by itself works well too.
     
      I've got everything displayed on screen correctly, my menus implemented,
     and my music working. I can also move the paddles up and down, while checking for
     collision on the top and bottom of the screen. Perfect.

    My problem is as follows: I can't seem to get the game itself to start. That is, getting the
    pong ball to begin moving. I'm almsot certain it has to do with the fact that I don't have
    SetUpMulti or SetUpSingle configured correctly.

    In the tutorial, the Game class handles the initialization, loading of content, and updating. In the
    framework though, the Game class doesn't do much. Most of the work seems to be handled
    by the GameplayScreen class. However, GameplayScreen doesn't have an initialization method.

    Where do I place my methods such as:

    1 private void SetUpSingle()  
    2         {  
    3             rightBat = new AIBat(Content, new Vector2(screenWidth, screenHeight), false);  
    4             leftBat = new Bat(Content, new Vector2(screenWidth, screenHeight), true);  
    5         }  
    6  
    7         private void SetUpMulti()  
    8         {  
    9             rightBat = new Bat(Content, new Vector2(screenWidth, screenHeight), false);  
    10             leftBat = new Bat(Content, new Vector2(screenWidth, screenHeight), true);  
    11         }  
    12  
    13         private void IncreaseSpeed()  
    14         {  
    15             ball.IncreaseSpeed();  
    16             leftBat.IncreaseSpeed();  
    17             rightBat.IncreaseSpeed();  
    18         }  
    19  


     

    I suppose this is a very rookie-like question to ask, but can every class have an initialization and update function?
    That is what confuses me most.

    I'm not sure of how to share my project on here, but I do have it saved as a .zip in my Dropbox,
    if that makes it any easy to share.

    Some of the classes which may be useful for solving this are found below.

    1 #region File Description  
    2 //-----------------------------------------------------------------------------  
    3 // Game.cs  
    4 //  
    5 // Microsoft XNA Community Game Platform  
    6 // Copyright (C) Microsoft Corporation. All rights reserved.  
    7 //-----------------------------------------------------------------------------  
    8 #endregion
    9
    10 #region Using Statements  
    11 using Microsoft.Xna.Framework;  
    12 using Microsoft.Xna.Framework.Graphics;
    13 #endregion  
    14  
    15 namespace MyXnaGame  
    16 {  
    17     /// <summary>  
    18     /// Sample showing how to manage different game states, with transitions  
    19     /// between menu screens, a loading screen, the game itself, and a pause  
    20     /// menu. This main game class is extremely simple: all the interesting  
    21     /// stuff happens in the ScreenManager component.  
    22     /// </summary>  
    23     public class GameStateManagementGame : Microsoft.Xna.Framework.Game  
    24     {
    25         #region Fields  
    26  
    27         GraphicsDeviceManager graphics;  
    28         ScreenManager screenManager;  
    29         public int screenWidth;  
    30         public int screenHeight;  
    31         public Input myInputClass;   
    32  
    33  
    34         // By preloading any assets used by UI rendering, we avoid framerate glitches  
    35         // when they suddenly need to be loaded in the middle of a menu transition.  
    36         static readonly string[] preloadAssets =  
    37         {  
    38             "gradient",  
    39         };
    40
    41
    42         #endregion  
    43  
    44         #region Initialization  
    45  
    46  
    47         /// <summary>  
    48         /// The main game constructor.  
    49         /// </summary>  
    50         public GameStateManagementGame()  
    51         {  
    52             Content.RootDirectory = "Content";  
    53  
    54             graphics = new GraphicsDeviceManager(this);  
    55             // Set back buffer resolution    
    56             screenWidth = 1280;  
    57             screenHeight = 720;  
    58             graphics.PreferredBackBufferWidth = screenWidth;  
    59             graphics.PreferredBackBufferHeight = screenHeight;  
    60  
    61                 
    62  
    63             // Create the screen manager component.  
    64             screenManager = new ScreenManager(this);  
    65  
    66             Components.Add(screenManager);  
    67  
    68             // Activate the first screens.  
    69             screenManager.AddScreen(new BackgroundScreen(), null);  
    70             //screenManager.AddScreen(new MainMenuScreen(), null);  
    71             screenManager.AddScreen(new PressStartScreen(), null);  
    72         }  
    73  
    74  
    75         /// <summary>  
    76         /// Loads graphics content.  
    77         /// </summary>  
    78         protected override void LoadContent()  
    79         {  
    80  
    81  
    82             foreach (string asset in preloadAssets)  
    83             {  
    84                 Content.Load<object>(asset);  
    85             }  
    86         }
    87
    88
    89
    90
    91
    92         #endregion  
    93  
    94         #region Draw  
    95  
    96  
    97         /// <summary>  
    98         /// This is called when the game should draw itself.  
    99         /// </summary>  
    100         protected override void Draw(GameTime gameTime)  
    101         {  
    102               
    103             graphics.GraphicsDevice.Clear(Color.Black);  
    104  
    105             // The real drawing happens inside the screen manager component.  
    106             base.Draw(gameTime);  
    107         }
    108
    109
    110         #endregion  
    111     }
    112
    113
    114     #region Entry Point  
    115  
    116     /// <summary>  
    117     /// The main entry point for the application.  
    118     /// </summary>  
    119     static class Program  
    120     {  
    121         static void Main()  
    122         {  
    123             using (GameStateManagementGame game = new GameStateManagementGame())  
    124             {  
    125                 game.Run();  
    126             }  
    127         }  
    128     }
    129
    130     #endregion  
    131 }  
    132  

    1 #region File Description  
    2 //-----------------------------------------------------------------------------  
    3 // GameplayScreen.cs  
    4 //  
    5 // Microsoft XNA Community Game Platform  
    6 // Copyright (C) Microsoft Corporation. All rights reserved.  
    7 //-----------------------------------------------------------------------------  
    8 #endregion
    9
    10 #region Using Statements  
    11 using System;  
    12 using System.Threading;  
    13 using System.Linq;  
    14 using System.Collections.Generic;  
    15 using Microsoft.Xna.Framework;  
    16 using Microsoft.Xna.Framework.Content;  
    17 using Microsoft.Xna.Framework.Graphics;  
    18 using Microsoft.Xna.Framework.Input;  
    19 using Microsoft.Xna.Framework.Media;  
    20 using Drawing;
    21 #endregion  
    22  
    23 namespace MyXnaGame  
    24 {  
    25     /// <summary>  
    26     /// This screen implements the actual game logic. It is just a  
    27     /// placeholder to get the idea across: you'll probably want to  
    28     /// put some more interesting gameplay in here!  
    29     /// </summary>  
    30     class GameplayScreen : GameScreen  
    31     {  
    32       public static GameStates gamestate;   
    33       public Ball ball;  
    34       public Bat rightBat;  
    35       public Bat leftBat;  
    36       private int resetTimer;  
    37       private bool resetTimerInUse;  
    38       private bool lastScored;  
    39       private Input myInputClass;         
    40       public HudContainer hudContainer = new HudContainer();        
    41       public SafeArea safeArea;  
    42       public Vector2 safeTopLeft = Vector2.Zero; // (2.0f * (safeArea.dx), 1.5f * (safeArea.dy));  
    43       public ContentManager content;  
    44       private SpriteFont gameFont;  
    45       private SpriteFont hudFont;  
    46       public SpriteFont arial;  
    47       public int screenWidth = 1280;  
    48       public int screenHeight = 720;  
    49       private Texture2D backgroundTexture;  
    50       public Song PlayingSong { getprivate set; }  
    51       Vector2 enemyPosition = new Vector2(100, 100);  
    52       Random random = new Random();  
    53       float pauseAlpha;  
    54  
    55         public enum GameStates  
    56         {  
    57             Menu,  
    58             Running,  
    59             End  
    60         }  
    61           
    62  
    63         public GameplayScreen()  
    64         {   
    65             safeArea = new SafeArea();  
    66             TransitionOnTime = TimeSpan.FromSeconds(1.5);  
    67             TransitionOffTime = TimeSpan.FromSeconds(0.5);  
    68             
    69          }  
    70  
    71  
    72         // LOADCONTENT  
    73         //  
    74         //  
    75         public override void LoadContent()  
    76         {  
    77             if (content == null)  
    78                 content = new ContentManager(ScreenManager.Game.Services, "Content");  
    79             DrawingHelper.Initialize(ScreenManager.GraphicsDevice);  
    80             safeArea.LoadGraphicsContent(ScreenManager.GraphicsDevice);  
    81             gameFont = content.Load<SpriteFont>("gamefont");   
    82             arial = content.Load<SpriteFont>("Arial");   
    83             hudFont = content.Load<SpriteFont>("menufont");            
    84             hudContainer.LoadGraphicsContent(ScreenManager.GraphicsDevice, hudFont, safeArea);  
    85             var hudInfo = new HudTextComponent("...Ninja Cats!", HudComponent.PresetPosition.BottomRight);  
    86             hudContainer.Add(hudInfo);  
    87  
    88             myInputClass = new Input();  
    89             PlayingSong = content.Load<Song>(@"sfx/boomer");  
    90             MediaPlayer.Play(PlayingSong);  
    91             backgroundTexture = content.Load<Texture2D>(@"gfx/mm7Background");               
    92               
    93            ball = new Ball(content, new Vector2 (ScreenManager.GraphicsDevice.Viewport.Width,   
    94             ScreenManager.GraphicsDevice.Viewport.Height));           
    95             rightBat = new Bat(content, new Vector2 (ScreenManager.GraphicsDevice.Viewport.Width,  
    96                 ScreenManager.GraphicsDevice.Viewport.Height), true);  
    97             leftBat = new Bat(content, new Vector2(ScreenManager.GraphicsDevice.Viewport.Width,  
    98                 ScreenManager.GraphicsDevice.Viewport.Height), false);  
    99                         
    100             // A real game would probably have more content than this sample, so  
    101             // it would take longer to load. We simulate that by delaying for a  
    102             // while, giving you a chance to admire the beautiful loading screen.  
    103             Thread.Sleep(1000);  
    104  
    105             // once the load has finished, we use ResetElapsedTime to tell the game's  
    106             // timing mechanism that we have just finished a very long frame, and that  
    107             // it should not try to catch up.  
    108             ScreenManager.Game.ResetElapsedTime();  
    109         }  
    110  
    111  
    112  
    113         public override void UnloadContent()  
    114         {  
    115             content.Unload();  
    116         }  
    117  
    118      
    119  
    120         // UPDATE  
    121         //  
    122         //  
    123         public override void Update(GameTime gameTime, bool otherScreenHasFocus,  
    124                                                        bool coveredByOtherScreen)  
    125         {  
    126             base.Update(gameTime, otherScreenHasFocus, false);  
    127  
    128             ball.UpdatePosition();  
    129             leftBat.UpdatePosition(ball);  
    130             rightBat.UpdatePosition(ball);  
    131             myInputClass.Update();  
    132  
    133  
    134  
    135             if (gamestate == GameStates.Running)  
    136             {  
    137                 if (leftBat.GetPoints() > 9)  
    138                 {  
    139                     //                  menu.InfoText = "Left Player Wins";  
    140                     gamestate = GameStates.End;  
    141                 }  
    142                 else if (rightBat.GetPoints() > 9)  
    143                 {  
    144                     //                  menu.InfoText = "Right Player Wins";  
    145                     gamestate = GameStates.End;  
    146                     if (resetTimerInUse)  
    147                     {  
    148                         resetTimer++;  
    149                         ball.Stop();  
    150                     }  
    151                     if (resetTimer == 120)  
    152                     {  
    153                         resetTimerInUse = false;  
    154                         ball.Reset(lastScored);  
    155                         resetTimer = 0;  
    156                     }  
    157  
    158                     if (!resetTimerInUse)  
    159                     {  
    160                         if (ball.GetPosition().X > screenWidth)  
    161                         {  
    162                             resetTimerInUse = true;  
    163                             lastScored = true;  
    164                             leftBat.IncrementPoints();  
    165                         }  
    166                         else if (ball.GetPosition().X < 0)  
    167                         {  
    168                             resetTimerInUse = true;  
    169                             lastScored = false;  
    170                             rightBat.IncrementPoints();  
    171                         }  
    172                     }  
    173  
    174  
    175                     // Gradually fade in or out depending on whether we are covered by the pause screen.  
    176                     if (coveredByOtherScreen)  
    177                         pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);  
    178                     else 
    179                         pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);  
    180                 }  
    181             }  
    182         }  
    183             
    184  
    185         private int CheckHitLocation(Bat bat)  
    186         {  
    187             int block = 0;  
    188             if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 20) block = 1;  
    189             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 2) block = 2;  
    190             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 3) block = 3;  
    191             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 4) block = 4;  
    192             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 5) block = 5;  
    193             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 6) block = 6;  
    194             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 7) block = 7;  
    195             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 10 * 8) block = 8;  
    196             else if (ball.GetPosition().Y < bat.GetPosition().Y + bat.GetSize().Height / 20 * 19) block = 9;  
    197             else block = 10;  
    198             return block;  
    199         }  
    200           
    201  
    202  
    203         /// <summary>  
    204         /// Lets the game respond to player input. Unlike the Update method,  
    205         /// this will only be called when the gameplay screen is active.  
    206         /// </summary>  
    207         public override void HandleInput(InputState input) //, GameTime gameTime)  
    208         {  
    209             if (input == null)  
    210                 throw new ArgumentNullException("input");  
    211             myInputClass.Update(); // Updates myInputClass, instead of the default one.  
    212  
    213             // Look up inputs for the active player profile.  
    214             int playerIndex = (int)ControllingPlayer.Value;  
    215  
    216             KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];  
    217             GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];  
    218  
    219             // The game pauses either if the user presses the pause button, or if  
    220             // they unplug the active gamepad. This requires us to keep track of  
    221             // whether a gamepad was ever plugged in, because we don't want to pause  
    222             // on PC if they are playing with a keyboard and have no gamepad at all!  
    223             bool gamePadDisconnected = !gamePadState.IsConnected &&  
    224                                        input.GamePadWasConnected[playerIndex];  
    225  
    226             if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)  
    227             {  
    228                 ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);  
    229             }  
    230  
    231             else 
    232             { // If/ElseIf is used so we don't move up AND down (by holding both buttons). It's either up OR down, not both  
    233                 if (myInputClass.LeftDown) leftBat.MoveDown();  
    234                 else if ((myInputClass.LeftUp)) leftBat.MoveUp();  
    235                 if (myInputClass.RightDown) rightBat.MoveDown();  
    236                 else if (myInputClass.RightUp) rightBat.MoveUp();  
    237             }  
    238  
    239             //checking if the rectangles collide.  
    240             if (ball.GetDirection() > 1.5f * Math.PI || ball.GetDirection() < 0.5f * Math.PI)  
    241             {  
    242                 if (rightBat.GetSize().Intersects(ball.GetSize()))  
    243                 {  
    244                     ball.BatHit(CheckHitLocation(rightBat));  
    245                 }  
    246             }  
    247             else 
    248             {  
    249                 if (leftBat.GetSize().Intersects(ball.GetSize()))  
    250                 {  
    251                     ball.BatHit(CheckHitLocation(leftBat));  
    252                 }  
    253             }  
    254  
    255              
    256  
    257             // Handles whether or not the ball went off the left or right side of the screen  
    258             if (ball.GetPosition().X > screenWidth)  
    259             {  
    260                 ball.Reset(true);  
    261             }  
    262             else if (ball.GetPosition().X < 0)  
    263             {  
    264                 ball.Reset(false);  
    265             }  
    266         }  
    267  
    268  
    269  
    270         private void SetUpSingle()  
    271         {  
    272             rightBat = new AIBat(content, new Vector2(screenWidth, screenHeight), false);  
    273             leftBat = new Bat(content, new Vector2(screenWidth, screenHeight), true);  
    274         }  
    275  
    276  
    277         public void SetUpMulti()  
    278         {  
    279             rightBat = new Bat(content, new Vector2(screenWidth, screenHeight), false);  
    280             leftBat = new Bat(content, new Vector2(screenWidth, screenHeight), true);  
    281         }  
    282  
    283  
    284  
    285         // DRAW CALLS  
    286         //  
    287         //  
    288         public override void Draw(GameTime gameTime)  
    289         {  
    290             // Our player and enemy are both actually just text strings.  
    291             SpriteBatch spriteBatch = ScreenManager.SpriteBatch;  
    292  
    293             spriteBatch.Begin();  
    294  
    295             // Draws the backgrund  
    296             spriteBatch.Draw(backgroundTexture, new Rectangle(0, 0, 800, 600), Color.White);  
    297  
    298             // Draws the score  
    299             spriteBatch.DrawString(arial, leftBat.GetPoints().ToString(), new Vector2  
    300                 (screenWidth / 4 - arial.MeasureString(rightBat.GetPoints().ToString()).X, 20), Color.White);  
    301             spriteBatch.DrawString(arial, rightBat.GetPoints().ToString(), new Vector2  
    302                 (screenWidth / 4 * 3 - arial.MeasureString(rightBat.GetPoints().ToString()).X, 20), Color.White);  
    303               
    304             // draw hud  
    305             hudContainer.Draw(spriteBatch);  
    306             spriteBatch.DrawString(gameFont, "Mega Man Pong",  
    307                                    enemyPosition, Color.Black);
    308
    309 #if DEBUG     // I've temporarily commented out the safeArea debug -DV    
    310 //            safeArea.Draw(spriteBatch);  
    311 #endif  
    312  
    313             // debug info  
    314             var safeAreaInfo = "dx=" + safeArea.dx + ",dy=" + safeArea.dy  
    315                 + ",w=" + safeArea.width + ",h=" + safeArea.height;  
    316                 //+ ", H = " + playerHorizDirection  
    317                 //+ ", V = " + playerVertDirection;  
    318             spriteBatch.DrawString(gameFont, safeAreaInfo, safeTopLeft, Color.Green);  
    319    
    320             // Draws ball and bats  
    321             ball.Draw(spriteBatch);  
    322             rightBat.Draw(spriteBatch);  
    323             leftBat.Draw(spriteBatch);  
    324              
    325             spriteBatch.End();  
    326  
    327            // If the game is transitioning on or off, fade it out to black.  
    328             if (TransitionPosition > 0 || pauseAlpha > 0)  
    329             {  
    330                 float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);  
    331                 ScreenManager.FadeBackBufferToBlack(alpha);  
    332             }  
    333         }  
    334     }  
    335 }  
    336  

  • 4/4/2012 9:51 PM In reply to

    Re: Not understanding where to place initialize and update functions

    Dave Voyles:
    So I think I've got my game up and running within this framework, but I'm still a bit confused when it comes to getting the two to work together.


    I'm confused too, looking at your code, because you shouldn't normally have two different Game subclasses in the same project. Normally there would be one master
    game class and both the menu and gameplay screens would be a drawable component. Having two instances of Game will create two parallel draw/update threads, which
    is almost certainly not what you want.

    My problem is as follows: I can't seem to get the game itself to start. That is, getting the

    pong ball to begin moving. I'm almsot certain it has to do with the fact that I don't have
    SetUpMulti or SetUpSingle configured correctly.

    One-time setup should be done in Initialize() (overriding the method in Game). Resetting game state should probably be done in the event handler for the 'start game' menu option.

  • 4/6/2012 12:27 AM In reply to

    Re: Not understanding where to place initialize and update functions


    ** I am OnekSoft Games and I approve this message ** 
    ;-)

    Hey Dave,

    In the code you posted, I see where you launch the "Press Start" screen, but I don't see the code for the start screen and the menu items that will launch your GameplayScreen. Please share the latest version with me via dropbox, and I can take a look at it.

    In the meantime, let me see if I can explain how to follow the path of a game through the code in my XNA Basic Starter Kit. The answer to your question is at the bottom, but please read these step-by-step explanations first. 

    1. The game starts within the static Main() method. This is inside Game.cs inside a static class called Program. This method essentially has 1 line of code game.Run() that kicks off the game.

    2. The "game" object here is of type GameStateManagementGame which is a public class defined in the same file Game.cs. Normally, you would organize each class in its own file, but that's not required, so I left it as is, from the GSM sample, since the Program class is so small.

    3. The GameStateManagementGame class is a subclass of the XNA Framework "Game" class which is required for it to be an XNA game. At the top of the GameStateManagementGame class, it initializes a GraphicsDeviceManager and a ScreenManager.

    4. The GraphicsDeviceManager is used to set the back-buffer dimensions and clear the screen.

    5. The ScreenManager is a type of DrawableGameComponent, that is added to a GameComponentCollection by using the line Components.Add() in the constructor GameStateManagementGame(). This is immediately followed by adding screens to the ScreenManager for the initial background and start screen.

    6. Since the ScreenManager is a "DrawableGameComponent", this means that it can have a bunch of overrides for Initialize(), LoadContent(), Update(), Draw() and UnloadContent(). You don't necessarily have to do anything in this class, since it takes care of the code that is used for loading, displaying and unloading your screens.

    7. There is an abstract class called GameScreen which is the "parent class" for every screen. You can change this GameScreen class if you want, and you will be creating a subclass of GameScreen, for every type of screen you need, e.g. you may want a HighScoreScreen that is a subclass of GameScreen.

    8. Every subclass of GameScreen will have overrides of LoadContent(), HandleInput(), Update(), Draw() and UnloadContent() so that each screen of yours can handle itself.

    9. Now on to a specific screen: GameplayScreen. This is the MEAT of the XNA Basic Starter Kit! You can rip apart this class to put your own stuff in it for your game. You can make it as small as you want, and extract out code into other new classes.

    10. As you mentioned, the GameplayScreen doesn't have an Initialize() method. This is only because it is a subclass of GameScreen, which doesn't have an Initialize() method, so there's no requirement for it to have an Initialize() method. If you need to initialize anything in GameplayScreen, you can do so in its own constructor GameplayScreen(). 

    Remember that the constructor of any class is the method that has the same name of the class, but does not have a return value. The "default constructor" does not take any parameters in parentheses.

    So, try calling the bat initializers from your GameplayScreen() constructor. Keep in mind that you will need to re-position the bats once every round. You won't have to re-create the bat objects again, but your bats should have a method to re-position themselves, that can be called from a method in your GameplayScreen class.

    Hope that helps.

    ~OnekSoft Games
    .
  • 4/6/2012 12:30 AM In reply to

    Re: Not understanding where to place initialize and update functions

    Bitphase Entertainment:
    ...
    I'm confused too, looking at your code, because you shouldn't normally have two different Game subclasses in the same project. Normally there would be one master
    game class and both the menu and gameplay screens would be a drawable component. Having two instances of Game will create two parallel draw/update threads, which
    is almost certainly not what you want....

    Hi Bitphase,

    Please see my explanation above. 

    If you look closely at Dave's code, you'll see it that doesn't have 2 subclasses of Game. The main one is a subclass of Game, and the other one is a subclass of GameScreen which is an abstract class from the GSM sample.

    ~OnekSoft Games
    .
Page 1 of 1 (4 posts) Previous Discussion Next Discussion