Game Development Community

2 Questions - Please Help

by Do Not Delete · in Torque X 2D · 09/05/2007 (7:46 pm) · 42 replies

1. What is the best way to pause a game using Torque X?

2. I've been tinkering around with the FireProjectileComponenet from the Blaster Tutorial and decided to add the code to the Player Controller.cs file. There is one problem though, it can't find SceneObject. The SceneObject in our case is the Dragon. What would the equivilent of SceneObject be in our case?

Code:

// Set the position based on the position of the object that's shooting.
                projectileObj.Position = SceneObject.Position;

                projectileObj.Layer = SceneObject.Layer + 1;
Can anyone help?

Thanks!
Page «Previous 1 2 3 Last »
#1
09/05/2007 (8:15 pm)
1. There's a GameTimeScale property on the TorqueEngineComponent singleton (found in the GarageGames.Torque.XNA namespace).

// pause the game
TorqueEngineComponent.Instance.GameTimeScale = 0f;

// resume the game
TorqueEngineComponent.Instance.GameTimeScale = 1f;

2. To avoid confusion, I should mention that the following applies to the Platformer Starter Kit. A controller doesn't have a scene object. The whole idea of a controller is that it can be attached to any number of actors/movers simultaneously and on the fly, so it's just a standalone object floating in memory. You'll want to take a look at how the ActorController pushes input events to it's ActorComponents and do something similar.

In other words, you'll want to use the a controller subclass to set a flag on your actor subclass and then override _updatePhysics on your actor subclass and check if the actor should be attacking. If so, you would create your projectile there. ActorComponent has the SceneObject property you're looking for.

Edit: Check out how the PlayerController tells the DragonActorComponent whether or not it should be gliding in the Demo project for a good example.
#2
09/05/2007 (8:30 pm)
Thanks! I'll try everything you said right now!
#3
09/05/2007 (8:37 pm)
One thing, I have a Quit button on the pause menu, but I get an exception.

Here is the code the exception happens on

SoundManager.menuMusic.Play()
There is a line before that that cleans all cues.

Here is the exception:

Quote:System.InvalidOperationException was unhandled
Message="The method or function called cannot be used in the manner requested."
Source="Microsoft.Xna.Framework"
StackTrace:
at Microsoft.Xna.Framework.Audio.Cue.Play()
at PlatformerStarter.GUI.PauseMenuGUI._PauseMenuMenu() in C:\code\Utopia\Utopia\Game\GUI\PauseMenu.cs:line 241
at PlatformerStarter.GUI.PauseMenuGUI._menuButton(Single val) in C:\code\Utopia\Utopia\Game\GUI\PauseMenu.cs:line 217
at GarageGames.Torque.Sim.InputMap.ProcessInput(InputEventData data)
at GarageGames.Torque.GUI.GUIControl.OnInputEvent(InputEventData& data)
at GarageGames.Torque.GUI.GUICanvas.ProcessInput(InputEventData data)
at GarageGames.Torque.Sim.InputManager.ProcessInputEvent(String eventName, InputEventData inputData)
at GarageGames.Torque.Core.TorqueEvent'1._Trigger(Delegate d)
at GarageGames.Torque.Core.TorqueEventManager._TriggerEvent(TorqueEventBase ev)
at GarageGames.Torque.Core.TorqueEventManager.MgrProcessEvents()
at GarageGames.Torque.Core.TorqueEventManager.ProcessEvents()
at GarageGames.Torque.XNA.TorqueEngineComponent.Update(GameTime gameTime)
at Microsoft.Xna.Framework.Game.Update(GameTime gameTime)
at PlatformerStarter.Game.Update(GameTime gameTime) in C:\code\Utopia\Utopia\Game\Game.cs:line 91
at Microsoft.Xna.Framework.Game.Tick()
at Microsoft.Xna.Framework.Game.HostIdle(Object sender, EventArgs e)
at Microsoft.Xna.Framework.GameHost.OnIdle()
at Microsoft.Xna.Framework.WindowsGameHost.ApplicationIdle(Object sender, EventArgs e)
at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at Microsoft.Xna.Framework.WindowsGameHost.Run()
at Microsoft.Xna.Framework.Game.Run()
at PlatformerStarter.GameStarter.Main(String[] args) in C:\code\Utopia\Utopia\Game\Main.cs:line 24

What do I do?
#4
09/05/2007 (9:02 pm)
This should really be in a separate post, but whatevers.

The cue reference you're holding has been disposed. That's what the Platformer Kit does before shutdown. The solution is to *not* try to play music while you're exiting the game. :P

if(!SoundManager.menuMusic.IsDisposed)
    SoundManager.menuMusic.Play();

Edit: Also, if anyone is interested, the SoundManager from the Platformer Kit has been polished up and brought into the engine, so expect to see it in the next update.
#5
09/05/2007 (9:04 pm)
It doesn't really exit the game, it just unloads the scene, and takes the user to the Main Menu.
#6
09/05/2007 (9:07 pm)
Hmm... post that whole method plz.
#7
09/05/2007 (9:11 pm)
SoundManager really isn't the best place for game-related cues. I'd suggest the Game class, but I guess it doesn't really matter too much...

When you call CleanAllCues the sound manager releases all references to all its managed sound cues and disposes them. If you don't want a sound cue to be managed, call GetCue on the sound manager and then call Play on the cue directly rather than calling PlaySound on the sound manager and using the cue returned from that.

Correct me if that's not the issue.
#8
09/05/2007 (9:26 pm)
Here is how I did it. I have one file called Sound.cs which has all the cues ready for playing, stopping, etc...

public static Cue menuMusic = SoundManager.Instance.GetCue(@"data\sound\music", "main_menu_music");
public static Cue gameMusic = SoundManager.Instance.GetCue(@"data\sound\music", "game_music");
public static Cue splashMusic = SoundManager.Instance.GetCue(@"data\sound\music", "splash_screen_music");
public static Cue beep = SoundManager.Instance.GetCue(@"data\sound\music", "beep");

For example if I want to play the menuMusic I would do

Sound.menuMusic.Play(); and it would play.

Here is the code in the PauseScreen file

protected virtual void _PauseMenuMenu()
        {
            PopFromCanvas();
            Sound.gameMusic.Stop(AudioStopOptions.AsAuthored);
            Game.Instance.SceneLoader.Unload(@"data\levels\sample_level.txscene");
            GUIStyle menuStyle = new GUIStyle();
            GUISceneview menu = new GUISceneview();
            menu.Name = "MenuScreen";
            menu.Style = menuStyle;

            GUICanvas.Instance.SetContentControl("MainMenu");
            
            SoundManager.Instance.CleanAllCues();
            Sound.menuMusic.Play();
        }

Am I doing anything wrong?
#9
09/05/2007 (9:33 pm)
Nothing really jumps out at me as "wrong". It looks perfect.

Could you post a screenshot or text of all the property and field values of that cue right before play is called?
#10
09/05/2007 (9:48 pm)
Just a head's up cause we've been replying to each other pretty rapidly, I'm heading out of the office for the day. I'll check this thread tomorrow when I get in.
#11
09/05/2007 (9:50 pm)
I think this is what you want....

//======================================================
        #region Public properties, operators, constants, and enums

        static public PauseMenuGUI Instance
        {
            get { return _instance; }
        }

        #endregion

        //======================================================
        #region Public methods

        public PauseMenuGUI()
        {
            _createPauseMenuGUI();
            _instance = this;
        }

        /// <summary>
        /// Display the Pause Menu.
        /// </summary>
        public void PushToCanvas()
        {
            // Pause the sound
            Sound.gameMusic.Pause();

            // Make the Pause Menu visible
            _prevFocusControl = GUICanvas.Instance.GetFocusControl();
            this.Folder = GUICanvas.Instance;
            GUICanvas.Instance.SetFocusControl(this);

            TorqueEngineComponent.Instance.GameTimeScale = 0f;
        }

        /// <summary>
        /// Take down the Pause Menu.
        /// </summary>
        public void PopFromCanvas()
        {
            Assert.Fatal(this.Folder != TorqueObjectDatabase.Instance.RootFolder, "PauseMenuGUI.PopFromCanvas(): Pause menu not pushed");
            if (this.Folder != TorqueObjectDatabase.Instance.RootFolder)
            {
                this.Folder = TorqueObjectDatabase.Instance.RootFolder;
                GUICanvas.Instance.ClearFocusControl();

                TorqueEngineComponent.Instance.GameTimeScale = 1f;
                //MyGame.Instance.GamePaused = false;

                if (_prevFocusControl != null)
                {
                    GUICanvas.Instance.SetFocusControl(_prevFocusControl);
                    _prevFocusControl = null;
                }
            }
        }

        #endregion

        //======================================================
        #region Private, protected, internal methods

        void _createPauseMenuGUI()
        {
            int gamepadId = InputManager.Instance.FindDevice("gamepad0");
            int keyboardId = InputManager.Instance.FindDevice("keyboard");

            GUIStyle style = new GUIStyle();
            style.FillColor = new Color(0, 0, 0, 128);
            style.PreserveAspectRatio = true;
            style.Anchor = AnchorFlags.All;

            this.Style = style;
            this.Name = "PauseMenu";
            this.Layer = 1;
            this.Size = new SizeF(1024, 768);
            this.Visible = true;
            this.Folder = TorqueObjectDatabase.Instance.RootFolder;
            this.InputMap.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Up, _buttonNavigationPrev);
            this.InputMap.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Down, _buttonNavigationNext);
            this.InputMap.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Escape, _continueButton);
            this.InputMap.BindAction(gamepadId, (int)XGamePadDevice.GamePadObjects.B, _continueButton);

            // Begin buttons
            float buttonX = 400;
            float buttonY = 330;

            GUIBitmapButtonStyle bstyle = new GUIBitmapButtonStyle();
            bstyle.SizeToBitmap = true;
            bstyle.Focusable = true;
            bstyle.Anchor = AnchorFlags.None;

            // Continue button
            GUIBitmapButton button = new GUIBitmapButton();
            button.Style = bstyle;
            button.Name = "PauseMenuContinueButton";
            button.NormalTexture = @"data\images\buttons\help";
            button.SelectedTexture = @"data\images\buttons\help_h";
            button.SetPosition(new PointF(buttonX, buttonY));
            button.Visible = true;
            button.FocusOnWake = true;
            button.Folder = this;
            button.InputMap.BindAction(gamepadId, (int)XGamePadDevice.GamePadObjects.A, _continueButton);
            button.InputMap.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Enter, _continueButton);
            button.OnGUIGainFocus += _guiGainFocus;

            buttonY += button.Size.Height;

            // Menu button
            button = new GUIBitmapButton();
            button.Style = bstyle;
            button.Name = "PauseMenuMenuButton";
            button.NormalTexture = @"data\images\buttons\quit";
            button.SelectedTexture = @"data\images\buttons\quit_h";
            button.SetPosition(new PointF(buttonX, buttonY));
            button.Visible = true;
            button.FocusOnWake = false;
            button.Folder = this;
            button.InputMap.BindAction(gamepadId, (int)XGamePadDevice.GamePadObjects.A, _menuButton);
            button.InputMap.BindAction(keyboardId, (int)Microsoft.Xna.Framework.Input.Keys.Enter, _menuButton);
            button.OnGUIGainFocus += _guiGainFocus;

            buttonY += button.Size.Height;

            // Back and Select image
            GUIBitmapStyle selectStyle = new GUIBitmapStyle();
            selectStyle.SizeToBitmap = true;
            selectStyle.Anchor = AnchorFlags.None;

            GUIBitmap selectImage = new GUIBitmap();
            selectImage.Style = selectStyle;
            selectImage.Bitmap = @"data\images\buttons\SelectOnly";
            selectImage.SetPosition(new PointF(790.0f, 601.0f));
            selectImage.Visible = true;
            selectImage.Folder = this;
        }

        /// <summary>
        /// Play a sound effect when a button is highlighted by the user.
        /// </summary>
        /// <param name="ctrl">The highlighted control.</param>
        private void _guiGainFocus(GUIControl ctrl)
        {
            
        }

        /// <summary>
        /// Move to the next button using the keyboard.  Changing focus with the gamepad
        /// is handled automatically by the Canvas.
        /// </summary>
        private void _buttonNavigationPrev(float val)
        {
            if (Epsilon.FloatIsNotZero(val))
            {
                GUICanvas.Instance.FocusPrev(SearchPolicy.Vertical);
            }
        }

        /// <summary>
        /// Move to the previous button using the keyboard.  Changing focus with the gamepad
        /// is handled automatically by the Canvas.
        /// </summary>
        private void _buttonNavigationNext(float val)
        {
            if (Epsilon.FloatIsNotZero(val))
            {
                GUICanvas.Instance.FocusNext(SearchPolicy.Vertical);
            }
        }

        /// <summary>
        /// Handle the Continue button being pressed.
        /// </summary>
        private void _continueButton(float val)
        {
            if (Epsilon.FloatIsNotZero(val))
            {
                _PauseMenuContinue();
            }
        }

        /// <summary>
        /// Handle the Menu button being pressed.
        /// </summary>
        private void _menuButton(float val)
        {
            if (Epsilon.FloatIsNotZero(val))
            {
                _PauseMenuMenu();
            }
        }

        protected virtual void _PauseMenuContinue()
        {
            PopFromCanvas();

            Sound.gameMusic.Resume();
        }

        protected virtual void _PauseMenuMenu()
        {
            PopFromCanvas();
            Sound.gameMusic.Stop(AudioStopOptions.AsAuthored);
            Game.Instance.SceneLoader.Unload(@"data\levels\sample_level.txscene");
            GUIStyle menuStyle = new GUIStyle();
            GUISceneview menu = new GUISceneview();
            menu.Name = "MenuScreen";
            menu.Style = menuStyle;

            GUICanvas.Instance.SetContentControl("MainMenu");
            
            SoundManager.Instance.CleanAllCues();
#12
09/06/2007 (3:50 pm)
I took a look at how I did it with the Platformer Demo..


Try something like this:
public void PlayOutdoorMusic()
{
    if (_musicCueName != _outdoorMusic)
    {
        _music.Stop(AudioStopOptions.AsAuthored);
        _musicCueName = _outdoorMusic;
        _music = SoundManager.Instance.PlaySound(_musicSoundGroup, _musicCueName);
    }
}

public void PlayIndoorMusic()
{
    if (_musicCueName != _indoorMusic)
    {
        _music.Stop(AudioStopOptions.AsAuthored);
        _musicCueName = _indoorMusic;
        _music = SoundManager.Instance.PlaySound(_musicSoundGroup, _musicCueName);
    }
}

I'm thinking it's possible that the cues become invalid after a certain amount of time of not being used for whatever reason. Try calling GetCue again and then playing it.
#13
09/06/2007 (6:36 pm)
I tried to do the GetCue method but that doesn't work either.

For the code you posted, does it go in the Sound.cs file or what?
#14
09/07/2007 (4:23 pm)
That's just an example of how to do it. The message was to store the cue names instead of the actual cues and only load them when you're about to play them.
#15
09/07/2007 (5:53 pm)
I can't get the code you posted integrated into my game, I looked at the Platformer Demo but that doesn't help either. What should I do?
#16
09/08/2007 (1:40 pm)
Just wanted to let everyone know that sound has gotten nowhere and I took all the code out. If anyone can give me a suggestion on how to play, stop, pause, and resume the sounds that would be great.

On the plus side, I got shooting to work

To sum it all up, I need to fix the following problems:

1. A good way to manage the sound using Sound Manager.
2. If I pause the game, quit, select single player from the main menu, go to the single player main menu, select new game I can't move the dragon with the controller, but I can shoot using the controller (only X button, no jumping with controller either). The keyboard works fine though.
3. I need to delete something from the Torque X Builder object tree that I can't find on the Scene View. How would I do this?

If anyone can help me with any of those problems that would be great!!
#17
09/08/2007 (2:55 pm)
Quote:On the plus side, I got shooting to work

Can you explain this in detail (idiot-proof for a beginner like me)?
#18
09/08/2007 (2:57 pm)
Sure!

I'll make a tutorial at the TDN. I'll let you guys know when thats up ;)
#19
09/08/2007 (3:20 pm)
Wow! I can't wait :-)
#20
09/08/2007 (3:21 pm)
Done!

Here is the link:
tdn.garagegames.com/wiki/TorqueX/PlatformerFrameworkShooter

Please let me know if anything is wrong with it :)
Page «Previous 1 2 3 Last »