/// <summary> /// Updates all block logic. /// </summary> public void Update() { //Enables pausing the game. if (game.KbState.IsKeyDown(Keys.Space)) { isPaused = true; } //Enables basic zooming. if (game.MsState.ScrollWheelValue > game.MsStateOld.ScrollWheelValue) { if (camZoom >= 2) { camZoom = 2; } else { //Works around inherent floating point error. camZoom = ((int)Math.Round(10 * (camZoom + 0.1))) / 10f; } } else if (game.MsState.ScrollWheelValue < game.MsStateOld.ScrollWheelValue) { if (camZoom <= 0.5) { camZoom = 0.5f; } else { //Works around inherent floating point error. camZoom = ((int)Math.Round(10 * (camZoom - 0.1))) / 10f; } } //Resets the drawn tooltip. if (OpMaxSteps == 0) { tooltip = ""; } else { tooltip = "steps: " + LvlSteps + " / " + OpMaxSteps + " | "; } if (ActorGoals > 0 || OpReqGoals > 0) { tooltip += "goals: " + ActorGoals + " / " + OpReqGoals + " | "; } //Does not update the game while a message is displayed. if (isPaused || isMessageShown) { if (game.KbState.IsKeyDown(Keys.Enter)) { isPaused = false; isMessageShown = false; } return; } //Tabs through the active actors. if (game.KbState.IsKeyDown(Keys.Tab) && game.KbStateOld.IsKeyUp(Keys.Tab) && !opSyncActors) { var actors = items.Where(o => o.BlockType == Type.Actor).ToList(); if (actors.IndexOf(actor) < actors.Count - 1) { actor = (MazeActor)actors[actors.IndexOf(actor) + 1]; } else if (actors.Count > 0) { actor = (MazeActor)actors.First(); } } //Updates the timer. _countdown--; if (_countdown == 0) { _countdown = _countdownStart; IsTimerZero = true; } else { IsTimerZero = false; } #region Handles MazeTurretBullet triggering //Gets a list of all bullets. List <GameObj> itemsTemp0 = items .Where(o => o.BlockType == Type.TurretBullet) .ToList(); foreach (GameObj item in itemsTemp0) { //Moves the bullet. item.X += ((int)Utils.DirVector(item.BlockDir).X *item.CustInt2); item.Y += ((int)Utils.DirVector(item.BlockDir).Y *item.CustInt2); //Gets a list of all solids in front of the bullet. List <GameObj> itemsFront = items.Where(obj => Math.Abs((obj.X * 32 + 16) - ((item.X + item.CustInt2))) < 7 && //TODO: 4 or custInt2? Math.Abs((obj.Y * 32 + 16) - ((item.Y + item.CustInt2))) < 7 && obj.Layer == item.Layer && obj.IsSolid).ToList(); foreach (GameObj item2 in itemsFront) { //Damages all actors it hits. if (item2.BlockType == Type.Actor) { (item2 as MazeActor).hp -= 25; game.playlist.Play(sndHit, item.X, item.Y); } #region Interaction: MazeMultiWay //If the multiway is in the direction of the bullet. if (item2.BlockType == Type.MultiWay && (item.BlockDir == item2.BlockDir || item2.IsEnabled == false || (item2.CustInt1 == 1 && item.BlockDir == Utils.DirOpp(item2.BlockDir)))) { continue; } #endregion #region Interaction: MazeMirror //The mirrors bend or absorb the bullets. else if (item2.BlockType == Type.Mirror) { //Bullet is coming in the opposite direction of the mirror. if (item.BlockDir == Utils.DirOpp(item2.BlockDir)) { if (!(item as MazeTurretBullet).mirrors.Contains(item2)) { (item as MazeTurretBullet).mirrors.Add(item2); item.BlockDir = Utils.DirPrev(item2.BlockDir); } continue; } //Bullet is coming in opposite to the other direction. else if (item.BlockDir == Utils.DirNext(item2.BlockDir)) { if (!(item as MazeTurretBullet).mirrors.Contains(item2)) { (item as MazeTurretBullet).mirrors.Add(item2); item.BlockDir = item2.BlockDir; } continue; } else if ((item as MazeTurretBullet).mirrors.Contains(item2)) { continue; } } #endregion #region Interaction: MazeLaserActuator //The laser actuator absorbs the bullets. else if (item2 is MazeLaserActuator item2AsLaserActuator) { item2AsLaserActuator.ReceivedBullet(); } #endregion RemoveItem(item); } } #endregion //Handles the behavior of blocks when the timer is zero. if (IsTimerZero) { #region Handles MazeBelt triggering List <GameObj> itemsTemp, itemsTop, itemsFront; //Gets a list of all belt blocks. itemsTemp = items.Where(o => o.BlockType == Type.Belt && o.IsEnabled).ToList(); //Tracks blocks that get moved and direction. //Moves all blocks in sync to avoid getting moved //multiple times in one update. List <GameObj> queueItems = new List <GameObj>(); List <Vector2> queuePos = new List <Vector2>(); foreach (GameObj belt in itemsTemp) { //Gets a list of all objects on the belt. itemsTop = items.Where(o => o.X == belt.X && o.Y == belt.Y && o.Layer == belt.Layer && o.BlockSprite.depth < belt.BlockSprite.depth).ToList(); itemsTop.Remove(belt); //Removes belt from list. //If there are blocks on the belt. if (itemsTop.Count != 0) { //Gets a list of all solids in front of the belt. itemsFront = items.Where(o => o.X == belt.X + Utils.DirVector(belt.BlockDir).X&& o.Y == belt.Y + Utils.DirVector(belt.BlockDir).Y&& o.Layer == belt.Layer && o.IsSolid).ToList(); #region Interaction: MazeMultiWay.cs itemsFront = itemsFront.Where(o => !(o.BlockType == Type.MultiWay && o.IsEnabled && ((o.CustInt1 == 0 && o.BlockDir == belt.BlockDir) || (o.CustInt1 != 0 && (o.BlockDir == belt.BlockDir || o.BlockDir == Utils.DirOpp(belt.BlockDir)))))).ToList(); #endregion //If nothing is blocking the belt. if (itemsFront.Count == 0) { //Moves the items on the belt over. foreach (GameObj itemTop in itemsTop) { //Adds to queues to update in sync. queueItems.Add(itemTop); queuePos.Add(new Vector2( Utils.DirVector(belt.BlockDir).X, Utils.DirVector(belt.BlockDir).Y)); } } } MazeLaserActuator.LoadContent(game.Content); } #endregion #region Handles MazeEnemy triggering //Gets a list of all enabled enemies. itemsTemp = items.Where(o => o.IsEnabled && o.BlockType == Type.Enemy).ToList(); foreach (GameObj item in itemsTemp) { //Gets a list of all solids in front of the enemy. itemsFront = items.Where(o => o.X == item.X + Utils.DirVector(item.BlockDir).X&& o.Y == item.Y + Utils.DirVector(item.BlockDir).Y&& o.Layer == item.Layer && o.IsSolid).ToList(); #region Interaction: MazeMultiWay.cs itemsFront = itemsFront.Where(o => !(o.BlockType == Type.MultiWay && o.IsEnabled && ((o.CustInt1 == 0 && o.BlockDir == item.BlockDir) || (o.CustInt1 != 0 && (o.BlockDir == item.BlockDir || o.BlockDir == Utils.DirOpp(item.BlockDir)))))).ToList(); #endregion //Moves the enemy if there are no solids, otherwise //bounces off the solid (damaging it if it's an actor). if (itemsFront.Count == 0) { item.X += (int)Utils.DirVector(item.BlockDir).X; item.Y += (int)Utils.DirVector(item.BlockDir).Y; } else { item.BlockDir = Utils.DirOpp(item.BlockDir); //Damages all actors it bounces off of. foreach (GameObj item2 in itemsFront) { if (item2.BlockType == Type.Actor) { (item2 as MazeActor).hp -= 25; game.playlist.Play(sndHit, item.X, item.Y); } } } } #endregion #region Handles MazeIce triggering //Gets a list of all ice blocks. itemsTemp = items.Where(o => o.BlockType == Type.Ice).ToList(); List <GameObj> iceItemsTop = items.Where( o => o.BlockType == Type.Actor || o.BlockType == Type.Enemy || o.BlockType == Type.Crate || o.BlockType == Type.Belt) .ToList(); foreach (GameObj ice in itemsTemp) { //Gets a list of actors/enemies/crates/belts in location. itemsTop = iceItemsTop.Where(o => o.X == ice.X && o.Y == ice.Y && o.Layer == ice.Layer) .ToList(); //if there are no belts on the ice. if (itemsTop.Where(o => o.BlockType == Type.Belt && o.IsEnabled).Count() == 0) { foreach (GameObj block in itemsTop) { //Gets a list of blocks in front of the block. itemsFront = items.Where(o => o.X == (int)block.X + Utils.DirVector(block.BlockDir).X&& o.Y == (int)block.Y + Utils.DirVector(block.BlockDir).Y&& o.Layer == block.Layer).ToList(); #region Interaction: MazeCrate.cs if (block.BlockType == Type.Crate) { itemsFront = itemsFront.Where(o => o.BlockType != Type.CrateHole).ToList(); } #endregion #region Interaction: MazeMultiWay.cs itemsFront = itemsFront.Where(o => !(o.BlockType == Type.MultiWay && o.IsEnabled && ((o.CustInt1 == 0 && o.BlockDir == block.BlockDir) || (o.CustInt1 != 0 && (o.BlockDir == block.BlockDir || o.BlockDir == Utils.DirOpp(block.BlockDir)))))) .ToList(); #endregion #region Interaction: MazeBelt.cs //Makes it so nothing stops on belts unless they //are in the total opposite direction. itemsFront = itemsFront.Where(o => !(o.BlockType == Type.Belt && (!o.IsEnabled || o.BlockDir != Utils.DirOpp(block.BlockDir)))).ToList(); //Can slide past all non-solid, non-belt objects. itemsFront = itemsFront.Where(o => o.IsSolid || (o.BlockType == Type.Belt && o.IsEnabled)).ToList(); //Removes disabled belts from the list so they //don't slide across the ice. if (block.BlockType == Type.Belt) { continue; } #endregion //If no solids block the path. if (itemsFront.Count == 0) { { queueItems.Add(block); queuePos.Add(new Vector2( Utils.DirVector(block.BlockDir).X, Utils.DirVector(block.BlockDir).Y)); } } } } } #endregion //Updates all moved blocks in sync. for (int i = 0; i < queueItems.Count; i++) { queueItems[i].X += (int)queuePos[i].X; queueItems[i].Y += (int)queuePos[i].Y; } } //Updates each item. foreach (GameObj item in items) { item.Update(); //Selects a new & valid actor when needed. if (actor.hp <= 0 || !actor.IsEnabled) { if (item.BlockType == Type.Actor) { if ((item as MazeActor).hp > 0 && (item as MazeActor).IsEnabled) { actor = (MazeActor)item; } } } //Processes win conditions. if (doWin) { break; } } //Handles winning. if (doWin) { doWin = false; if (game.GmState != GameState.stateGameplay) { if (opLvlLink == "") { SfxPlaylist.Play(sndWin); if (game.GmState == GameState.stateGameplayEditor) { game.GmState = GameState.stateMenuEditor; } else { game.GmState = GameState.stateCampaignModes; } } else { SfxPlaylist.Play(sndFinish); game.mngrLvl.LoadPlay(opLvlLink); } } else { SfxPlaylist.Play(sndFinish); game.mngrCampaign.CurrentSeries().LevelNum++; if (game.mngrCampaign.CurrentSeries().LevelExists()) { game.mngrCampaign.CurrentSeries().LoadCampaign(); } else { SfxPlaylist.Play(sndWin); if (game.GmState == GameState.stateGameplayEditor) { game.GmState = GameState.stateMenuEditor; } else { game.GmState = GameState.stateGameplaySeriesComplete; } } } } //If there are no valid actors, reverts. //If the max steps has been reached, reverts. if ((actor.hp <= 0 || !actor.IsEnabled) || (OpMaxSteps != 0 && LvlSteps >= OpMaxSteps)) { doRevert = true; } #region Player reverts/restarts level //If R is pressed, revert to the last checkpoint. if (game.KbState.IsKeyDown(Keys.R) && game.KbStateOld.IsKeyUp(Keys.R)) { //If control is held, restarts the whole level. if (game.KbState.IsKeyDown(Keys.LeftControl) || game.KbState.IsKeyDown(Keys.RightControl)) { doRestart = true; } else //otherwise, reverts to last checkpoint. { doRevert = true; } } #endregion #region Handles checkpoints and restarting. //Reverts to last checkpoint if desired. if (doRevert) { doRevert = false; LevelRevert(); } //Restarts the level if desired. else if (doRestart) { doRestart = false; LevelStart(new List <GameObj>(ItemsOrig)); } //Saves a checkpoint if initiated. if (doCheckpoint) { SfxPlaylist.Play(sndCheckpoint); doCheckpoint = false; actorCoinsChkpt = ActorCoins; actorGoalsChkpt = ActorGoals; _lvlStepsChkpt = LvlSteps; //Checkpoints the level by overwriting the chkpt list. itemsChkpt = new List <GameObj>(); foreach (GameObj item in items) { itemsChkpt.Add(item.Clone()); } } #endregion //Updates the camera position. Camera = Matrix.CreateTranslation( new Vector3(-actor.BlockSprite.rectDest.X, -actor.BlockSprite.rectDest.Y, 0)) * Matrix.CreateScale(new Vector3(camZoom, camZoom, 1)) * Matrix.CreateTranslation( new Vector3(game.GetScreenSize().X * 0.5f, game.GetScreenSize().Y * 0.5f, 0)); }
///<summary> ///Loads relevant graphics into memory. /// /// Dependencies: MainLoop.cs, maze block textures. /// </summary> public void LoadContent(ContentManager Content) { //Loads relevant assets. sndCheckpoint = Content.Load <SoundEffect>("Content/Sounds/sndCheckpoint"); sndFinish = Content.Load <SoundEffect>("Content/Sounds/sndFinish"); sndHit = Content.Load <SoundEffect>("Content/Sounds/sndHit"); sndWin = Content.Load <SoundEffect>("Content/Sounds/sndWin"); TexPixel = new Texture2D(game.GraphicsDevice, 1, 1); TexPixel.SetData(new Color[] { Color.White }); TexMenuHud = game.Content.Load <Texture2D>("Content/Sprites/Gui/sprMenuHud"); //Sets up hud sprites. sprHudOverlay = new Sprite(true, TexPixel); sprHudOverlay.color = Color.Gray; sprHudOverlay.alpha = 0.5f; sprHudOverlay.rectDest = new SmoothRect (0, game.GetScreenSize().Y - 32, game.GetScreenSize().X, 32); sprMenuHud = new Sprite(true, TexMenuHud); sprMenuHud.rectDest = new SmoothRect (0, game.GetScreenSize().Y - 32, 64, 32); //Loads all maze block textures. GameObj._LoadContent(game.Content); //base class. MazeActor.LoadContent(game.Content); MazeBelt.LoadContent(game.Content); MazeCoin.LoadContent(game.Content); MazeCoinLock.LoadContent(game.Content); MazeCrate.LoadContent(game.Content); MazeCrateHole.LoadContent(game.Content); MazeEnemy.LoadContent(game.Content); MazeFilter.LoadContent(game.Content); MazeFloor.LoadContent(game.Content); MazeFreeze.LoadContent(game.Content); MazeGate.LoadContent(game.Content); MazeHealth.LoadContent(game.Content); MazeIce.LoadContent(game.Content); MazeKey.LoadContent(game.Content); MazeLaserActuator.LoadContent(game.Content); MazeLock.LoadContent(game.Content); MazeMultiWay.LoadContent(game.Content); MazePanel.LoadContent(game.Content); MazeSpawner.LoadContent(game.Content); MazeSpike.LoadContent(game.Content); MazeStairs.LoadContent(game.Content); MazeTeleporter.LoadContent(game.Content); MazeThaw.LoadContent(game.Content); MazeWall.LoadContent(game.Content); MazeCheckpoint.LoadContent(game.Content); MazeEPusher.LoadContent(game.Content); MazeELight.LoadContent(game.Content); MazeEAuto.LoadContent(game.Content); MazeGoal.LoadContent(game.Content); MazeFinish.LoadContent(game.Content); MazeMessage.LoadContent(game.Content); MazeClick.LoadContent(game.Content); MazeRotate.LoadContent(game.Content); MazeTurret.LoadContent(game.Content); MazeTurretBullet.LoadContent(game.Content); MazeMirror.LoadContent(game.Content); }