Skip to content
This repository has been archived by the owner on Nov 26, 2024. It is now read-only.

ぬるぬる動くようになった #49

Merged
merged 12 commits into from
Aug 19, 2024
13 changes: 8 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<!doctype html>
<html lang="en">
<!DOCTYPE html>
claustra01 marked this conversation as resolved.
Show resolved Hide resolved
<html lang="ja">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/webp" href="/logo.webp" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Dela+Gothic+One&family=Yuji+Syuku&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Dela+Gothic+One&family=Yuji+Syuku&display=swap"
rel="stylesheet"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>VIRTUAL_NATSUMATSURI</title>
</head>
Expand Down
15 changes: 8 additions & 7 deletions src/components/Yatai/TargetOverlay.module.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
.target {
position: absolute;
z-index: 1;
width: 100px;
height: 100px;
transform: translate(calc(-50%+50px), calc(-50%+50px));
position: absolute;
z-index: 1;
width: 100px;
height: 100px;
transform: translate(calc(-50%+50px), calc(-50%+50px));
transition: all 0.1s linear;
claustra01 marked this conversation as resolved.
Show resolved Hide resolved
}

.image {
width: 100%;
height: 100%;
width: 100%;
height: 100%;
}
25 changes: 10 additions & 15 deletions src/components/Yatai/TargetOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,35 @@
import { useEffect, useState } from "react";
import { useSocketReceiver } from "../../hooks/useSocketReceiver";
import {
type ActionSchema,
MessageType,
type Target,
} from "../../type/shooting";
import type { ActionSchema, PointerSchema, Target } from "../../type/shooting";
import { MessageType } from "../../type/shooting";
import styles from "./TargetOverlay.module.css";

export const TargetOverlay = () => {
const { onMessage } = useSocketReceiver();

useEffect(() => {
onMessage((data) => {
// ここも本来はPointerSchemaになる
if (data.message_type === MessageType.Action) {
shotTarget(data);
}
if (data.message_type === MessageType.Pointer) {
aimTarget(data);
}
});
}, [onMessage]);

// TODO: これらは一人用,いつかマルチプレイヤー対応する
const [aim, setAim] = useState<Target | undefined>(undefined);
// TODO: エイム照準の実装
// const aimTarget = (data: PointerSchema) => {
// const x = window.innerWidth * data.target.x + window.innerWidth / 2;
// const y = window.innerHeight * data.target.y + window.innerHeight / 2;
// setAim({ x, y });
// };
const aimTarget = (data: PointerSchema) => {
const x = window.innerWidth / 2 + data.target.x * 1200;
const y = window.innerHeight / 2 + data.target.y * 1200;
setAim({ x, y });
};

// const [target, setTarget] = useState<Target | undefined>(undefined);
const shotTarget = (data: ActionSchema) => {
const x = window.innerWidth / 2 + data.target.x * 1200;
const y = window.innerHeight / 2 + data.target.y * 1200;
// TODO: エイム実装ができたらここのsetAimは削除する
setAim({ x, y });
// setTarget({ x, y });
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この辺、pointerはaimで、actionはtargetでx,yを保持していようという意図の宣言だったんですけど、よく考えたら別にaimだけで良さそうですね
であれば、aimTargetとshotTargetも統合できるので、不要なコメント群諸々綺麗にして欲しいです

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あーこの使い分け意味あるのかと思ったけど統合していいやつなのね
統合しときます

};

return (
Expand Down
102 changes: 68 additions & 34 deletions src/pages/shooter/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { type KeyboardEventHandler, useEffect, useState } from "react";
import {
type KeyboardEventHandler,
useCallback,
useEffect,
useState,
} from "react";
import { DefaultButton } from "../../components/ui/Button";
import { Modal } from "../../components/ui/Modal";
import { ShooterButton } from "../../components/ui/ShooterButton";
import { useOrientation } from "../../hooks/useOrientation";
import { useSocketReceiver } from "../../hooks/useSocketReceiver";
import type { Orientation } from "../../hooks/useOrientation";
import { useSocketSender } from "../../hooks/useSocketSender";
import { useUUIDStore } from "../../store";
import { message_type } from "../../type/schema";
import { MessageType } from "../../type/shooting";
import style from "./index.module.css";

const Shooter = () => {
const [isOpen, setIsOpen] = useState(true);
const [score, setScore] = useState<number>(0);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このscoreは命中した数のカウント用なんだ!!消さないでくれ🥺🥺

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あ、ミスって消してたわ
戻しとく

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sea10さんのzustandでのscore管理をマージしたので、そのまま消しておきます

const { orientationDiff } = useOrientation();
const { sendData } = useSocketSender();
const { onMessage } = useSocketReceiver();

const initialImages = [
"/2D_material/cork.webp",
Expand All @@ -25,39 +25,56 @@ const Shooter = () => {

const [images, setImages] = useState(initialImages);
const uuid = useUUIDStore((state) => state.uuid);
// const intervalId = useRef<number | null>(null);
const [initialOrientation, setInitialOrientation] = useState<Orientation>({
alpha: 0,
beta: 0,
gamma: 0,
});

const send = useCallback(
(event: DeviceOrientationEvent, msg_type: message_type) => {
if (!event.alpha || !event.beta || !event.gamma) {
return;
}
console.log(event.alpha, event.beta, event.gamma);
K-Kizuku marked this conversation as resolved.
Show resolved Hide resolved
sendData(msg_type, uuid, {
alpha: initialOrientation
? (event.gamma - initialOrientation.gamma) * 2
: event.gamma,
beta: initialOrientation
? event.beta - initialOrientation.beta
: event.beta,
claustra01 marked this conversation as resolved.
Show resolved Hide resolved
});
},
[sendData, uuid, initialOrientation],
);
useEffect(() => {
let intervalId: number | null = null;

intervalId = window.setInterval(() => {
sendData(message_type.status, uuid, orientationDiff);
const intervalId = setInterval(() => {
window.addEventListener(
"deviceorientation",
(event) => send(event, message_type.status),
{ once: true },
);
}, 100);

return () => {
if (intervalId !== null) {
clearInterval(intervalId);
}
clearInterval(intervalId);
};
}, [uuid, orientationDiff, sendData]);
}, [send]);

useEffect(() => {
onMessage((data) => {
if (data.message_type === MessageType.Hit && data.id === uuid) {
setScore((prevScore) => prevScore + 1);
console.log(score);
}
});
}, [onMessage, uuid, score]);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この辺でtype=hitのwebsocketメッセージを受け取ってスコアをカウントしてる
消さないでくれ🥺🥺

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同じく戻しとく

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上に同じ


const handleClick = () => {
const handleClick = async () => {
window.addEventListener(
"deviceorientation",
(event) => send(event, message_type.action),
{ once: true },
);
const audio = new Audio("/sound/cork_sound.mp3");
audio
.play()
.then(() => {})
.catch((error) => {
console.error("オーディオの音が出なかった", error);
});
sendData(message_type.action, uuid, orientationDiff);
setImages((prevImages) => prevImages.slice(1));
};

Expand All @@ -70,7 +87,10 @@ const Shooter = () => {
return (
<div>
<Modal open={isOpen} onClose={() => setIsOpen(false)}>
<ModalContent setIsOpen={setIsOpen} />
<ModalContent
setIsOpen={setIsOpen}
setInitialOrientation={setInitialOrientation}
/>
</Modal>
<div className={style.trigger}>
<ShooterButton onClick={handleClick} onKeyUp={handleKeyUp} />
Expand All @@ -87,10 +107,27 @@ const Shooter = () => {

type ModalContentProps = {
setIsOpen: (isOpen: boolean) => void;
setInitialOrientation: (orientation: Orientation) => void;
};

const ModalContent: React.FC<ModalContentProps> = ({ setIsOpen }) => {
const { reset } = useOrientation();
const ModalContent: React.FC<ModalContentProps> = ({
setIsOpen,
setInitialOrientation,
}) => {
const handleClick = () => {
window.addEventListener(
"deviceorientation",
(event) => {
setInitialOrientation({
alpha: event.alpha || 0,
beta: event.beta || 0,
gamma: event.gamma || 0,
});
},
{ once: true },
);
setIsOpen(false);
};
return (
<div className={style["modal-wrapper"]}>
<img
Expand All @@ -111,10 +148,7 @@ const ModalContent: React.FC<ModalContentProps> = ({ setIsOpen }) => {
variant="outlined"
color="red"
size="md"
onClick={() => {
reset();
setIsOpen(false);
}}
onClick={handleClick}
>
置いたよ!
</DefaultButton>
Expand Down