Thread: Need help with rotation in Tetris game

  1. #16
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Hmm I went to look up z-spins but the google results suggested you must have meant t-spins. Watching a video of one t-spin just looked downright wrong to me. The piece appears to go down by two rows upon rotation where no valid orientation could have allowed it to sit in the rows between. I would certainly not allow that.

    This should help, most of the proper rules for tetris titles are listed here:
    Tetris Guideline - Tetris Wiki
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  2. #17
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I went to look up z-spins but the google results suggested you must have meant t-spins.
    They are largely related, but they are not the same thing because the pieces involved behave differently in different situations. (The technique is named after the piece so you have "z spin", "s spin", and "t spin".)

    The "z spin" in the earliest incarnation was actually a coding error allowing only the "z" shaped piece to spin "through" a one block hole if the piece could have otherwise fit in the lines beneath that hole. (It required extremely precise timing.) The error became legend which became a commonly implemented extension in "Tetris" clones and official "Tetris" games. I think, but I'm not positive, that every official "Tetris" game has offered it intentionally in at least some modes.

    Watching a video of one t-spin just looked downright wrong to me.
    Yep. That's a "t spin" alright.

    When the timing is "loose" it is largely just a "funsies" thing. The vast majority of "Tetris" clones that implement the technique (intentionally) make it unavailable in certain modes. One of the best puzzle based versions, a Java game if I recall, forced players to spin through fixed (blocks that can't be destroyed) layers to clear off every line with one piece.)

    When the timing is "tight" it becomes experience based making it a useful feature in challenge or competitive modes. This is, of course, mostly limited to intentional implementations because lines cleared with complicated spinning get you a lot more points. (The points awarded for spinning multiple pieces into place over consecutive lines clears is usually worth more than a tetris clear.)

    I would certainly not allow that.
    Yet the vast majority of "Tetris" clones do and have done for over a decade.

    This is a lot like the other technique called "spinning". (It has been called other things; I call it this because it is what I've always called it.) The other "spinning" technique is where a lot of "Tetris" clones allow a piece to spin forever (always moveable never becoming fixed) as a way to counteract the essentially instantaneous drop at higher speeds. That "spinning" technique offered a way to solve the original games problem (At higher speeds it was impossible to move the piece to the edges of the play field.) without unnecessarily limited the fall speed. When this "spinning" technique is poorly implemented it decreases the difficulty of the game to absurdly low levels making it really not a fun a game to play.

    most of the proper rules for tetris titles are listed here
    That is a good website.

    It should be noted that the website suggests, as most "Tetris" clones do in any event, allowing, recognizing, and rewarding players for "t spin" moves.

    So, whether you allow it or not, some variation of the "? spin" moves are extremely common and if going to be supported should be considered from the start.

    Soma

  3. #18
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_O

    I clicked on this thread (instead of the original posters name) by accident and got a delightfully frightful rush of "déjà vu".

    Have we discussed "Tetris" before on some other forum?

    Soma

  4. #19
    Registered User
    Join Date
    Feb 2012
    Posts
    26
    Here is what I am currently trying to do:
    rotation in shape class:
    Code:
    void Shape::rot(int x , int y)
    {
        int xp, yp;
    
        xp=x-y+y; //x-y is pivot points
        yp=x+y-x; //x+y is pivot points
    
    }
    I do not know how to call this function if it works?

    I also thuoght about making 4 different versions of each shape, but didn't know how to rotate between the 4 of them?


    Code:
    //Dark GDK - The Game Creators - www.thegamecreators.com
    
    //the wizard has created a very simple project that uses Dark GDK
    //it contains the basic code for a GDK application
    
    //whenever using Dark GDK you must ensure you include the header file
    #include "DarkGDK.h"
    
    
    //Global
    int Block_Size=20; 
    int grid[20][10];
    //colors
    const DWORD Red = dbRGB(255,0,0);
    const DWORD Green = dbRGB(0,255,0);
    const DWORD Blue = dbRGB(0,0,255);
    const DWORD Magenta = dbRGB(255,0,255);
    const DWORD Black = dbRGB(0,0,0);
    const DWORD White = dbRGB(255,255,255);
    const DWORD Yellow = dbRGB(255,255,0);
    const DWORD Cyan = dbRGB(0,255,255);
    const DWORD Orange = dbRGB(255,165,0);
    const DWORD Grey = dbRGB(177,177,177);
    //end colors
    //end global
    
    //Classes
    
    class Block {
    private:
        DWORD color;
        //int blocks[4];
    public:
        int x,y;
        Block();
        Block(int, int, DWORD);
        void draw();
        void move(int, int);
        void clear();
        //bool col();
    
    };
    Block::Block(){
    x = 0;
    y =0;
    color = White;
    }
    //Methods (Block)
    
    Block::Block(int X, int Y, DWORD COLOR)
    {
        x=X;
        y=Y;
        color=COLOR;
    }
    
    void Block::draw()
    {
        int x1, y1, x2, y2;
        x1=x*Block_Size;
        y1=y*Block_Size;
        x2=x1+Block_Size;
        y2=y1+Block_Size;
    
    //    dbInk(color, Black);
        dbBox(x1,y1,x2,y2);
    }
    
    void Block::clear()
    {
    
        dbInk(Black, Black);
        //dbBox(x1,y1,x2,y2);
        draw();
    }
    
    void Block::move(int dx, int dy)
    {
        x=x+dx;
        y=y+dy;
        dbInk(color, Black);
        draw();
    }
    
    //End Method (Block)
    
    class Shape {
    
    private:
        Block blocks[4];
        //int pos[8];
    public:
        int pos[8];
        DWORD color;
        Shape();
        void make_ishape();
        void make_oshape();
        void make_jshape();
        void make_lshape();
        void make_tshape();
        void make_zshape();
        void make_sshape();
        void move_shape(int,int);
        void draw_shape();
        bool col(int,int);
        //void rotate_zshape();
        void rot(int,int);
        
    };
    //Methods (Shape)
    Shape::Shape() {
    blocks[0] = Block(0,0, White);
    blocks[1] = Block(0,0, White);
    blocks[2] = Block(0,0, White);
    blocks[3] = Block(0,0, White);
    }
    bool Shape::col(int dx, int dy)
    {
        for (int i=0; i<=4; i++)
        {
            if (blocks[i].y + dy > 19 || blocks[i].x + dx < 0 || blocks[i].x +dx > 9)
            {
                return false;
            }
            
        }
        return true;
    }
    
    
    void Shape::rot(int x , int y)
    {
        int xp, yp;
    
        xp=x-y+y;
        yp=x+y-x;
    
    }
    void Shape::make_ishape()
    {
        blocks[0] = Block(pos[0],pos[1],Blue);
        blocks[1] = Block(pos[2],pos[3],Blue);
        blocks[2] = Block(pos[4],pos[5],Blue);
        blocks[3] = Block(pos[6],pos[7],Blue);
        
    }
    void Shape::make_oshape()
    {
        blocks[0] = Block(pos[0],pos[1],Green);
        blocks[1] = Block(pos[2],pos[3],Green);
        blocks[2] = Block(pos[4],pos[5],Green);
        blocks[3] = Block(pos[6],pos[7],Green);
        
    }
    void Shape::make_jshape()
    {
        blocks[0] = Block(pos[0],pos[1],Yellow);
        blocks[1] = Block(pos[2],pos[3],Yellow);
        blocks[2] = Block(pos[4],pos[5],Yellow);
        blocks[3] = Block(pos[6],pos[7],Yellow);
        
    }
    void Shape::make_lshape()
    {
        blocks[0] = Block(pos[0],pos[1],Orange);
        blocks[1] = Block(pos[2],pos[3],Orange);
        blocks[2] = Block(pos[4],pos[5],Orange);
        blocks[3] = Block(pos[6],pos[7],Orange);
        
    }
    void Shape::make_tshape()
    {
        blocks[0] = Block(pos[0],pos[1],Cyan);
        blocks[1] = Block(pos[2],pos[3],Cyan);
        blocks[2] = Block(pos[4],pos[5],Cyan);
        blocks[3] = Block(pos[6],pos[7],Cyan);
        
    }
    void Shape::make_zshape()
    {
        blocks[0] = Block(pos[0],pos[1],Red);
        blocks[1] = Block(pos[2],pos[3],Red);
        blocks[2] = Block(pos[4],pos[5],Red);
        blocks[3] = Block(pos[6],pos[7],Red);
        
    }
    /*/void Shape::rotate_zshape()
    {
        blocks[0] = Block(pos[0],pos[1],Red);
        blocks[1] = Block(pos[2],pos[3],Red);
        blocks[2] = Block(pos[4],pos[5],Red);
        blocks[3] = Block(pos[6],pos[7],Red);
    }
        /*/
    void Shape::make_sshape()
    {
        blocks[0] = Block(pos[0],pos[1],Magenta);
        blocks[1] = Block(pos[2],pos[3],Magenta);
        blocks[2] = Block(pos[4],pos[5],Magenta);
        blocks[3] = Block(pos[6],pos[7],Magenta);
        
    }
    void Shape::draw_shape()
    {
        for (int i=0; i<4; i++)
        {
            blocks[i].draw();
        }
    }
    
    void Shape::move_shape(int dx, int dy)
    {
        for (int i=0; i<4; i++)
        {
            blocks[i].clear();
        }
        for (int i=0; i<4; i++)
        {
            blocks[i].move(dx,dy);
        }
    }
    
    
    class I_Shape: public Shape{
    public:
        I_Shape(int,int);
        
    private:
        DWORD color;
        //int pos[8];
    };
    
    //Methods (I_Shape)
    
    
    I_Shape::I_Shape(int x, int y):Shape()
    {
    
        color=Blue;
        pos[0]=x-1;
        pos[1]=y;
        pos[2]=x;
        pos[3]=y;
        pos[4]=x+1;
        pos[5]=y;
        pos[6]=x+2;
        pos[7]=y;
        make_ishape(); //makes I_Shape
    }
    
    
    class O_Shape: public Shape{
    public:
        O_Shape(int,int);
    private:
        DWORD color;
    };
    O_Shape::O_Shape(int x, int y):Shape()
    {
        color=Red;
        pos[0]=x;
        pos[1]=y;
        pos[2]=x;
        pos[3]=y-1;
        pos[4]=x+1;
        pos[5]=y-1;
        pos[6]=x+1;
        pos[7]=y;
        make_oshape(); //makes O_Shape
    }
    
    class J_Shape: public Shape{
    public:
        J_Shape(int,int);
    private:
        DWORD color;
    };
    J_Shape::J_Shape(int x, int y):Shape()
    {
        color=Yellow;
        pos[0]=x-1;
        pos[1]=y;
        pos[2]=x;
        pos[3]=y;
        pos[4]=x+1;
        pos[5]=y;
        pos[6]=x+1;
        pos[7]=y-1;
        make_jshape(); //makes I_Shape
    }
    
    class L_Shape: public Shape{
    public:
        L_Shape(int,int);
    private:
        DWORD color;
    };
    L_Shape::L_Shape(int x, int y):Shape()
    {
        color=Orange;
        pos[0]=x+1;
        pos[1]=y;
        pos[2]=x;
        pos[3]=y;
        pos[4]=x-1;
        pos[5]=y;
        pos[6]=x-1;
        pos[7]=y-1;
        make_lshape(); //makes L_Shape
    }
    
    class T_Shape: public Shape{
    public:
        T_Shape(int,int);
    private:
        DWORD color;
    };
    T_Shape::T_Shape(int x, int y):Shape()
    {
        color=Cyan;
        pos[0]=x-1;
        pos[1]=y;
        pos[2]=x;
        pos[3]=y;
        pos[4]=x;
        pos[5]=y-1;
        pos[6]=x+1;
        pos[7]=y;
        make_tshape(); //makes T_Shape
    }
    
    class Z_Shape: public Shape{
    public:
        Z_Shape(int,int);
        //Rotate_Z(int,int);
    private:
        DWORD color;
    };
    Z_Shape::Z_Shape(int x, int y):Shape()
    {
        color=Red;
        pos[0]=x-1;
        pos[1]=y;
        pos[2]=x;
        pos[3]=y;
        pos[4]=x;
        pos[5]=y+1;
        pos[6]=x+1;
        pos[7]=y+1;
        make_zshape(); //makes Z_Shape
        
    }
    /*/class Rotate_Z: public Shape{
    public:
        Rotate_Z(int, int);
    private:
        DWORD color;
    };
    
    Rotate_Z::Rotate_Z(int x, int y):Shape()
    {
        color=Red;
        pos[0]=x;
        pos[1]=y+1;
        pos[2]=x;
        pos[3]=y;
        pos[4]=x+1;
        pos[5]=y;
        pos[6]=x+1;
        pos[7]=y-1;
        rotate_zshape();
    
    }/*/
    /*/class S_Shape: public Shape{
    public:
        S_Shape(int,int);
    private:
        DWORD color;
    };
    S_Shape::S_Shape(int x, int y):Shape()
    {
        color=Magenta;
        pos[0]=x-1;
        pos[1]=y;
        pos[2]=x;
        pos[3]=y;
        pos[4]=x;
        pos[5]=y+1;
        pos[6]=x-1;
        pos[7]=y+1;
        make_sshape(); //makes S_Shape
    }/*/
    
    // the main entry point for the application is this function 
    //(MAIN)
    void DarkGDK ( void )
    {
        dbInk(White,Black);
        dbBox(0,0,200,400);
        
        //I_Shape First(3,1);
        //O_Shape First(3,1);
        //J_Shape First(3,1);
        //L_Shape First(3,1);
        //T_Shape First(3,1);
        Z_Shape First(3,1);
        
        // turn on sync rate and set maximum rate to 1 fps
        dbSyncOn   ( );
        dbSyncRate (2);
        First.draw_shape();
        //First.move_shape(5,4);
        
    
        // our main loop
        while ( LoopGDK ( ) )
        { 
            
            
                if (dbLeftKey())
                {
                    if (First.col(-1,0))
                    {    
                    First.move_shape(-1,0);
                    }
                }
                if (dbRightKey())
                {
                    if (First.col(1,0))
                    {
                    First.move_shape(1,0);
                    }
                }    
    
            
                if (dbDownKey())
                {
                    if (First.col(0,1))
                    {
                    First.move_shape(0,1);        
                    }
                }
            // update the screen
            dbSync ( );
            dbWaitKey();
        }
        
        
        // return back to windows
        return;
    }

  5. #20
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Your Shape::col function is a good example of a function that uses the return value. However, as you may have noticed, the return value can only be one thing. So you can either return a struct that contains the x & y, or you can pass in some parameters by reference and set them inside the method (in other words, using out parameters).
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #21
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Why are you creating classes for each piece? Classes should be about behaviors not roles. All Tetris pieces can be represented by one simple class.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with movement in tetris c++ game
    By Dylan Metz in forum C++ Programming
    Replies: 8
    Last Post: 05-23-2012, 09:56 AM
  2. problem with tetris game...
    By Sokay in forum C Programming
    Replies: 4
    Last Post: 10-11-2009, 03:16 AM
  3. Tetris game
    By Da-Nuka in forum Game Programming
    Replies: 1
    Last Post: 01-16-2005, 09:27 AM
  4. My tetris game 2.0
    By PJYelton in forum Game Programming
    Replies: 12
    Last Post: 04-25-2003, 03:40 AM
  5. tetris game
    By mrt in forum Game Programming
    Replies: 2
    Last Post: 04-08-2002, 10:01 AM

Tags for this Thread