Arcade 3D di browser: bagaimana kami membuat game di React + Redux

Halo, Habr! Pada tahun-tahun yang tidak terlalu jauh, pada tahun pertama saya di fakultas "programmer", saya suka bertanya kepada sesama siswa pertanyaan: "Mengapa Anda bahkan pergi ke sini untuk belajar?" Tentu saja, saya tidak menyimpan statistik jawaban yang akurat, tetapi saya ingat dengan pasti: lebih dari setengahnya ingin membuat game. Sebagian besar dari mereka yang menjawab dengan cara ini tidak siap untuk kelimpahan berbagai jenis "ahli matematika" dan "ahli fisika" dengan siapa kita kewalahan dalam dua tahun pertama studi. Tidak semua selamat - pada akhir tahun kedua dari lima kelompok yang penuh sesak ada tiga yang tidak lengkap.


Belum lama berselang, tim front-end kami diberi kesempatan untuk mencoba sendiri dalam peran gamedev. Secara singkat, tugasnya adalah ini: untuk membuat game 3D nyata, sehingga Anda dapat bermain hanya dengan membuka browser. Bahkan ponsel. Bahkan dalam tampilan web.



, , , — React + Redux, « », , , .



RnD , : « CodeFest — . — ». , , , . Gods in the sky.


Foto dari grup CodeFest di VK / https://vk.com/codefest.  Sumber foto ada di sini.
CodeFest .


MMO TPS , , . , , , . CodeFest. , .



2 , , 2 . , , .


: -, — , . , N , — 1 . , — 15 . , , 16-. , , :


  1. 30 . CodeFest, — , «». , .
  2. «» . , :
    • 90 CPU;
    • 120 ;
    • 270 /c — , 675 /c — .
  3. 4,2 /c. , . — UDP WebRTC, . .
  4. . 2 , , , . , - Node.js , .

, , ( ?), , , , . .


, . , «». — .


:


, , , . , , 5 , , 40 .


-. , , — . React Redux. c 3D-, , Gods in the sky, three.js.


, .



:



, Node.js. :


  • , - ( , IE11);
  • access-;
  • html- .

SSR . kubernetes , . , . , , , , ( ). . Nginx.



. TS, AppState, :


interface AppState {
    gameState: GameState;
    gameObjects: GameObjects;
    data: Data;
    requests: RequestsState;
}

requests — , — . , — . .


data — , , , , «». .


GameState :


  1. stage: 'factoids' | 'citySelect' | 'flyShow' | 'game' | 'results'; — . :


    • ;
    • ;
    • ;
    • ;
    • .

  2. elapsedTime: number; — , , .



, factoids flyShow, , — elapsedTime. 0, . , . , , , . , . … - , .


, , :


interface GameObjects {
    user: UserInGame;
    gifts: { [id: string]: GiftInGame; };
    boosts: { [id: string]: Boost; };
    bombs: { [id: string]: Bomb; };
}

, : , , . — .


GameObjects — . , FPS . GPU 100 . Redmi Note 7 40 FPS ( ). MI 5S 30 FPS, 20 , .


, . .



- Redux, — . Redux , . ? Redux, .


, . , . «» ( . behavior — ). , .


. — tick, . , . tick . :


  • , , , . , , , .
  • ( Redux-), .
    , «» .
  • , gameObjects, . , «», .

25 ( ).


. ( ), React, . - , «- » ( , , ).


Anggota tim lain hari itu.  Foto diambil dari pixabay.com
. pixabay.com


, FPS- 13. , , - MI 5S, FPS- — 5-6, . .


: performance — , . , , .


FPS=30 , :


  • Redux FPS * ~[ ] ~= 750 , , .
  • React’ FPS * ~2 * ~[ ] .
  • three.js , , WebGL . , .
  • (.. 150 ) 4-6 , .. .
  • CSS- .
  • , FPS 2-4 ( , «» ).
  • React.memo, - , .

React :


  • * ~2 , connect. connect — - HOC, , .
  • , React – (render pass), CPU, GPU.


: React.memo , , «», , DOM-, .


, React + Redux, .


Redux


Redux — . ~1 , . ~1, - — . -, , GameObjects , :


export function setNextGameObjects(payload: GameObjects) {
    return {
        type: 'SET_NEXT_GAME_OBJECTS' as const,
        payload,
    };
}

GameObjects :


  1. , . SET_NEXT_GAME_OBJECTS.
  2. , , GameObjects. Redux , - . SET_NEXT_GAME_OBJECTS.

:


let state = store.getState().gameObjects;
for (const action of this.collectedActions) {
    state = gameObjectsFakeStateReducer(state, action);
}
store.dispatch(setNextGameObjects(state));

collectedActions — , . — , .


— ~25 10 : ~2 . , gameObjectsFakeStateReducer . 25 . , .


? , perf-. 3 :


  1. ES2018, ~50 < ES2018 (, Firefox — ). , spread.
  2. Object.assign 300 .
  3. 500 , « » .

, , , — ES2018, . Firefox.


№3 , … . .


Object.assign. gameObjectsFakeStateReducer gameObjectsFastStateReducer, - :


switch (action.type) {
    case 'PARTIAL_GIFT_STATE_PATCH':
        if (!state.gifts[action.payload.id]) {
            return state;
        }
        Object.assign(state.gifts[action.payload.id], action.payload);
        break;
    // case, default ...
}

? , . , . 25 1 2-4 ( CPU). :


gambar


«» , , Redux 10 . , - , , connect gameObjects. , .


React


React . — DOM. , , — reselect, React.memo/React.PureComponent, shouldComponentUpdate . .


, , ~2, — 5. , React , .. DOM .


batch React + Redux. , — . , ?


, , connect . , .


. , <ScoreBoard />,


  1. ;
  2. , .

React.PureComponent, connect mapStateToProps. elapsedTime score. Score , elapsedTime — . elapsedTime - render. , FPS, shouldComponentUpdate. HOC’a connect — shouldComponentUpdate .


, «» , :


  1. shouldComponentUpdate, elapsedTime ( ). , HOC’a connect.
  2. mapStateToProps . , , . connect’a.
  3. useSelector. , .. . , , , .
  4. — connect, — . , . ScoreBoard .

— ! ScoreBoard’a connect, , . mapStateToProps , .


, connect. , — - - canvas-, three.js (, , .). render , :


return <div id="map" className={s.map} ref={mapRef} />;


return <canvas id="scene" className={s.scene} ref={sceneRef} />;

, DOM — . , React . , componentDidUpdate, . , componentDidUpdate :


public componentDidUpdate() {
    const { geoPos, orientedRotationQuanternion } = this.props;
    const { map } = this.state;
    map.setQuat(orientedRotationQuanternion);
    map.setCenter([geoPos[0], geoPos[1]], { animate: false });
    map.setZoom(getMapZoomFromHeight(geoPos[2]), { animate: false });
}

, componentDidUpdate . :


  1. connect. , mapStateToProps;
  2. public shouldComponentUpdate() { return false; } — «» «»;
  3. Redux ( ) useStore ;
  4. (store.subscribe(() => { /* … */}));
  5. ;
  6. !

:


store.subscribe(() => {
    const state = store.getState();
    const { map } = this.state;
    const { geoPos, orientedRotationQuanternion } = state.gameObjects.user;

    map.setQuat(orientedRotationQuanternion);
    map.setCenter([geoPos[0], geoPos[1]], { animate: false });
    map.setZoom(getMapZoomFromHeight(geoPos[2]), { animate: false });
}); 

, , .


, - , .



. — React Tree Reconcilation + Commit



React Tree Reconcilation + Commit



React + Redux , :


  • , , , «» React , ;
  • ;
  • « », , ;
  • , .

, . , . , . ? .


:


  1. , , , , . , .
  2. , React’ 30 . : .
  3. , .
  4. . . , .
  5. .
  6. Performance — . CPU — , Intel i9.
  7. - : 12–20 – . , .
  8. , . , , . , .
  9. , , . IE11 , . 70- Edge 18- ( ).
  10. WebGL . - , , -, Firefox linux, . . — . -, . , , « », .

, :


  1. Firefox. . , WebGL, — spread. FPS Firefox , Chrome. , , .
  2. IPhone. Safari IE6 220 . , , . , , . . — - .
  3. . . . , , (, , ). .
  4. . , , . , , , «» .
  5. ( ), – , . .

, , . iOS, Android Web .


All Articles