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

Commit

Permalink
refactor: create yatai components
Browse files Browse the repository at this point in the history
  • Loading branch information
claustra01 committed Aug 15, 2024
1 parent cfceaa5 commit 07f685e
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 214 deletions.
8 changes: 8 additions & 0 deletions src/components/Yatai/CameraController.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useThree } from "@react-three/fiber";

export const CameraController = () => {
const { camera } = useThree();
camera.position.set(0, 3, 12);
camera.lookAt(0, 2, 0);
return null;
};
7 changes: 7 additions & 0 deletions src/components/Yatai/TargetOverlay.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.target {
position: absolute;
z-index: 1;
width: 100px;
height: 100px;
}

57 changes: 57 additions & 0 deletions src/components/Yatai/TargetOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useEffect, useState } from "react";
import { useSocketReceiver } from "../../hooks/useSocketReceiver";
import {
type ActionSchema,
MessageType,
type Target,
} 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);
}
});
}, [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 [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 });
};

return (
<div
className={styles.target}
style={{
left: `${aim?.x}px`,
top: `${aim?.y}px`,
transform: "translate(-50%, -50%)",
}}
>
<img
src="/2D_material/target.webp"
alt="照準の表示"
width="100%"
height="100%"
/>
</div>
);
};
37 changes: 37 additions & 0 deletions src/components/Yatai/YataiFoundation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useBox } from "@react-three/cannon";
import type { ThreeElements } from "@react-three/fiber";
import type {
BufferGeometry,
Material,
Mesh,
NormalBufferAttributes,
Object3DEventMap,
} from "three";

export const YataiFoundation = (props: ThreeElements["mesh"]) => {
const args: [number, number, number] = [10, 2, 2];
const [ref] = useBox(() => ({
mass: 0,
position: props.position as [number, number, number],
args: args,
}));
return (
<mesh
ref={
ref as React.Ref<
Mesh<
BufferGeometry<NormalBufferAttributes>,
Material | Material[],
Object3DEventMap
>
>
}
{...props}
castShadow
receiveShadow
>
<boxGeometry args={[...args]} />
<meshStandardMaterial color={"red"} />
</mesh>
);
};
6 changes: 6 additions & 0 deletions src/components/Yatai/YataiStage.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.canvas {
width: 100%;
height: 100%;
background-color: transparent;
}

38 changes: 38 additions & 0 deletions src/components/Yatai/YataiStage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Physics } from "@react-three/cannon";
import { Canvas } from "@react-three/fiber";
import { memo } from "react";
import { CameraController } from "./CameraController";
import { YataiFoundation } from "./YataiFoundation";
import styles from "./YataiStage.module.css";
import { YataiTarget } from "./YataiTarget";

export const YataiStage = memo(() => {
return (
<div className={styles.canvas}>
<Canvas shadows camera={{ fov: 25 }}>
<Physics>
{/* 全体ライト */}
<ambientLight intensity={Math.PI / 16} />
{/* スポットライト */}
<spotLight
castShadow
position={[4, 12, 8]}
angle={0.5}
penumbra={0}
decay={0}
intensity={Math.PI}
shadow-mapSize-width={1024}
shadow-mapSize-height={1024}
shadow-bias={-0.0001}
/>
<CameraController />
<YataiFoundation position={[0, 2, -2]} />
<YataiFoundation position={[0, 0, 0]} />
<YataiTarget position={[-3, 1.8, 0]} />
<YataiTarget position={[0, 1.8, 0]} />
<YataiTarget position={[3, 1.8, 0]} />
</Physics>
</Canvas>
</div>
);
});
84 changes: 84 additions & 0 deletions src/components/Yatai/YataiTarget.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { useBox } from "@react-three/cannon";
import type { ThreeElements } from "@react-three/fiber";
import { useEffect, useState } from "react";
import type {
BufferGeometry,
Material,
Mesh,
NormalBufferAttributes,
Object3DEventMap,
} from "three";
import { randFloat } from "three/src/math/MathUtils.js";
import { useSocketReceiver } from "../../hooks/useSocketReceiver";
import { useSocketSender } from "../../hooks/useSocketSender";
import { message_type } from "../../type/schema";
import {
type ActionSchema,
MessageType,
type Target,
} from "../../type/shooting";

export const YataiTarget = (props: ThreeElements["mesh"]) => {
const { sendData } = useSocketSender();
const { onMessage } = useSocketReceiver();
const position = props.position as [number, number, number];

const args: [number, number, number] = [0.7, 2, 0.7];
const [ref, api] = useBox(() => ({
mass: 1,
position: position,
args: args,
}));

useEffect(() => {
onMessage((data) => {
if (data.message_type === MessageType.Action) {
shotTarget(data);
}
});
}, [onMessage]);

// TODO: これらは一人用,いつかマルチプレイヤー対応する
const [uuid, setUuid] = useState<string>("");
const [target, setTarget] = useState<Target | undefined>(undefined);
const shotTarget = (data: ActionSchema) => {
setUuid(data.id);
setTarget({ x: data.target.x, y: data.target.y });
};

useEffect(() => {
if (!target) return;
if (
target.x * 8 > position[0] - args[0] / 2 &&
target.x * 8 < position[0] + args[0] / 2 &&
target.y * 8 > position[1] - args[1] / 2 - 2 &&
target.y * 8 < position[1] + args[1] / 2 - 2
) {
api.applyImpulse(
[randFloat(-2, 2), 4, 8],
[randFloat(-1, 1), randFloat(-1, 1), randFloat(-1, 1)],
);
sendData(message_type.Hit, uuid, { alpha: 0, beta: 0 });
}
}, [uuid, target, position, api, sendData]);

return (
<mesh
ref={
ref as React.Ref<
Mesh<
BufferGeometry<NormalBufferAttributes>,
Material | Material[],
Object3DEventMap
>
>
}
{...props}
castShadow
receiveShadow
>
<boxGeometry args={[...args]} />
<meshStandardMaterial color={"yellow"} />
</mesh>
);
};
13 changes: 0 additions & 13 deletions src/pages/yatai/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,3 @@
justify-content: center;
align-items: center;
}

.canvas {
width: 100%;
height: 100%;
background-color: transparent;
}

.target {
position: absolute;
z-index: 1;
width: 100px;
height: 100px;
}
Loading

0 comments on commit 07f685e

Please sign in to comment.