Self-sufficiency: Build HTML5 Tetris

Source: Internet
Author: User

Time: 2:36

Duration: Two nights + half afternoon

Code: approx. 300 lines

These two days fever, headache skull faint, unexpectedly still can have power to do small game, in fact, this is not my first time to get a Tetris, a few weeks before trying to get a, and then the messy code into the endless Abyss, finally reluctantly put a few days of code a key to delete. This time from the beginning to comb the idea, redesign, the result also just confirms someone's sentence: Sometimes it's easier to start over than fix bugs.

Before the beginning of the text to be wordy, the title of the so-called self-sufficiency, is in no reference to any design ideas on the premise of the development of the game, you may be puzzled, if the reference to excellent ideas, it is not more than the multiplier, of course, reference and not reference are beneficial, I only say not reference to the benefit, After dozens of bug fixes and finally finished a piece of work, I can proudly say to others: "Look, I developed the game!" "Of course, creativity is not my, but this does not affect their own" vanity ", for a classic game to give self-understanding, and will it into the game, it is not an interesting thing, and, back to look at other people's thinking, sometimes will outraged," This I did not think of it? "This problem can be solved", "This design idea is much better than my train of thought!" "It's much better to think about it than to start by looking at other people's ideas, right?"

Good Dalat, the text begins ~

Want to see the effect first, jump to try it!

Tetris, the main game interface should be composed of one block, such as, of course, the finished product inside these grids are not visible, here is only to help understand, the main interface size is 400x500, the size of each brick (grid) is 20x20, each row has 20 bricks, each column has 25 bricks. Related code:

Brickwidth =,    // brick size width = n, height =;  // Canvas width high, 20x25

Referring to the main interface of the grid, it is necessary to mention a very important variable, it is board, a two-dimensional array, it is visualized that its size is 20x26, the stored value is 0 or 1,0 means there is no brick, 1 means that the location has bricks, in the next few judgments have important role, The game of careful classmate may find, why is 20x26, and not corresponding to the main interface grid 20x25, I was set to 20x25 at the beginning, and later notice if Add a row and the value of this line is 1 can easily determine whether the brick to touch the bottom of the main interface. Related code:

// Initialize the board, note that there are 26 longitudinal, the last row is used to determine whether to touch the bottom  for (i=0;i<20;i++) {    = [];      for (j=0;j<26;j++) {        if(j==25) {            = 1        else  {             = 0;}}    }

Next look at the "shape" composed of 4 bricks, there are five kinds, for the sake of description, I put them to name, Tian (Tian), Chu (hoe), Tu (convex), Thunder (Lightning), line (a horizontal), haha interesting name, forgive me not to find their English name it.

First define a brick class brick:

function Brick () {}

There are several prototype variables and methods under it:

Brick.prototype.embattle =NULL;//layout of bricks (reload required)Brick.prototype.isOverturn = 0;//whether to flipBrick.prototype.originX = 9;//the beginning of the drawing of the bricks xBrick.prototype.originY =-3;//the beginning of the drawing of Bricks yBrick.prototype.direction = 0;//Brick facingBrick.prototype.autoMoveTimer =NULL;//Auto-Move timerBrick.prototype.draw =function() { ...... }//How to draw bricksBrick.prototype.move =function(MoveX, Movey) { ...... }//How to moveBrick.prototype.autoMove =function() { ...... }//how to move automaticallyBrick.prototype.change =function() { ...... }//Transform Bricks towards

Brick sub-class has: Tian,chu,tu,thunder,line five, each sub-class is overloaded brick embattle variable, embattle is what, English translation meaning is the array, what is the matrix? First of all, the students should understand my thinking, with Tu embattle For example, the code is as follows:

this. embattle = [    [[0,4,5,8], [1,4,5,6], [1,4,5,9], [0,1,2,5]],  // layout table is a 4x4 table, The number is the position    of the Brick [[0,4,5,8], [1,4,5,6], [1,4,5,9], [0,1,2,5]]   // times the behavior of the flip case ];

Embattle is a three-dimensional array, the first dimension is whether to flip Isoverturn (image is like a horizontal flip of the picture), the second dimension is the direction direction (top left and bottom right), the third dimension is the shape of the 4 bricks distribution, I have each new Shape object defined in a 4x4 array, For example, Tu's this.embattle[0][0] is [0,4,5,8], and the number is where the brick is located, such as:

So to determine the position and appearance of a shape, need to isoverturn determine whether to flip, need to direction determine its direction, need to Originx and originy determine the "array" position.

Next, we explain the 4 prototype methods of brick respectively.

Brick.prototype.draw

 Ctx.fillstyle = ' rgb (' +math.floor (Math.random () *256) + ', ' +math.floor (Math.random () *256) + ', ' +math.floor ( Math.random () *256) + '  for  (I=0;i<4;i++ = this . Isoverturn][this  .direction][i]    ; Ctx.fillrect (( this . originx+tmp%4) *brickwidth, (    this . Originy+math.floor (TMP/4)) *brickwidth, Brickwidth, brickwidth); Ctx.strokerect (this . originx+tmp%4) *brickwidth+1, (   this . Originy+math.floor (TMP/4)) *brickwidth+1, brickWidth-2, brickWidth-2); Note +1 and minus 2} 

There is said to determine the shape of the position and appearance of the method, after the purely canvas drawing, 4 bricks One by one, do not look at the code is very long actually is a little bit, Originx, originy and bricks in the position of the block can be determined to draw the starting point of the brick. Notice the code of the comment No, when the border, it is drawn from the beginning to the outside, like I put a plastic bag outside of another plastic bag, for the convenience of the subsequent removal and do not affect the other bricks, the border painted into the FillRect territory, It's like I'm putting this plastic bag out of the way and putting it in the other plastic bag.

Brick.prototype.move

This is the longest one, when moving, Movex and Movey represent the vertical increment, not at the same time not 0 (this is a man-made setting, either sideways or vertically moving), of course, to determine whether the location to be moved is violated:

Transverse:

If the array is on the left side of the main interface, you cannot move to the left Movex cannot be-1

(This.originx==0 && Movex==-1)

Judgment on the right is more troublesome, because you can not directly use the array to determine whether to stick to the right side (see the front of the picture to know that the right side of the array and the bottom may not have bricks), this time to determine whether 4 bricks have at least one at the right, then cannot move to the right

|| (this. originx+tmp[0]%4==19 && movex==1)| | (this. originx+tmp[1]%4==19 && movex==1)| | (this. originx+tmp[2]%4==19 && movex==1)| | (this. originx+tmp[3]%4==19 && movex==1)

Finally, it is necessary to determine whether there are already bricks in the near position.

|| (board[this. originx+tmp[0]%4+movex][this. Originy+math.floor (TMP[0]/4)]==1) | | (board[this. originx+tmp[1]%4+movex][this. Originy+math.floor (TMP[1]/4)]==1) | | (board[this. originx+tmp[2]%4+movex][this. Originy+math.floor (TMP[2]/4)]==1) | | (board[this. originx+tmp[3]%4+movex][Originy+math.floor (TMP[3]/4)]==1)

Longitudinal:

Will arrive at the location is already has the brick, notice the following code of && Movex==0, the original is not, and later found every time the bricks are just piled up under the bricks can no longer move, the original transverse movement when also carried out this judgment, that just on the bottom of the bricks, If you want to move around at this time, but there are bricks underneath, but the problem comes, there is no brick and I move around what is the relationship? Right.

if ((as==1 | | bs==1 | | cs==1 | | ds==1) && movex==0) { ...... }

Vertical termination of judgment inside the main do a few things: clear Automovetimer, set board in the shape of the current position of the value of 1, there can be eliminated the whole line to eliminate , add points to change, Judge Victory/failure, delete the current object, summon the next shape.

When there is no violation of the horizontal vertical:

At this point, the shape of the previous position of the bricks clear, update Originx and Originy, and then draw out.

 for (i=0;i<4;i++) {    this. embattle[the. isoverturn][this.direction][i ];    Ctx.clearrect (originx+tmp%4) *brickwidth, (this. Originy+math.floor(TMP/4)) * Brickwidth, Brickwidth, brickwidth); }this. Originx + = MoveX; this. Originy + = Movey; this. Draw ();

Brick.prototype.autoMove

Just do one thing, set the timer, and move it down regularly.

var  This ; this. Automovetimer = SetInterval (function() {    = self.move (0,1);},speed);

Brick.prototype.change

Change the direction of the shape, very good, do not have embattle array it? Of course it's not that simple, it's not just a change of the number group. To consider whether the position occupied after changing direction is already a brick, if the shape is affixed to the right edge of the main interface is even worse, such as the original is vertical line, change its direction into a horizontal, occupy the array of 0, 1, 2, 3, if the line is affixed to the right edge, Originx 19, into the horizontal, occupy the array of 0 1, 2, 3, after three bricks have overflowed the main interface.

The solution is: if you have a brick that crosses the border, move the array to the left until you stop crossing the border.

 while (Ox+tmp[0]%4 > | | ox+tmp[1]%4 > | | ox+tmp[2]%4 > + | | ox+tmp[3]%4 >) {    -= 1;}

Finally, if it's all right, you can clear the original position and draw the shape after changing direction.

is not too perfect, because some of the card position is not considered in the situation, what is the card bit, see, you know the line instance calls the change method of the result is what? In fact, it should not be a successful change of direction, right? There are some other card-bit situations.

Brick's 4 prototype methods are introduced here. Now if I want to display the next shape in the information interface on the right, the most straightforward way is to instantiate an object with the constructor of the shape, to prevent it from automatically calling Automove, and to add Ismodel to the constructor to determine if it is intended to be used for prompting.

There are key event monitoring, Nextbrick functions and deleteobj see for yourself, it is easy to understand that the entrance to the game is the Nextbrick function.

Also, I'm not sure if Deleteobj really succeeded in getting the GC to recycle the object.

What's more, I wanted to add the level function because I was free to set the speed variable and put the function on.

Other:

Online Demo: http://xzh-loop.github.io/Manji/lab/html5game/20141114-tetris.html

Visit the GitHub location for this project: Https://github.com/xzh-loop/Manji/tree/gh-pages/lab/html5game

Visit my GitHub pages:http://xzh-loop.github.io/

-----------------------------------------------

You may be interested in: Build your own HTML5 Star Trek

Self-sufficiency: Build HTML5 Tetris

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.