Ejemplo n.º 1
0
 private void RaiseField()
 {
     for (int y = ((int)field_height) - 1; y > 0; y--)
     {
         for (int x = 0; x < 6; x++)
         {
             m_field[x, y] = m_field[x, y - 1];
         }
     }
     for (int x = 0; x < 6; x++)
     {
         m_field[x, 0] = new Block { Colour = m_below_field[x, 1] };
     }
     MakeBelowRow();
     m_cruiser_pos.Y++;
     m_fast_lifting = false;
 }
Ejemplo n.º 2
0
        public void Cycle()
        {
            switch (m_state)
            {
                case GameState.Main:
                    Block theblock;
                    freeze_lift = false;

                    // === 1: Process blocks involved in combos, perform lag timing ===
                    for (int y = 0; y < field_height; y++)
                    {
                        for (int x = 0; x < 6; x++)
                        {
                            theblock = m_field[x, y];

                            switch (theblock.State)
                            {
                                case BlockState.Vanishing:
                                case BlockState.ComboVanishing:
                                    freeze_lift = true;
                                    if (theblock.Parameter > 0) theblock.Parameter--;
                                    else if (theblock.FaceTime == 1)
                                    {
                                        // TODO: Forward an event to draw flashy graphics & sound for a block disappearing.
                                        theblock.FaceTime--;
                                    }
                                    else if (theblock.FaceTime > 0) theblock.FaceTime--;
                                    else if (theblock.InvisTime > 0) theblock.InvisTime--;
                                    else
                                    {
                                        theblock.Colour = BlockColour.Empty;
                                        theblock.State = BlockState.Normal;
                                        if (y < field_height - 1)
                                        {
                                            SetLagColumn(BlockState.ComboLag, x, y + 1, 1);
                                        }
                                    }
                                    break;
                                case BlockState.SwitchLag:
                                    freeze_lift = true;
                                    if (y < 11)
                                    {
                                        Block b3 = m_field[x, y + 1];
                                        if ((b3.State != BlockState.SwitchLag) && (b3.State != BlockState.ComboLag))
                                        {
                                            // A block has been dropped on top of a laggy block. Give it a fresh lag.
                                            // If this falling block was energized from a combo, it stays that way.
                                            SetLagColumn((b3.State == BlockState.ComboFall) ? BlockState.ComboLag : BlockState.SwitchLag, x, y + 1, 0);
                                        }
                                    }
                                    if (theblock.Parameter > 0) theblock.Parameter--;
                                    else
                                    {
                                        theblock.State = BlockState.Normal; // Set to NORMAL instead of Fall to permit ninja chaining to work.
                                    }
                                    break;
                                case BlockState.ComboLag:
                                    freeze_lift = true;
                                    if (y < 11)
                                    {
                                        Block b3 = m_field[x, y + 1];
                                        if ((b3.State != BlockState.SwitchLag) && (b3.State != BlockState.ComboLag))
                                        {
                                            // A block has been dropped on top of a laggy block. Give it a fresh lag.
                                            // If this falling block was energized from a combo, it stays that way.
                                            SetLagColumn((b3.State == BlockState.ComboFall) ? BlockState.ComboLag : BlockState.SwitchLag, x, y + 1, 0);
                                        }
                                    }
                                    if (theblock.Parameter > 0) theblock.Parameter--;
                                    else
                                    {
                                        theblock.State = BlockState.ComboFall;
                                    }
                                    break;
                            }
                            m_field[x, y] = theblock;
                        }
                    }

                    // === 2: Process block falling, switching ===
                    for (int y = 0; y < field_height; y++)
                    {
                        for (int x = 0; x < 6; x++)
                        {
                            theblock = m_field[x, y];

                            switch (theblock.State)
                            {
                                case BlockState.Fall: // If a block is SEEN in this state it has landed. (Otherwise it would have slipped through the cracks)
                                    freeze_lift = true;
                                    if (y > 0) // there is a laggy or switching block further down the stack
                                    {
                                        Block lowblock = m_field[x, y - 1];
                                        if ((lowblock.State == BlockState.SwitchLeft) || (lowblock.State == BlockState.SwitchRight) ||
                                            (lowblock.State == BlockState.SwitchLag) || (lowblock.State == BlockState.ComboLag) ||
                                            (lowblock.State == BlockState.Fall) || (lowblock.State == BlockState.ComboFall))
                                        {
                                            goto case BlockState.Normal;
                                        }
                                    }
                                    theblock.State = BlockState.Normal;
                                    theblock.Parameter = 6; // Bounce
                                    goto case BlockState.Normal;
                                case BlockState.ComboFall:
                                    freeze_lift = true;
                                    if (y > 0) // there is a laggy or switching block further down the stack
                                    {
                                        Block lowblock = m_field[x, y - 1];
                                        if ((lowblock.State == BlockState.SwitchLeft) || (lowblock.State == BlockState.SwitchRight) ||
                                            (lowblock.State == BlockState.SwitchLag) || (lowblock.State == BlockState.ComboLag) ||
                                            (lowblock.State == BlockState.Fall) || (lowblock.State == BlockState.ComboFall))
                                        {
                                            goto case BlockState.Normal;
                                        }
                                    }
                                    theblock.State = BlockState.ComboLanded;
                                    theblock.Parameter = 6; // Bounce
                                    goto case BlockState.Normal;
                                case BlockState.Normal:
                                    if (theblock.Colour == BlockColour.Empty)
                                    {
                                        if (y < field_height - 1)
                                        {
                                            Block highblock = m_field[x, y + 1];
                                            if (((int)(highblock.Colour) > 0) && ((int)(highblock.Colour) < 8))
                                            {
                                                if ((highblock.State == BlockState.Normal) || (highblock.State == BlockState.Fall) || (highblock.State == BlockState.ComboFall))
                                                {
                                                    // A block with space below it: move it down by one.
                                                    freeze_lift = true;
                                                    theblock = highblock;
                                                    if (theblock.State == BlockState.Normal) theblock.State = BlockState.Fall;
                                                    else if (theblock.State == BlockState.ComboLanded) theblock.State = BlockState.ComboFall;
                                                    m_field[x, y + 1] = new Block();
                                                }
                                            }
                                            else if ((highblock.Colour == BlockColour.Garbage) || (highblock.Colour == BlockColour.ShockGarbage))
                                            {
                                                throw new NotImplementedException("Garbage blocks you crazy??");
                                            }
                                        }
                                    }
                                    else if ((int)(theblock.Colour) < 8)
                                    {
                                        if (theblock.Parameter > 0)
                                        {
                                            theblock.Parameter--;
                                        }
                                    }
                                    else
                                    {
                                        throw new NotImplementedException("Garbage blocks you crazy??");
                                    }
                                    break;
                                case BlockState.SwitchLeft:
                                case BlockState.SwitchRight:
                                    if (m_field[x, y + 1].State == BlockState.ComboFall)
                                    {
                                        Block b2 = m_field[x, y + 1];
                                        b2.State = BlockState.ComboLag;
                                        if (m_difficulty < Difficulty.Normal) b2.Parameter = 9;
                                        else if (m_difficulty > Difficulty.Normal) b2.Parameter = 5;
                                        else b2.Parameter = 7;
                                        m_field[x, y + 1] = b2;
                                    }
                                    if (theblock.Parameter > 0)
                                    {
                                        theblock.Parameter--;
                                    }
                                    else
                                    {
                                        Block rightblock = theblock; // RightBlock: Block going TO the right.
                                        theblock = m_field[x + 1, y]; // Has to be safe or stuff has gone horribly wrong.

                                        theblock.State = BlockState.Normal;
                                        rightblock.State = BlockState.Normal;
                                        if (y > 0)
                                        {
                                            // Only lag the block if it's slid to over empty space.
                                            if (m_field[x, y - 1].Colour == BlockColour.Empty)
                                            {
                                                theblock.State = BlockState.SwitchLag;
                                                theblock.Parameter = LagTime();
                                            }
                                            if (m_field[x + 1, y - 1].Colour == BlockColour.Empty)
                                            {
                                                rightblock.State = BlockState.SwitchLag;
                                                rightblock.Parameter = LagTime();
                                            }
                                        }

                                        // Set lag when switching a block out of a column
                                        if (x < 11)
                                        {
                                            if (theblock.Colour == BlockColour.Empty)
                                            {
                                                Block hiblock = m_field[x, y + 1];
                                                hiblock.State = BlockState.SwitchLag;
                                                hiblock.Parameter = LagTime();
                                                m_field[x, y + 1] = hiblock;
                                            }
                                            else if (rightblock.Colour == BlockColour.Empty)
                                            {
                                                Block hiblock = m_field[x + 1, y + 1];
                                                hiblock.State = BlockState.SwitchLag;
                                                hiblock.Parameter = LagTime();
                                                m_field[x + 1, y + 1] = hiblock;
                                            }
                                        }

                                        m_field[x + 1, y] = rightblock;
                                    }
                                    break;
                            }

                            m_field[x, y] = theblock;
                        }
                    }

                    // === 3: Find combos ===

                    bool chain_active = false; // Set true if any blocks energized by combos are on the screen.
                    bool is_chain_combo = false; // Set true if a row of blocks found on this frame are part of a chain.

                    for (int y = 0; y < field_height; y++)
                    {
                        for (int x = 0; x < 6; x++)
                        {
                            theblock = m_field[x, y];
                            Block block1, block2;
                            bool chain_this_try = false;

                            if (((int)(theblock.Colour) > 0) && ((int)(theblock.Colour) < 8))
                            {
                                switch (theblock.State)
                                {
                                    case BlockState.ComboLanded:
                                        chain_this_try = true;
                                        goto case BlockState.Normal;
                                    case BlockState.VanishMarked:
                                    case BlockState.Normal:
                                        // 1. Horizontal check.
                                        if (x < 4)
                                        {
                                            block1 = m_field[x + 1, y];
                                            block2 = m_field[x + 2, y];

                                            if ((block1.Colour == theblock.Colour) &&
                                                (block2.Colour == theblock.Colour) &&
                                                ((block1.State == BlockState.Normal) ||
                                                 (block1.State == BlockState.ComboLanded) ||
                                                 (block1.State == BlockState.VanishMarked)) &&
                                                ((block2.State == BlockState.Normal) ||
                                                 (block2.State == BlockState.ComboLanded) ||
                                                 (block2.State == BlockState.VanishMarked)))
                                            {
                                                if ((block1.State == BlockState.ComboLanded) || (block2.State == BlockState.ComboLanded) || chain_this_try)
                                                {
                                                    is_chain_combo = true;
                                                    chain_active = true;
                                                }

                                                theblock.State = BlockState.VanishMarked;
                                                block1.State = BlockState.VanishMarked;
                                                block2.State = BlockState.VanishMarked;

                                                m_field[x, y] = theblock;
                                                m_field[x + 1, y] = block1;
                                                m_field[x + 2, y] = block2;
                                            }
                                        }
                                        if (y < field_height - 3)
                                        {
                                            block1 = m_field[x, y + 1];
                                            block2 = m_field[x, y + 2];

                                            if ((block1.Colour == theblock.Colour) &&
                                                (block2.Colour == theblock.Colour) &&
                                                ((block1.State == BlockState.Normal) ||
                                                 (block1.State == BlockState.ComboLanded) ||
                                                 (block1.State == BlockState.VanishMarked)) &&
                                                ((block2.State == BlockState.Normal) ||
                                                 (block2.State == BlockState.ComboLanded) ||
                                                 (block2.State == BlockState.VanishMarked)))
                                            {
                                                if ((block1.State == BlockState.ComboLanded) || (block2.State == BlockState.ComboLanded) || chain_this_try)
                                                {
                                                    is_chain_combo = true;
                                                    chain_active = true;
                                                }

                                                theblock.State = BlockState.VanishMarked;
                                                block1.State = BlockState.VanishMarked;
                                                block2.State = BlockState.VanishMarked;

                                                m_field[x, y] = theblock;
                                                m_field[x, y + 1] = block1;
                                                m_field[x, y + 2] = block2;
                                            }
                                        }
                                        break;
                                }
                            }

                            // === 4: Chain keep-alive check ===
                            switch (theblock.State)
                            {
                                case BlockState.ComboFall:
                                case BlockState.ComboLag:
                                case BlockState.ComboVanishing:
                                    chain_active = true;
                                    break;
                                case BlockState.ComboLanded:
                                    theblock.State = BlockState.Normal;
                                    m_field[x, y] = theblock;
                                    break;
                            }
                        }
                    }

                    // === 4: Count blocks involved in the combo on this frame ===
                    uint BlockCount = 0;
                    Point ch_pos = new Point(0, 0);
                    for (int y = 0; y < field_height; y++)
                    {
                        for (int x = 0; x < 6; x++)
                        {
                            if (m_field[x, y].State == BlockState.VanishMarked)
                            {
                                BlockCount++; // Maybe I can do this in the above loop but the logic is stupid

                                // Kind of odd. Picks the rightmost block in the topmost row and declares it the important block for this combo/chain event
                                // Replace with a more authentic approach.
                                ch_pos.X = x;
                                ch_pos.Y = y;
                            }
                        }
                    }

                    uint Delayer = 1;

                    // === 5: Set this frame's combo's blocks to the vanishing state ===
                    for (int y = ((int)field_height) - 1; y >= 0; y--)
                    {
                        for (int x = 0; x < 6; x++)
                        {
                            theblock = m_field[x, y];
                            if (theblock.State == BlockState.VanishMarked)
                            {
                                theblock.State = is_chain_combo ? BlockState.ComboVanishing : BlockState.Vanishing;
                                theblock.Parameter = m_flash_frames;
                                theblock.FaceTime = m_face_frames + Delayer * m_vanish_speed;
                                theblock.InvisTime = (BlockCount - Delayer) * m_vanish_speed;
                                theblock.ComboOrdinal = Delayer;
                                Delayer++;
                            }
                            m_field[x, y] = theblock;
                        }
                    }

                    if (!freeze_lift)
                    {
                        ushort liftold = m_lift_phase;
                        m_lift_phase += m_fast_lifting ? (ushort)4096 : m_lift_speed;
                        if (m_cruiser_pos.Y >= 11) m_cruiser_pos.Y = 10;

                        if (m_lift_phase < liftold)
                        {
                            m_lift_phase = 0;
                            RaiseField();
                        }
                    }

                    if (BlockCount > 3) // Combo event
                    {
                        if (OnCombo != null) OnCombo(this, new PaneponEventArgs(ch_pos, BlockCount));
                    }

                    if (is_chain_combo) // Chain event
                    {
                        m_chain_length++;
                        if (OnChain != null) OnChain(this, new PaneponEventArgs(ch_pos, m_chain_length));
                    }

                    // TODO: Scoring based on BlockCount, m_chain_length, and m_level

                    if (!chain_active) m_chain_length = 1;

                    break;
            }
        }