Гость
Форумы / HTML, JavaScript, VBScript, CSS [игнор отключен] [закрыт для гостей] / Проблема в жизненном цикле при организации пошаговой отрисовки / React-Hooks / 2 сообщений из 2, страница 1 из 1
03.09.2020, 09:23
    #39995124
keon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема в жизненном цикле при организации пошаговой отрисовки / React-Hooks
Задача:

Есть поле (грид) по которому двигается голова змейки, при нажатии на стрелки голова меняет направление. Рендер должен происходить согласно начальной скорости (а так же может меняться в зависимости от условий, не входит в контекст этого запроса), скорость исчисляется в секундах/миллисекундах. Весь код работает отлично за исключением проблемы (метод GameSleep) с управлением этой самой задержки рендера до следующего шага (рендера).



Кто может помочь с настройкой жизненного цикла удовлетворяющего исходной задаче?

p.s. решение с циклами while, setInterval/setTimeout в основном lifecycle компонента результата не дадут - т.к. из-за замыкания новое значение direction (направление для змейки), полученное в SnakeEventListener, не попадет в этот самые циклы. Вся сложность создать управляемый цикл (периодичность управляемая значением speed).

p.s.s. код естественно сократил до минимума, чтобы не потерялась нить бизнес-логики

КОД

Точка входа: Index.js:

Код: javascript
1.
ReactDOM.render(<Provider store={store}><Snake/></Provider>, document.getElementById('root'));



Snake.js:

Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
const Snake = (props) => {
  const [process, setProcess] = useReducer(
    ReducerProcess, {start: false, victory: false, gameover: false, reset: true }
  );
  const [direction, setDirection] = useState(undefined);
  
  const SnakeEventListener = useCallback((event) => {
    if( checkKey(event.code) ) {
      const direction = getDirection(event.code);
      setDirection(direction);
    }
  }, []);

  const onProcess = useCallback((inType) => {
    switch(inType) {
      case STATE.reset:
        setDirection(undefined); break;
      case STATE.start:
        document.addEventListener('keydown', SnakeEventListener, false); break;
      case STATE.victory:
        document.removeEventListener('keydown', SnakeEventListener, false); break;
      case STATE.gameover:
        document.removeEventListener('keydown', SnakeEventListener, false); break;
      default: break;
    }
    setProcess({type: inType});
  }, [SnakeEventListener]);

return (
  <div>
    <Grid process={process} toProcess={onProcess} direction={direction} toDirection={setDirection}/>
    <button onClick={()=>onProcess('reset')}>Reset</button>
    <button onClick={()=>onProcess('start')}>Start</button>
  </div>
);
}



Grid.js:

Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
const Grid = (props) => {
  const {process, toProcess, direction, toDirection} = props;
  const [snake, setSnake] = useState(undefined);
  const [grid, setGrid] = useState(undefined);

  // Effect => Initial
  useEffect(() => {
    const Initial = () => {
      setSnake( initSnake() );
      toDirection( initDirection() );
      setGrid( InitGrid() );
    }
    if(process.reset && !direction) { Initial(); }
  }, [process, direction, toDirection]);

  // Effect => Game Loop
  useEffect(() => {
    const GameLoop = () => {
      const build = BuildGrid(snake, direction);
      if(build.victory || build.gameover) {
        if(build.victory) { toProcess('victory'); }
        if(build.gameover) { toProcess('gameover'); }
      }else{
        setSnake(build.snake);
        setGrid(build.grid);
      }
    }
    if(process.start && direction) { GameLoop(); }
  }, [process, toProcess, direction, snake]);

  return (<div>{ Cells(grid) }</div>);
}



Building.js:

Код: javascript
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
const BuildGrid = (input) => {
  const content = Execute(input);
  … … …
  return content;
}

const Execute = async (input) => {
  await GameSleep(input.speed);
  let newSnake = input.snake;
  … … …
  return { snake: newSnake, grid: grid, victory: victory, gameover: gameover };
}

const GameSleep = async (delay) => {
  return new Promise(resolve => setTimeout(resolve, delay));
}
...
Рейтинг: 0 / 0
03.09.2020, 10:22
    #39995144
crutchmaster
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проблема в жизненном цикле при организации пошаговой отрисовки / React-Hooks
Ну так запихай свой mainloop в setInterval, который его будет дёргать каждые n ms. Какие проблемы? Когда поменяется скорость выкинь старый интервал, сделай новый. Или сделай интервал 10ms и пропускай сколько надо до следующего "хода".
...
Рейтинг: 0 / 0
Форумы / HTML, JavaScript, VBScript, CSS [игнор отключен] [закрыт для гостей] / Проблема в жизненном цикле при организации пошаговой отрисовки / React-Hooks / 2 сообщений из 2, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]