/// <summary> /// Load graphics content for the game. /// </summary> public override void LoadContent() { if (content == null) { content = new ContentManager(ScreenManager.Game.Services, "Content"); } //***ALL THE TEXTURES ARE PLACED HERE***// Texture2D playerTexture = content.Load <Texture2D>("PongPlayer"); Texture2D ballTexture = content.Load <Texture2D>("PongBall"); borderTexture = content.Load <Texture2D>("pongborder"); font = content.Load <SpriteFont>("pongFont"); //***INITIALIZE STARTING POSITIONS OF TEXTURES***// Vector2 player1Position = new Vector2(playerTexture.Width, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Y + ScreenManager.GraphicsDevice.Viewport.Height * 3 / 7); Vector2 player2Position = new Vector2(ScreenManager.GraphicsDevice.Viewport.Width - playerTexture.Width * 2, ScreenManager.GraphicsDevice.Viewport.Height * 3 / 7); Vector2 ballPosition = new Vector2(ScreenManager.GraphicsDevice.Viewport.Width / 2 + 8, ScreenManager.GraphicsDevice.Viewport.Height / 2); //***INITIALIZE ALL GAME RESOURCES HERE***// player1.Initialize(playerTexture, player1Position); player2.Initialize(playerTexture, player2Position); ball.Initialize(ballTexture, ballPosition); //***ALL SOUNDS ARE LOADED HERE***// bounceSound = content.Load <SoundEffect>("sound/plink"); scoreSound = content.Load <SoundEffect>("sound/score"); gameplayMusic = content.Load <Song>("sound/Wonderwall"); //PlayMusic(gameplayMusic); // A real game would probably have more content than this sample, so // it would take longer to load. We simulate that by delaying for a // while, giving you a chance to admire the beautiful loading screen. //Thread.Sleep(1000); // once the load has finished, we use ResetElapsedTime to tell the game's // timing mechanism that we have just finished a very long frame, and that // it should not try to catch up. ScreenManager.Game.ResetElapsedTime(); }
// This runs in its own Thread // It is the actual game private void _arenaRun() { Console.WriteLine("[{0:000}] Waiting for players", Id); GameTime gameTime = new GameTime(); // Varibables used in the switch TimeSpan notifyGameStartTimeout = TimeSpan.FromSeconds(2.5); TimeSpan sendGameStateTimeout = TimeSpan.FromMilliseconds(1000f / 30f); // How often to update the players // The loop bool running = true; bool playerDropped = false; while (running) { // Pop off a message (if there is one) NetworkMessage message; bool haveMsg = _messages.TryDequeue(out message); switch (State.Value) { case ArenaState.WaitingForPlayers: if (haveMsg) { // Wait until we have two players _handleConnectionSetup(LeftPlayer, message); _handleConnectionSetup(RightPlayer, message); // Check if we are ready or not if (LeftPlayer.HavePaddle && RightPlayer.HavePaddle) { // Try sending the GameStart packet immediately _notifyGameStart(LeftPlayer, new TimeSpan()); _notifyGameStart(RightPlayer, new TimeSpan()); // Shift the state State.Value = ArenaState.NotifyingGameStart; } } break; case ArenaState.NotifyingGameStart: // Try sending the GameStart packet _notifyGameStart(LeftPlayer, notifyGameStartTimeout); _notifyGameStart(RightPlayer, notifyGameStartTimeout); // Check for ACK if (haveMsg && (message.Packet.Type == PacketType.GameStartAck)) { // Mark true for those who have sent something if (message.Sender.Equals(LeftPlayer.Endpoint)) { LeftPlayer.Ready = true; } else if (message.Sender.Equals(RightPlayer.Endpoint)) { RightPlayer.Ready = true; } } // Are we ready to send/received game data? if (LeftPlayer.Ready && RightPlayer.Ready) { // Initlize some game object positions _ball.Initialize(); LeftPlayer.Paddle.Initialize(); RightPlayer.Paddle.Initialize(); // Send a basic game state _sendGameState(LeftPlayer, new TimeSpan()); _sendGameState(RightPlayer, new TimeSpan()); // Start the game timer State.Value = ArenaState.InGame; Console.WriteLine("[{0:000}] Starting Game", Id); _gameTimer.Start(); } break; case ArenaState.InGame: // Update the game timer TimeSpan now = _gameTimer.Elapsed; gameTime = new GameTime(now, now - gameTime.TotalGameTime); // Get paddle postions from clients if (haveMsg) { switch (message.Packet.Type) { case PacketType.PaddlePosition: _handlePaddleUpdate(message); break; case PacketType.Heartbeat: // Respond with an ACK HeartbeatAckPacket hap = new HeartbeatAckPacket(); PlayerInfo player = message.Sender.Equals(LeftPlayer.Endpoint) ? LeftPlayer : RightPlayer; _sendTo(player, hap); // Record time player.LastPacketReceivedTime = message.ReceiveTime; break; } } //Update the game components _ball.ServerSideUpdate(gameTime); _checkForBallCollisions(); // Send the data _sendGameState(LeftPlayer, sendGameStateTimeout); _sendGameState(RightPlayer, sendGameStateTimeout); break; } // Check for a quit from one of the clients if (haveMsg && (message.Packet.Type == PacketType.Bye)) { // Well, someone dropped PlayerInfo player = message.Sender.Equals(LeftPlayer.Endpoint) ? LeftPlayer : RightPlayer; running = false; Console.WriteLine("[{0:000}] Quit detected from {1} at {2}", Id, player.Paddle.Side, _gameTimer.Elapsed); // Tell the other one if (player.Paddle.Side == PaddleSide.Left) { // Left Quit, tell Right if (RightPlayer.IsSet) { _server.SendBye(RightPlayer.Endpoint); } } else { // Right Quit, tell Left if (LeftPlayer.IsSet) { _server.SendBye(LeftPlayer.Endpoint); } } } // Check for timeouts playerDropped |= _timedOut(LeftPlayer); playerDropped |= _timedOut(RightPlayer); // Small nap Thread.Sleep(1); // Check quit values running &= !_stopRequested.Value; running &= !playerDropped; } // End the game _gameTimer.Stop(); State.Value = ArenaState.GameOver; Console.WriteLine("[{0:000}] Game Over, total game time was {1}", Id, _gameTimer.Elapsed); // If the stop was requested, gracefully tell the players to quit if (_stopRequested.Value) { Console.WriteLine("[{0:000}] Notifying Players of server shutdown", Id); if (LeftPlayer.IsSet) { _server.SendBye(LeftPlayer.Endpoint); } if (RightPlayer.IsSet) { _server.SendBye(RightPlayer.Endpoint); } } // Tell the server that we're finished _server.NotifyDone(this); }