Overnap

Merge branch 'develop' into feature/ingame

......@@ -127,7 +127,7 @@
`drawer`는 라운드가 시작된 뒤 바로 `wordSet`을 통해 선택 가능한 단어들을 수신받습니다. 수신받는 단어 수는 3개입니다. `drawer`는 이 중 하나를 선택해서 그림을 그릴 수 있습니다. 단어를 선택하면 해당 단어를 `chooseWord`에 담아 서버로 송신합니다. 서버는 이를 확인하고 타이머를 동작시킵니다. 이때 모든 플레이어는 오직 정답의 글자수만을 담고 있는 `wordChosen`과 타이머의 시작을 알리는 `timer`를 수신받습니다.
그림은 `drawer`의 브러시 움직임을 그대로 시뮬레이션하여 만들어집니다. `drawer`가 색깔, 굵기를 바꾸면 `setBrush`가 서버로 전송되고, 나머지 플레이어들은 이를 수신받게 됩니다. `size`는 브러시의 지름을 픽셀 단위로 나타내고, `color`는 브러시의 색상을 6자리 소문자 16진수로 나타냅니다. 이 메세지는 `drawing` 필드도 담고 있는데, 이는 마우스가 눌린 상태인지, 즉 브러시로 칠을 하는 상태인지를 나타냅니다. 중요한 것은 `drawer`가 캔버스 위에 마우스를 누르는 순간 `drawing``true`로 설정된 메세지가, 캔버스에서 마우스를 떼는 순간 `false`로 설정된 메세지가 서버로 전송되어야 한다는 점입니다.
만약 `drawer`가 캔버스 위에서 그림을 그리는 중이라면 실시간으로 `moveBrush`가 서버로 전송되어야 합니다. `x``y`는 캔버스 오른쪽 아래 지점을 (0, 0)로 설정했을 때의 마우스의 좌표를 픽셀 단위로 나타냅니다.
만약 `drawer`가 캔버스 위에서 그림을 그리는 중이라면 실시간으로 `moveBrush`가 서버로 전송되어야 합니다. `x``y`는 캔버스 쪽 아래 지점을 (0, 0)로 설정했을 때의 마우스의 좌표를 픽셀 단위로 나타냅니다.
다른 플레이어들은 `setBrush`를 통해 `drawing``true`로 설정된 시점부터, 다시 `drawing``false`로 설정되는 시점까지, 마우스가 움직이는 모든 위치에 대해 점이 찍히게 됩니다. 정확히는 마우스의 좌표가 업데이트 될 때 이전 지점과 현재 지점을 선으로 이어 칠해주는 방식으로 보간을 해야 할 것입니다.
전체 과정을 정리하자면 다음과 같습니다.
......@@ -139,7 +139,7 @@
이 정보들을 가지고 캔버스를 칠하는 컴포넌트를 만들어서, 이를 `drawer`의 클라이언트에도 동일하게 사용하는 방식으로 구현하여 `drawer`와 다른 플레이어의 캔버스가 동일하게 보이도록 해야 할 것입니다.
캔버스의 크기: 512x384 (4:3) (추후 변경 가능)
캔버스의 크기: 640x480 (추후 변경 가능)
브러시 사이즈: 1 ~ 64px
### guesser
......
......@@ -112,6 +112,7 @@ interface ServerOutboundMessageMap {
duration: number;
roles: {
username: string;
nickname: string;
role: Role;
}[];
};
......
......@@ -103,8 +103,8 @@ export class Game {
return { ok: false };
}
this.brush.x = Math.max(Math.min(message.x, 1), 0);
this.brush.y = Math.max(Math.min(message.y, 1), 0);
this.brush.x = Math.max(Math.min(message.x, 640), 0);
this.brush.y = Math.max(Math.min(message.y, 480), 0);
this.room.broadcast(
"moveBrush",
......@@ -259,13 +259,22 @@ export class Game {
});
}
private makeRoleArray(): { username: string; role: Role }[] {
private makeRoleArray(): {
username: string;
nickname: string;
role: Role;
}[] {
let roleArray: {
username: string;
nickname: string;
role: Role;
}[] = [];
this.roles.forEach((role, user) =>
roleArray.push({ username: user.username, role: role })
roleArray.push({
username: user.username,
nickname: user.nickname,
role: role,
})
);
return roleArray;
}
......
......@@ -12,10 +12,10 @@ describe("라운드 브러시 이동", () => {
it("영역을 벗어난 좌표는 Clamp 처리됩니다", () => {
const { drawerSocket, guesserSockets } = prepareGame(2);
drawerSocket.testOk("moveBrush", { x: -1, y: 2 });
drawerSocket.testOk("moveBrush", { x: -1, y: 1000 });
expect(guesserSockets[0].socket.received("moveBrush")).deep.eq({
x: 0,
y: 1,
y: 480,
});
});
it("drawer가 아닌 다른 사람들은 브러시를 이동할 수 없습니다", () => {
......