/// /// <summary> /// Performs an update tick on the game object. /// </summary> /// /// <param name="gameTime">Time passed since the last call to Update.</param> /// protected override void Update(GameTime gameTime) { // Get the keyboard/mouse states. k = Keyboard.GetState(); m = Mouse.GetState(); IsMouseVisible = !mouseLocked; // Make sure the game switches to an unfocused state when not active. if (!this.IsActive) { if (this.gameState.Equals(GameState.Running)) { this.gameState = GameState.Unfocused; } } handleNetworkMessages(); switch (this.gameState) { // The client and server has connected successfully, now waiting for the game data to be loaded over. case GameState.ConnectingLoading: if (world != null) { gameState = GameState.Running; } break; // After many attempts, the connection to the server has failed. case GameState.ConnectionFailed: break; // Attempts are being made to connect to the server. case GameState.Connecting: if (client.ConnectionStatus.Equals(NetConnectionStatus.Connected)) { Thread.Sleep(750); // Get the world from the server. NetOutgoingMessage refreshRequest = client.CreateMessage(); refreshRequest.Write(NETWORK_REFRESH_REQUEST); client.SendMessage(refreshRequest, NetDeliveryMethod.ReliableOrdered); gameState = GameState.ConnectingLoading; } else { if (connectionAttemptTimer >= 70) { // Discover the server... Console.WriteLine("Attempting connection with server at {0}:{1}...", serverIP, 1945, client.ConnectionStatus, client.Status); client.DiscoverKnownPeer(serverIP, 1945); handleNetworkMessages(); connectionAttempts++; if (connectionAttempts >= 10) { gameState = GameState.ConnectionFailed; } connectionAttemptTimer = 0; } else { connectionAttemptTimer++; } } break; // The game is running normally. case GameState.Running: case GameState.RunningInventory: switch (gameState) { case GameState.Running: case GameState.RunningInventory: // Find out how far the mouse has moved since the last upate. Vector2 lookMovement = Vector2.Zero; if (mouseLocked && gameState.Equals(GameState.Running)) { lookMovement = new Vector2( m.X - (graphics.PreferredBackBufferWidth / 2), m.Y - (graphics.PreferredBackBufferHeight / 2)); } // Update the world. if (world != null) { world.update(GameSide.Client, k, lookMovement); } // Update the current action. if (currentAction != null) { if (currentAction.tick()) { currentAction.perform(client, world, world.player.skills, ref notifications); currentAction = null; } } break; } #region 3D View // Move the camera with the player. if (world != null) { camera.position = world.player.position + new Vector3(0.0F, world.player.height * 0.90F, 0.0F); camera.target = world.player.lookTarget; } #endregion #region Tile Cursor if (contextMenu == null) { // Determine if there are any tile cursors. Vector3 rayStart = camera.position; Vector3 rayDirection = camera.target - camera.position; rayDirection.Normalize(); Point?currentTile = world.getSelectedTile(camera); if (currentTile.HasValue) { tileCursorEnabled = true; tileCursorPosition = currentTile.Value; } else { tileCursorEnabled = false; } } // Move the tile name indicator back & forth. if (tileCursorEnabled) { indicatorOffset += (50.0F - indicatorOffset) / 10.0F; } else { indicatorOffset += (0.0F - indicatorOffset) / 10.0F; } // Allow the context menu to be opened if (gameState.Equals(GameState.Running) || gameState.Equals(GameState.RunningInventory)) { if (m.RightButton.Equals(ButtonState.Pressed) && canOpenContextMenu && tileCursorEnabled) { contextMenu = new ContextMenu( world.player.skills, tileCursorPosition, world, null); mouseLocked = false; canOpenContextMenu = false; } if (contextMenu == null && m.RightButton.Equals(ButtonState.Released)) { canOpenContextMenu = true; } // Allow the context menu to be closed, if clicked away from. // Also, update the context menu. if (contextMenu != null) { // Update the context menu. int result = contextMenu.update(m, graphics); if (result >= 0) { if (currentAction == null) { currentAction = new TimedAction(contextMenu.actionList[result], world.player.skills); contextMenu = null; if (gameState.Equals(GameState.Running)) { mouseLocked = true; } } else { //TODO: Allow actions to stack. } } else { // Then allow the menu to be closed. Rectangle contextMenuRectangle = contextMenu.calculateSize(FontResources.interfaceFont, graphics); if (m.LeftButton.Equals(ButtonState.Pressed) && ( m.X < contextMenuRectangle.Left || m.X > contextMenuRectangle.Right || m.Y < contextMenuRectangle.Top || m.Y > contextMenuRectangle.Bottom )) { contextMenu = null; if (gameState.Equals(GameState.Running)) { mouseLocked = true; } } } } } #endregion #region Mouse Looking // Reset the mouse to the middle of the screen. if (mouseLocked && gameState.Equals(GameState.Running)) { Mouse.SetPosition( graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2); } #endregion #region Notifications // Update the first notification. if (notifications.Count >= 1) { if (notifications[0].update()) { notifications.RemoveAt(0); } } #endregion break; // The game is not the active window. case GameState.Unfocused: // Allow the player to resume the game. if (this.IsActive && m.LeftButton.Equals(ButtonState.Pressed)) { this.gameState = GameState.Running; } break; // The game wants to quit. case GameState.Quitting: // Quit the game. Console.WriteLine("Game is currently in 'Quitting' state; closing."); client.Disconnect("Game closed"); this.Exit(); break; // Where the current Game State is unknown. default: Console.WriteLine("Error! - Unhandled Game State: " + this.gameState.ToString()); this.Exit(); break; } #region Inventory Window & Such if (gameState.Equals(GameState.RunningInventory)) { world.player.inventory.update( Container.WindowStyle.Inventory, graphics, k, m, ref canSelectItem, world, client, ref contextMenu); } if (world != null) { inventoryOffset += ((gameState.Equals(GameState.RunningInventory) ? 0.0F : 700.0F) - inventoryOffset) / 4.0F; world.player.inventory.slideOffset = inventoryOffset; } #endregion // Allow the inventory to be toggled. #region Inventory Toggling if (gameState.Equals(GameState.RunningInventory) || gameState.Equals(GameState.Running)) { if (canToggleInventory && k.IsKeyDown(Keys.Tab)) { gameState = (gameState.Equals(GameState.Running) ? GameState.RunningInventory : GameState.Running); mouseLocked = !gameState.Equals(GameState.RunningInventory); contextMenu = null; Mouse.SetPosition(graphics.PreferredBackBufferWidth / 2, graphics.PreferredBackBufferHeight / 2); canToggleInventory = false; } else if (!canToggleInventory && k.IsKeyUp(Keys.Tab)) { canToggleInventory = true; } } #endregion // Allow the game to exit. if (k.IsKeyDown(Keys.Escape)) { gameState = GameState.Quitting; } // Update the 'old' mouse and keyboard states. mOld = m; kOld = k; base.Update(gameTime); }