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

Есть поле (грид) по которому двигается голова змейки, при нажатии на стрелки голова меняет направление. Рендер должен происходить согласно начальной скорости (а так же может меняться в зависимости от условий, не входит в контекст этого запроса), скорость исчисляется в секундах/миллисекундах. Весь код работает отлично за исключением проблемы (метод 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
Проблема в жизненном цикле при организации пошаговой отрисовки / React-Hooks
    #39995144
Фотография crutchmaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну так запихай свой mainloop в setInterval, который его будет дёргать каждые n ms. Какие проблемы? Когда поменяется скорость выкинь старый интервал, сделай новый. Или сделай интервал 10ms и пропускай сколько надо до следующего "хода".
...
Рейтинг: 0 / 0
2 сообщений из 2, страница 1 из 1
Форумы / HTML, JavaScript, VBScript, CSS [игнор отключен] [закрыт для гостей] / Проблема в жизненном цикле при организации пошаговой отрисовки / React-Hooks
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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