Tetris is a classic game that has always been implemented by various programming languages. There are many versions of JavsScript. Tetris with React became one of my goals.
Stamp: chvin. Making. IO/react – tetri… Have some fun!
Open source: github.com/chvin/react…
Results the preview
Normal speed recording, smooth experience.
responsive
It refers not only to screen adaptation, but also to responsive manipulation using the keyboard on the PC and the finger on the phone:
Data persistence
What are you most afraid of playing PC games? Without electricity. State is stored in localStorage by subscribing to Store. subscribe, keeping an accurate record of all states. The web page has been closed and refreshed, the application has crashed, the phone is out of battery, re-open the connection, you can continue.
Redux Status Preview (Redux DevTools extension)
The Redux design manages all the required state, which is the guarantee of persistence above.
The React + Redux framework uses imdux as an instance of Redux state. React and Redux can be learned from Redux and React.
1. What is Immutable?
Immutable is data that, once created, cannot be changed. Any modification or addition or deletion of an Immutable object returns a new Immutable object.
First:
Let’s look at the following code:
function keyLog(touchFn) {
let data = { key: 'value' };
f(data);
console.log(data.key); // Guess what will be printed?
}Copy the code
Without looking at F, you don’t know what it does to data, and you can’t confirm what will be printed. But if data is Immutable, you can be sure to print value:
function keyLog(touchFn) {
let data = Immutable.Map({ key: 'value' });
f(data);
console.log(data.get('key')); // value
}Copy the code
Object and Array in JavaScript use reference assignment. The new Object simply refers to the original Object. Changing the new Object also affects the old:
foo = {a: 1}; bar = foo; bar.a = 2;
foo.a / / 2Copy the code
Although this can save memory, but when the application is complex, resulting in uncontrollable state, is a great hidden danger, saving memory advantages become more than worth the loss.
Immutable is not the same, corresponding:
foo = Immutable.Map({ a: 1 }); bar = foo.set('a'.2);
foo.get('a') / / 1Copy the code
Simple:
In Redux, it is optimal to return a new object (array) per reducer, so we often see code like this:
// reducer. return [ ...oldArr.slice(0.3), newValue, ... oldArr.slice(4)];Copy the code
In order to return new objects (arrays), you have to have the odd look above, which can get trickier when using deeper data structures. Let’s look at Immutable:
// reducer. return oldArr.set(4, newValue);Copy the code
Isn’t that neat?
About “= = =” :
=== === === === === =
{a:1.b:2.c:3} = = = {a:1.b:2.c:3}; // false
[1.2[3.4= = = []]1.2[3.4]].// falseCopy the code
Only deepCopy and deepCompare can be used for traversal comparison, which is not only troublesome but also good performance.
Let’s feel the Immutable way!
map1 = Immutable.Map({a:1.b:2.c:3});
map2 = Immutable.Map({a:1.b:2.c:3});
Immutable.is(map1, map2); // true
// List1 = Immutable.List([1, 2, Immutable.List[3, 4]]);
List1 = Immutable.fromJS([1.2[3.4]]);
List2 = Immutable.fromJS([1.2[3.4]]);
Immutable.is(List1, List2); // trueCopy the code
There seems to be a breeze blowing.
A great way to optimize React is to use shouldComponentUpdate(), but it returns true by default and always executes render(), followed by a Virtual DOM comparison.
ShouldComponentUpdate = true/false; shouldComponentUpdate = true/false; shouldComponentUpdate = true/false After Immutable, it is easy to compare deep structures using the above method.
For Tetris, think of the board as a two-dimensional array, and the moving squares as shapes (also two-dimensional arrays)+ coordinates. The superposition of the checkerboard and squares forms the final Matrix. The above attributes are constructed Immutable, and shouldComponentUpdate is easy to write using its comparison method. Source: / SRC/components/matrix/index js# L35
Immutable mutable
- Immutable.js
- Immutable; React; Immutable
How to use Immutable in Redux
Target: make state -> Immutable. Key library: Gajus /redux-immutable combineReducers redux-immutable
// rootReduers.js
// import { combineReducers } from 'redux'; // The old way
import { combineReducers } from 'redux-immutable'; // New method
import prop1 from './prop1';
import prop2 from './prop2';
import prop3 from './prop3';
const rootReducer = combineReducers({
prop1, prop2, prop3,
});
// store.js
// Create store as usual
import { createStore } from 'redux';
import rootReducer from './reducers';
const store = createStore(rootReducer);
export default store;Copy the code
The new combineReducers will convert store objects to Immutable, and will be slightly different when used in Containers (but that’s what we want) :
const mapStateToProps = (state) = > ({
prop1: state.get('prop1'),
prop2: state.get('prop2'),
prop3: state.get('prop3'),
next: state.get('next')});export default connect(mapStateToProps)(App);Copy the code
3. Web Audio Api
There are a lot of different sound effects in the game, and only one sound file is actually referenced: /build/music.mp3. The Web Audio Api makes it possible to play sound with millisecond accuracy at high frequencies that the < Audio > tag does not. Hold down the D-pad to move a block while playing and you can hear a high-frequency sound effect.
WAA is a new set of relatively independent interface system, audio files have higher processing permissions and more professional built-in audio effects, is the W3C recommended interface, professional processing of “sound speed, volume, environment, timbre visualization, high frequency, tone orientation” and other requirements, the following figure describes the use of WAA process.
Where Source represents an audio Source, Destination represents the final output, and Destination is synthesized from multiple sources. Source code: / SRC /unit/music.js Ajax load MP3, and to WAA, control the playback process.
WAA support in the latest 2 versions of each browser (CanIUse)
You can see IE camp can’t be used with most Android, other OK.
The Web Audio Api
- | MDN Web API interface
- Getting Started with Web Audio API
4. Optimization of game experience
- Technology:
- / SRC /unit/event.js; / SRC /unit/event.js;
- Moving from side to side can delay the speed of falling, but the delay is smaller when moving against the wall. Delay ensures a complete horizontal movement in a row at speed 6;
- Register the buttons simultaneously
touchstart
andmousedown
Events for responsive play. whentouchstart
Does not trigger when it occursmousedown
And whenmousedown
Occurs when the event element can not fire due to the mouse moving awaymouseup
, will listen simultaneouslymouseout
simulationmouseup
. The source code:/src/components/keyboard/index.js; - Listen to the
visibilitychange
Event, when the page is hidden \ switch, the game will not play, switch back will continue, thisfocus
States are also written into Redux. So when you play with your phoneThe phone
, the game progress will be saved; You don’t hear Gameover when you’re playing a game on your PC. It’s kind of likeios
Switching applications. - in
any
Refresh the page at any time (e.g. eliminate blocks, end of game) can also restore the current state; - The only images used in the game are
, everything else is CSS;
- Compatible with Chrome, Firefox, IE9+, Edge, etc.
- Game:
- You can specify the initial board (ten levels) and speed (six levels) before the game starts;
- A single elimination earns 100 points for 1 line, 300 points for 2 lines, 700 points for 3 lines, and 1,500 points for 4 lines.
- [Fixed] Block drop speed increases with the number of eliminated rows (one level for every 20 rows)
5. Experience sorting in development
- For all the
component
Write theshouldComponentUpdate
The performance of mobile phones has been significantly improved. ShouldComponentUpdate shouldComponentUpdate shouldComponentUpdate shouldComponentUpdate shouldComponentUpdate shouldComponentUpdate shouldComponentUpdate Stateless component
(Stateless Functional Components) has no life cycle. Because of the above factor, all components should have a life cycle shouldComponentUpdate, so stateless components are not used.- in
webpack.config.js
The devServer property inHost: '0.0.0.0'
, can be accessed at development time using IP, not limited to localhost; - In the story
store
It is not only through connect that methods are passed tocontainer
, can jump out of the component, in another file out to do flow control (dispatch), source code:/src/control/states.js; - Persisting react+redux is very convenient, just store the REdux state and read it when each reduer is initialized.
- By configuring.eslintrc.js
With webpack. Config. Js
Is integrated into the projectESLint
Inspection. Using ESLint allows code to be written to specifications, effectively controlling code quality. Nonconforming code can be found at development time (or build time) through the IDE and console. Reference:Airbnb: React usage specifications;
6, summary
- As a React application for practice, many details can be optimized and polished in the implementation process. This is the time to test the carefulness and skill of a front-end engineer.
- The optimization direction is both React itself, such as which states are stored by Redux and which states are given to component states. Out of the frame and there are many features of the product can play, in order to meet your needs, these will naturally promote the development of technology.
- A project from scratch, function slowly accumulated, will be built into a high-rise, do not be afraid of difficult, have an idea to knock it up. ^_^
7. Control process
This article joins the nuggets technical essay: juejin.cn/post/684490…