Because it is not a regular Tetris, when eliminated, it is likely to produce irregular graphics, so how to determine whether to achieve the elimination of conditions, as well as the clipping of the block will be a key issue of the game.
When I was doing this game, I used the most direct method, that is, the most stupid method, directly to cut the decision. If there is a better algorithm, I hope you can communicate with me.
First, next, since the rigid body model we created needs to be a convex polygon, each initial block consists of four squares of small squares.
In this game, the rotation of the block should be arbitrary (rather than the original game each rotation is a degree). Therefore, when the upper block stops, it is likely that this is the direction:
Therefore, when the block is eliminated, this elimination may occur:
This is the need to crop, and to meet the cut after the internal rigid body or convex polygon. In fact, it is clear that we just have to cut the inside of a few small squares. It is obvious that a convex polygon is cut in a straight line and the resulting shape is a convex polygon.
The next thing to do is to crop up how to do it.
Although each elimination is to eliminate the middle part of two straight lines, there is no essential difference between two straight line split graphs and a straight line split graph. Therefore, in this case, only single-line cropping is considered.
Now, we're going to start thinking about clipping in a single case,
The clipping line and the graph may intersect and do not want to cross the problem, even if the intersection, it may be only part of the inner block intersect, and for one of the squares, but also to consider which side of the intersection, so to cut that one side.
Since the end is trimmed by edges, we do not consider the whole, not the small squares that make up the whole, but consider the few sides that make up the small squares.
As a result, there are several situations where the blue dot represents the starting point, and the green Point represents the terminating point (an edge is a vector):
This situation is two points above the clipping line and does not need to be cropped.
This situation is two points below the clipping line and does not need to be cropped.
This is the case where the clipping line intersects the edge, and two points are split on both sides of the clipping line, but the starting point (the blue dot) is down, and the ending point (the green point) is on.
Cropping is required at this point, starting point (blue point) and crop point (the point at which the clipping line intersects the edge) becomes the edge of the bottom shape after cropping is finished, the clipping point (the point where the clipping line intersects the edge), and the ending point (the green point) are the edges of the top shape after cropping is complete.
This is the case where the clipping line intersects the edge, and the two points are split on both sides of the clipping line, but the starting point (the blue dot) is on, and the end point (the green dot) is below.
Cropping is required at this point, starting point (blue point) and crop point (the point at which the clipping line intersects the edge) becomes the edge of the top graphic after cropping is finished, the clipping point (the point where the clipping line intersects the edge), and the ending point (green point) are the edges of the bottom shape after cropping is complete.
We do not need to calculate the intersection of points, and then judge. Therefore, you can use the above method, first judge the situation, and then according to the circumstances of the timely calculation of the crop.
The idea used here is that after cropping is finished, the upper and lower graphs are generated. The upper part of the clipping line is encoded as 0and the lower part is 1. Take the two-point, start-point, and end-point of the block in a clockwise direction. according to the Y value of two point , the coded value of two points is judged directly.
If the encoded value is the same, the two point is on the same side of the clipping line, and the edge must not intersect the clipping line. Therefore, cropping is not done. However, depending on the coded values, these two points are grouped in the order of the upper or lower graphs.
If the coded values are different, crop them to get the clipping point. Then, based on the starting point location, if the starting point is encoded at 0, and at the top of the clipping line, the starting point and the clipping point are grouped in the upper graph, the clipping point and the ending point are grouped into the lower graph sequentially, and the starting point and the clipping point are then grouped into the lower drawing. The crop point and the ending point are grouped in the upper drawing sequentially.
The idea of the algorithm is roughly the same, the code is implemented as follows:
Vector<baseblock *> * baseblock::bottomlinecutting (float y) {//define the upper and lower polygon set STD::VECTOR<VEC2 *> * TOPBLOCK;STD: : VECTOR<VEC2 *> * bottomblock;std::vector<int> * topvecsnumber;std::vector<int> * bottomVecsNumber; Topblock = new STD::VECTOR<VEC2 *> () Bottomblock = new STD::VECTOR<VEC2 *> (); topvecsnumber = new std::vector& Lt;int> (); bottomvecsnumber = new std::vector<int> (); bool iscutting = false;for (int i=0; i<shapeamount; i++) {//define top, bottom two segment crop point set std::vector<vec2> * topshape;std::vector<vec2> * bottomshape;topshape = new std::vector< Vec2> (); bottomshape = new std::vector<vec2> ();//Edge clipping for (int j=0; j<shapevecamount->at (i); j + +) {VEC2 StartPoint = This->coordinatespin (Shapevecs->at (i) [j]); VEC2 endPoint = This->coordinatespin (Shapevecs->at (i) [(j+1)%shapevecamount->at (i)]); int Cstart = 0;int CEnd = 0;if ((Fabs (startpoint.y-y) < 1e-6) && (Fabs (endpoint.y-y) < 1e-6)) {if (topshape->size ()! = 0)Cstart = Cend = 0;else Cstart = cend = 1;} else if (Fabs (startpoint.y-y) < 1e-6) {if (Endpoint.y-y < 1e-6) Cstart = Cend = 1;} else if (Fabs (endpoint.y-y) < 1e-6) {if (Startpoint.y-y < 1e-6) Cstart = Cend = 1;} Else{if (Startpoint.y-y < 1e-6) Cstart = 1;if (Endpoint.y-y < 1e-6) cend = 1;} if (Cstart = = cend) {//Two vertices are on the same side without cropping if (Cstart = = 0) {//vertex above, record to top vertex set Topshape->push_back (Coordinategoback ( StartPoint));//topshape->push_back (Coordinategoback (EndPoint));} else{//vertices are below, recorded to the bottom vertex set bottomshape->push_back (Coordinategoback (StartPoint));//bottomshape->push_back ( Coordinategoback (EndPoint));}} else{//two vertices on different sides, need to be cropped float cutting_x = startpoint.x + (endpoint.x-startpoint.x) * (Y-STARTPOINT.Y)/(Endpoint.y-sta RTPOINT.Y) iscutting = true;if (Cstart = = 0) {//start on, end at next Topshape->push_back (Coordinategoback (startPoint)); Topshape->push_back (Coordinategoback (VEC2 (cutting_x, y));//bottomshape->push_back (Coordinategoback ( EndPoint)); Bottomshape->push_back (CoordinategOback (VEC2 (cutting_x, y)));} else{//starting point at the end of the Bottomshape->push_back (Coordinategoback (StartPoint)); Bottomshape->push_back ( Coordinategoback (VEC2 (cutting_x, y));//topshape->push_back (Coordinategoback (StartPoint)); Topshape->push_ Back (Coordinategoback (VEC2 (cutting_x, y)));}}} Add to block set VEC2 * toptempshape = new vec2[topshape->size ()]; VEC2 * Bottomtempshape = new Vec2[bottomshape->size ()];for (int index = 0; index < topshape->size (); index++) {topt Empshape[index] = topshape->at (index);} for (int index = 0; index < bottomshape->size (); index++) {Bottomtempshape[index] = bottomshape->at (index);} if (topshape->size ()! = 0) {topblock->push_back (toptempshape); Topvecsnumber->push_back (TopShape->size ( ));} if (bottomshape->size ()! = 0) {bottomblock->push_back (bottomtempshape); Bottomvecsnumber->push_back ( Bottomshape->size ());}} if (iscutting) {vector<baseblock *> * baseblockset = new Vector<baseblock *> ();D Rawnode * draw = DrawNode::crea Te (); Texture2d * texture = this->gettexture (); Rendertexture * Texture1 = Rendertexture::create (This->getcontentsize (). Width, this->getcontentsize (). Height) Auto Base1 = Baseblock::createwithtexture (This->gettexture ()); auto Base2 = Baseblock::createwithtexture (this- >gettexture ()); Base1->initform (Topblock, Topvecsnumber, Topblock->size ()); Base2->initform ( Bottomblock, Bottomvecsnumber, Bottomblock->size ()); Base1->setposition (This->getposition ());base2-> SetPosition (This->getposition ()); Base1->setrotation (This->getrotation ()); Base2->setrotation (this- >getrotation ()); Baseblockset->pushback (BASE1); Baseblockset->pushback (BASE2); return baseblockset;} Else{if (bottomblock->size ()! = 0) {Vector<baseblock *> * baseblockset = new Vector<baseblock *> (); auto Base = Baseblock::createwithtexture (This->gettexture ()); Baseblockset->pushback (base); return baseblockset;} Else{return NULL;}}}
For a list of other blogs related to making games, I putUse cocos2dx3.2 to make a gravity version of Tetris (Crazy Tetris)
cocos2dx3.2 Crazytetris Single-line clipping thinking of the elimination of Judgment (I.)