From 8c15e07e84dc8de84f7593074b2e8ccf1b259bc2 Mon Sep 17 00:00:00 2001 From: ikura-hamu <104292023+ikura-hamu@users.noreply.github.com> Date: Sun, 26 Jan 2025 00:19:41 +0900 Subject: [PATCH 1/8] =?UTF-8?q?:sparkles:=20speakerPhone=E3=81=AE=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pixi/World.tsx | 76 ++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/client/src/pixi/World.tsx b/client/src/pixi/World.tsx index 57eb30ec..05cd6672 100644 --- a/client/src/pixi/World.tsx +++ b/client/src/pixi/World.tsx @@ -12,6 +12,7 @@ import messagesAtom from "../state/message"; import MessageIcon from "./components/MessageIcon"; import useMessageExpanded from "./hooks/message"; import { isInsideField } from "../util/field"; +import fieldSpeakerPhonesAtom from "../state/speakerPhone"; interface Props { userPosition: Position; @@ -27,7 +28,9 @@ const World: React.FC = ({ const { expanded, collapseMessage, expandMessage, message } = useMessageExpanded(); const messages = useAtomValue(messagesAtom); - const messageNodes = []; + const speakerPhones = useAtomValue(fieldSpeakerPhonesAtom); + + const messageNodes: JSX.Element[] = []; for (const message of messages.values()) { if (!isInsideField(message.position, fieldSize, userPosition)) { continue; @@ -42,24 +45,49 @@ const World: React.FC = ({ ); } + const speakerPhoneNodes = Array.from(speakerPhones.values()) + .filter((speakerPhone) => + isInsideField(speakerPhone.position, fieldSize, userPosition), + ) + .map((speakerPhone) => ( + + )); + //TODO: モック用なので後で消す - for (let i = 1; i <= 3; i++) { - messageNodes.push( - , - ); + { + for (let i = 1; i <= 3; i++) { + messageNodes.push( + , + ); + } + for (let i = 4; i <= 6; i++) { + speakerPhoneNodes.push( + , + ); + } } return ( @@ -79,17 +107,7 @@ const World: React.FC = ({ fillColor={0xeeeeee} fillAlpha={1} /> - - - + {speakerPhoneNodes} {messageNodes} Date: Sun, 26 Jan 2025 00:20:11 +0900 Subject: [PATCH 2/8] :recycle: fieldSpeakerPhonesAtom -> speakerPhonesAtom --- client/src/pixi/World.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/pixi/World.tsx b/client/src/pixi/World.tsx index 05cd6672..90206450 100644 --- a/client/src/pixi/World.tsx +++ b/client/src/pixi/World.tsx @@ -12,7 +12,7 @@ import messagesAtom from "../state/message"; import MessageIcon from "./components/MessageIcon"; import useMessageExpanded from "./hooks/message"; import { isInsideField } from "../util/field"; -import fieldSpeakerPhonesAtom from "../state/speakerPhone"; +import speakerPhonesAtom from "../state/speakerPhone"; interface Props { userPosition: Position; @@ -28,7 +28,7 @@ const World: React.FC = ({ const { expanded, collapseMessage, expandMessage, message } = useMessageExpanded(); const messages = useAtomValue(messagesAtom); - const speakerPhones = useAtomValue(fieldSpeakerPhonesAtom); + const speakerPhones = useAtomValue(speakerPhonesAtom); const messageNodes: JSX.Element[] = []; for (const message of messages.values()) { From 9ade6194b97762bd6ada59f0a93aacbdce124c88 Mon Sep 17 00:00:00 2001 From: ikura-hamu <104292023+ikura-hamu@users.noreply.github.com> Date: Sun, 26 Jan 2025 00:22:55 +0900 Subject: [PATCH 3/8] =?UTF-8?q?:sparkles:=20reaction=E3=81=AE=E8=A1=A8?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pixi/World.tsx | 56 ++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/client/src/pixi/World.tsx b/client/src/pixi/World.tsx index 90206450..1977fa82 100644 --- a/client/src/pixi/World.tsx +++ b/client/src/pixi/World.tsx @@ -13,6 +13,7 @@ import MessageIcon from "./components/MessageIcon"; import useMessageExpanded from "./hooks/message"; import { isInsideField } from "../util/field"; import speakerPhonesAtom from "../state/speakerPhone"; +import fieldReactionsAtom from "../state/reactions"; interface Props { userPosition: Position; @@ -29,6 +30,7 @@ const World: React.FC = ({ useMessageExpanded(); const messages = useAtomValue(messagesAtom); const speakerPhones = useAtomValue(speakerPhonesAtom); + const reactions = useAtomValue(fieldReactionsAtom); const messageNodes: JSX.Element[] = []; for (const message of messages.values()) { @@ -58,6 +60,22 @@ const World: React.FC = ({ /> )); + const reactionsNodes = Array.from(reactions.values()) + .filter((reaction) => + isInsideField(reaction.position, fieldSize, userPosition), + ) + .map((reaction) => ( + + )); + //TODO: モック用なので後で消す { for (let i = 1; i <= 3; i++) { @@ -88,6 +106,19 @@ const World: React.FC = ({ />, ); } + for (let i = 7; i <= 9; i++) { + reactionsNodes.push( + , + ); + } } return ( @@ -109,30 +140,7 @@ const World: React.FC = ({ /> {speakerPhoneNodes} {messageNodes} - - - + {reactionsNodes} Date: Sun, 26 Jan 2025 00:23:38 +0900 Subject: [PATCH 4/8] :recycle: fieldReactionsAtom -> reactionsAtom --- client/src/pixi/World.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/pixi/World.tsx b/client/src/pixi/World.tsx index 1977fa82..4d10afa1 100644 --- a/client/src/pixi/World.tsx +++ b/client/src/pixi/World.tsx @@ -13,7 +13,7 @@ import MessageIcon from "./components/MessageIcon"; import useMessageExpanded from "./hooks/message"; import { isInsideField } from "../util/field"; import speakerPhonesAtom from "../state/speakerPhone"; -import fieldReactionsAtom from "../state/reactions"; +import reactionsAtom from "../state/reactions"; interface Props { userPosition: Position; @@ -30,7 +30,7 @@ const World: React.FC = ({ useMessageExpanded(); const messages = useAtomValue(messagesAtom); const speakerPhones = useAtomValue(speakerPhonesAtom); - const reactions = useAtomValue(fieldReactionsAtom); + const reactions = useAtomValue(reactionsAtom); const messageNodes: JSX.Element[] = []; for (const message of messages.values()) { From bc03080bf27893139d6dad489321e218e2eecfc8 Mon Sep 17 00:00:00 2001 From: ikura-hamu <104292023+ikura-hamu@users.noreply.github.com> Date: Sun, 26 Jan 2025 01:05:53 +0900 Subject: [PATCH 5/8] =?UTF-8?q?:sparkles:=20=E4=BB=96=E3=81=AEexplorer?= =?UTF-8?q?=E3=81=AE=E8=A1=A8=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pixi/World.tsx | 14 +++++ client/src/pixi/components/OtherExplorer.tsx | 60 ++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/client/src/pixi/World.tsx b/client/src/pixi/World.tsx index 4d10afa1..1e60f3f9 100644 --- a/client/src/pixi/World.tsx +++ b/client/src/pixi/World.tsx @@ -14,6 +14,8 @@ import useMessageExpanded from "./hooks/message"; import { isInsideField } from "../util/field"; import speakerPhonesAtom from "../state/speakerPhone"; import reactionsAtom from "../state/reactions"; +import fieldExplorersAtom from "../state/explorer"; +import OtherExplorer from "./components/OtherExplorer"; interface Props { userPosition: Position; @@ -31,6 +33,7 @@ const World: React.FC = ({ const messages = useAtomValue(messagesAtom); const speakerPhones = useAtomValue(speakerPhonesAtom); const reactions = useAtomValue(reactionsAtom); + const explorers = useAtomValue(fieldExplorersAtom); const messageNodes: JSX.Element[] = []; for (const message of messages.values()) { @@ -76,6 +79,16 @@ const World: React.FC = ({ /> )); + const explorerNodes = Array.from(explorers.values()).map((explorer) => { + return ( + + ); + }); + //TODO: モック用なので後で消す { for (let i = 1; i <= 3; i++) { @@ -140,6 +153,7 @@ const World: React.FC = ({ /> {speakerPhoneNodes} {messageNodes} + {explorerNodes} {reactionsNodes} = ({ explorer, previousPosition }) => { + // previousPosition: 1つ前の受信時の位置 + const { position: targetPosition, userId } = explorer; // 目標の位置 + const { data, error, isLoading } = useUser(userId); + const [position, setPosition] = useState(targetPosition); // 実際の現在の位置 + + useTick(() => { + if (previousPosition) { + if (position.x === targetPosition.x && position.y === targetPosition.y) { + return; + } + setPosition((pos) => { + const diff = { + x: pos.x - previousPosition.x, + y: pos.y - previousPosition.y, + }; + if (Math.abs(diff.x) < 3 && Math.abs(diff.y) < 3) { + return targetPosition; + } + const speed = 0.1; + return { + x: position.x + diff.x * speed, + y: position.y + diff.y * speed, + }; + }); + } + }); + + if (isLoading || error || !data) { + return null; + } + const user = data.user; + if (!user) { + return null; + } + + return ( + + ); +}; + +export default OtherExplorer; From 3baa647c59ce3b12f53c0562046ed8d38ad4f32e Mon Sep 17 00:00:00 2001 From: ikura-hamu <104292023+ikura-hamu@users.noreply.github.com> Date: Sun, 26 Jan 2025 01:06:29 +0900 Subject: [PATCH 6/8] :recycle: fieldExplorersAtom => explorersAtom --- client/src/pixi/World.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/pixi/World.tsx b/client/src/pixi/World.tsx index 1e60f3f9..afcfb140 100644 --- a/client/src/pixi/World.tsx +++ b/client/src/pixi/World.tsx @@ -14,7 +14,7 @@ import useMessageExpanded from "./hooks/message"; import { isInsideField } from "../util/field"; import speakerPhonesAtom from "../state/speakerPhone"; import reactionsAtom from "../state/reactions"; -import fieldExplorersAtom from "../state/explorer"; +import explorersAtom from "../state/explorer"; import OtherExplorer from "./components/OtherExplorer"; interface Props { @@ -33,7 +33,7 @@ const World: React.FC = ({ const messages = useAtomValue(messagesAtom); const speakerPhones = useAtomValue(speakerPhonesAtom); const reactions = useAtomValue(reactionsAtom); - const explorers = useAtomValue(fieldExplorersAtom); + const explorers = useAtomValue(explorersAtom); const messageNodes: JSX.Element[] = []; for (const message of messages.values()) { From 6d808dbfa34e084b6862cc08c63e83f8b1ed0e7d Mon Sep 17 00:00:00 2001 From: ikura-hamu <104292023+ikura-hamu@users.noreply.github.com> Date: Sun, 26 Jan 2025 01:12:33 +0900 Subject: [PATCH 7/8] =?UTF-8?q?:sparkles:=20=E4=BD=8D=E7=BD=AE=E6=83=85?= =?UTF-8?q?=E5=A0=B1=E3=82=92=E9=80=81=E4=BF=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pixi/Canvas.tsx | 49 ++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/client/src/pixi/Canvas.tsx b/client/src/pixi/Canvas.tsx index 91b631c4..4f689783 100644 --- a/client/src/pixi/Canvas.tsx +++ b/client/src/pixi/Canvas.tsx @@ -14,6 +14,7 @@ import { } from "../model/position"; import Explorer from "./components/Explorer"; import PIXI from "pixi.js"; +import useExplorerDispatcher from "../api/explorer"; const mountHandler = import.meta.env.DEV ? (app: PIXI.Application) => { @@ -40,6 +41,7 @@ const Canvas: React.FC = (props) => { } | null>(null); const [intervalID, setIntervalID] = useState(null); const stageRef = useRef(null); + const dispatcher = useExplorerDispatcher(); useEffect(() => { const width = (window.innerWidth * 3) / 5; @@ -66,25 +68,36 @@ const Canvas: React.FC = (props) => { }; }, [fieldSize]); - const updateUserPosition = useCallback((targetPosition: Position) => { - setUserPosition((position) => { - if (position === null) { - return null; - } - const diff = { - x: targetPosition.x - position.x, - y: targetPosition.y - position.y, - }; - if (Math.abs(diff.x) < 3 && Math.abs(diff.y) < 3) { - return targetPosition; - } - const nextPosition = calcNewPosition(position, { - x: diff.x / 10, - y: diff.y / 10, + const updateUserPosition = useCallback( + (targetPosition: Position) => { + setUserPosition((position) => { + if (position === null || fieldSize === null) { + return null; + } + const diff = { + x: targetPosition.x - position.x, + y: targetPosition.y - position.y, + }; + if (Math.abs(diff.x) < 3 && Math.abs(diff.y) < 3) { + dispatcher({ + position: targetPosition, + size: fieldSize, + }); + return targetPosition; + } + const nextPosition = calcNewPosition(position, { + x: diff.x / 10, + y: diff.y / 10, + }); + dispatcher({ + position: nextPosition, + size: fieldSize, + }); + return nextPosition; }); - return nextPosition; - }); - }, []); + }, + [dispatcher, fieldSize], + ); const onFieldClick = useCallback( (e: React.MouseEvent) => { From 9fcc3a5ac90d9da7a65e9de131b1a3add310eff3 Mon Sep 17 00:00:00 2001 From: ikura-hamu <104292023+ikura-hamu@users.noreply.github.com> Date: Sun, 26 Jan 2025 01:16:06 +0900 Subject: [PATCH 8/8] =?UTF-8?q?:bug:=20=E7=A7=BB=E5=8B=95=E3=81=AE?= =?UTF-8?q?=E3=83=AD=E3=82=B8=E3=83=83=E3=82=AF=E9=96=93=E9=81=95=E3=81=A3?= =?UTF-8?q?=E3=81=A6=E3=81=84=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pixi/components/OtherExplorer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/pixi/components/OtherExplorer.tsx b/client/src/pixi/components/OtherExplorer.tsx index ba6dc092..f67e17f8 100644 --- a/client/src/pixi/components/OtherExplorer.tsx +++ b/client/src/pixi/components/OtherExplorer.tsx @@ -24,8 +24,8 @@ const OtherExplorer: React.FC = ({ explorer, previousPosition }) => { } setPosition((pos) => { const diff = { - x: pos.x - previousPosition.x, - y: pos.y - previousPosition.y, + x: targetPosition.x - pos.x, + y: targetPosition.y - pos.y, }; if (Math.abs(diff.x) < 3 && Math.abs(diff.y) < 3) { return targetPosition;