/// <summary>
        /// Runs through detecting (hover/click) logic.
        /// </summary>
        public void Update()
        {
            //If the mouse becomes hovered.
            if (Sprite.IsIntersecting(BttnSprite, new SmoothRect(
                                          game.MsState.X, game.MsState.Y, 1, 1)))
            {
                if (!IsHovered)
                {
                    IsHovered = true;

                    //Intentional truncation.
                    BttnSpriteAtlas.frame += BttnSpriteAtlas.atlasCols;
                    SfxPlaylist.Play(sndBttnHover);
                }
            }
            //If the mouse is no longer hovered.
            else if (IsHovered)
            {
                IsHovered              = false;
                BttnSpriteAtlas.frame -= BttnSpriteAtlas.atlasCols;
            }
            //If the mouse is hovered and clicked.
            if (IsHovered && game.MsState.LeftButton ==
                ButtonState.Released && game.MsStateOld.LeftButton ==
                ButtonState.Pressed)
            {
                isClicked = true;
                SfxPlaylist.Play(sndBttnClick);
            }

            BttnSpriteAtlas.Update(true); //updates the atlas.
        }
Beispiel #2
0
        /// <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>
        /// Responds to movement requests.
        /// </summary>
        public override void Update()
        {
            #region Updates the sprite.
            //Updates the actor sprite by direction.
            //Depends on the texture frames and orientation.
            if (BlockDir == Dir.Right)
            {
                spriteAtlas.frame         = 0;
                BlockSprite.spriteEffects = SpriteEffects.None;
            }
            else if (BlockDir == Dir.Down)
            {
                spriteAtlas.frame         = 1;
                BlockSprite.spriteEffects = SpriteEffects.None;
            }
            else if (BlockDir == Dir.Left)
            {
                spriteAtlas.frame         = 0;
                BlockSprite.spriteEffects = SpriteEffects.FlipHorizontally;
            }
            else
            {
                spriteAtlas.frame         = 2;
                BlockSprite.spriteEffects = SpriteEffects.None;
            }
            if (this == game.mngrLvl.actor)
            {
                spriteAtlas.frame += 3;
            }
            #endregion

            #region Updates timer.
            _countdown--;
            if (_countdown == 0)
            {
                _countdown  = _countdownStart;
                IsTimerZero = true;
            }
            else
            {
                IsTimerZero = false;
            }
            #endregion

            #region Checks for actor death.
            if (hp <= 0)
            {
                if (game.mngrLvl.opSyncDeath)
                {
                    game.mngrLvl.doRevert = true;
                }
                else
                {
                    game.mngrLvl.RemoveItem(this);
                }
            }
            #endregion

            #region Player movement
            //Captures keyboard commands to move.
            if (IsEnabled && (this == game.mngrLvl.actor ||
                              game.mngrLvl.opSyncActors))
            {
                //Represents intent and ability to move.
                bool doMove = false, canMove = true;

                //Contains previous direction.
                Dir dirPrev = BlockDir;

                //If dir should be reverted. Almost never set to false.
                bool doRevertDir = true;

                //If the character hasn't met the step limit.
                //Prevents keystroke processing when app is inactive.
                if ((game.mngrLvl.OpMaxSteps == 0 ||
                     game.mngrLvl.LvlSteps < game.mngrLvl.OpMaxSteps) &&
                    game.IsActive)
                {
                    if ((game.KbState.IsKeyDown(Keys.D) &&
                         game.KbStateOld.IsKeyUp(Keys.D)) ||
                        (game.KbState.IsKeyDown(Keys.Right) &&
                         game.KbStateOld.IsKeyUp(Keys.Right)))
                    {
                        _countdown  = _countdownStart;
                        IsTimerZero = true;
                    }
                    else if ((game.KbState.IsKeyDown(Keys.S) &&
                              game.KbStateOld.IsKeyUp(Keys.S)) ||
                             (game.KbState.IsKeyDown(Keys.Down) &&
                              game.KbStateOld.IsKeyUp(Keys.Down)))
                    {
                        _countdown  = _countdownStart;
                        IsTimerZero = true;
                    }
                    else if ((game.KbState.IsKeyDown(Keys.A) &&
                              game.KbStateOld.IsKeyUp(Keys.A)) ||
                             (game.KbState.IsKeyDown(Keys.Left) &&
                              game.KbStateOld.IsKeyUp(Keys.Left)))
                    {
                        _countdown  = _countdownStart;
                        IsTimerZero = true;
                    }
                    else if ((game.KbState.IsKeyDown(Keys.W) &&
                              game.KbStateOld.IsKeyUp(Keys.W)) ||
                             (game.KbState.IsKeyDown(Keys.Up) &&
                              game.KbStateOld.IsKeyUp(Keys.Up)))
                    {
                        _countdown  = _countdownStart;
                        IsTimerZero = true;
                    }

                    //Updates the player direction based on movement.
                    //Prevents keystroke processing when app is inactive.
                    if (game.IsActive && IsTimerZero)
                    {
                        if (game.KbState.IsKeyDown(Keys.D) ||
                            game.KbState.IsKeyDown(Keys.Right))
                        {
                            BlockDir = Dir.Right;
                            doMove   = true;
                        }
                        else if (game.KbState.IsKeyDown(Keys.S) ||
                                 game.KbState.IsKeyDown(Keys.Down))
                        {
                            BlockDir = Dir.Down;
                            doMove   = true;
                        }
                        else if (game.KbState.IsKeyDown(Keys.A) ||
                                 game.KbState.IsKeyDown(Keys.Left))
                        {
                            BlockDir = Dir.Left;
                            doMove   = true;
                        }
                        else if (game.KbState.IsKeyDown(Keys.W) ||
                                 game.KbState.IsKeyDown(Keys.Up))
                        {
                            BlockDir = Dir.Up;
                            doMove   = true;
                        }
                    }

                    if (doMove)
                    {
                        //Considers all scenarios where the player can't move.
                        //Gets a list of all blocks at the location to move.
                        List <GameObj> items = game.mngrLvl.items.Where(o =>
                                                                        o.X == X + Utils.DirVector(BlockDir).X&&
                                                                        o.Y == Y + Utils.DirVector(BlockDir).Y&&
                                                                        o.Layer == Layer).ToList();

                        foreach (GameObj item in items)
                        {
                            #region Interaction: MazeBelt.cs
                            //Can't move into opposing belts.
                            if (item.BlockType == Type.Belt &&
                                item.IsEnabled &&
                                item.BlockDir == Utils.DirOpp(BlockDir))
                            {
                                canMove = false;
                            }
                            #endregion

                            //Can't move if space is occupied.
                            if (item.IsSolid)
                            {
                                #region Interaction: MazeLock.cs
                                if (item.BlockType == Type.Lock)
                                {
                                    if (keys.Count == 0)
                                    {
                                        canMove = false;
                                    }

                                    bool isFound = false;
                                    for (int i = keys.Count - 1; i >= 0; i--)
                                    {
                                        if (keys[i] == item.BlockSprite.color)
                                        {
                                            isFound = true;
                                            game.mngrLvl.RemoveItem(item);
                                            keys.RemoveAt(i);
                                            game.playlist.Play(sndLockOpen, X, Y);
                                            break;
                                        }
                                    }

                                    //Prevents walking through locks.
                                    if (!isFound)
                                    {
                                        canMove = false;
                                    }
                                }
                                #endregion

                                #region Interaction: MazeCoinLock.cs
                                if (item.BlockType == Type.CoinLock)
                                {
                                    bool isOpened = false;

                                    //Opens if player has enough coins.
                                    if (game.mngrLvl.ActorCoins >= item.CustInt1)
                                    {
                                        //Subtracts the coins.
                                        if (item.CustInt2 == 1)
                                        {
                                            game.mngrLvl.ActorCoins -= item.CustInt1;
                                        }

                                        isOpened = true;
                                        game.mngrLvl.RemoveItem(item);
                                        game.playlist.Play(sndLockOpen, X, Y);
                                        break;
                                    }

                                    //Prevents walking through locks.
                                    if (!isOpened)
                                    {
                                        canMove = false;
                                    }
                                }
                                #endregion

                                #region Interaction: MazeCrate.cs
                                else if (item.BlockType == Type.Crate)
                                {
                                    #region Interaction: MazeIce.cs
                                    //If the actor is on ice.
                                    if (game.mngrLvl.items.Any(o =>
                                                               o.BlockType == Type.Ice &&
                                                               o.X == X && o.Y == Y &&
                                                               o.Layer == Layer))
                                    {
                                        //If on ice without solid objects in
                                        //front, moving crates is not allowed.
                                        //This prevents moving crates to the
                                        //side of the actor while they slide.
                                        if (!game.mngrLvl.items.Any(o =>
                                                                    o.X == X + Utils.DirVector(dirPrev).X&&
                                                                    o.Y == Y + Utils.DirVector(dirPrev).Y&&
                                                                    o.Layer == Layer && o.IsSolid))
                                        {
                                            canMove = false;
                                            continue;
                                        }
                                    }
                                    #endregion

                                    //Gets a list of all solids ahead of the
                                    //crate in the player's direction.
                                    List <GameObj> itemsFront =
                                        game.mngrLvl.items.Where(o => o.X ==
                                                                 item.X + Utils.DirVector(BlockDir).X&&
                                                                 o.Y == item.Y + Utils.DirVector(BlockDir).Y &&
                                                                 o.Layer == Layer && o.BlockType !=
                                                                 Type.CrateHole).ToList();

                                    //Gets a list of all items the crate is on.
                                    List <GameObj> itemsTop =
                                        game.mngrLvl.items.Where(o => o.X ==
                                                                 item.X && o.Y == item.Y && o.Layer ==
                                                                 Layer && o.IsEnabled).ToList();

                                    //Removes crate from affecting itself.
                                    itemsTop.Remove(item);

                                    #region Interaction: MazeBelt.cs
                                    //Can't move crates into opposing belts.
                                    itemsFront = itemsFront.Where(o =>
                                                                  o.IsSolid || (o.BlockType == Type.Belt &&
                                                                                o.BlockDir == Utils.DirOpp(BlockDir) &&
                                                                                o.IsEnabled)).ToList();

                                    //Can't move crates from belts.
                                    itemsTop = itemsTop.Where(o =>
                                                              o.IsSolid || (o.BlockType == Type.Belt &&
                                                                            o.IsEnabled && o.BlockDir != BlockDir)).ToList();
                                    #endregion

                                    #region Interaction: MazeMultiWay.cs
                                    itemsFront = itemsFront.Where(o =>
                                                                  !(o.IsEnabled &&
                                                                    o.BlockType == Type.MultiWay &&
                                                                    ((o.CustInt1 == 0 && o.BlockDir == BlockDir) ||
                                                                     (o.CustInt1 != 0 && (o.BlockDir == BlockDir ||
                                                                                          o.BlockDir == Utils.DirOpp(BlockDir))))))
                                                 .ToList();

                                    itemsTop = itemsTop.Where(o =>
                                                              !(o.IsEnabled &&
                                                                o.BlockType == Type.MultiWay &&
                                                                ((o.CustInt1 == 0 && o.BlockDir == BlockDir) ||
                                                                 (o.CustInt1 != 0 && (o.BlockDir == BlockDir ||
                                                                                      o.BlockDir == Utils.DirOpp(BlockDir))))))
                                               .ToList();
                                    #endregion

                                    //If nothing is in way, moves the crate.
                                    if (itemsFront.Count == 0 &&
                                        itemsTop.Count == 0)
                                    {
                                        #region Interaction: MazeTurretBullet.cs
                                        //Finds all bullets skipped over by moving 32px at a time.
                                        //The +32 at the end accounts for sprite width and height.
                                        float          xMin    = Math.Min(item.X * 32, (item.X + Utils.DirVector(item.BlockDir).X) * 32);
                                        float          xMax    = Math.Max(item.X * 32, (item.X + Utils.DirVector(item.BlockDir).X) * 32) + 32;
                                        float          yMin    = Math.Min(item.Y * 32, (item.Y + Utils.DirVector(item.BlockDir).Y) * 32);
                                        float          yMax    = Math.Max(item.Y * 32, (item.Y + Utils.DirVector(item.BlockDir).Y) * 32) + 32;
                                        List <GameObj> bullets = game.mngrLvl.items.Where(o =>
                                                                                          o.BlockType == Type.TurretBullet &&
                                                                                          o.Layer == item.Layer &&
                                                                                          o.X >= xMin && o.X <= xMax &&
                                                                                          o.Y >= yMin && o.Y <= yMax)
                                                                 .ToList();

                                        for (int i = 0; i < bullets.Count; i++)
                                        {
                                            game.mngrLvl.RemoveItem(bullets[i]);
                                        }
                                        #endregion

                                        //Plays the crate-moving sound.
                                        game.playlist.Play
                                            (sndMoveCrate, X, Y);

                                        item.BlockDir = BlockDir; //used for ice.
                                        item.X       += (int)Utils.DirVector(BlockDir).X;
                                        item.Y       += (int)Utils.DirVector(BlockDir).Y;

                                        //Recalculates sprite (no flicker).
                                        item.Update();
                                    }
                                    else
                                    {
                                        canMove = false;
                                    }
                                }
                                #endregion

                                #region Interaction: MazeMultiWay.cs
                                else if (item.BlockType == Type.MultiWay)
                                {
                                    if ((item.CustInt1 == 0 &&
                                         item.BlockDir != BlockDir) ||
                                        (item.CustInt1 != 0 &&
                                         item.BlockDir != BlockDir &&
                                         item.BlockDir != Utils.DirOpp(BlockDir)) ||
                                        (item.IsEnabled == false))
                                    {
                                        canMove = false;
                                    }
                                }
                                else
                                {
                                    canMove = false;
                                }
                                #endregion
                            }
                        }

                        //Considers all scenarios where the player can't move.
                        //Gets a list of all blocks at the current location.
                        items = game.mngrLvl.items.Where(o => o.X == X &&
                                                         o.Y == Y && o.Layer == Layer && o.IsEnabled)
                                .ToList();

                        foreach (GameObj item in items)
                        {
                            #region Interaction: MazeBelt.cs
                            //Cannot move while on a belt.
                            if (item.BlockType == Type.Belt && item.IsEnabled)
                            {
                                canMove     = false;
                                doRevertDir = true;
                            }
                            #endregion

                            #region Interaction: MazeIce.cs
                            else if (item.BlockType == Type.Ice)
                            {
                                //Gets a list of blocks in front.
                                List <GameObj> itemsTemp;
                                itemsTemp = game.mngrLvl.items.Where(o =>
                                                                     o.X == X + Utils.DirVector(dirPrev).X&&
                                                                     o.Y == Y + Utils.DirVector(dirPrev).Y&&
                                                                     o.Layer == Layer).ToList();

                                #region Interaction: MazeMultiWay.cs
                                itemsTemp = itemsTemp.Where(o =>
                                                            !(o.IsEnabled && o.BlockType == Type.MultiWay &&
                                                              ((o.CustInt1 == 0 && o.BlockDir == dirPrev) ||
                                                               (o.CustInt1 != 0 && (o.BlockDir == dirPrev ||
                                                                                    o.BlockDir == Utils.DirOpp(dirPrev)
                                                                                    ))))).ToList();
                                #endregion
                                #region Interaction: MazeBelt.cs
                                //Blocked by solids and enabled belts.
                                itemsTemp = itemsTemp.Where(o =>
                                                            o.IsSolid || (o.BlockType == Type.Belt &&
                                                                          o.BlockDir != Utils.DirOpp(BlockDir))).ToList();
                                #endregion

                                //Can't move unless blocked.
                                if (itemsTemp.Count == 0)
                                {
                                    canMove = false;
                                }
                            }
                            #endregion

                            #region Interaction: MazeMultiWay.cs
                            else if (item.BlockType == Type.MultiWay)
                            {
                                if ((item.CustInt1 == 0 && item.BlockDir != BlockDir) ||
                                    (item.CustInt1 != 0 && item.BlockDir != BlockDir &&
                                     item.BlockDir != Utils.DirOpp(BlockDir)))
                                {
                                    canMove = false;
                                }
                            }
                            #endregion
                        }
                    }

                    //Moves the player if capable.
                    if (doMove && canMove)
                    {
                        #region Interaction: MazeFilter.cs
                        //Gets a list of all filters the actor is standing on.
                        List <GameObj> items = game.mngrLvl.items.Where(o =>
                                                                        o.X == X && o.Y == Y && o.Layer == Layer &&
                                                                        o.BlockType == Type.Filter).ToList();

                        //Decrements each filter's countdown.
                        foreach (GameObj item in items)
                        {
                            if (item.IsEnabled && item.CustInt1 > 0)
                            {
                                item.CustInt1--;
                            }
                        }
                        #endregion

                        #region Interaction: MazeTurretBullet.cs
                        //Finds all bullets skipped over by moving 32px at a time.
                        //The +32 at the end accounts for sprite width and height.
                        float          xMin    = Math.Min(X * 32, (X + Utils.DirVector(BlockDir).X) * 32);
                        float          xMax    = Math.Max(X * 32, (X + Utils.DirVector(BlockDir).X) * 32) + 32;
                        float          yMin    = Math.Min(Y * 32, (Y + Utils.DirVector(BlockDir).Y) * 32);
                        float          yMax    = Math.Max(Y * 32, (Y + Utils.DirVector(BlockDir).Y) * 32) + 32;
                        List <GameObj> bullets = game.mngrLvl.items.Where(o =>
                                                                          o.BlockType == Type.TurretBullet &&
                                                                          o.Layer == Layer &&
                                                                          o.X >= xMin && o.X <= xMax &&
                                                                          o.Y >= yMin && o.Y <= yMax)
                                                 .ToList();

                        List <GameObj> thisActor = new List <GameObj>();
                        thisActor.Add(this);

                        hp -= 25 * bullets.Count;
                        game.playlist.Play(MngrLvl.sndHit, X, Y);

                        for (int i = 0; i < bullets.Count; i++)
                        {
                            game.mngrLvl.RemoveItem(bullets[i]);
                        }
                        #endregion

                        X += (int)Utils.DirVector(BlockDir).X;
                        Y += (int)Utils.DirVector(BlockDir).Y;

                        //Increments the step counter if applicable.
                        if (this == game.mngrLvl.actor)
                        {
                            game.mngrLvl.LvlSteps++;
                        }
                    }
                    else if (doRevertDir)
                    {
                        BlockDir = dirPrev;
                    }
                }
            }
            #endregion

            #region player clicks to select actor
            if (!game.mngrLvl.opSyncActors && game.IsActive)
            {
                //If the player is clicked.
                if (game.MsState.LeftButton == ButtonState.Pressed &&
                    game.MsStateOld.LeftButton == ButtonState.Released &&
                    Sprite.IsIntersecting(BlockSprite, new SmoothRect
                                              (game.mngrLvl.GetCoordsMouse(), 1, 1)) &&
                    Layer == game.mngrLvl.actor.Layer)
                {
                    if (this != game.mngrLvl.actor)
                    {
                        game.mngrLvl.actor = this;

                        //Interaction: TitleItemMain.cs
                        SfxPlaylist.Play(TitleItemMain.sndBttnClick);
                    }
                }
            }
            #endregion

            spriteAtlas.Update(true);
            base.Update();
        }