/// <summary> /// Sets up the grid in terms of decoding the integer array into items /// and sets up the canvas. /// </summary> /// <param name="gameCanvas">The canvas reference is needed</param> /// <param name="enemyType"></param> public void SetupGrid(ref Canvas gameCanvas, ref Canvas exitCanvas, ProtagonistType protagonistType, EnemyType enemyType) { //setup protagonist types etc so that we know what pages to go etc this.protagonistType = protagonistType; this.enemyType = enemyType; DecodeGridStartLocations(protagonistType, enemyType); //Add grid items for (int y = 0; y < GridStartLocations.GetLength(0); y++) { for (int x = 0; x < GridStartLocations.GetLength(1); x++) { gameCanvas.Children.Add(_gridManager.GridItems[y, x]); MoveItemToPlace(_gridManager.GridItems[y, x], _gridManager.GridItems[y, x].Position); } } //Add character for (int i = 0; i < 2; i++) { gameCanvas.Children.Add(_gridManager.CharactersViews[i]); MoveItemToPlace(_gridManager.CharactersViews[i], _gridManager.Characters[i].Position); //Add the characters weight if specified in level file (used in client/server to communicate //the weights to the clients) if (characterWeights != null && characterWeights.Length == 2) { GameGridManager.Instance.Characters[i].Weight = characterWeights[i]; } } //Add exit rectangle exitCanvas.Children.Add(ExitRectanglePlacement()); }
public WaitPage(ProtagonistType pt, EnemyType et, Level.Level level) { InitializeComponent(); this.pt = pt; this.et = et; this.level = level; foreach (var ip in MessageManager.Instance.GetLocalIPs()) { txtLocalIps.Text += ip + "\n"; } MessageManager.Instance.MessageHandler += StartHandler; Loaded += (s, e) => { //Create a thread to waiting until a start message has been received without blocking //the ui thread waitingThread = new Thread(new ThreadStart(() => { //Wait until the start message has been received while (!gameStarted) { Thread.Sleep(1000); } //Start the game MessageManager.Instance.MessageHandler -= StartHandler; TopFrameManager.Instance.MainFrame.Dispatcher.Invoke(new Action(() => { GamePage gp = new GamePage(pt, et, level); TopFrameManager.Instance.MainFrame.Navigate(gp); })); })); waitingThread.Start(); }; }
/// <summary> /// Only call this on the overlay panel /// </summary> public LosePage(Level.Level level, ProtagonistType pt, EnemyType et, bool isNetworked) { InitializeComponent(); //Stop the game if (TopFrameManager.Instance.MainFrame.Content is GamePage) { (TopFrameManager.Instance.MainFrame.Content as GamePage).StopTimers(); if (isNetworked) { CommunicationManager.Instance.Stop(); } } this.level = level; this.pt = pt; this.et = et; this.isNetworked = isNetworked; }
/// <summary> /// Sets the enemy types required to do things with the network /// </summary> /// <param name="pt"></param> /// <param name="et"></param> public bool SetupEnemyTypes(ProtagonistType pt, EnemyType et) { if (_connectionTimer.IsEnabled) { //If the timer is running return false because you couldn't update it return(false); } if ((pt == ProtagonistType.Remote && et == EnemyType.Remote) || (pt != ProtagonistType.Remote && et != EnemyType.Remote)) { throw new Exception("Error in CommunicationManager.SetupEnemyTypes(), only one remote character allowed."); } //If the enemy is remote, then player 1 is local, if enemy is not remote then player 1 is remote and enemy is local LocalCharacterNumber = et == EnemyType.Remote ? 1 : 2; //We know its networked IsNetworked = true; return(true); }
/// <summary> /// Creates an instance of GamePage /// </summary> /// <param name="pt">The type of protagonist to generate</param> /// <param name="et">The type of enemy to generate</param> public GamePage(ProtagonistType pt, EnemyType et, Level.Level _level, double protagonistWeight = 1, double enemyWeight = 1) { InitializeComponent(); level = _level; Protagonist = pt; Enemy = et; //Sets up the grid by decoding the int array and placing everything on the canvas level.SetupGrid(ref cvsPlayArea, ref cvsExitArea, pt, et); //Set the characters weights (for turning moments) GameGridManager.Instance.Characters[0].Weight = protagonistWeight; GameGridManager.Instance.Characters[1].Weight = enemyWeight; //Set the canvas of the singleton for easier access to the canvas (so the canvas does //not need to be referenced every tick for the collision detection visualisation to work) GameGridManager.Instance.GameCanvas = cvsPlayArea; //Setup the angles that open the exits ExitingManager.FindAnglesNeededToOpen(level.ExitLocation.HeightFromAnchor, level.ExitLocation.Length); keyboardInputTimer = new DispatcherTimer() { //Every ~1/1000 of a second update Interval = new TimeSpan(0, 0, 0, 0, 1) }; //Have the timer use the timertick event keyboardInputTimer.Tick += KeyboardInputTimerTick; rotationTimer = new DispatcherTimer() { //Update every 1/4 second Interval = new TimeSpan(0, 0, 0, 0, 250) }; rotationTimer.Tick += (s, e) => { double rotation = Rotation.AbsAngleDelta() * Algorithms.Rotation.RotationMultiplier(GameGridManager.Instance.Characters); GameGridManager.RotateStoryBoard((int)rotation); }; //If there is some networking involved within characters then start the communication manager and tie it to the message manager if (gameType == GameType.Networked) { CommunicationManager.Instance.SetupEnemyTypes(pt, et); //Also tell the server that it has received and loaded the map messageInstance = MessageManager.Instance; messageInstance.MessageHandler += HandleMessage; messageInstance.SendMessage("received"); //Also start the timers StartTimers(); } //Setups up AI timer if this is a singleplayer game if (gameType == GameType.Singleplayer) { aiTimer = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, 400) }; aiTimer.Tick += AiTimerOnTick; //Also show path tickbox chkShowPath.Visibility = Visibility.Visible; } //Allow keydown so that starts the game etc allowKeyDown = true; }
/// <summary> /// Converts the integer array for the start locations into the grid items, grid views, characters, characters' views, and exitable items /// </summary> /// <param name="protagonistType">The type of protagonist to instantiate</param> /// <param name="enemyType">The type of enemy to instantiate</param> private void DecodeGridStartLocations(ProtagonistType protagonistType, EnemyType enemyType) { GridItem[,] gridItems = new GridItem[yLength(), xLength()]; Character[] characters = new Character[2]; CharacterItem[] charactersView = new CharacterItem[2]; List <Exitable> exitables = new List <Exitable>(); int exitableIndex = 0; for (int y = 0; y < yLength(); y++) { for (int x = 0; x < xLength(); x++) { switch (GridStartLocations[y, x]) { //walkable object case 0: Walkable walkable = new Walkable() { Position = new Position(x, y) }; gridItems[y, x] = walkable; break; //non-walkable object case 1: NonWalkable nonWalkable = new NonWalkable() { Position = new Position(x, y) }; gridItems[y, x] = nonWalkable; break; //player 1 case 2: PlayerOne playerOne = new PlayerOne() { Position = new Position(x, y) }; CharacterItem playerOneItem = new CharacterItem(playerOne); //gridItems[y, x] = playerOneItem; gridItems[y, x] = new Walkable() { Position = new Position(x, y) }; charactersView[0] = playerOneItem; characters[0] = playerOne; break; //Enemy case 3: //Choose which type of Enemy: Enemy enemy = new Enemy(); enemy.Position = new Position(x, y); var enemyItem = new CharacterItem(enemy); gridItems[y, x] = new Walkable { Position = new Position(x, y) }; charactersView[1] = enemyItem; characters[1] = enemy; break; //Exitable block case 5: //Set the array index to the correct value and immedietly increment Exitable exitable = new Exitable(exitableIndex++) { Position = new Position(x, y) }; gridItems[y, x] = exitable; exitables.Add(exitable); break; default: throw new NotImplementedException($"The value of {GridStartLocations[y,x]} is not implemented in Level.Level.GridStartLocation()"); } } } _gridManager = GameGridManager.NewGameGrid(characters, charactersView, gridItems, exitables.ToArray()); }