123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- #region File Description
- //-----------------------------------------------------------------------------
- // LobbyScreen.cs
- //
- // Microsoft XNA Community Game Platform
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- #endregion
- #region Using Statements
- using System;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.GamerServices;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Net;
- #endregion
- namespace NetRumble
- {
- /// <summary>
- /// The lobby screen is shows the players in the game, outside the gameplay.
- /// </summary>
- public class LobbyScreen : MenuScreen, IDisposable
- {
- #region Constants
- /// <summary>
- /// The instructions shown to the player at the bottom of the lobby screen.
- /// </summary>
- const string instructions =
- "Press X to mark/unmark ready, LB/RB to toggle color, LT/RT to toggle ship";
- #endregion
- #region Gameplay Data
- /// <summary>
- /// The primary object for this game.
- /// </summary>
- private World world;
- #endregion
- #region Networking Data
- /// <summary>
- /// The network session for this game.
- /// </summary>
- private NetworkSession networkSession;
- /// <summary>
- /// The packet writer used to send data from this screen.
- /// </summary>
- private PacketWriter packetWriter = new PacketWriter();
-
- /// <summary>
- /// Event handler for the session-ended event.
- /// </summary>
- EventHandler<NetworkSessionEndedEventArgs> sessionEndedHandler;
- /// <summary>
- /// Event handler for the game-ended event.
- /// </summary>
- EventHandler<GameStartedEventArgs> gameStartedHandler;
- /// <summary>
- /// Event handler for the gamer-left event.
- /// </summary>
- EventHandler<GamerJoinedEventArgs> gamerJoinedHandler;
- #endregion
- #region Initialization
- /// <summary>
- /// Constructs a new LobbyScreen object.
- /// </summary>
- public LobbyScreen(NetworkSession networkSession) : base()
- {
- // safety-check the parameter
- if (networkSession == null)
- {
- throw new ArgumentNullException("networkSession");
- }
- // apply the parameters
- this.networkSession = networkSession;
- // add the single menu entry
- MenuEntries.Add("");
- // set the transition time
- TransitionOnTime = TimeSpan.FromSeconds(1.0);
- TransitionOffTime = TimeSpan.FromSeconds(0.0);
- gamerJoinedHandler = new EventHandler<GamerJoinedEventArgs>(
- networkSession_GamerJoined);
- gameStartedHandler = new EventHandler<GameStartedEventArgs>(
- networkSession_GameStarted);
- sessionEndedHandler = new EventHandler<NetworkSessionEndedEventArgs>(
- networkSession_SessionEnded);
- }
- /// <summary>
- /// Load graphics content for the game.
- /// </summary>
- public override void LoadContent()
- {
- base.LoadContent();
- // create the world object
- world = new World(ScreenManager.GraphicsDevice, ScreenManager.Content,
- networkSession);
- // set the networking events
- networkSession.GamerJoined += gamerJoinedHandler;
- networkSession.GameStarted += gameStartedHandler;
- networkSession.SessionEnded += sessionEndedHandler;
- }
- #endregion
- #region Updating Methods
- /// <summary>
- /// Updates the lobby. This method checks the GameScreen.IsActive
- /// property, so the game will stop updating when the pause menu is active,
- /// or if you tab away to a different application.
- /// </summary>
- public override void Update(Microsoft.Xna.Framework.GameTime gameTime,
- bool otherScreenHasFocus, bool coveredByOtherScreen)
- {
- if (networkSession != null)
- {
- // update the network session
- try
- {
- networkSession.Update();
- }
- catch (NetworkException ne)
- {
- System.Console.WriteLine(
- "Network failed to update: " + ne.ToString());
- if (networkSession != null)
- {
- networkSession.Dispose();
- networkSession = null;
- }
- }
- }
- // update the world
- if ((world != null) && !otherScreenHasFocus && !coveredByOtherScreen)
- {
- if (world.GameWon)
- {
- // unload the existing world
- world.Dispose();
- world = null;
- // make sure that all of the ships have cleaned up
- foreach (NetworkGamer networkGamer in networkSession.AllGamers)
- {
- PlayerData playerData = networkGamer.Tag as PlayerData;
- if ((playerData != null) && (playerData.Ship != null))
- {
- playerData.Ship.Die(null, true);
- }
- }
- // make sure the collision manager is up-to-date
- CollisionManager.Collection.ApplyPendingRemovals();
- // create a new world
- world = new World(ScreenManager.GraphicsDevice,
- ScreenManager.Content, networkSession);
- }
- else if (world.GameExited)
- {
- if (!IsExiting)
- {
- ExitScreen();
- }
- if (world != null)
- {
- world.Dispose();
- world = null;
- }
- if (networkSession != null)
- {
- networkSession.Dispose();
- networkSession = null;
- }
- base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
- return;
- }
- else
- {
- world.Update((float)gameTime.ElapsedGameTime.TotalSeconds, true);
- }
- }
- // update the menu entry text
- if (otherScreenHasFocus == false)
- {
- if ((networkSession.LocalGamers.Count > 0) &&
- (networkSession.SessionState == NetworkSessionState.Lobby))
- {
- if (!networkSession.LocalGamers[0].IsReady)
- {
- MenuEntries[0] = "Press X to Mark as Ready";
- }
- else if (!networkSession.IsEveryoneReady)
- {
- MenuEntries[0] = "Waiting for all players to mark as ready...";
- }
- else if (!networkSession.IsHost)
- {
- MenuEntries[0] = "Waiting for the host to start game...";
- }
- else
- {
- MenuEntries[0] = "Starting the game...";
- networkSession.StartGame();
- }
- }
- else if (networkSession.SessionState == NetworkSessionState.Playing)
- {
- MenuEntries[0] = "Game starting...";
- }
- // if the game is playing and the world is initialized, then start up
- if ((networkSession.SessionState == NetworkSessionState.Playing) &&
- (world != null) && world.Initialized)
- {
- GameplayScreen gameplayScreen =
- new GameplayScreen(networkSession, world);
- gameplayScreen.ScreenManager = this.ScreenManager;
- ScreenManager.AddScreen(gameplayScreen);
- }
- }
- base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
- }
- /// <summary>
- /// Lets the game respond to player input. Unlike the Update method,
- /// this will only be called when the gameplay screen is active.
- /// </summary>
- public override void HandleInput(InputState input)
- {
- // safety-check the parameter
- if (input == null)
- {
- throw new ArgumentNullException("input");
- }
- if ((networkSession != null) && (networkSession.LocalGamers.Count > 0))
- {
- // update the ready state
- if (input.MarkReady)
- {
- networkSession.LocalGamers[0].IsReady =
- !networkSession.LocalGamers[0].IsReady;
- }
- // update the player data
- PlayerData playerData = networkSession.LocalGamers[0].Tag as PlayerData;
- if (playerData != null)
- {
- bool playerDataChanged = false;
- if (input.ShipColorChangeUp)
- {
- playerData.ShipColor = Ship.GetNextUniqueColorIndex(
- playerData.ShipColor, networkSession);
- playerDataChanged = true;
- }
- else if (input.ShipColorChangeDown)
- {
- playerData.ShipColor = Ship.GetPreviousUniqueColorIndex(
- playerData.ShipColor, networkSession);
- playerDataChanged = true;
- }
- if (input.ShipModelChangeUp)
- {
- playerData.ShipVariation =
- (byte)((playerData.ShipVariation + 1) % 4);
- playerDataChanged = true;
- }
- else if (input.ShipModelChangeDown)
- {
- if (playerData.ShipVariation == 0)
- {
- playerData.ShipVariation = 3;
- }
- else
- {
- playerData.ShipVariation--;
- }
- playerDataChanged = true;
- }
- // if the data changed, send an update to the others
- if (playerDataChanged)
- {
- packetWriter.Write((int)World.PacketTypes.PlayerData);
- playerData.Serialize(packetWriter);
- networkSession.LocalGamers[0].SendData(packetWriter,
- SendDataOptions.ReliableInOrder);
- }
- }
- }
- base.HandleInput(input);
- }
- /// <summary>
- /// Responds to user menu selections.
- /// </summary>
- protected override void OnSelectEntry(int entryIndex) { }
- /// <summary>
- /// Force the end of a network session so that a new one can be joined.
- /// </summary>
- public void EndSession()
- {
- if (networkSession != null)
- {
- networkSession.Dispose();
- networkSession = null;
- }
- }
- /// <summary>
- /// Exit this screen.
- /// </summary>
- public override void ExitScreen()
- {
- if (!IsExiting && (networkSession != null))
- {
- networkSession.GamerJoined -= gamerJoinedHandler;
- networkSession.GameStarted -= gameStartedHandler;
- networkSession.SessionEnded -= sessionEndedHandler;
- }
- base.ExitScreen();
- }
- /// <summary>
- /// Screen-specific update to gamer rich presence.
- /// </summary>
- public override void UpdatePresence()
- {
- if (!IsExiting && (networkSession != null))
- {
- foreach (LocalNetworkGamer localGamer in networkSession.LocalGamers)
- {
- SignedInGamer signedInGamer = localGamer.SignedInGamer;
- if (signedInGamer.IsSignedInToLive)
- {
- if (networkSession.IsHost)
- {
- signedInGamer.Presence.PresenceMode = GamerPresenceMode.WaitingForPlayers;
- }
- else
- {
- signedInGamer.Presence.PresenceMode = GamerPresenceMode.WaitingInLobby;
- }
- }
- }
- }
- }
- #endregion
- #region Drawing Methods
- /// <summary>
- /// Draw the lobby screen.
- /// </summary>
- /// <param name="gameTime"></param>
- public override void Draw(Microsoft.Xna.Framework.GameTime gameTime)
- {
- // draw in four columns
- Vector2[] columnPositions = new Vector2[4];
- columnPositions[0] = new Vector2(
- ScreenManager.GraphicsDevice.Viewport.Width * 0.2f,
- ScreenManager.GraphicsDevice.Viewport.Height * 0.70f);
- columnPositions[1] = new Vector2(
- ScreenManager.GraphicsDevice.Viewport.Width * 0.4f,
- ScreenManager.GraphicsDevice.Viewport.Height * 0.70f);
- columnPositions[2] = new Vector2(
- ScreenManager.GraphicsDevice.Viewport.Width * 0.6f,
- ScreenManager.GraphicsDevice.Viewport.Height * 0.70f);
- columnPositions[3] = new Vector2(
- ScreenManager.GraphicsDevice.Viewport.Width * 0.8f,
- ScreenManager.GraphicsDevice.Viewport.Height * 0.70f);
- ScreenManager.SpriteBatch.Begin();
- // draw all of the players data
- if (networkSession != null)
- {
- for (int i = 0; i < networkSession.AllGamers.Count; i++)
- {
- world.DrawPlayerData((float)gameTime.TotalGameTime.TotalSeconds,
- networkSession.AllGamers[i], columnPositions[i % 4],
- ScreenManager.SpriteBatch, true);
- columnPositions[i % 4].Y +=
- ScreenManager.GraphicsDevice.Viewport.Height * 0.03f;
- }
- }
- // draw the instructions
- ScreenManager.SpriteBatch.DrawString(ScreenManager.Font, instructions,
- new Vector2(ScreenManager.TitleSafeArea.X,
- ScreenManager.TitleSafeArea.Y + ScreenManager.TitleSafeArea.Height -
- ScreenManager.Font.LineSpacing), Color.White);
- ScreenManager.SpriteBatch.End();
- base.Draw(gameTime);
- }
- /// <summary>
- /// When the user cancels the main menu, ask if they want to exit the sample.
- /// </summary>
- protected override void OnCancel()
- {
- if (!IsExiting)
- {
- ExitScreen();
- }
- if (world != null)
- {
- world.Dispose();
- world = null;
- }
- if (networkSession != null)
- {
- networkSession.Dispose();
- networkSession = null;
- }
- }
- #endregion
- #region Networking Event Handlers
- /// <summary>
- /// Handle the end of the network session.
- /// </summary>
- void networkSession_SessionEnded(object sender, NetworkSessionEndedEventArgs e)
- {
- if (!IsExiting)
- {
- ExitScreen();
- }
- if (world != null)
- {
- world.Dispose();
- world = null;
- }
- if (networkSession != null)
- {
- networkSession.Dispose();
- networkSession = null;
- }
- }
- /// <summary>
- /// Handle the start of the game session.
- /// </summary>
- void networkSession_GameStarted(object sender, GameStartedEventArgs e)
- {
- // if we're the host, generate the data
- if ((networkSession != null) && networkSession.IsHost && (world != null))
- {
- world.GenerateWorld();
- }
- }
-
-
- /// <summary>
- /// Handle a new player joining the session.
- /// </summary>
- void networkSession_GamerJoined(object sender, GamerJoinedEventArgs e)
- {
- // make sure the data exists for the new gamer
- for (int i = 0; i < networkSession.AllGamers.Count; i++)
- {
- if (networkSession.AllGamers[i] == e.Gamer)
- {
- PlayerData playerData = new PlayerData();
- e.Gamer.Tag = playerData;
- playerData.ShipVariation = (byte)(i % 4);
- playerData.ShipColor = (byte)i;
- }
- }
- // send my own data to the new gamer
- if ((networkSession.LocalGamers.Count > 0) && !e.Gamer.IsLocal)
- {
- PlayerData playerData = networkSession.LocalGamers[0].Tag as PlayerData;
- if (playerData != null)
- {
- packetWriter.Write((int)World.PacketTypes.PlayerData);
- playerData.Serialize(packetWriter);
- networkSession.LocalGamers[0].SendData(packetWriter,
- SendDataOptions.ReliableInOrder, e.Gamer);
- }
- }
- }
- #endregion
-
- #region IDisposable Implementation
- /// <summary>
- /// Finalizes the LobbyScreen object, calls Dispose(false)
- /// </summary>
- ~LobbyScreen()
- {
- Dispose(false);
- }
- /// <summary>
- /// Disposes the LobbyScreen object.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Disposes this object.
- /// </summary>
- /// <param name="disposing">
- /// True if this method was called as part of the Dispose method.
- /// </param>
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- lock (this)
- {
- if (world != null)
- {
- world.Dispose();
- world = null;
- }
- if (packetWriter != null)
- {
- packetWriter.Close();
- packetWriter = null;
- }
- }
- }
- }
- #endregion
- }
- }
|