In the previous article, I recorded the framework of the game based on the react native Tetris games, which is a record of how to achieve the shape,shape of Tetris to represent a moving and falling figure. Art Drawing Basics
To complete the shape of Tetris, you must first understand the drawing base in the lower react native. React native built a gallery of art for drawing purposes, the following is a simple way to record the use of the art library. The following code is used to draw a square with a side length of 100 pixels in the center of the phone's screen:
import react, {Component} from ' react '; import {StyleSheet, View, ART, Dimensions} from ' react-native ';
Type Props = {}; Export default class App extends Component<props> {render () {Const PATH = ART.
Path ();
Path.moveto (0, 0);
Path.lineto (100, 0);
Path.lineto (100, 100);
Path.lineto (0, 100);
Path.lineto (0, 0);
Path.close (); Return (<view style={styles.container}> <art. Surface width={100} height={100}> <art. Shape D={path} fill= "#6699FF" stroke= "#FF0000" strokewidth={2}/> </art.
Surface> </View>); } Const STYLES = Stylesheet.create ({container: {flex:1, justifycontent: ' Center ', Alignitems: ' Center '
,
},
});
The effect of the code running is as follows:
The steps for drawing a square are as follows:
1. Import Art Package: import {ART} from ' react-native ';
2. Create the Path object and determine the contour of the graph with the path object, as follows:
Const PATH = ART. Path ();
Path.moveto (0, 0);
Path.lineto (100, 0);
Path.lineto (100, 100);
Path.lineto (0, 100);
Path.lineto (0, 0);
Path.close ();
3. Use <art. Surface> and <art. Shape> Draw the graph. What needs to be noted here is the <art. Shape> components must be wrapped in <art. Surface> assembly, by giving <art. The shape> setting D={path} property determines the shape of the graphic, and the Fill property specifies the fill color of the shape, the border color of the shape specified by the Stroke property, and the border width of the graphic specified by the strokewidth. Design and implementation of shape class
With the drawing foundation of art, we can finish the design and implementation of the Shape class. Design of Shape class
A shape class represents a shape that can be moved around, can be deformed and dropped, and in the game there are many different shapes, such as strips, squares, bends, and so on. We use a 4x4 two-dimensional array to represent the structure of a graph, with 0 and one in the array representing the hollow and solid, where the shape class is designed by using art drawing in a solid place, without drawing anything in the hollow, in order to complete the design of the shapes, as in the following two-dimensional array:
[1, 1, 1, 0],
[0, 1, 0, 0], [0, 0, 0
, 0],
[0, 0, 0, 0]
It means a T-shaped square. Code implementation of Shape class
After designing the shape class, you need to encode this class, shape has some properties such as: start coordinates, shape two-dimensional array data, shape and some other methods such as: Left, right, deformation, automatic whereabouts, shape touch to ground after processing. Deformation of shape
First, consider the shape deformation, taking the T-shape as an example, a T-shape can be deformed to a inverted T-shaped or partial t-shape, in order to handle the shape's distortion, we use an array to hold all the possible shapes of a shape, which becomes a three-dimensional array, as follows:
Let shapedata = [[[
1, 0, 0, 0],
[1, 1, 0, 0], [1, 0, 0,
0],
[0, 0, 0, 0]], [[1, 1,
1,
0],
[ 0, 1, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
], [
[0, 0, 1, 0],
[0, 1, 1, 0],
[0, 0, 1, 0],
[0, 0, 0, 0]
], [
[0, 0, 0, 0], [0, 1, 0, 0
],
[1, 1, 1, 0],
[0, 0, 0, 0]
]]
In the initial case, the graph is the above shapedata[0] data, when the graph needs to deform, becomes the shapedata[1 "the data, then needs to deform, becomes shapedata[2] The data, in turn loops." The left and right movements and whereabouts of shape
The left and right movement of shape is simpler, changing the coordinates of the shape, where we set a starting point (POSX, posy) for shape, stored in state, and when we change this coordinate in state, shape is automatically redrawn to achieve the effect of movement, The code for Shape movement is as follows:
MoveLeft () {
this.setstate ({posx:this.state.posx-1});
}
MoveRight () {
this.setstate ({PosX:this.state.posX + 1});
}
MoveDown () {
this.setstate ({PosY:this.state.posY + 1});
}
Automatic whereabouts of shape
When we do not do anything, a graphic will automatically fall, where we need to use a timed task to allow the graphics to automatically fall, but every drop needs to be judged, if the shape touched the ground, think that the shape of death, was ground eaten, At this time to turn off the timing of the automatic drop of shape, and also to determine whether the game is over, if the game is not over, you need to produce new shape and automatic whereabouts, the logic here is slightly more complex, to judge the conditions are more, first put the shape automatically falling code:
Automovedown () {//Auto drop
This.movefun = () =>{//This is a timed execution method used to drive the graphics auto Drop
if (This.props.canShapeMoveDown && Amp This.props.canShapeMoveDown ()) {//If the graphic can fall, drop
this.setstate ({
PosX:this.state.posX,
posy:1 + This.state.posY
});
else {
//cannot fall, clear timed task
this._clearinterval ();
Triggering a graphical death callback
This.props.onShapeDieListener && This.props.onShapeDieListener (This.state.posX, This.state.posY, Shapearrdata[shapeindex]);
To determine if the game is over, the end condition is that the posy coordinates are the same as the original posy coordinates when the shape is eaten
(This.state.posY = = this.inity) {
//end
of game This.props.onGameOverListener && This.props.onGameOverListener ();
} else {
//game not ended
This._reset ();
}
return;
}
This.intervalid = SetInterval (This.movefun);
}
The above code involves some of the methods in the <GamePlayingView> component, such as a way to determine whether a graph can fall or not, Canshapemovedown The graph is onshapedielistener by the callback method of death after ground is eaten, which will be recorded in subsequent space. Drawing of shape
In react native, we need to implement the component's Render method to complete the rendering of the component, where we render a shape shape. Since shape's data is a two-dimensional array of integers, we can iterate through the array in a loop, draw the color of the value 1 in the array, and draw a transparent color where the value is 0, thus forming a complete graph. Drawing is mainly the following two methods:
Generates a small square (a lattice in a 4x4), based on fill to determine whether to fill the color Generatecell (POSX, Posy, Indexx, indexy, fill) {Const PATH = ART.
Path ();
Path.moveto ((posx + indexx) * width, (posy + indexy) * width);
Path.lineto ((posx + Indexx + 1) * width, (posy + indexy) * width);
Path.lineto ((posx + Indexx + 1) * width, (posy + indexy + 1) * width);
Path.lineto ((posx + indexx) * width, (posy + indexy + 1) * width);
Path.lineto ((posx + indexx) * width, (posy + indexy) * width);
Path.close (); Processing return <art with the IF (fill) {//value of 1. Shape D={path} fill= "#33CC99" stroke= "#6699CC" Strokewidth={divider_width}/>} else {//value 0 of processing return < ART.
Shape D={path} fill= "#00000000"/>}//Generate a shape (entire shape of 4x4) Generateshape (Shapearr) {Let shape = []; Iterate through the two-dimensional array, saving all the small squares for (let row = 0; row < 4; row++) {for (let col = 0; col < 4; col++) {Shape.push (
This.generatecell (This.state.posX, This.state.posY, col, Row, Shapearr[row][col]);
} return shape; }
Finally our render method, we just need to call the above Generateshape method on the line. The complete code for the shape class is placed below:
Import react, {Component} from ' react ';
Import {ART, View} from ' react-native ';
Import shapefactory from './shapefactory '; Import {cell_hor_count, WIDTH, divider_width} from ' ...
/utils/constants ';
Let Shapeindex = 0;
Const Shapefactory = new Shapefactory ();
Let Shapearrdata = Shapefactory.getrandomshapedata ();
Export default class Shape extends Component {constructor (props) {super (props);
THIS.INITX = parseint (CELL_HOR_COUNT/2)-2;
this.inity = 5; This.state = {//initial coordinates PosX:this.initX, PosY:this.initY}} getPosition () {//Return shape's current coordinates retu
RN {PosX:this.state.posX, PosY:this.state.posY};
GetData () {//Returns the shape's two-dimensional array data return SHAPEARRDATA[SHAPEINDEX];
Getnextshapedata () {//returns the two-dimensional array data for the next shape of shape return shapearrdata[(Shapeindex + 1)% 4];
_reset () {//Be ground eaten and reset Shapearrdata = Shapefactory.getrandomshapedata ();
Shapeindex = 0; This.setstate ({PosX:this.initX, posY:this.inity}, () =>{this.automovedown ();
}); } Generatecell (Posx, Posy, Indexx, indexy, fill) {//Generate a small square, based on fill to determine whether to fill the color const PATH = ART.
Path ();
Path.moveto ((posx + indexx) * width, (posy + indexy) * width);
Path.lineto ((posx + Indexx + 1) * width, (posy + indexy) * width);
Path.lineto ((posx + Indexx + 1) * width, (posy + indexy + 1) * width);
Path.lineto ((posx + indexx) * width, (posy + indexy + 1) * width);
Path.lineto ((posx + indexx) * width, (posy + indexy) * width);
Path.close (); if (fill) {return <art. Shape D={path} fill= "#33CC99" stroke= "#6699CC" Strokewidth={divider_width}/>} else {return <art.
Shape D={path} fill= "#00000000"/>}} generateshape (Shapearr) {//Generate a shape let shape = []; for (let row = 0; row < 4; row++) {for (let col = 0; col < 4; col++) {Shape.push (t
His.state.posX, This.state.posY, col, Row, Shapearr[row][col]); }
return shape; Automovedown () {//Auto drop This.movefun = () =>{if (This.props.canShapeMoveDown && this.props.canSh
Apemovedown ()) {this.setstate ({PosX:this.state.posX, posy:1 + This.state.posY});
else {//Cannot drop this._clearinterval (); This.props.onShapeDieListener && This.props.onShapeDieListener (This.state.posX, This.state.posY,
Shapearrdata[shapeindex]); To determine if the game is over, the end condition is that the posy coordinates are the same as the original posy coordinates when the shape is eaten (This.state.posY = = this.inity) {//game end this
. Props.ongameoverlistener && This.props.onGameOverListener ();
else {//game not finished This._reset ();
} return;
} this.intervalid = SetInterval (This.movefun, 600);
Componentwillmount () {//When the component is about to be mounted, the timing task is turned on to allow shape to fall automatically this.automovedown (); } render () {//Render shape return This.generateshape (shapearrdata[shapeindex% 4]);
Transform () {//Graphics variant Shapeindex = (++shapeindex)% 4;
} moveLeft () {this.setstate ({posx:this.state.posx-1});
} moveright () {this.setstate ({PosX:this.state.posX + 1});
} movedown () {this.setstate ({PosY:this.state.posY + 1});
_clearinterval () {//Purge timed Tasks this.intervalid && clearinterval (this.intervalid);
Componentwillunmount () {//component is about to uninstall, stop Timing Task this._clearinterval ();
}
}
Subsequent
The next article will record the ground class design and coding implementation. Source
Click to view project Source-github
Click to view project Source-code Cloud