Skip to content
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
1 change: 1 addition & 0 deletions apps/frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
height: 100vh;
position: relative;
overflow: hidden;
background-color: rgb(163, 139, 102);
}

.title {
Expand Down
31 changes: 28 additions & 3 deletions apps/frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
import Board from "./features/chess/compomemt/Board";
import { Canvas } from "@react-three/fiber";
import { Text3D, Center } from "@react-three/drei";
import * as THREE from "three";

import "@/App.css";

function App() {
return (
<>
<div className="app-container">
<div className="title">Chess</div>
<Board className="container-3d" />
<div className='app-container'>
<Canvas>
{/* ライトをCanvas直下に配置 */}
<directionalLight position={[0, 0, 15]} />
<ambientLight intensity={0.2} />

<Center position={[0, 3.1, 0.3]}>
<Text3D
font='https://threejs.org/examples/fonts/helvetiker_regular.typeface.json'
size={0.5}
height={0.1}
bevelEnabled={true} // ベベルを有効化
bevelThickness={0.1}
rotation={[Math.PI / 7, 0, 0]}
>
AI Chess
{/* マテリアルを追加 */}
<meshStandardMaterial
color={new THREE.Color("rgba(249, 209, 8, 1)")}
/>
</Text3D>
</Center>

<Board className='container-3d' />
</Canvas>
</div>
</>
);
Expand Down
21 changes: 11 additions & 10 deletions apps/frontend/src/features/chess/compomemt/Board.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Line, Loader } from "@react-three/drei";
import { OrbitControls } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import ChessPieces from "./ChessPieces";
import { Microphone } from "@/features/microphone";
import { useState } from "react";
Expand All @@ -19,7 +18,9 @@ interface BoardProps {
function ChessLine() {
const squares = [];
const squareSize = 0.6; // 1マスのサイズ
const borderColor = new THREE.Color("rgba(228, 221, 209, 1)").convertSRGBToLinear();
const borderColor = new THREE.Color(
"rgba(228, 221, 209, 1)"
).convertSRGBToLinear();

for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
Expand Down Expand Up @@ -57,16 +58,16 @@ function ChessLine() {
</>
);
}
const Board: React.FC<BoardProps> = ({ className }) => {
const Board: React.FC<BoardProps> = ({}) => {
const [commanddata, setCommanddata] = useState<VoiceInput | null>(null);
const { turn } = useTurnStore();

return (
<Canvas className={className}>
<>
<OrbitControls />
<Loader />
<ambientLight intensity={0.6} />
<directionalLight position={[5, 5, 5]} />
<directionalLight position={[5, 6.5, 5]} />
{turn == "white" && (
<Microphone
onTranscript={(text) => console.log("認識結果:", text)}
Expand All @@ -76,7 +77,7 @@ const Board: React.FC<BoardProps> = ({ className }) => {
}}
onListeningChange={(listening) => console.log("録音中:", listening)}
onError={(err) => console.error(err)}
position={[0, 1.5, 5]}
position={[3, 0.8, 1.8]}
/>
)}
{turn == "black" && (
Expand All @@ -88,7 +89,7 @@ const Board: React.FC<BoardProps> = ({ className }) => {
}}
onListeningChange={(listening) => console.log("録音中:", listening)}
onError={(err) => console.error(err)}
position={[0, 1.5, 5]}
position={[3, 0.8, 1.8]}
/>
)}

Expand All @@ -98,13 +99,13 @@ const Board: React.FC<BoardProps> = ({ className }) => {
>
<mesh>
<planeGeometry args={[6, 6]} />
<Mark />
<meshPhongMaterial color="rgba(173, 138, 41, 1)" />
<Mark color={turn} />
<meshPhongMaterial color='rgba(173, 138, 41, 1)' />
</mesh>
<ChessLine />
<ChessPieces command={commanddata} />
</group>
</Canvas>
</>
);
};

Expand Down
118 changes: 60 additions & 58 deletions apps/frontend/src/features/chess/compomemt/ChooseFromSixPieces.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ import type { Piece } from "@repo/schema";
import { useAnimationStore, useTurnStore } from "./store";
import { useFrame } from "@react-three/fiber";
import { useRef, useEffect } from "react";
import * as THREE from "three";

interface ChessPieceProps {
piece: Piece;
}

// ポーン
function Pawn({ color }: { color: string }) {
function Pawn({ color }: { color: THREE.Color }) {
return (
<group rotation={[Math.PI / 2, 0, 0]}>
<mesh position={[0, 0.05, 0]}>
<cylinderGeometry args={[0.2, 0.22, 0.1, 16]} />
<mesh position={[0, 0.065, 0]}>
<cylinderGeometry args={[0.2, 0.22, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.25, 0]}>
<cylinderGeometry args={[0.08, 0.15, 0.3, 16]} />
<mesh position={[0, 0.325, 0]}>
<cylinderGeometry args={[0.08, 0.15, 0.39, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.5, 0]}>
<mesh position={[0, 0.65, 0]}>
<sphereGeometry args={[0.12, 16, 16]} />
<meshStandardMaterial color={color} />
</mesh>
Expand All @@ -29,31 +29,31 @@ function Pawn({ color }: { color: string }) {
}

// ルーク
function Rook({ color }: { color: string }) {
function Rook({ color }: { color: THREE.Color }) {
return (
<group rotation={[Math.PI / 2, 0, 0]}>
<mesh position={[0, 0.05, 0]}>
<cylinderGeometry args={[0.22, 0.24, 0.1, 16]} />
<mesh position={[0, 0.065, 0]}>
<cylinderGeometry args={[0.22, 0.24, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.3, 0]}>
<cylinderGeometry args={[0.12, 0.18, 0.4, 16]} />
<mesh position={[0, 0.39, 0]}>
<cylinderGeometry args={[0.12, 0.18, 0.52, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.55, 0]}>
<cylinderGeometry args={[0.18, 0.14, 0.1, 16]} />
<mesh position={[0, 0.715, 0]}>
<cylinderGeometry args={[0.18, 0.14, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
{[0, 90, 180, 270].map((angle) => (
<mesh
key={angle}
position={[
Math.cos((angle * Math.PI) / 180) * 0.12,
0.65,
0.845,
Math.sin((angle * Math.PI) / 180) * 0.12,
]}
>
<boxGeometry args={[0.08, 0.1, 0.08]} />
<boxGeometry args={[0.08, 0.13, 0.08]} />
<meshStandardMaterial color={color} />
</mesh>
))}
Expand All @@ -62,50 +62,50 @@ function Rook({ color }: { color: string }) {
}

// ナイト
function Knight({ color }: { color: string }) {
function Knight({ color }: { color: THREE.Color }) {
return (
<group rotation={[Math.PI / 2, 0, 0]}>
<mesh position={[0, 0.05, 0]}>
<cylinderGeometry args={[0.22, 0.24, 0.1, 16]} />
<mesh position={[0, 0.065, 0]}>
<cylinderGeometry args={[0.22, 0.24, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.35, -0.05]} rotation={[-0.3, 0, 0]}>
<boxGeometry args={[0.15, 0.4, 0.25]} />
<mesh position={[0, 0.455, -0.05]} rotation={[-0.3, 0, 0]}>
<boxGeometry args={[0.15, 0.52, 0.25]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.55, -0.15]} rotation={[-0.5, 0, 0]}>
<boxGeometry args={[0.12, 0.15, 0.3]} />
<mesh position={[0, 0.715, -0.15]} rotation={[-0.5, 0, 0]}>
<boxGeometry args={[0.12, 0.195, 0.3]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0.05, 0.65, -0.1]} rotation={[-0.3, 0, 0.2]}>
<boxGeometry args={[0.04, 0.1, 0.06]} />
<mesh position={[0.05, 0.845, -0.1]} rotation={[-0.3, 0, 0.2]}>
<boxGeometry args={[0.04, 0.13, 0.06]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[-0.05, 0.65, -0.1]} rotation={[-0.3, 0, -0.2]}>
<boxGeometry args={[0.04, 0.1, 0.06]} />
<mesh position={[-0.05, 0.845, -0.1]} rotation={[-0.3, 0, -0.2]}>
<boxGeometry args={[0.04, 0.13, 0.06]} />
<meshStandardMaterial color={color} />
</mesh>
</group>
);
}

// ビショップ
function Bishop({ color }: { color: string }) {
function Bishop({ color }: { color: THREE.Color }) {
return (
<group rotation={[Math.PI / 2, 0, 0]}>
<mesh position={[0, 0.05, 0]}>
<cylinderGeometry args={[0.22, 0.24, 0.1, 16]} />
<mesh position={[0, 0.065, 0]}>
<cylinderGeometry args={[0.22, 0.24, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.3, 0]}>
<cylinderGeometry args={[0.1, 0.18, 0.4, 16]} />
<mesh position={[0, 0.39, 0]}>
<cylinderGeometry args={[0.1, 0.18, 0.52, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.55, 0]}>
<coneGeometry args={[0.12, 0.25, 16]} />
<mesh position={[0, 0.715, 0]}>
<coneGeometry args={[0.12, 0.325, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.72, 0]}>
<mesh position={[0, 0.936, 0]}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial color={color} />
</mesh>
Expand All @@ -114,35 +114,35 @@ function Bishop({ color }: { color: string }) {
}

// クイーン
function Queen({ color }: { color: string }) {
function Queen({ color }: { color: THREE.Color }) {
return (
<group rotation={[Math.PI / 2, 0, 0]}>
<mesh position={[0, 0.05, 0]}>
<cylinderGeometry args={[0.24, 0.26, 0.1, 16]} />
<mesh position={[0, 0.065, 0]}>
<cylinderGeometry args={[0.24, 0.26, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.35, 0]}>
<cylinderGeometry args={[0.1, 0.2, 0.5, 16]} />
<mesh position={[0, 0.455, 0]}>
<cylinderGeometry args={[0.1, 0.2, 0.65, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.65, 0]}>
<cylinderGeometry args={[0.14, 0.1, 0.1, 16]} />
<mesh position={[0, 0.845, 0]}>
<cylinderGeometry args={[0.14, 0.1, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
{[0, 72, 144, 216, 288].map((angle) => (
<mesh
key={angle}
position={[
Math.cos((angle * Math.PI) / 180) * 0.1,
0.75,
0.975,
Math.sin((angle * Math.PI) / 180) * 0.1,
]}
>
<sphereGeometry args={[0.04, 8, 8]} />
<meshStandardMaterial color={color} />
</mesh>
))}
<mesh position={[0, 0.8, 0]}>
<mesh position={[0, 1.04, 0]}>
<sphereGeometry args={[0.06, 16, 16]} />
<meshStandardMaterial color={color} />
</mesh>
Expand All @@ -151,27 +151,27 @@ function Queen({ color }: { color: string }) {
}

// キング
function King({ color }: { color: string }) {
function King({ color }: { color: THREE.Color }) {
return (
<group rotation={[Math.PI / 2, 0, 0]}>
<mesh position={[0, 0.05, 0]}>
<cylinderGeometry args={[0.24, 0.26, 0.1, 16]} />
<mesh position={[0, 0.065, 0]}>
<cylinderGeometry args={[0.24, 0.26, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.35, 0]}>
<cylinderGeometry args={[0.1, 0.2, 0.5, 16]} />
<mesh position={[0, 0.455, 0]}>
<cylinderGeometry args={[0.1, 0.2, 0.65, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.65, 0]}>
<cylinderGeometry args={[0.12, 0.1, 0.1, 16]} />
<mesh position={[0, 0.845, 0]}>
<cylinderGeometry args={[0.12, 0.1, 0.13, 16]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.8, 0]}>
<boxGeometry args={[0.04, 0.2, 0.04]} />
<mesh position={[0, 1.04, 0]}>
<boxGeometry args={[0.04, 0.26, 0.04]} />
<meshStandardMaterial color={color} />
</mesh>
<mesh position={[0, 0.85, 0]}>
<boxGeometry args={[0.12, 0.04, 0.04]} />
<mesh position={[0, 1.105, 0]}>
<boxGeometry args={[0.12, 0.052, 0.04]} />
<meshStandardMaterial color={color} />
</mesh>
</group>
Expand All @@ -185,7 +185,9 @@ const ChooseFromSixPieces = ({ piece }: ChessPieceProps) => {
const { animatingPiece, clearAnimation } = useAnimationStore();
const { change: changeTurn } = useTurnStore();

const pieceColor = color === "white" ? "#f5f5dc" : "#4a3728";
const threeColor = new THREE.Color(
color === "white" ? "rgba(205, 188, 139, 1)" : "hsla(37, 68%, 24%, 1.00)"
);

// この駒がアニメーション対象かどうか
const isAnimating = animatingPiece?.id === id;
Expand All @@ -212,7 +214,7 @@ const ChooseFromSixPieces = ({ piece }: ChessPieceProps) => {
);

// 滑らかに移動(lerpの係数を調整で速度変更可能)
groupRef.current.position.lerp(target, 0.02);
groupRef.current.position.lerp(target, 0.04);

// 目標位置に十分近づいたらアニメーション完了
if (groupRef.current.position.distanceTo(target) < 0.01) {
Expand All @@ -234,7 +236,7 @@ const ChooseFromSixPieces = ({ piece }: ChessPieceProps) => {

return (
<group ref={groupRef} position={[position.x!, position.y!, position.z!]}>
<PieceComponent color={pieceColor} />
<PieceComponent color={threeColor} />
</group>
);
};
Expand Down
Loading