Making Tetris game with electron

Time:2020-11-28

background

In tossing ES6, I suddenly remembered that I wrote Tetris in C language when I was in college. In this project, I mainly used the class feature of ES6 for object-oriented programming. Project adoption node.js V6.2.0 + electronic V1.1.0 can run across all platforms.

thinking

  • Full application of the object-oriented design idea makes the function cohesive.

  • Think of the seven squares as separate “biological” objects, allowing them to “see” the world around them.

  • Instead of using the traditional large two-dimensional array to represent the state of the game scene, Tetris is allowed to “see” itself.

  • Using HTML 5 canvas to complete, more like CGI programming.

  • Using the least canvas feature, we only use fillRect, strokerect, getimagedata, clearrect and other functions.

design sketch

The highest record I played^_^

Making Tetris game with electron

Operation method

Project adoption node.js For desktop development with v6.2.0 + electronic V1.1.0, please install the relevant system first:

npm install electron-prebuilt -g

Note: the scheme adopted in this project can run across all platforms. In case of permission problem, please add sudo on the command line.

Source code:

git clone https://git.oschina.net/zhoutk/Tetris.git

Or:

git clone https://github.com/zhoutk/Tetris

Enter project directory:

cd Tetris

Operation procedure:

electron .

Critical code analysis

The functions are as cohesive as possible. The class block encapsulates all the operations of small blocks, and the canvas interface function is basically encapsulated in this class; the Tetris class combines block and encapsulates most of the operations of Tetris.

Block class (small block class)

class Block{
    constructor(ctx,fillColor,strokeColor){
        this.ctx  =CTX; // Canvas object
        this.width  =Blockwidth; // side length of small square
        this.fillColor  =Fillcolor |'Blue '; // direct color
        this.strokeColor  =Strokecolor |'white '; // stroke color
    }
    Draw (x, y) {// draw block
        this.ctx.save();
        this.ctx.fillStyle = this.fillColor;
        this.ctx.fillRect(x*this.width + 1,y*this.width + 1,this.width-2,this.width-2)
        this.ctx.strokeStyle = this.strokeColor;
        this.ctx.strokeRect(x*this.width + 1,y*this.width + 1,this.width-2,this.width-2);
        this.ctx.restore();
    }
    Erase (x, y) {// erase small square
        this.ctx.clearRect(x*this.width , y*this.width , 30, 30)
    }
    Cansee (x, y) {// check if a location is empty
        let c = this.ctx.getImageData(x*this.width+9,y*this.width+9,1,1)
        return c.data[0] | c.data[1] | c.data[2] | c.data[3];
    }
    Getcolor (x, y) {// takes the color at a certain position
        let c = this.ctx.getImageData(x*this.width+9,y*this.width+9,1,1)
        return 'rgba('+c.data[0]+','+c.data[1]+','+c.data[2]+','+c.data[3]+')';
    }
}

Tetris class (Tetris class)

class Tetris {
    constructor(shape,ctx,x,y){
        this.data  =[[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]]; // block shape data
        this.shape  =Shape | 0; // block shape code
        this.ctx  =CTX; // Canvas object
        This. X = x | 0; // block position data
        this.y =  y || 0;
        this.block  =New block (CTX, colors [shape]); // combines block objects

        for(let i = 0; i < SHAPES[ this.shape ]. length; I + +) {// square shape initialization 
            if(SHAPES[this.shape][i]){
                this.data[i % 4][1 + Math.floor(i/4)] = 1;
            }
        }
    }
    Clean up () {...} // eliminate the layer, score
    Movenext() {...} // move the square down one space
    Moveleft() {...} // move the square one space to the left
    Moveright() {...} // move the square to the right one space
    Movedown() {...} // the square moves to the end
    Rotate() {...} // square rotation
    Candrawnext() {...} // check whether the new square can be placed or not, and detect the end of the game
    Draw() {...} // call the block object to draw Tetris
    Erase() {...} // call the block object to erase the Tetris
    Cansee {...} // calls the block object to detect the placement of Tetris

Block.canSee

Select the color attribute of the pixel to simulate the “vision” of the box.

canSee(x,y){
        let c = this.ctx.getImageData(x*this.width+9,y*this.width+9,1,1)
        Return c.data [0] | c.data [1] | c.data [2] | c.data [3]; // black is all zero. When XOR is 0, the position is empty, and others indicate that the position has been occupied.
    }

Tetris.cleanup

It is complicated to eliminate the formation, so it should be noted.

cleanup(){
        Let H = 19, levelcount = 0; // eliminate the level statistical variables at one time
        While (H > = 0) {// from the bottom to the top
            Let count = 0; // record the number of positions above the same level
            For (let I = 0; I < 10; I + +) {// traverse one layer
                If ( this.canSee (I, H)) {// position is empty, variable plus one
                    count++;
                }
            } 
            If (count = = 0) {// the layer is full and needs to be eliminated
                Let level = h; // layer to be eliminated
                Levelcount + +; // add one to the number of elimination layers
                SOUNDS['score'].play();
                While (level > = 0) {// move all layers above the layer to be eliminated one layer down as a whole
                    Let CT = 0; // record the number of positions above the same level
                    for(let j = 0; j < 10; j++){
                        this.block.erase (J, level); // clear the grid of the layer to be eliminated
                        If ( this.canSee (J, level-1)) {// null location statistics
                            ct++;
                        }else{
                            Let BK = new // take the color block of the upper vertical grid( this.ctx , this.block.getColor (j,level-1)) 
                            bk.draw (J, level) // move down
                        }
                    }
                    If (CT = = 10) {// the first floor is empty, and the whole move down is completed ahead of time.
                        break;
                    }else{
                        Level --; // floor up
                    }
                }
            }Else if (count = = 10) {// the first floor is empty, and the layer elimination is completed ahead of time.
                break;
            }else{
                h--;
            }
        }
        return levelCount;
    }

Tetris.moveNext

It’s more complicated to move the box down one level, with comments.

moveNext(){
        Let flag = true; // variable set for jumping out of double loop
        For (let I = 0; I < 4; I + +) {// check whether it can be moved down
            for(let j = 0; j < 4; j++){
                if(this.data[i][j] && (j ==3 || this.data[i][j+1] == 0)){
                    if(!this.canSee(this.x + i, this.y + 1 + j)){
                        Flag = false; // it's finished
                        break;
                    }
                }
            }
            if(!flag){
                break;
            }
        }
        If (flag) {// move down
            this.erase();
            this.y++;
            this.draw();
            return true;
        }Else {// final processing
            let level =  this.cleanup (); // layer elimination
            If (level > 0) {// the number of elimination layers is greater than zero
                Levels + = level; // scoring
                scores += LVSCS[level]
                document.getElementById('levelShow').value = levels;
                document.getElementById('scoreShow').value = scores;
                If ( Math.floor (scores / stepval)! = step) {// speed adjustment level
                    clearInterval(interval)
                    interval = setInterval( tick, TICKVAL - ++STEP * STEPVAL );
                    document.getElementById('speedShow').value = STEP + 1;
                }
            }else{
                SOUNDS['down'].play()
            }
            return false;
        }
    }

Operation and rules

  • Up key: rotate

  • Direction left key: move left

  • Right click: move right

  • Direction down key: move down

  • Space bar: move down to the bottom

  • Scoring: 1 point for the first floor, 3 points for the second floor, 3 points for the third floor and 10% for the fourth floor

  • The speed is divided into ten levels, and the difference of each level is 50ms

Summary

The project is now in v1.0.0 version, complete all the basic functions of Tetris game, with sound effects. In the future, I will consider network war, man-machine war and machine self war. I mainly want to do artificial intelligence experiments, from let the algorithm play Tetris!

Recommended Today

Configuring Maven with IntelliJ idea (getting started)

First of all, I declare that this article is not original by eamonsec. I don’t know where it came from now. Maybe the person I transferred is not original… 1. Download maven Official address:http://maven.apache.org/download.cgi Unzip and create a new local warehouse folder 2. Configure the local warehouse path   3. Configure Maven environment variables      4. Configure […]