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

命中判定を送ったり受け取ったり #45

Merged
merged 17 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,384 changes: 1,844 additions & 1,540 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

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;
};
12 changes: 12 additions & 0 deletions src/components/Yatai/TargetOverlay.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.target {
position: absolute;
z-index: 1;
width: 100px;
height: 100px;
transform: translate(calc(-50%+50px), calc(-50%+50px));
}

.image {
width: 100%;
height: 100%;
}
55 changes: 55 additions & 0 deletions src/components/Yatai/TargetOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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`,
K-Kizuku marked this conversation as resolved.
Show resolved Hide resolved
}}
>
<img
src="/2D_material/target.webp"
alt="照準の表示"
className={styles.image}
/>
</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>
);
};
22 changes: 22 additions & 0 deletions src/hooks/useSocketReceiver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useSocketRefStore } from "../store";
import type { ActionSchema, HitSchema, PointerSchema } from "../type/shooting";

export const useSocketReceiver = () => {
const socketRef = useSocketRefStore((state) => state.socketRef);

const onMessage = (
handler: (data: PointerSchema | ActionSchema | HitSchema) => void,
) => {
const onMessage = (event: MessageEvent) => {
const data = JSON.parse(event.data);
handler(data);
};
const currentSocketRef = socketRef?.current;
currentSocketRef?.addEventListener("message", onMessage);
return () => {
currentSocketRef?.removeEventListener("message", onMessage);
};
};

return { onMessage };
};
41 changes: 41 additions & 0 deletions src/hooks/useSocketSender.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useCallback } from "react";
import { useSocketRefStore } from "../store";
import { type Schema, event_type, type message_type } from "../type/schema";

export const useSocketSender = () => {
const socketRef = useSocketRefStore((state) => state.socketRef);

const sendData = useCallback(
(
mes_type: message_type,
uuid: string,
orientationDiff: { alpha: number; beta: number },
) => {
const data: Schema = {
id: uuid,
interval: 0,
angle: {
x: -orientationDiff.alpha,
y: -orientationDiff.beta,
},
acceleration: {
x: 0,
y: 0,
z: 0,
},
distance: {
x: 0,
y: 0,
z: 0,
},
message_type: mes_type,
event_type: event_type.shooter,
};
console.log(data);
socketRef?.current?.send(JSON.stringify(data));
},
[socketRef],
);

return { sendData };
};
Loading