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

Add: shooter_scoreを元にresultへの遷移 #46

Merged
merged 8 commits into from
Aug 18, 2024
Binary file modified public/drink/bottle0.webp
Binary file not shown.
Binary file modified public/drink/bottle2.webp
Binary file not shown.
Binary file modified public/drink/bottle3.webp
Binary file not shown.
14 changes: 6 additions & 8 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,12 @@ import Yatai from "./pages/yatai";

const AppRoutes = () => {
return (
<>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/shooter" element={<Shooter />} />
<Route path="/yatai" element={<Yatai />} />
<Route path="/result" element={<Result />} />
</Routes>
</>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/shooter" element={<Shooter />} />
<Route path="/result" element={<Result score={0} />} />
<Route path="/yatai" element={<Yatai />} />
</Routes>
);
};

Expand Down
18 changes: 12 additions & 6 deletions src/pages/result/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@ import GetImage from "../../components/GetImage";
import { DefaultButton } from "../../components/ui/Button";
import styles from "./index.module.css";

function Result() {
type ResultProps = {
score: number;
};

const Result = ({ score }: ResultProps) => {
const images = [
"/drink/bottle0.webp",
"/drink/bottle1.webp",
"/drink/bottle2.webp",
"/drink/bottle3.webp",
];

const image = images[score] || images[0];
K-Kizuku marked this conversation as resolved.
Show resolved Hide resolved

return (
<div>
<div className={styles["result-text"]}>
<p>結果発表!</p>
</div>
<div className={styles["get-image-container"]}>
<GetImage
images={images}
alt="ランダムに表示されるボトル画像"
images={[image]}
alt={`スコア ${score} に対応するボトル画像`}
width={160}
height={160}
/>
Expand All @@ -32,11 +38,11 @@ function Result() {
/>
</div>
<div className={styles["get-text"]}>
<p>Bottle Get!</p>
<p>{score}本倒した!</p>
</div>
<div className={styles["share-btn"]}>
<a
href="https://twitter.com/intent/tweet?text=Webの射的で遊んだよ.%20%23virtualnatsumatsuri%20%23炎上開発%20%23鹿児島ハッカソン"
href={`https://twitter.com/intent/tweet?text=Webの射的で遊んだよ。${score}本倒した!%20%23ハックツ夏祭り`}
target="_blank"
rel="noopener noreferrer"
>
Expand All @@ -50,6 +56,6 @@ function Result() {
</div>
</div>
);
}
};

export default Result;
47 changes: 26 additions & 21 deletions src/pages/shooter/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import { type KeyboardEventHandler, useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
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 { useSocketSender } from "../../hooks/useSocketSender";
import { useUUIDStore } from "../../store";
import { useScoreStore } from "../../store/useScoreStore";
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);
const { orientationDiff } = useOrientation();
const { sendData } = useSocketSender();
const { onMessage } = useSocketReceiver();
const uuid = useUUIDStore((state) => state.uuid);
const navigate = useNavigate();
const score = useScoreStore((state) => state.score);
const setScore = useScoreStore((state) => state.setScore);

const initialImages = [
"/2D_material/cork.webp",
"/2D_material/cork.webp",
"/2D_material/cork.webp",
];

const [images, setImages] = useState(initialImages);
const uuid = useUUIDStore((state) => state.uuid);

useEffect(() => {
let intervalId: number | null = null;
Expand All @@ -33,30 +36,28 @@ const Shooter = () => {
sendData(message_type.status, uuid, orientationDiff);
}, 100);

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

useEffect(() => {
onMessage((data) => {
if (data.message_type === MessageType.Hit && data.id === uuid) {
setScore((prevScore) => prevScore + 1);
console.log(score);
setScore((prevScore: number) => prevScore + 1);
Sea10wood marked this conversation as resolved.
Show resolved Hide resolved
}
});
}, [onMessage, uuid, score]);
}, [onMessage, uuid, setScore]);

useEffect(() => {
if (images.length === 0) {
navigate("/result", { state: { score } });
}
}, [images, navigate, score]);

const handleClick = () => {
const audio = new Audio("/sound/cork_sound.mp3");
audio
.play()
.then(() => {})
.catch((error) => {
console.error("オーディオの音が出なかった", error);
});
audio.play().catch((error) => {
console.error("オーディオの音が出なかった", error);
});
sendData(message_type.action, uuid, orientationDiff);
setImages((prevImages) => prevImages.slice(1));
};
Expand All @@ -76,10 +77,14 @@ const Shooter = () => {
<ShooterButton onClick={handleClick} onKeyUp={handleKeyUp} />
</div>
<div className={style.cork}>
{images.map((src, i) => (
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
<img key={i} src={src} alt="コルクの残量を表示しています" />
))}
{images.length > 0 ? (
images.map((src, i) => (
// biome-ignore lint/suspicious/noArrayIndexKey: <explanation>
<img key={i} src={src} alt="コルクの残量を表示しています" />
))
) : (
<p>コルクがなくなりました!</p>
)}
</div>
</div>
);
Expand Down
11 changes: 11 additions & 0 deletions src/store/useScoreStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import create from "zustand";
Sea10wood marked this conversation as resolved.
Show resolved Hide resolved

type Store = {
score: number;
setScore: (updater: (prevScore: number) => number) => void;
};

export const useScoreStore = create<Store>((set) => ({
score: 0,
setScore: (updater) => set((state) => ({ score: updater(state.score) })),
}));