I have this Card component, when clicked it activates and expands the block. wanted to click on one and then the other they switch positions. something like:
// Initial Board
1,1,1,1,
2,2,2,2,
3,3,3,3,
4,4,4,4,
and not alowing to same number on line. Row, Column or Main Diagonal. to be finished ordering the blocks like:
// win condition for Board
1, 2, 3, 4,
4, 3, 2, 1,
2, 1, 4, 3,
3, 4, 1, 2,
// the Card component
const Card = ({locale, args, color, speed}) => {
const mesh = useRef(null)
useFrame(() => (mesh.current.rotation.x = mesh.current.rotation.y += 0.01));
// expand state of the mesh. change size on click event
const [expand, setExpand] = useState(false);
const props = useSpring({
scale: expand ? [1.4, 1.4, 1.4]: [1,1,1],
})
return (
<a.mesh
onClick={() => setExpand(!expand)}
scale={props.scale}
castShadow
position={locale}
ref={mesh}>
<boxBufferGeometry attach='geometry' args={args} />
<MeshWobbleMaterial attach='material' color={color} speed={speed} factor={0.6} />
</a.mesh>
)
}
// its rendering inside Canvas from react-three-fiber
<Card locale={[-2, 1, -2]} color={'navy'} speed={6} />
<Card locale={[0, 1, -2]} color={'navy'} speed={6} />
<Card locale={[2, 1, -2]} color={'navy'} speed={6} />
<Card locale={[4, 1, -2]} color={'navy'} speed={6} />
<Card locale={[-2, 3, -2]} color={'teal'} speed={3} />
<Card locale={[0, 3, -2]} color={'teal'} speed={3} />
<Card locale={[2, 3, -2]} color={'teal'} speed={3} />
<Card locale={[4, 3, -2]} color={'teal'} speed={3} />
<Card locale={[-2, 5, -2]} color={'blue'} speed={9} />
<Card locale={[0, 5, -2]} color={'blue'} speed={9} />
<Card locale={[2, 5, -2]} color={'blue'} speed={9} />
<Card locale={[4, 5, -2]} color={'blue'} speed={9} />
<Card locale={[-2, -1, -2]} color={'aqua'} speed={2} />
<Card locale={[0, -1, -2]} color={'aqua'} speed={2} />
<Card locale={[2, -1, -2]} color={'aqua'} speed={2} />
<Card locale={[4, -1, -2]} color={'aqua'} speed={2} />
github link is here: https://github.com/iagokrt/board-game-threejs i'm coming up with a dumb logic for the board.
This problem is far more complex than a standard stackoverflow answer, so I answer part of it only. The animation part was the most interesting for me, so I solved that problem.
If you want to swap cubes on the board, you must animate by their x,y position. So I added the x,y coordinates to the useSpring, it will use the locale property. You must add an interpolate function where you want to use them in the mesh position property.
const Card = ({ locale, args, color, speed }) => {
const mesh = useRef(null);
useFrame(() => (mesh.current.rotation.x = mesh.current.rotation.y += 0.01));
// expand state of the mesh. change size on click event
const [expand, setExpand] = useState(false);
const props = useSpring({
scale: expand ? [1.4, 1.4, 1.4] : [1, 1, 1],
xy: [locale[0], locale[1]]
});
return (
<a.mesh
onClick={() => setExpand(!expand)}
scale={props.scale}
castShadow
position={props.xy.interpolate((x, y) => [x, y, locale[2]])}
ref={mesh}
>
<boxBufferGeometry attach="geometry" args={args} />
<MeshWobbleMaterial
attach="material"
color={color}
speed={speed}
factor={0.6}
/>
</a.mesh>
);
};
This way if you change the locale property of the Card component then it will animate the new position.
I created a little example. I change the locale in a timer and you can see that it swaps with animation.
https://codesandbox.io/s/react-tree-fiber-board-5mbns?file=/src/App.js