private void PerformRotation(IStateOwner pOwner, Nomino grp, bool ccw)
 {
     if (!grp.Controllable)
     {
         return;
     }
     grp.Rotate(ccw);
     Sounds.PlaySound(pOwner.AudioThemeMan.BlockGroupRotate.Key, pOwner.Settings.std.EffectVolume);
     pOwner.Feedback(0.3f, 100);
     grp.Clamp(PlayField.RowCount, PlayField.ColCount);
 }
Ejemplo n.º 2
0
 public void Feedback(float Strength, int Length)
 {
     GameOwner?.Feedback(Strength, Length);
 }
        public override void HandleGameKey(IStateOwner pOwner, GameKeys g)
        {
            if (HandleBlockGroupKey(pOwner, g))
            {
                return;
            }


            if (g == GameKeys.GameKey_RotateCW || g == GameKeys.GameKey_RotateCCW)
            {
                bool ccw = g == GameKeys.GameKey_RotateCCW;
                foreach (var activeitem in PlayField.BlockGroups)
                {
                    if (!activeitem.Controllable)
                    {
                        continue;
                    }
                    if (PlayField.CanRotate(activeitem, ccw))
                    {
                        PerformRotation(pOwner, activeitem, ccw);
                    }
                    else if (this.GameOptions.AllowWallKicks)

                    {
                        //we will add up to 3 and subtract up to 3 to the X coordinate. if any say we can rotate then we proceed with allowing the rotation.

                        int[] checkoffsets = new int[] { 1, -1, 2, -2, 3, -3 };


                        int     OriginalPos = activeitem.X;
                        Boolean revertpos   = true;

                        foreach (int currentoffset in checkoffsets)
                        {
                            if (currentoffset == 0)
                            {
                                continue;
                            }
                            activeitem.X = OriginalPos + currentoffset;
                            if (PlayField.CanRotate(activeitem, ccw))
                            {
                                PerformRotation(pOwner, activeitem, ccw);
                                revertpos = false;
                                break;
                            }
                        }

                        if (revertpos)
                        {
                            activeitem.X = OriginalPos;
                        }
                    }
                }
            }
            else if (g == GameKeys.GameKey_Down)
            {
                HandleActiveGroups(pOwner, true);
            }
            else if (g == GameKeys.GameKey_Drop)
            {
                //drop all active groups.
                Nomino FirstGroup = PlayField.BlockGroups.FirstOrDefault();



                if (FirstGroup != null)
                {
                    //store the block positions for each block in the nomino.


                    foreach (var activeitem in PlayField.BlockGroups)
                    {
                        if (!activeitem.Controllable)
                        {
                            continue;
                        }
                        List <Tuple <BCPoint, NominoElement> > StartBlockPositions = new List <Tuple <BCPoint, NominoElement> >();
                        List <Tuple <BCPoint, NominoElement> > EndBlockPositions   = new List <Tuple <BCPoint, NominoElement> >();
                        foreach (var element in activeitem)
                        {
                            StartBlockPositions.Add(new Tuple <BCPoint, NominoElement>(new BCPoint(activeitem.X + element.X, activeitem.Y + element.Y), element));
                        }
                        int dropqty = 0;
                        var ghosted = GetGhostDrop(pOwner, activeitem, out dropqty, 0);
                        foreach (var element in ghosted)
                        {
                            EndBlockPositions.Add(new Tuple <BCPoint, NominoElement>(new BCPoint(ghosted.X + element.X, ghosted.Y + element.Y), element));
                        }
                        GenerateDropParticles(StartBlockPositions, EndBlockPositions);
                        activeitem.X = ghosted.X;
                        activeitem.SetY(pOwner, ghosted.Y);
                        PlayField.SetGroupToField(activeitem);
                        PlayField.RemoveBlockGroup(activeitem);
                        if (GameStats is TetrisStatistics ts)
                        {
                            GameStats.AddScore((dropqty * (5 + (ts.LineCount / 10))));
                        }
                    }

                    pOwner.Feedback(0.6f, 200);
                    Sounds.PlaySound(pOwner.AudioThemeMan.BlockGroupPlace.Key, pOwner.Settings.std.EffectVolume);
                    GameHandler.ProcessFieldChange(this, pOwner, FirstGroup);
                    //ProcessFieldChangeWithScore(pOwner, FirstGroup);
                }
            }
            else if (g == GameKeys.GameKey_Right || g == GameKeys.GameKey_Left)
            {
                int XMove = g == GameKeys.GameKey_Right ? 1 : -1;
                foreach (var ActiveItem in PlayField.BlockGroups)
                {
                    if (!ActiveItem.Controllable)
                    {
                        continue;
                    }
                    if (PlayField.CanFit(ActiveItem, ActiveItem.X + XMove, ActiveItem.Y, false) == TetrisField.CanFitResultConstants.CanFit)
                    {
                        lastHorizontalMove = DateTime.Now;
                        ActiveItem.X      += XMove;
                        Sounds.PlaySound(pOwner.AudioThemeMan.BlockGroupMove.Key, pOwner.Settings.std.EffectVolume);
                        pOwner.Feedback(0.1f, 50);
                    }
                    else
                    {
                        Sounds.PlaySound(pOwner.AudioThemeMan.BlockStopped.Key, pOwner.Settings.std.EffectVolume);
                        pOwner.Feedback(0.4f, 75);
                    }
                }
            }
            else if (g == GameKeys.GameKey_Pause)
            {
                if (g == GameKeys.GameKey_Pause)
                {
                    pOwner.LastPausedTime = DateTime.Now;
                    pOwner.CurrentState   = new PauseGameState(pOwner, this);

                    var playing = Sounds.GetPlayingMusic_Active();
                    playing?.Pause();
                    Sounds.PlaySound(pOwner.AudioThemeMan.Pause.Key, pOwner.Settings.std.EffectVolume);
                }

                //pOwner.CurrentState = new PauseGameState(this);
            }
            else if (g == GameKeys.GameKey_Hold)
            {
                if (HoldBlock != null && !BlockHold)
                {
                    //if there is a holdblock, take it and put it into the gamefield and make the first active blockgroup the new holdblock,
                    //then set BlockHold to block it from being used until the next Tetromino is spawned.
                    Nomino FirstGroup = PlayField.BlockGroups.FirstOrDefault();
                    if (FirstGroup != null)
                    {
                        if (FirstGroup.Controllable)
                        {
                            PlayField.RemoveBlockGroup(FirstGroup);

                            PlayField.AddBlockGroup(HoldBlock);

                            //We probably should set the speed appropriately here for the level. As is it will retain the speed from whe nthe hold block was
                            //held.
                            PlayField.Theme.ApplyTheme(HoldBlock, GameHandler, PlayField, NominoTheme.ThemeApplicationReason.Normal);
                            HoldBlock.X = (int)(((float)PlayField.ColCount / 2) - ((float)HoldBlock.GroupExtents.Width / 2));
                            HoldBlock.SetY(pOwner, 0);
                            HoldBlock.HighestHeightValue = 0; //reset the highest height as well, so the falling animation doesn't goof
                            HoldBlock = FirstGroup;
                            Sounds.PlaySound(pOwner.AudioThemeMan.Hold.Key, pOwner.Settings.std.EffectVolume);
                            pOwner.Feedback(0.9f, 40);
                            BlockHold = true;
                        }
                    }
                }
                else if (!BlockHold)
                {
                    Nomino FirstGroup = PlayField.BlockGroups.FirstOrDefault();
                    if (FirstGroup != null)
                    {
                        if (FirstGroup.Controllable)
                        {
                            PlayField.RemoveBlockGroup(FirstGroup);
                            HoldBlock = FirstGroup;
                            BlockHold = true;
                            Sounds.PlaySound(pOwner.AudioThemeMan.Hold.Key, pOwner.Settings.std.EffectVolume);
                        }
                    }
                }
            }
            else if (g == GameKeys.GameKey_Debug1)
            {
                pOwner.CurrentState = new ShowHighScoresState(TetrisGame.ScoreMan["Standard"], pOwner.CurrentState);
            }
            else if (g == GameKeys.GameKey_Debug2)
            {
                OptionsMenuSettingsSelectorState OptionState = new OptionsMenuSettingsSelectorState(BackgroundDrawers.StandardImageBackgroundGDI.GetStandardBackgroundDrawer(),
                                                                                                    pOwner, pOwner.CurrentState);

                pOwner.CurrentState = OptionState;

                /*if (pOwner.CurrentState is StandardTetrisGameState)
                 * {
                 *  ((StandardTetrisGameState) pOwner.CurrentState).GameStats.Score += 1000;
                 * }*/
            }
            else if (g == GameKeys.GameKey_Debug3)
            {
                int  DesiredFontPixelHeight = (int)(pOwner.GameArea.Height * (23d / 644d));
                Font standardFont           = new Font(TetrisGame.RetroFont, DesiredFontPixelHeight, FontStyle.Bold, GraphicsUnit.Pixel);
                Font ItemFont = new Font(TetrisGame.RetroFont, (int)((float)DesiredFontPixelHeight * (3f / 4f)), FontStyle.Bold, GraphicsUnit.Pixel);
                //set state to a testing menu state.

                MenuState ms = new MenuState(BackgroundDrawers.StandardImageBackgroundGDI.GetStandardBackgroundDrawer());
                ms.StateHeader    = "This is a Menu";
                ms.HeaderTypeface = standardFont.Name;
                ms.HeaderTypeSize = standardFont.Size;

                MenuStateTextMenuItem returnitem = new MenuStateTextMenuItem();
                returnitem.FontFace  = ItemFont.Name;
                returnitem.FontSize  = ItemFont.Size;
                returnitem.Text      = "Return";
                returnitem.BackColor = Color.Transparent;
                returnitem.ForeColor = Color.DarkBlue;
                var OriginalState = pOwner.CurrentState;
                ms.MenuElements.Add(returnitem);

                var scaleitem = new MenuStateScaleMenuItem(pOwner);
                scaleitem.FontFace = ItemFont.Name;
                scaleitem.FontSize = ItemFont.Size;
                ms.MenuElements.Add(scaleitem);

                ms.MenuItemActivated += (obj, e) =>
                {
                    if (e.MenuElement == returnitem)
                    {
                        pOwner.CurrentState = OriginalState;
                    }
                };
                for (int i = 0; i < 8; i++)
                {
                    MenuStateTextMenuItem mts = new MenuStateTextMenuItem();
                    mts.FontFace  = ItemFont.Name;
                    mts.FontSize  = ItemFont.Size;
                    mts.BackColor = Color.Transparent;
                    mts.ForeColor = Color.Black;
                    mts.Text      = "Item " + i.ToString();
                    ms.MenuElements.Add(mts);
                }
                pOwner.CurrentState = ms;
            }
            else if (g == GameKeys.GameKey_Debug4)
            {
                if (pOwner is IGamePresenter gp)
                {
                    var _Present = gp.GetPresenter();
                    if (_Present.ai == null)
                    {
                        _Present.ai = new StandardNominoAI(pOwner);
                    }
                    else
                    {
                        _Present.ai.AbortAI();
                        _Present.ai = null;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        public FieldChangeResult ProcessFieldChange(GameplayGameState state, IStateOwner pOwner, Nomino Trigger)
        {
            var HotLines                    = new List <HotLine>();
            FieldChangeResult FCR           = new FieldChangeResult();
            int           rowsfound         = 0;
            List <int>    CompletedRows     = new List <int>();
            List <Action> AfterClearActions = new List <Action>();
            var           PlayField         = state.PlayField;
            var           Sounds            = state.Sounds;
            var           GameOptions       = state.GameOptions;

            //checks the field contents for lines. If there are lines found, they are removed, and all rows above it are shifted down.
            for (int r = 0; r < PlayField.RowCount; r++)
            {
                if (PlayField.Contents[r].All((d) => d != null))
                {
                    Debug.Print("Found completed row at row " + r);
                    if (PlayField.Flags.HasFlag(TetrisField.GameFlags.Flags_Hotline) && PlayField.HotLines.ContainsKey(r))
                    {
                        Debug.Print("Found hotline row at row " + r);
                        HotLines.Add(PlayField.HotLines[r]);
                    }
                    CompletedRows.Add(r);
                    rowsfound++;
                    //enqueue an action to perform the clear. We'll be replacing the current state with a clear action state, so this should execute AFTER that state returns control.
                    var r1 = r;
                    AfterClearActions.Add
                        (() =>
                    {
                        for (int g = r1; g > 0; g--)
                        {
                            Debug.Print("Moving row " + (g - 1).ToString() + " to row " + g);

                            for (int i = 0; i < PlayField.ColCount; i++)
                            {
                                PlayField.Contents[g][i] = PlayField.Contents[g - 1][i];
                            }
                        }
                    });
                }
            }
            AfterClearActions.Add(() => { PlayField.HasChanged = true; });

            long PreviousLineCount = Statistics.LineCount;

            if (Trigger != null)
            {
                Statistics.AddLineCount(Trigger.GetType(), rowsfound);
            }

            if ((PreviousLineCount % 10) > (Statistics.LineCount % 10))
            {
                state.InvokePlayFieldLevelChanged(state, new TetrisField.LevelChangeEventArgs((int)Statistics.LineCount / 10));
                Statistics.SetLevelTime(pOwner.GetElapsedTime());

                state.Sounds.PlaySound(pOwner.AudioThemeMan.LevelUp.Key, pOwner.Settings.std.EffectVolume);
                PlayField.SetFieldColors(this);
                state.f_RedrawStatusBitmap = true;
            }

            if (rowsfound > 0 && rowsfound < 4)
            {
                Sounds.PlaySound(pOwner.AudioThemeMan.ClearLine.Key, pOwner.Settings.std.EffectVolume * 2);
            }
            else if (rowsfound == 4)
            {
                Sounds.PlaySound(pOwner.AudioThemeMan.ClearTetris.Key, pOwner.Settings.std.EffectVolume * 2);
            }


            int topmost = PlayField.RowCount;

            //find the topmost row with any blocks.
            for (int i = 0; i < PlayField.RowCount; i++)
            {
                if (PlayField.Contents[i].Any((w) => w != null))
                {
                    topmost = i;
                    break;
                }
            }

            topmost = topmost + rowsfound; //subtract the rows that were cleared to get an accurate measurement.
            if (topmost < 9)
            {
                if (state.currenttempo == 1)
                {
                    state.currenttempo = 68;
                    if (GameOptions.MusicRestartsOnTempoChange)
                    {
                        if (GameOptions.MusicEnabled)
                        {
                            Sounds.PlayMusic(pOwner.AudioThemeMan.BackgroundMusic.Key, pOwner.Settings.std.MusicVolume, true);
                        }
                    }

                    var grabbed = Sounds.GetPlayingMusic_Active();
                    if (grabbed != null)
                    {
                        Sounds.GetPlayingMusic_Active().Tempo = 75f;
                    }
                }
            }
            else
            {
                if (state.currenttempo != 1)
                {
                    state.currenttempo = 1;
                    if (GameOptions.MusicRestartsOnTempoChange)
                    {
                        if (GameOptions.MusicEnabled)
                        {
                            if (pOwner.Settings.std.MusicOption == "<RANDOM>")
                            {
                                Sounds.PlayMusic(pOwner.AudioThemeMan.BackgroundMusic.Key, pOwner.Settings.std.MusicVolume, true);
                            }
                            else
                            {
                                Sounds.PlayMusic(pOwner.Settings.std.MusicOption, pOwner.Settings.std.MusicVolume, true);
                            }
                        }
                    }
                    var grabbed = Sounds.GetPlayingMusic_Active();
                    if (grabbed != null)
                    {
                        grabbed.Tempo = 1f;
                    }
                }
            }

            PlayField.HasChanged |= rowsfound > 0;

            if (rowsfound > 0)
            {
                var ClearState = new FieldLineActionGameState(state, CompletedRows.ToArray(), AfterClearActions);
                ClearState.ClearStyle = TetrisGame.Choose((FieldLineActionGameState.LineClearStyle[])(Enum.GetValues(typeof(FieldLineActionGameState.LineClearStyle))));

                pOwner.CurrentState = ClearState;
            }

            //if(rowsfound > 0) pOwner.CurrentState = new FieldLineActionDissolve(this,CompletedRows.ToArray(),AfterClearActions);
            var scoreresult = GetScore(rowsfound, HotLines, state, pOwner, Trigger);

            pOwner.Feedback(0.9f * (float)scoreresult, scoreresult * 250);
            FCR.ScoreResult = rowsfound;
            return(FCR);
        }