From 02870a00ab2a0ba89bc6208e670022a2654d66e3 Mon Sep 17 00:00:00 2001 From: ramram1048 Date: Mon, 7 Dec 2020 16:30:00 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20GameObject=EC=97=90=20roll()=20meth?= =?UTF-8?q?od=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - move하면서 rotate하게하는 method. move와 달리 easing function이 적용되지 않았습니다. - rollCount: 몇바퀴 돌건지. rollClockwise: 시계/반시계방향. - TODO: - move()함수와 많은 부분 겹치므로 따로 뺄수있으면 빼자. - roll을 만들게 아니라 rotate를 roll처럼만들고 position과 독립적으로 동작하게 해야될까?? --- src/frontend/engine/GameObject.js | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/frontend/engine/GameObject.js b/src/frontend/engine/GameObject.js index dc9501f0..705946f5 100644 --- a/src/frontend/engine/GameObject.js +++ b/src/frontend/engine/GameObject.js @@ -147,6 +147,60 @@ const GameObject = class { this.animationFrame = requestAnimationFrame(animateFunction); } + roll( + x = 0, + y = 0, + duration = TIME.ONE_SECOND / 2, + rollCount = 1, + rollClockwise = Math.random() < 0.5, + ) { + // TODO: move()와 겹치는 부분들 refactor... + this.position = [x, y]; + const xString = makeUnitString(x, '%'); + const yString = makeUnitString(y, '%'); + + if (this.animationFrame) cancelAnimationFrame(this.animationFrame); + if (!xString && !yString) { + this.instance.style.removeProperty('top'); + this.instance.style.removeProperty('left'); + } + if (duration === 0) { + this.instance.style.top = yString; + this.instance.style.left = xString; + return; + } + const initialY = makeFloat(this.instance.style.top) || 0; + const initialX = makeFloat(this.instance.style.left) || 0; + const targetY = y; + const targetX = x; + + let start = null; + const animateFunction = (timestamp) => { + if (!start) start = timestamp; + const elapsed = timestamp - start; + if (elapsed > duration) { + this.instance.style.top = yString; + this.instance.style.left = xString; + this.animationFrame = null; + return; + } + const newY = initialY + (targetY - initialY) * (elapsed / duration); + const newX = initialX + (targetX - initialX) * (elapsed / duration); + this.angle = rollClockwise + ? this.angle + rollCount * 4 * (elapsed / duration) + : this.angle - rollCount * 4 * (elapsed / duration); + this.rotateStyle = makeUnitString(this.angle, 'deg'); + + this.instance.style.left = makeUnitString(newX, '%'); + this.instance.style.top = makeUnitString(newY, '%'); + this.instance.style.transform = `rotateZ(${this.rotateStyle}) ${this.originStyle}`; + + requestAnimationFrame(animateFunction); + }; + + this.animationFrame = requestAnimationFrame(animateFunction); + } + rotate(angle = 0, duration = TIME.ONE_SECOND / 5) { this.angle = angle; const angleString = makeUnitString(angle, 'deg'); From b80653fd397a6da2536cf83f255e2ec98cfd9155 Mon Sep 17 00:00:00 2001 From: ramram1048 Date: Mon, 7 Dec 2020 18:24:39 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20player=20waiting=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83/=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - duck, card가 포함되있지 않음 --- src/frontend/scenes/playerWaiting/index.js | 5 +++-- src/frontend/scenes/playerWaiting/playerWaiting.scss | 0 src/frontend/scenes/playerWaiting/render.js | 8 +++++++- src/frontend/scenes/playerWaiting/style.scss | 12 ++++++++++++ src/frontend/utils/text.js | 2 ++ 5 files changed, 24 insertions(+), 3 deletions(-) delete mode 100644 src/frontend/scenes/playerWaiting/playerWaiting.scss create mode 100644 src/frontend/scenes/playerWaiting/style.scss diff --git a/src/frontend/scenes/playerWaiting/index.js b/src/frontend/scenes/playerWaiting/index.js index a757af66..35a4cfc0 100644 --- a/src/frontend/scenes/playerWaiting/index.js +++ b/src/frontend/scenes/playerWaiting/index.js @@ -1,8 +1,9 @@ -import rendePlayerWaiting from './render'; +import './style.scss'; +import renderPlayerWaiting from './render'; const PlayerWaiting = class { render() { - const { arrayToBeRemoved = [] } = rendePlayerWaiting(); + const { arrayToBeRemoved } = renderPlayerWaiting(); this.arrayToBeRemoved = arrayToBeRemoved; } diff --git a/src/frontend/scenes/playerWaiting/playerWaiting.scss b/src/frontend/scenes/playerWaiting/playerWaiting.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/src/frontend/scenes/playerWaiting/render.js b/src/frontend/scenes/playerWaiting/render.js index 5267d6d1..748168ad 100644 --- a/src/frontend/scenes/playerWaiting/render.js +++ b/src/frontend/scenes/playerWaiting/render.js @@ -1,6 +1,7 @@ -import './playerWaiting.scss'; import ProgressBarObject from '@engine/ProgressBarObject'; +import TextObject from '@engine/TextObject'; import TIME from '@utils/time'; +import TEXT from '@utils/text'; const renderPlayerWaiting = () => { const ProgressBar = new ProgressBarObject(); @@ -9,6 +10,11 @@ const renderPlayerWaiting = () => { ProgressBar.setTime(TIME.SELECT_CARD); ProgressBar.start(); + const HelpText = new TextObject(); + HelpText.addClass('player-waiting-helper-text'); + HelpText.setContent(TEXT.WAIT_PLAYER_SELECT); + HelpText.attachToRoot(); + const arrayToBeRemoved = [ProgressBar]; return { diff --git a/src/frontend/scenes/playerWaiting/style.scss b/src/frontend/scenes/playerWaiting/style.scss new file mode 100644 index 00000000..f787cc38 --- /dev/null +++ b/src/frontend/scenes/playerWaiting/style.scss @@ -0,0 +1,12 @@ +@import '@utils/common'; + +.player-waiting-helper-text { + position: absolute; + z-index: $z-index-layouts; + top: 30%; + left: 50%; + font-size: x-large; + text-align: center; + transform: translateX(-50%); + white-space: nowrap; +} diff --git a/src/frontend/utils/text.js b/src/frontend/utils/text.js index a03a791d..748cabcd 100644 --- a/src/frontend/utils/text.js +++ b/src/frontend/utils/text.js @@ -2,6 +2,8 @@ const TEXT = { TELLER_SELECT: '당신은 이야기꾼입니다.\n어떤 카드로 이야기를 해볼까요?', WAIT_TELLER_SELECT: '이야기꾼이 카드를 고르고 있습니다.\n잠시만 기다려주세요.', + WAIT_PLAYER_SELECT: + '다른 플레이어들이 카드를 고르고 있습니다.\n잠시만 기다려주세요.', TELLER: { true: '당신은 이야기꾼입니다.\n어떤 카드로 이야기를 해볼까요?', false: '이야기꾼이 카드를 고르고 있습니다.\n잠시만 기다려주세요.', From ae19643123f4b09bcc33148cbb414ebc5013295d Mon Sep 17 00:00:00 2001 From: ramram1048 Date: Mon, 7 Dec 2020 18:49:33 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EB=96=A8=EC=96=B4=EC=A7=80?= =?UTF-8?q?=EB=8A=94=20=EC=B9=B4=EB=93=9C,=20=EC=9B=80=EC=A7=81=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20=EC=98=A4=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - event를 받을 때마다 duck을 생성하고 카드가 한장 떨어짐. - z-index를 어떻게 관리할지가 걱정. scss에서도 쓰고 js에서도 쓴다. --- src/frontend/scenes/playerWaiting/index.js | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/frontend/scenes/playerWaiting/index.js b/src/frontend/scenes/playerWaiting/index.js index 35a4cfc0..5bb3c930 100644 --- a/src/frontend/scenes/playerWaiting/index.js +++ b/src/frontend/scenes/playerWaiting/index.js @@ -1,7 +1,54 @@ import './style.scss'; +import CardObject from '@engine/CardObject'; +import DuckObject from '@engine/DuckObject'; +import { DUCK_TYPE } from '@utils/type'; +import PlayerManager from '@utils/PlayerManager'; +import { $id } from '@utils/dom'; import renderPlayerWaiting from './render'; +import { moveMyDuck } from '../waitingRoom/events'; + +const createDuck = ({ + color = '', + x = 25 + Math.random() * 50, + y = 25 + Math.random() * 50, +} = {}) => { + const duck = new DuckObject({ type: DUCK_TYPE.CURSOR }); + duck.setColor(color); + duck.createElement(); + duck.setOriginCenter(); + duck.move(x, y, 0); + duck.setDepth(2); + duck.attachToRoot(); + return duck; +}; const PlayerWaiting = class { + constructor() { + this.cards = []; + this.ducks = new Map(); + + PlayerManager.forEach(({ socketID, ...duckData }) => { + const duck = createDuck(duckData); + this.ducks.set(socketID, duck); + }); + const myDuck = this.ducks.get(PlayerManager.currentPlayerID); + myDuck.setDepth(3); + this.duckMoveEvent = (e) => moveMyDuck(e, myDuck); + $id('root').addEventListener('click', this.duckMoveEvent); + this.dropNewCard(); + } + + dropNewCard() { + const newCard = new CardObject(); + newCard.move(50, -50, 0); + newCard.setWidth(150); + newCard.angle = Math.random() * 360 - 180; + newCard.roll(40 + Math.random() * 20, 65 + Math.random() * 20, 3000); + newCard.attachToRoot(); + + this.cards = [...this.cards, newCard]; + } + render() { const { arrayToBeRemoved } = renderPlayerWaiting(); this.arrayToBeRemoved = arrayToBeRemoved; From dea4c95396bd26e6d94692a1eb3c597897d74a40 Mon Sep 17 00:00:00 2001 From: ramram1048 Date: Tue, 8 Dec 2020 02:11:26 +0900 Subject: [PATCH 4/6] =?UTF-8?q?style:=20player=20waiting=20=EB=8F=84?= =?UTF-8?q?=EC=9B=80=EB=A7=90=20=ED=85=8D=EC=8A=A4=ED=8A=B8=EC=97=90=20?= =?UTF-8?q?=EB=B0=98=ED=88=AC=EB=AA=85=EB=B0=B0=EA=B2=BD=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/scenes/playerWaiting/style.scss | 1 + src/frontend/utils/common.scss | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/frontend/scenes/playerWaiting/style.scss b/src/frontend/scenes/playerWaiting/style.scss index f787cc38..d99327d3 100644 --- a/src/frontend/scenes/playerWaiting/style.scss +++ b/src/frontend/scenes/playerWaiting/style.scss @@ -1,6 +1,7 @@ @import '@utils/common'; .player-waiting-helper-text { + @include helper-text-white-background; position: absolute; z-index: $z-index-layouts; top: 30%; diff --git a/src/frontend/utils/common.scss b/src/frontend/utils/common.scss index 868c2a58..c967d6d1 100644 --- a/src/frontend/utils/common.scss +++ b/src/frontend/utils/common.scss @@ -41,6 +41,13 @@ html { display: none; } +@mixin helper-text-white-background { + padding: 0.5em; + background-color: #fffa; + border-radius: 1em; + box-shadow: 0 0 4em 1em $white-color; +} + @mixin button { display: flex; flex-direction: row; From 25266c51aff0a1545d97007104459e932f82aed6 Mon Sep 17 00:00:00 2001 From: ramram1048 Date: Tue, 8 Dec 2020 12:43:15 +0900 Subject: [PATCH 5/6] =?UTF-8?q?refactor:=20#137=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기본값 magic number 제거 - roll 로직 "조금" 개선 --- src/frontend/engine/GameObject.js | 12 +++++------- src/frontend/scenes/playerWaiting/index.js | 6 ++++-- src/frontend/utils/time.js | 1 + 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/frontend/engine/GameObject.js b/src/frontend/engine/GameObject.js index 705946f5..b5b26f2e 100644 --- a/src/frontend/engine/GameObject.js +++ b/src/frontend/engine/GameObject.js @@ -101,7 +101,7 @@ const GameObject = class { this.instance.style.zIndex = zIndex; } - move(x = 0, y = 0, duration = TIME.ONE_SECOND / 2) { + move(x = 0, y = 0, duration = TIME.DEFAULT_TRANSITION) { this.position = [x, y]; const xString = makeUnitString(x, '%'); const yString = makeUnitString(y, '%'); @@ -150,9 +150,9 @@ const GameObject = class { roll( x = 0, y = 0, - duration = TIME.ONE_SECOND / 2, + duration = TIME.DEFAULT_TRANSITION, rollCount = 1, - rollClockwise = Math.random() < 0.5, + rollClockwise = Math.random() < 0.5 ? 1 : -1, ) { // TODO: move()와 겹치는 부분들 refactor... this.position = [x, y]; @@ -186,9 +186,7 @@ const GameObject = class { } const newY = initialY + (targetY - initialY) * (elapsed / duration); const newX = initialX + (targetX - initialX) * (elapsed / duration); - this.angle = rollClockwise - ? this.angle + rollCount * 4 * (elapsed / duration) - : this.angle - rollCount * 4 * (elapsed / duration); + this.angle += rollClockwise * rollCount * 4 * (elapsed / duration); this.rotateStyle = makeUnitString(this.angle, 'deg'); this.instance.style.left = makeUnitString(newX, '%'); @@ -201,7 +199,7 @@ const GameObject = class { this.animationFrame = requestAnimationFrame(animateFunction); } - rotate(angle = 0, duration = TIME.ONE_SECOND / 5) { + rotate(angle = 0, duration = TIME.DEFAULT_TRANSITION) { this.angle = angle; const angleString = makeUnitString(angle, 'deg'); const keyframes = [ diff --git a/src/frontend/scenes/playerWaiting/index.js b/src/frontend/scenes/playerWaiting/index.js index 5bb3c930..acc2116b 100644 --- a/src/frontend/scenes/playerWaiting/index.js +++ b/src/frontend/scenes/playerWaiting/index.js @@ -39,8 +39,10 @@ const PlayerWaiting = class { } dropNewCard() { - const newCard = new CardObject(); - newCard.move(50, -50, 0); + const newCard = new CardObject({ + origin: [50, 50], + position: [50, -50], + }); newCard.setWidth(150); newCard.angle = Math.random() * 360 - 180; newCard.roll(40 + Math.random() * 20, 65 + Math.random() * 20, 3000); diff --git a/src/frontend/utils/time.js b/src/frontend/utils/time.js index a81fb9d6..dfc15d7d 100644 --- a/src/frontend/utils/time.js +++ b/src/frontend/utils/time.js @@ -3,4 +3,5 @@ export default { SELECT_CARD: 60000, ONE_SECOND: 1000, HALF_SECOND: 500, + DEFAULT_TRANSITION: 200, }; From cebb3d2da262dd08dde456a8e3a8c95c724e47ff Mon Sep 17 00:00:00 2001 From: ramram1048 Date: Tue, 8 Dec 2020 12:44:08 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20setOrigin=20parameter=EA=B0=80=20str?= =?UTF-8?q?ing=EC=9D=B4=EC=97=88=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20=EB=8C=80?= =?UTF-8?q?=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 다른 method들은 다 number를 받도록 되있는데 setOrigin만 '10%' 같은 string으로 받게 되어있었음 --- src/frontend/engine/GameObject.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/frontend/engine/GameObject.js b/src/frontend/engine/GameObject.js index b5b26f2e..4697fa8d 100644 --- a/src/frontend/engine/GameObject.js +++ b/src/frontend/engine/GameObject.js @@ -81,11 +81,11 @@ const GameObject = class { this.setOrigin(); } - setOrigin(x = '50%', y = '50%') { - const numberY = makeFloat(y); - const numberX = makeFloat(x); - this.originStyle = `translate(-${x}, -${y})`; - this.instance.style.transformOrigin = `${50 - numberX}% ${50 - numberY}%`; + setOrigin(x = 50, y = 50) { + const xString = makeUnitString(x, '%'); + const yString = makeUnitString(y, '%'); + this.originStyle = `translate(-${xString}, -${yString})`; + this.instance.style.transformOrigin = `${50 - x}% ${50 - y}%`; this.transform(); }