Guidelines for building 2D/3D games using React Three Fiber, covering setup, physics, controls, textures, and game loop best practices.
Always follow these guidelines when building a JavaScript game:
This stack supports simple JavaScript game development for 2D/3D games and simulation projects.
Use DREI keyboard controls for movement.
// Define your controls as an enum
enum Controls {
forward = 'forward',
back = 'back',
left = 'left',
right = 'right',
jump = 'jump',
}
// In your main component
function Game() {
// Define key mappings
const keyMap = [
{ name: Controls.forward, keys: ['ArrowUp', 'KeyW'] },
{ name: Controls.back, keys: ['ArrowDown', 'KeyS'] },
{ name: Controls.left, keys: ['ArrowLeft', 'KeyA'] },
{ name: Controls.right, keys: ['ArrowRight', 'KeyD'] },
{ name: Controls.jump, keys: ['Space'] },
];
return (
<KeyboardControls map={keyMap}>
<YourGameComponent />
</KeyboardControls>
);
}
function PlayerComponent() {
// This will re-render when forward key is pressed
const forwardPressed = useKeyboardControls<Controls>(state => state.forward);
return (
<div>
{forwardPressed ? "Moving forward!" : "Standing still"}
</div>
);
}
function PlayerMovement() {
const [subscribe, getState] = useKeyboardControls<Controls>();
// Subscribe to changes
useEffect(() => {
// Clean up automatically when component unmounts
return subscribe(
state => state.forward,
isPressed => console.log("Forward key:", isPressed)
);
}, []);
// Use in game loop
useFrame(() => {
// Get current state without causing re-renders
const controls = getState();
if (controls.forward) moveForward();
if (controls.jump) jump();
// etc...
});
return null;
}
Textures are available in the client/public/textures folder and should be used in the following manner: useTexture("/textures/asphalt.png"); by the client.
Always search for existing textures before generating new ones.
IMPORTANT! Do NOT use any textures except the ones in the client/public/textures folder. For example, using a non-existing texture such as the following will not work:
const texture = useTexture("/textures/sun.png") or useTexture("/textures/car.jpg"); // this will not work as it doesn't exist
Similarly, referencing a texture anywhere else in the code that tries use it will not work.
{
"texture": "/textures/exotic_planet.jpg" // this will not work as it doesn't exist
}
If no suitable textures are listed in the directory, its okay to not use a texture.
Math.random() directly in JSX or render methodsuseState, useEffect, and useMemo to manage random valuesimport * as THREE from "three" where needed.