setup()
setup() runs once at startup and initializes the entire game environment: the Three.js scene, lights, camera, all static geometry (ground, house, trees), UI elements, and input listeners. It's the crucial foundation where you would add new environment objects or change rendering quality.
function setup() {
createCanvas(1, 1);
noLoop();
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
camera.position.copy(playerPosition);
hemisphereLight = new THREE.HemisphereLight(0xadd8e6, 0x00008b, 0.5);
scene.add(hemisphereLight);
directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 5);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 2048;
directionalLight.shadow.mapSize.height = 2048;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 50;
directionalLight.shadow.camera.left = -20;
directionalLight.shadow.camera.right = 20;
directionalLight.shadow.camera.top = 20;
directionalLight.shadow.camera.bottom = -20;
scene.add(directionalLight);
houseInteriorLight = new THREE.PointLight(0xffffee, 0.8, 10);
houseInteriorLight.position.set(0, 3, 0);
houseInteriorLight.castShadow = true;
scene.add(houseInteriorLight);
createGround();
createMapBarriers();
createHouse();
createPalmTrees(10);
controls = new THREE.PointerLockControls(camera, renderer.domElement);
scene.add(controls.getObject());
uiDiv = createDiv();
uiDiv.id('ui');
uiDiv.style('position', 'absolute');
uiDiv.style('top', '10px');
uiDiv.style('left', '10px');
uiDiv.style('color', 'white');
uiDiv.style('font-family', 'monospace');
uiDiv.style('font-size', '16px');
uiDiv.style('z-index', '100');
healthSpan = createSpan(`Health: ${playerHealth}`);
healthSpan.id('health');
uiDiv.child(healthSpan);
uiDiv.child(createElement('br'));
ammoSpan = createSpan(`Ammo: ${playerAmmo}`);
ammoSpan.id('ammo');
uiDiv.child(ammoSpan);
uiDiv.child(createElement('br'));
hungerSpan = createSpan(`Hunger: ${playerHunger}`);
hungerSpan.id('hunger');
uiDiv.child(hungerSpan);
uiDiv.child(createElement('br'));
nightSpan = createSpan(`Nights Survived: ${nightsSurvived}`);
nightSpan.id('nights');
uiDiv.child(nightSpan);
uiDiv.child(createElement('br'));
messageDiv = createDiv('');
messageDiv.id('message');
messageDiv.style('font-size', '24px');
messageDiv.style('text-align', 'center');
messageDiv.style('position', 'absolute');
messageDiv.style('width', '100%');
messageDiv.style('top', '40%');
uiDiv.child(messageDiv);
instructionsDiv = createDiv(`<p>Welcome to Island Survival!</p><p>Controls:</p><ul><li>W, A, S, D: Move</li><li>Space: Jump</li><li>Mouse: Look around</li><li>Left Click: Shoot (at night)</li><li>R: Reload (at night)</li><li>E: Interact (e.g., harvest fruit from trees)</li><li>Q: Hire a guard (${GUARD_COST_HUNGER} hunger)</li><li>Esc: Exit Pointer Lock</li></ul><p>Survive 7 nights to win. Zombies appear at night. A gun will appear when night falls. Keep your hunger up by eating fruit!</p>`);
instructionsDiv.id('instructions');
instructionsDiv.style('position', 'absolute');
instructionsDiv.style('top', '50%');
instructionsDiv.style('left', '50%');
instructionsDiv.style('transform', 'translate(-50%, -50%)');
instructionsDiv.style('background', 'rgba(0,0,0,0.7)');
instructionsDiv.style('padding', '20px');
instructionsDiv.style('border-radius', '10px');
instructionsDiv.style('color', 'white');
instructionsDiv.style('text-align', 'left');
instructionsDiv.style('z-index', '101');
document.body.appendChild(instructionsDiv.elt);
startGameButton = createButton('Click to Start Game');
startGameButton.parent(instructionsDiv);
startGameButton.style('margin-top', '20px');
startGameButton.style('padding', '10px 20px');
startGameButton.style('font-size', '18px');
startGameButton.style('cursor', 'pointer');
startGameButton.mousePressed(startGame);
gunMesh = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.5), new THREE.MeshStandardMaterial({ color: 0x808080 }));
gunMesh.position.set(0.3, -0.2, -0.5);
gunMesh.castShadow = true;
gunMesh.receiveShadow = true;
gunMesh.visible = false;
camera.add(gunMesh);
renderer.domElement.addEventListener('mousedown', onMouseDown, false);
}
Line-by-line explanation (25 lines)
🔧 Subcomponents:
scene = new THREE.Scene();
Creates the 3D scene container that holds all game objects, lights, and the camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
Sets up a 75-degree field-of-view first-person camera with aspect ratio matching the window
renderer = new THREE.WebGLRenderer({ antialias: true });
Creates the WebGL renderer that draws the 3D scene to the canvas
hemisphereLight = new THREE.HemisphereLight(0xadd8e6, 0x00008b, 0.5);
Adds ambient lighting that simulates the sky and ground colors
uiDiv = createDiv();
Creates HTML UI elements (health, ammo, hunger, nights display) overlaid on the canvas
createCanvas(1, 1);- Creates a tiny p5.js canvas (1x1 pixel) just to enable p5.js lifecycle—Three.js does the actual rendering
noLoop();- Stops p5.js draw loop initially; it will restart in startGame() when the player clicks Start
scene = new THREE.Scene();- Initializes the 3D scene that will contain all 3D objects (ground, house, trees, zombies, etc.)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);- Creates a perspective camera with 75-degree field of view, window aspect ratio, near clipping at 0.1 units, far at 1000 units
renderer = new THREE.WebGLRenderer({ antialias: true });- Creates a WebGL renderer with antialiasing enabled for smoother edges
renderer.setSize(window.innerWidth, window.innerHeight);- Sizes the renderer to fill the entire window
document.body.appendChild(renderer.domElement);- Adds the Three.js canvas to the HTML body, making it visible
renderer.shadowMap.enabled = true;- Enables shadow rendering so objects can cast shadows on the ground and walls
hemisphereLight = new THREE.HemisphereLight(0xadd8e6, 0x00008b, 0.5);- Adds a hemisphere light with light-blue sky color (0xadd8e6) and dark-blue ground color (0x00008b) at half intensity
directionalLight = new THREE.DirectionalLight(0xffffff, 1);- Creates a white directional light (the sun) at full intensity that casts shadows
directionalLight.position.set(5, 10, 5);- Positions the sun initially in the sky; this will animate during the day-night cycle
directionalLight.shadow.mapSize.width = 2048;- Sets shadow map resolution to 2048x2048 pixels for crisp, detailed shadows
houseInteriorLight = new THREE.PointLight(0xffffee, 0.8, 10);- Creates a point light (pale yellow) inside the house at intensity 0.8 with range of 10 units
createGround();- Calls function to create the ground plane mesh and add it to the scene
createMapBarriers();- Calls function to create invisible collision barriers at the island edges
createHouse();- Calls function to create the house with walls, roof, door, furniture, and collision objects
createPalmTrees(10);- Calls function to create 10 palm trees with trunks, leaves, and harvestable red fruit
controls = new THREE.PointerLockControls(camera, renderer.domElement);- Initializes pointer lock controls that capture mouse movement for free-look camera control
scene.add(controls.getObject());- Adds the camera to the scene via the controls object so movement updates are applied correctly
healthSpan = createSpan(`Health: ${playerHealth}`);- Creates a text span showing current health; will be updated every frame in drawUI()
hungerSpan = createSpan(`Hunger: ${playerHunger}`);- Creates a text span showing current hunger level
gunMesh = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.5), new THREE.MeshStandardMaterial({ color: 0x808080 }));- Creates a simple grey box to represent the gun; it will be positioned at the camera and shown only at night
gunMesh.visible = false;- Hides the gun initially; it appears when night starts
camera.add(gunMesh);- Attaches the gun to the camera so it moves and rotates with the player's view
renderer.domElement.addEventListener('mousedown', onMouseDown, false);- Registers a mousedown listener so left-click fires bullets when the gun is equipped