コード例 #1
0
        public override SKColor GetColor(TetrisField field, Nomino Element, NominoElement block, NESBlockTypes BlockType, BCT PixelType)
        {
            int LevelNum   = field.Level;
            int LevelIndex = MathHelper.mod(LevelNum, AllLevelColors.Length);

            switch (PixelType)
            {
            case BCT.Transparent:
                return(SKColors.Transparent);

            case BCT.Glint:
                return(SKColors.White);

            case BCT.Base_Dark:
                return(LevelColorSets[LevelIndex][0]);

            case BCT.Base_Light:
                return(LevelColorSets[LevelIndex][1]);

            case BCT.Black:
                return(SKColors.Black);

            default:
                return(LevelColorSets[LevelIndex][0]);
            }
        }
コード例 #2
0
        //redraws the StatisticsBackground SKImage.
        public void GenerateStatisticsBackground(GameplayGameState Self)
        {
            using (SKBitmap sourcebit = new SKBitmap(new SKImageInfo(1120, 2576, SKColorType.Rgba8888)))
            {
                Size BlockSize   = new Size(128, 128);
                int  ColumnCount = (sourcebit.Width / BlockSize.Width) + 1;
                int  RowCount    = (sourcebit.Height / BlockSize.Height) + 1;

                using (SKCanvas g = new SKCanvas(sourcebit))
                {
                    g.Clear(Color.Black.ToSKColor());
                    for (int col = 0; col < ColumnCount; col++)
                    {
                        for (int row = 0; row < RowCount; row++)
                        {
                            int DrawBlockX = col * BlockSize.Width;
                            int DrawBlockY = row * BlockSize.Height;
                            StandardColouredBlock GenerateColorBlock = new StandardColouredBlock();
                            Nomino ArbitraryGroup = new Nomino();
                            ArbitraryGroup.AddBlock(new Point[] { Point.Empty }, GenerateColorBlock);
                            Self.PlayField.Theme.ApplyRandom(ArbitraryGroup, Self.GameHandler, Self.PlayField);
                            //this.PlayField.Theme.ApplyTheme(ArbitraryGroup, this.PlayField);
                            TetrisBlockDrawSkiaParameters tbd = new TetrisBlockDrawSkiaParameters(g, new SKRect(DrawBlockX, DrawBlockY, DrawBlockX + BlockSize.Width, DrawBlockY + BlockSize.Height), null, new SettingsManager());
                            RenderingProvider.Static.DrawElement(null, tbd.g, GenerateColorBlock, tbd);
                        }
                    }
                }

                StatisticsBackground      = SKImage.FromBitmap(sourcebit);
                LastStatisticsTheme       = Self.PlayField.Theme;
                Self.f_RedrawStatusBitmap = false;
            }
        }
コード例 #3
0
ファイル: TetrisAI.cs プロジェクト: BCProgramming/BASeTris
        public static IEnumerable <StoredBoardState> GetPossibleResults(NominoBlock[][] Source, Nomino bg, StoredBoardState.BoardScoringRuleData rules)
        {
            //Debug.Print("Calculating possible results:" + Source.Sum((u)=>u.Count((y)=>y!=null)) + " Non null entries.");
            for (int useRotation = 0; useRotation < 4; useRotation++)
            {
                for (int x = -5; x < Source[0].Length + 5; x++)
                {
                    if (rules.StupidFactor < 1)
                    {
                        if (TetrisGame.rgen.NextDouble() < rules.StupidFactor)
                        {
                            continue;
                        }
                    }
                    Nomino cloneFor = new Nomino(bg);
                    foreach (var resetblock in cloneFor)
                    {
                        resetblock.Block = new StandardColouredBlock();
                    }

                    int XOffset = x - bg.X;
                    StoredBoardState BuildState = new StoredBoardState(Source, cloneFor, XOffset, useRotation);
                    if (!BuildState.InvalidState)
                    {
                        yield return(BuildState);
                    }
                }
            }
        }
コード例 #4
0
ファイル: TetrisAI.cs プロジェクト: BCProgramming/BASeTris
        private bool CanFit(Nomino Source, NominoBlock[][] Field, int Y, int X)
        {
            bool result   = false;
            int  ROWCOUNT = Field.Length - 1;
            int  COLCOUNT = Field[0].Length - 1;

            foreach (var checkblock in Source)
            {
                int CheckRow = Y + checkblock.Y;
                int CheckCol = X + checkblock.X;
                if (CheckCol < 0)
                {
                    return(false);
                }
                else if (CheckRow > ROWCOUNT || CheckCol > COLCOUNT)
                {
                    return(false);
                }
                else
                {
                    var grabpos = Field[CheckRow][CheckCol];
                    if (grabpos != null)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
コード例 #5
0
        public void GenerateStatisticsBackground(GameplayGameState Self)
        {
            Bitmap buildbg     = new Bitmap(1120, 2576);
            Size   BlockSize   = new Size(128, 128);
            int    ColumnCount = (buildbg.Width / BlockSize.Width) + 1;
            int    RowCount    = (buildbg.Height / BlockSize.Height) + 1;

            using (Graphics g = Graphics.FromImage(buildbg))
            {
                g.Clear(Color.Black);
                for (int col = 0; col < ColumnCount; col++)
                {
                    for (int row = 0; row < RowCount; row++)
                    {
                        int DrawBlockX = col * BlockSize.Width;
                        int DrawBlockY = row * BlockSize.Height;
                        StandardColouredBlock GenerateColorBlock = new StandardColouredBlock();
                        Nomino ArbitraryGroup = new Nomino();
                        ArbitraryGroup.AddBlock(new Point[] { Point.Empty }, GenerateColorBlock);
                        Self.PlayField.Theme.ApplyRandom(ArbitraryGroup, Self.GameHandler, Self.PlayField);
                        //this.PlayField.Theme.ApplyTheme(ArbitraryGroup, this.PlayField);
                        TetrisBlockDrawGDIPlusParameters tbd = new TetrisBlockDrawGDIPlusParameters(g, new RectangleF(DrawBlockX, DrawBlockY, BlockSize.Width, BlockSize.Height), null, new SettingsManager());
                        RenderingProvider.Static.DrawElement(null, tbd.g, GenerateColorBlock, tbd);
                    }
                }
            }

            StatisticsBackground = buildbg;
            GeneratedImageTheme  = Self.PlayField.Theme;
        }
コード例 #6
0
        public List <Nomino> ProcessBlockDroppage(GameplayGameState state, int Column, int Row, ref HashSet <Nomino> AdditionalSkipBlocks)
        {
            List <Nomino> CreateResult = new List <Nomino>();
            var           currentblock = state.PlayField.Contents[Row][Column];
            bool          isPopping    = false;

            if (currentblock != null)
            {
                if (currentblock is CascadingBlock cb)
                {
                    if (currentblock is LineSeriesBlock lsb)
                    {
                        isPopping = lsb.Popping;  //blocks that are popping shouldn't be resurrected.
                    }
                    if (!isPopping && !cb.IsSupported(cb.Owner, state.PlayField, new[] { cb }.ToList()) && !AdditionalSkipBlocks.Contains(cb.Owner))
                    {
                        //we initialize the list of recursion blocks to the block we are testing, since it cannot support itself.
                        //resurrect this block and other blocks that are in the same nomino.
                        //since we remove busted blocks from the nomino, we can take the Duomino this
                        //block belongs to and add it back to the Active Groups, then remove all the blocks that are in the nomino from the field.
                        foreach (var iterate in cb.Owner)
                        {
                            var useX = iterate.X + cb.Owner.X;
                            var useY = iterate.Y + cb.Owner.Y;
                            state.PlayField.Contents[useY][useX] = null;
                        }

                        Nomino resurrect = cb.Owner;
                        resurrect.Controllable = false;
                        resurrect.FallSpeed    = 250;
                        resurrect.MoveSound    = true;
                        resurrect.PlaceSound   = false;
                        resurrect.NoGhost      = true;
                        AdditionalSkipBlocks.Add(resurrect);
                        CreateResult.Add(resurrect);
                    }
                }

                //now recursively process for the block to our left, the block to our right, and the block above. But only if that block is not part of the same nomino as currentblock or currentblock is null.

                foreach (Point offset in new Point[] { new Point(-1, 0), new Point(0, -1), new Point(1, 0) })
                {
                    var checkblock = state.PlayField.Contents[Row + offset.Y][Column + offset.X];
                    if (checkblock != null && (currentblock == null || !currentblock.Owner.HasBlock(checkblock)))
                    {
                        List <Nomino> CurrResult = ProcessBlockDroppage(state, Column + offset.X, Row + offset.Y, ref AdditionalSkipBlocks);
                        foreach (var iterateresult in CurrResult)
                        {
                            CreateResult.Add(iterateresult);
                        }
                    }
                }
            }


            return(CreateResult);
        }
コード例 #7
0
        public Image GetTetrominoImage(IStateOwner pOwner, Nomino nom)
        {
            String sKey = PlayField.Theme.GetNominoKey(nom, GameHandler, PlayField);

            if (!NominoImages.ContainsKey(sKey))
            {
                return(AddTetrominoImage(pOwner, nom));
            }
            return(GetTetrominoImage(sKey));
        }
コード例 #8
0
        public SKBitmap GetTetrominoSKBitmap(IStateOwner pOwner, Nomino nom)
        {
            String GetKey = PlayField.Theme.GetNominoKey(nom, GameHandler, PlayField);

            if (!NominoSKBitmaps.ContainsKey(GetKey))
            {
                return(AddTetrominoBitmapSK(pOwner, nom));
            }
            return(GetTetrominoSKBitmap(GetKey));
        }
コード例 #9
0
 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);
 }
コード例 #10
0
 private void DrMarioNominoTweaker(Nomino Source)
 {
     //tweak the nomino and set a random combining index.
     foreach (var iterate in Source)
     {
         if (iterate.Block is LineSeriesBlock lsb)
         {
             lsb.CombiningIndex = TetrisGame.Choose(GetValidBlockCombiningTypes());
         }
     }
 }
コード例 #11
0
ファイル: Duomino.cs プロジェクト: BCProgramming/BASeTris
        public Duomino()
        {
            //generate a new Duomino. Duomino's don't actually use StandardColouredBlocks.


            BlockData = Nomino.GetNominoEntries(new[] { Duomino_Point_1, Duomino_Point_2 },
                                                (i) => new LineSeriesBlock()
            {
                CombiningIndex = TetrisGame.Choose(new LineSeriesBlock.CombiningTypes[] { LineSeriesBlock.CombiningTypes.Yellow, LineSeriesBlock.CombiningTypes.Red, LineSeriesBlock.CombiningTypes.Blue })
            }).ToList();

            base.SpecialName = "Pill";
            base.SetBlockOwner();
            base.RecalcExtents();
        }
コード例 #12
0
ファイル: TetrisAI.cs プロジェクト: BCProgramming/BASeTris
        public override void AIActionFrame()
        {
            //do our hard thinking here.
            //first we only do stuff with the standard game state.
            if (_Owner == null)
            {
                return;
            }
            if (_Owner.CurrentState is GameplayGameState)
            {
                GameplayGameState stdState = _Owner.CurrentState as GameplayGameState;
                //next, we only want to do stuff if there is one active blockgroup...
                if (stdState.PlayField.GetActiveBlockGroups().Count == 1)
                {
                    //todo: we want to copy the playfield for our inspection here... we'll want to see what happens based on moving the blockgroup left or right up to each side and dropping it and evaluate the result to select the ideal
                    //then slap those keys into the queue.
                    Nomino ActiveGroup    = stdState.PlayField.BlockGroups[0];
                    var    PossibleStates = GetPossibleResults(stdState.PlayField.Contents, ActiveGroup, ScoringRules).ToList();

                    Debug.Print("Found " + PossibleStates.Count + " possible states...");
                    var Sorted = (ScoringRules.Moronic?PossibleStates.OrderByDescending((w) => TetrisGame.rgen.Next()):  PossibleStates.OrderByDescending((w) => w.GetScore(stdState.GameHandler.GetType(), ScoringRules))).ToList();

                    //var Scores = (from p in PossibleStates orderby p.GetScore(ScoringRules) descending select new Tuple<StoredBoardState, double>(p, p.GetScore(ScoringRules))).ToArray();

                    /*foreach (var writedebug in Scores)
                     * {
                     *  Debug.Print("Possible State: Move " + writedebug.Item1.XOffset + ", Rotate " + writedebug.Item1.RotationCount + " To get score " + writedebug.Item1.GetScore(ScoringRules));
                     *  Debug.Print("What it will look like\n" + writedebug.Item1.GetBoardString());
                     *  Debug.Print("------");
                     * }*/

                    var maximumValue = Sorted.FirstOrDefault();
                    Debug.Print("Best Move: Move " + maximumValue.XOffset + ", Rotate " + maximumValue.RotationCount + " To get score " + maximumValue.GetScore(stdState.GameHandler.GetType(), ScoringRules));
                    Debug.Print("What it will look like\n" + maximumValue.GetBoardString());
                    Debug.Print("------");

                    //int randomint = TetrisGame.rgen.Next(Scores.Length);
                    //int randomint2 = TetrisGame.rgen.Next(Scores.Length);
                    //StoredBoardState FirstState = Scores[randomint2].Item1;
                    StoredBoardState IdealState = maximumValue;
                    PushButtonInputs(IdealState);
                    //if(maximumValue!=null)
                    //{
                    //    PushButtonInputs(maximumValue);
                    //}
                }
            }
        }
コード例 #13
0
        public override SKColor GetColor(TetrisField field, Nomino Element, NominoElement Block, BasicBlockTypes BlockType, BBP PixelType)
        {
            var Level      = (field.Handler.Statistics is TetrisStatistics ts) ? ts.Level : 0;
            int LevelField = MathHelper.mod(Level, LevelColors.Length);

            switch (PixelType)
            {
            case BBP.Transparent:
                return(SKColors.Transparent);

            case BBP.Glint:
            case BBP.Center:
            case BBP.Shade:
            case BBP.DoubleShade:
                return(LevelColors[LevelField][((int)PixelType) - 1]);
            }
            return(SKColors.Black);
        }
コード例 #14
0
ファイル: TetrisAI.cs プロジェクト: BCProgramming/BASeTris
        private void DropBlock(Nomino Source, ref NominoBlock[][] FieldState, int XOffset)
        {
            bool result   = true;
            int  YOffset  = 0;
            bool neverfit = true;
            int  ROWCOUNT = FieldState.Length - 1;
            int  COLCOUNT = FieldState[0].Length - 1;

            Nomino Duplicator = new Nomino(Source);

            int dropLength = 0;

            while (true)
            {
                if (CanFit(Duplicator, FieldState, Duplicator.Y + 1, Duplicator.X + XOffset))
                {
                    dropLength++;
                    Duplicator.SetY(null, Duplicator.Y + 1);
                }
                else
                {
                    break;
                }
            }

            foreach (var iterate in Duplicator)
            {
                int Row = iterate.Y + Duplicator.Y;
                int Col = iterate.X + Duplicator.X + XOffset;
                if (Row > RowCount - 1 || Col > ColCount - 1 || Row < 0 || Col < 0)
                {
                }
                else
                {
                    if (FieldState[Row][Col] != null)
                    {
                        throw new ArgumentException("Invalid state...");
                    }
                    FieldState[Row][Col] = iterate.Block;
                }
            }
        }
コード例 #15
0
ファイル: TetrisAI.cs プロジェクト: BCProgramming/BASeTris
        public StoredBoardState(NominoBlock[][] InitialState, Nomino pGroup, int pXOffset, int pRotationCount)
        {
            RowCount      = InitialState.GetUpperBound(0);
            ColCount      = InitialState[0].GetUpperBound(0);
            _BoardState   = StandardNominoAI.DuplicateField(InitialState);
            _SourceGroup  = new Nomino(pGroup);
            XOffset       = pXOffset;
            RotationCount = pRotationCount;
            foreach (var resetblock in _SourceGroup)
            {
                resetblock.Block = new StandardColouredBlock();
            }


            for (int i = 0; i < RotationCount; i++)
            {
                _SourceGroup.Rotate(false);
            }
            //move the Nomino by the specified offset...

            _SourceGroup.RecalcExtents();

            /*
             * if(_SourceGroup.GroupExtents.Left+_SourceGroup.X+XOffset < 0 || _SourceGroup.GroupExtents.Right+XOffset+_SourceGroup.X > _BoardState[0].Length)
             * {
             *  InvalidState = true; //nothing else to do- this is an invalid state as the move puts us "off" the board.
             * }
             * else*/
            {
                //get our board state...
                try
                {
                    DropBlock(_SourceGroup, ref _BoardState, pXOffset);
                }
                catch (Exception exx)
                {
                    InvalidState = true;
                    return;
                }
            }
        }
コード例 #16
0
        private GroupOperationResult HandleGroupOperation(IStateOwner pOwner, Nomino activeItem)
        {
            if (activeItem.HandleBlockOperation(pOwner))
            {
                return(GroupOperationResult.Operation_Success);
            }
            var fitresult = PlayField.CanFit(activeItem, activeItem.X, activeItem.Y + 1, false);

            if (fitresult == TetrisField.CanFitResultConstants.CanFit)
            {
                activeItem.SetY(pOwner, activeItem.Y + 1);
            }
            else if (fitresult == TetrisField.CanFitResultConstants.CantFit_Field)
            {
                if (GameOptions.MoveResetsSetTimer && (DateTime.Now - lastHorizontalMove).TotalMilliseconds > pOwner.Settings.std.LockTime)
                {
                    var elapsed = pOwner.GetElapsedTime();
                    //any and all blockgroups in the field that are set not to allow input must have not moved in the last 750ms before we allow any groups to set.

                    var allgroups  = PlayField.GetActiveBlockGroups();
                    var Applicable = allgroups.All((f) =>
                    {
                        return(!f.Controllable || (elapsed - f.LastFall).TotalMilliseconds > 750);
                    });
                    Applicable = true;
                    if (Applicable)
                    {
                        PlayField.SetGroupToField(activeItem);
                        GameStats.AddScore(25 - activeItem.Y);
                        if (activeItem.PlaceSound)
                        {
                            Sounds.PlaySound(pOwner.AudioThemeMan.BlockGroupPlace.Key, pOwner.Settings.std.EffectVolume);
                        }
                        return(GroupOperationResult.Operation_Success);
                    }
                }
            }


            return(GroupOperationResult.Operation_Error);
        }
コード例 #17
0
        public override BlockTypeReturnData  GetBlockType(Nomino group, NominoElement element, TetrisField field)
        {
            var bg = group;

            if (bg is Tetromino_I || bg is Tetromino_T || bg is Tetromino_O)
            {
                return(new BlockTypeReturnData(NESBlockTypes.Boxed));
            }
            else if (bg is Tetromino_J || bg is Tetromino_Z)
            {
                return(new BlockTypeReturnData(NESBlockTypes.Darker));
            }
            else if (bg is Tetromino)
            {
                return(new BlockTypeReturnData(NESBlockTypes.Lighter));
            }
            else
            {
                return(new BlockTypeReturnData(TetrisGame.Choose(new NESBlockTypes[] { NESBlockTypes.Boxed, NESBlockTypes.Darker, NESBlockTypes.Lighter })));
            }
        }
コード例 #18
0
        public void PrepareField(GameplayGameState state, IStateOwner pOwner)
        {
            //likely will need to have stats and stuff abstracted to each Handler.
            state.PlayField.Reset();

            HashSet <SKPointI> usedPositions = new HashSet <SKPointI>();
            //primary count is based on our level.
            int numPrimaries = (int)((Level * 1.33f) + 4);

            for (int i = 0; i < numPrimaries; i++)
            {
                //choose a random primary type.
                var chosentype = TetrisGame.Choose(GetValidPrimaryCombiningTypes());
                LineSeriesPrimaryBlock lsmb = new LineSeriesPrimaryBlock()
                {
                    CombiningIndex = chosentype
                };
                var Dummino = new Nomino()
                {
                };
                Dummino.AddBlock(new Point[] { new Point(0, 0) }, lsmb);
                state.PlayField.Theme.ApplyTheme(Dummino, this, state.PlayField, NominoTheme.ThemeApplicationReason.Normal);
                lsmb.CriticalMass = 4; //TODO: should this be changed?

                int      RandomXPos = TetrisGame.rgen.Next(state.PlayField.ColCount);
                int      RandomYPos = state.PlayField.RowCount - 1 - TetrisGame.rgen.Next(state.PlayField.RowCount / 2);
                SKPointI randomPos  = new SKPointI(RandomXPos, RandomYPos);
                while (usedPositions.Contains(randomPos))
                {
                    int rndXPos = TetrisGame.rgen.Next(state.PlayField.ColCount);
                    int rndYPos = state.PlayField.RowCount - 1 - TetrisGame.rgen.Next(state.PlayField.RowCount / 2);
                    randomPos = new SKPointI(rndXPos, rndYPos);
                }
                state.PlayField.Contents[RandomYPos][RandomXPos] = lsmb;
                PrimaryBlockCount++;
            }
            PrimaryBlockAppearanceState appearstate = new PrimaryBlockAppearanceState(state);

            pOwner.CurrentState = appearstate;
        }
コード例 #19
0
        public SKBitmap AddTetrominoBitmapSK(IStateOwner pOwner, Nomino Source)
        {
            String sAddKey    = PlayField.Theme.GetNominoKey(Source, GameHandler, PlayField);
            float  useSize    = 18 * (float)pOwner.ScaleFactor;
            SKSize useTetSize = new SKSize(useSize, useSize);


            PlayField.Theme.ApplyTheme(Source, GameHandler, PlayField, NominoTheme.ThemeApplicationReason.Normal);

            SKBitmap buildBitmap = TetrisGame.OutlineImageSK(Source.GetImageSK(useTetSize));

            if (!NominoSKBitmaps.ContainsKey(sAddKey))
            {
                NominoSKBitmaps.Add(sAddKey, new List <SKBitmap>()
                {
                    buildBitmap
                });
            }


            return(buildBitmap);
        }
コード例 #20
0
        protected override Nomino GetNext()
        {
            if (AIWorker == null)
            {
                AIWorker          = new Thread(AIChooserWorker);
                AIWorker.Priority = ThreadPriority.Normal;
                AIWorker.Start();
            }

            while (WorkQueue.IsEmpty)
            {
                Thread.Sleep(5);
            }

            Nomino getresult = null;

            while (!WorkQueue.TryDequeue(out getresult))
            {
                Thread.Sleep(15);
            }

            return(getresult);
        }
コード例 #21
0
        private void PlayField_BlockGroupSet(object sender, TetrisField.BlockGroupSetEventArgs e)
        {
            if (e._groups.All((n) => n.Y < 1))
            {
                GameOvered = true;
            }
            //reapply the theme when setting it down. Some themes may want
            //to have different appearances for blocks that are "set" versus those that are still "active".

            //TODO: for Dr Mario theme, the block set is using the "original" rotation when setting.
            //I suspect setting it to the field must be resetting the rotation of the blocks,

            foreach (var group in e._groups)
            {
                var    firstBlock = group.FirstOrDefault();
                Nomino useGroup   = group;
                if (firstBlock != null)
                {
                    useGroup = firstBlock.Block.Owner ?? group;
                }

                PlayField.Theme.ApplyTheme(useGroup, GameHandler, PlayField, NominoTheme.ThemeApplicationReason.FieldSet);
            }
        }
コード例 #22
0
 public override BlockFlags GetBlockFlags(Nomino Group, NominoElement element, TetrisField field)
 {
     return(CustomPixelTheme <BCT, NESBlockTypes> .BlockFlags.Static);
 }
コード例 #23
0
 public abstract SKColor GetColor(TetrisField field, Nomino Element, NominoElement block, BlockEnum BlockType, PixelEnum PixelType);
コード例 #24
0
 public TetrisBlockDrawGDIPlusParameters(Graphics pG, RectangleF pRegion, Nomino pGroupOwner, SettingsManager pSettings) : base(pGroupOwner, pSettings)
 {
     g      = pG;
     region = pRegion;
 }
コード例 #25
0
 public TetrisBlockDrawParameters(Nomino pGroupOwner, SettingsManager pSettings)
 {
     GroupOwner = pGroupOwner;
     Settings   = pSettings;
 }
コード例 #26
0
        public bool IsSupported(Nomino Owner, TetrisField field, List <CascadingBlock> RecursionBlocks = null)
        {
            if (Fixed)
            {
                return(true);
            }
            if (RecursionBlocks == null)
            {
                RecursionBlocks = new List <CascadingBlock>()
                {
                };
            }
            else
            {
            }



            //search through our owner's Nominos...
            foreach (var iterate in Owner)
            {
                if (RecursionBlocks.Contains(iterate.Block))
                {
                    continue;
                }
                //find the field position of this block.
                int PosX = iterate.X + Owner.X;
                int PosY = iterate.Y + Owner.Y;
                //grab the block at this position.
                var fieldblock = field.Contents[PosY][PosX];
                if (fieldblock == iterate.Block)
                {
                    if (fieldblock is CascadingBlock cb2)
                    {
                        if (cb2.ConnectionIndex != this.ConnectionIndex)
                        {
                            continue;                                              //since the connection index is different, this block in our nomino cannot support us.
                        }
                    }
                    //ensure the block that is in the field is the one we reference.
                    //we need to do this because a destroyed block will be removed from the field,
                    //but it will not be removed from our owning nomino.
                    //check if the block in question has another block beneath it or is touching the bottom.
                    int CheckPosX = PosX;
                    int CheckPosY = PosY + 1;
                    if (CheckPosY > field.Contents.Length - 1)
                    {
                        return(true); //this block is supported by the bottom of the stage/field.
                    }
                    else
                    {
                        //retrieve the block beneath this one.
                        NominoBlock belowBlock = field.Contents[CheckPosY][CheckPosX];
                        if (belowBlock != null)
                        {
                            //If the block below is part of the same nomino as the one we are checking, then we must disregard it as supporting this one. A Nomino cannot support itself!
                            if (!Owner.HasBlock(belowBlock))
                            {
                                if (belowBlock is CascadingBlock cb && !RecursionBlocks.Contains(cb))
                                {
                                    if (belowBlock is LineSeriesBlock lsb)
                                    {
                                        if (lsb.Popping)
                                        {
                                            return(false);             //popping LineSeriesBlocks are not considered solid (this might make more sense as a property of the block... IsSolid or something....)
                                        }
                                    }
                                    RecursionBlocks.Add(this);
                                    if (cb.IsSupported(Owner, field, RecursionBlocks))
                                    {
                                        return(true);
                                    }
                                }
                                else if ((belowBlock is CascadingBlock cbx && RecursionBlocks.Contains(cbx)))
                                {
                                    //if recursionblocks contains this, we just skip evaluating it.
                                }
                                else
                                {
                                    //we consider other block types to be solid.
                                    return(true);
                                }
                            }
                        }
                    }
                }
コード例 #27
0
 public Nomino GetGhostDrop(IStateOwner pOwner, Nomino Source, out int dropLength, int CancelProximity = 3)
 {
     return(PlayField.GetGhostDrop(pOwner, Source, out dropLength, CancelProximity));
 }
コード例 #28
0
        private void SetLevelSpeed(Nomino group)
        {
            var Level = (GameHandler.Statistics is TetrisStatistics ts) ? ts.Level : 0;

            group.FallSpeed = Math.Max(1000 - (Level * 100), 50);
        }
コード例 #29
0
        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;
                    }
                }
            }
        }
コード例 #30
0
 public override BlockTypeReturnData GetBlockType(Nomino group, NominoElement element, TetrisField field)
 {
     return(new BlockTypeReturnData(BasicBlockTypes.Basic));
 }