Self-sufficiency: Create html5 Tetris and html5 Tetris

Source: Internet
Author: User

Self-sufficiency: Create html5 Tetris and html5 Tetris

Time:

Duration: Two And A Half afternoons

Code: about 300 lines

These two days I had a fever and a headache, but I did not expect to have the motivation to play games. In fact, this is not the first time I want to get a Russian square, several weeks ago, I tried to get one, and the messy code was brought into the endless abyss. Finally, I reluctantly deleted the code for a few days with one click. This time, we reviewed our ideas and re-designed them. The results also confirmed someone's sentence: sometimes re-starting is easier than fixing bugs.

Before the beginning of the text, I have to worry about the self-sufficiency in the title. You may be puzzled to develop this game without referring to any design ideas. If you refer to the excellent ideas, it doesn't mean to get twice the result with half the effort. Of course, both reference and non-reference are advantageous. I only want to say that I don't have reference advantages. When I have worked so hard and finally completed a piece of work after dozens of BUG modifications, I can proudly say to others: "Look, my game!" Of course, creativity is not mine, but it does not affect my "vanity". It gives a classic game a self-understanding and integrates it into the game, it's not an interesting thing. Besides, when I look back and look at other people's ideas, I sometimes make a case. "Why didn't I think of it at the beginning? ", "This problem can be solved in this way." "This design idea is much better than mine !", It is better to block your own thinking than to directly look at others' ideas at the beginning, right?

Okay. The text starts ~

If you want to see the results first, jump to the trial!

Tetris, the main game interface should be composed of one square, such as, of course, these grids in the finished product cannot be seen, here only helps to understand, the main interface size is 400 × 500, set the size of each brick (GRID) to 20*20. Each row has 20 bricks and each column has 25 bricks.Related code:

BrickWidth = 20, // brick size width = 400, height = 500; // canvas width and height, 20X25

When it comes to the mesh of the main interface, we need to mention a very important variable. It is a BOARD, a two-dimensional array, which is visually 20 × 26 in size, if the storage value is 0 or, it indicates that there are no bricks in the position. If the value is 1, it indicates that there are bricks in the position, which plays an important role in the following judgment. Careful players may find that, why is it 20 × 26, instead of 20 × 25 corresponding to the mesh of the main interface? I set it to 20 × 25 at the beginning, later I noticed that if a line is added and the value of this line is 1, it is easy to judge whether the brick is hitting the bottom of the main interface.Related code:

// Initialize the BOARD. Note that there are 26 vertical lines. The last row is used to determine whether the bottoming is for (I = 0; I <20; I ++) {BOARD [I] = []; for (j = 0; j <26; j ++) {if (j = 25) {BOARD [I] [j] = 1} else {BOARD [I] [j] = 0 ;}}}

Next we will look at the "shape" composed of four bricks. There are five types. For better description, I will name them separately. Tian, Chu ), tu (highlighted), Thunder (lightning), Line (landscape), haha interesting names. Forgive me for not finding their English names.

First define a Brick:

function Brick() { }

There are several prototype variables and methods:

Brick. prototype. embattle = null; // Brick layout (reload required) Brick. prototype. isOverturn = 0; // whether to flip Brick. prototype. origick = 9; // The starting point for drawing bricks. XBrick. prototype. originY =-3; // The starting point for drawing bricks. prototype. direction = 0; // Brick orientation Brick. prototype. autoMoveTimer = null; // automatically moves the timer Brick. prototype. draw = function (){...... } // Method for creating bricks Brick. prototype. move = function (moveX, moveY ){...... } // Method for moving Brick. prototype. autoMove = function (){...... } // Method for Automatic Movement Brick. prototype. change = function (){...... } // Change the brick Orientation

Brick has five sub-classes: Tian, Chu, Tu, Thunder, and Line. Each sub-class contains the embattle variable of Brick. What is embattle, what is this array? First, the students should understand my ideas and use Tu's embattle as an example. The Code is as follows:

This. embattle = [[[,], [,], [,], [,], // The layout table is 4x4, the number indicates the position of a brick [[0, 4, 5, 8], [, 5, 6], [,], [,], and the behavior is flipped].

Embattle is a three-dimensional array. The first dimension is whether to flip the isOverturn (the image is like the horizontal flip of the image), and the second dimension is the direction (top left bottom right ), the third dimension is the distribution of four bricks in the shape. I define each new shape object in a 4 × 4 array, for example, this of the Tu. embattle [0] [0] is [0, 4, 5, 8]. The number indicates the position of the brick, for example:

Therefore, to determine the position and appearance of a shape, isOverturn is required to determine whether to flip, and direction is required to determine its direction. originX and originY are required to determine the position of the "array.

Next, explain the Four prototype methods of Brick.

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 ++) {tmp = this. embattle [this. isOverturn] [this. direction] [I]; ctx. fillRect (this. origwidth + 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 subtract 2}

There is the method for determining the shape position and appearance mentioned above, followed by drawing purely canvas, with four bricks painted one by one. Don't look at the code as long as it is actually a little bit, originX, originY and the position of the bricks in the array can determine the start point of the bricks. I noticed that the Code has not been commented out. When I draw a border, it is drawn from the starting point, just as I put a plastic bag outside another plastic bag, in order to facilitate the removal in the future without affecting other bricks, draw the border into the territory of fillRect, just as I put this plastic bag outside but into another plastic bag, that's what it means.

Brick. prototype. move

This is the longest one. When moving, moveX and moveY indicate the horizontal and vertical increments, but not both 0 (this is a manual setting, either horizontal or vertical movement ), of course, it is necessary to determine whether the location to be moved is illegal:

Horizontal:

If the array is attached to the left of the main interface, it cannot be moved to the left, that is, moveX cannot be-1.

(This. originX = 0 & moveX =-1)

It is troublesome to judge the right side, because you cannot directly use the array to determine whether to stick it to the right side (you can see from the previous figure that there may be no bricks on the right and bottom of the array ), in this case, it is necessary to determine whether at least one of the four bricks is at the rightmost. At this time, the right cannot be moved.

|| (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, determine whether there are bricks in the coming 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][this.originY+Math.floor(tmp[3]/4)]==1)

Vertical:

Check whether there are bricks in the coming position. Note that & moveX = 0 in the following code, later, I found that every time the bricks have just been stacked on the bottom, they can no longer be moved. This was also made when they moved horizontally, that is, they just rely on the upper and lower bricks, if you want to move the left and right sides, but there are bricks below, but the problem arises. Is there any relationship between the bricks below and the movement between the left and right sides? Right.

if((as==1 || bs==1 || cs==1 || ds==1) && moveX==0) { …… }

The vertical termination judgment mainly involves several things: Clear autoMoveTimer, set the value of the current position of the BOARD in this shape to 1, eliminate the whole line that can be eliminated, and add points to change points, determine victory/failure, delete the current object, and summon the next shape.

When there are no violations:

In this case, clear the bricks in the previous position of the shape, update originX and originY, and draw the bricks.

for(i=0;i<4;i++) {    tmp = this.embattle[this.isOverturn][this.direction][i];    ctx.clearRect((this.originX+tmp%4)*brickWidth, (this.originY+Math.floor(tmp/4))*brickWidth, brickWidth, brickWidth);}this.originX += moveX;this.originY += moveY;this.draw();

Brick. prototype. autoMove

Only do one thing. Set the timer and regularly move down.

var status, self = this;this.autoMoveTimer = setInterval(function() {    status = self.move(0,1);},speed);

Brick. prototype. change

It's easy to change the orientation of the shape. Isn't there an embattle array? Of course it is not that simple, not just an array. Consider whether there are bricks in the position occupied after changing the direction. If the shape is close to the right boundary of the main interface, it is even worse. For example, if the Line is originally a vertical Line, it is changed to a horizontal direction, occupies the array 0, 1, 2, and 3. If Line is attached to the right boundary, originX is 19 and changes to transverse. occupies the array 0, 1, 2, and 3, the next three bricks have overflows the main interface.

Solution: if there is a cross-border brick, move it to the left until it does not cross the border.

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

Finally, if everything is okay, you can clear the original position and draw the shape after changing the direction.

It's not perfect, because some card locations are not taken into account. What is a card location? Do you know what the result of the Line instance calling the change method is? In fact, it should not change its direction successfully, right? There are other card locations.

Here are the four prototype methods of Brick. Now, if I want to display the next shape on the information interface on the right, the most direct method is to instantiate an object through the shape constructor to prevent it from automatically calling autoMove, added an isModel for the constructor to determine whether it is intended for prompt use.

You can also check the button event listening, NextBrick function, and deleteObj function. It is easy to understand. The game entry is the NextBrick function.

In addition, I cannot determine whether deleteObj is successful and the GC recycles the object.

In addition, I wanted to add the level function because I could set the speed variable freely.

---------- Update 20141114 ---

The initialization is put into an init function.

We have implemented the level function, and the speed will be faster and faster. How many levels can you challenge? Partition _ Partition

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

Others:

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

Visit GitHub for this Project location: 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 creating html5 Star Trek by yourself

Related Article

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.