Yjs의 React & Conflict-free 복제 데이터 유형(CRDT)을 사용하여 실시간 멀티플레이어 게임 구축
TL;DR: In this article, you will learn how to build a real-time, collaborative Tic Tac Toe game application that enables two users to play the game simultaneously. To create this app, you will use React & Yjs.
실시간 멀티플레이어 편집 기능을 ToolJet에 구축하려고 했습니다( https://github.com/ToolJet/ToolJet/ ). ToolJet에 익숙하지 않은 사람들은 오픈 소스 로우 코드 애플리케이션 빌더입니다. 우리는 이를 위해 다른 접근 방식을 시도했지만 Yjs가 가장 좋은 접근 방식이라는 것을 알았습니다. 이 튜토리얼이 Yjs 및 CRDT를 시작하는 데 도움이 되기를 바랍니다. CRDT가 얼마나 가능한지 확인하려면 ToolJet에서 애플리케이션의 실시간 멀티플레이어 편집에 대한 당사PR를 확인하십시오.
Yjs은 내부 데이터 구조를 공유 유형으로 노출하는 CRDT 구현으로, 실시간 협업 게임 tic tac toe를 구축하는 데 사용할 것입니다.
Want to jump straight to the code? here it is: https://github.com/ToolJet/yjs-crdt-game
UI 구축
먼저 게임용 3x3 그리드 사용자 인터페이스를 빌드한 다음 반응성을 추가해 보겠습니다.
부모 구성 요소
<div className="game">
<div className="game-board">
...
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
게임 구성요소는 다음을 수행합니다.
<div className="game-board">
<Board
squares={current.squares}
onClick={i => this.handleClick(i)}
/>
</div>
보드 구성 요소는 사용자 입력을 위해 표시해야 하는 사각형을 렌더링합니다.
class Board extends React.Component {
renderSquare(i) {
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
);
}
render() {
return (
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
);
}
.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 34px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}
이러한 구성 요소를 모두 추가한 후 UI는 다음과 같아야 합니다.
게임 로직 추가
this.state = {
history: [
{
squares: Array(9).fill(null),
},
],
stepNumber: 0,
xIsNext: true,
};
처음에는 9개의 사각형 모두 "X"또는 "O"로 채워지지 않으므로 9개의 null 값으로 배열을 저장하고 카운트 0으로 단계를 초기화하고 "X"가 가장 먼저 이동하도록 합니다.
tic tac toe 의 게임에서는 플레이어가 가로, 세로 또는 대각선 행에 세 개의 마크를 표시하는 데 성공할 때마다 승자가 결정됩니다.
이것을 코드로 변환해 봅시다:
function calculateWinner(squares) {
const lines = [
[0, 1, 2], // horizontal
[3, 4, 5], // horizontal
[6, 7, 8], // horizontal
[0, 3, 6], // vertical
[1, 4, 7], // vertical
[2, 5, 8], // vertical
[0, 4, 8], // diagonal
[2, 4, 6], // diagonal
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
위의 함수에서
squares
라는 변수를 전달합니다. 각 square[i]에는 'X' 또는 'O'가 포함됩니다. 위의 for 루프에서 수평, 수직 또는 대각선의 세 연속 값이 동일한 값, 즉 X 또는 O를 포함하는지 확인합니다. 참이면 'X' 또는 'O'가 승자로 반환됩니다.게임을 협력적으로 만들기
두 명의 사용자가 공동으로 게임을 플레이할 수 있도록 코드에 yjs를 추가해 보겠습니다.
이를 위해 yjs 및 y-webrtc 두 개의 패키지를 사용할 것입니다.
const ydoc = new Y.Doc();
const provider = new WebrtcProvider(`tutorial-tic-tac-toe`, ydoc);
우선 yjs 문서를 나타내는 ydoc을 만듭니다. 이 문서는 P2P 연결을 생성하기 위해 공용 신호 서버를 활용하는 데 도움이 되는 webrtc 공급자에게 전달됩니다.
componentDidMount() {
const ymap = ydoc.getMap('state');
ymap.observe(() => {
this.setState({
...ymap.get('state')
})
});
}
componentDidMount 함수에서 'state'라는 공유 데이터 유형 Y.Map을 가져오는 변수 ymap을 선언할 것입니다.
그런 다음 공유 데이터 유형에서 관찰 가능 항목을 추가하여 상태의 변경 사항을 관찰합니다.
handleClick(i) {
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState(
{
history: history.concat([
{
squares: squares,
},
]),
stepNumber: history.length,
xIsNext: !this.state.xIsNext,
},
() => {
const ymap = ydoc.getMap('state');
ymap.set('state', this.state);
}
);
}
사용자가 사각형을 클릭할 때마다
ymap.set(..)
함수를 사용하여 Y.map 공유 데이터 유형에 키 값을 설정합니다.이제 ydoc에 변경 사항이 있을 때마다 observable이 호출되고 webrtc 신호 서버를 통해 룸에 연결된 모든 피어가 업데이트를 수신합니다.
최종 결과는 아래와 같습니다.
You can find the code at the GitHub repo https://github.com/ToolJet/yjs-crdt-game
Reference
이 문제에 관하여(Yjs의 React & Conflict-free 복제 데이터 유형(CRDT)을 사용하여 실시간 멀티플레이어 게임 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/tooljet/building-a-realtime-multiplayer-game-using-react-conflict-free-replicated-data-types-crdt-of-yjs-16o7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)