Feature: DJ has a gameboy music controller

This commit is contained in:
Dejvino 2026-01-04 06:47:21 +00:00
parent 6b292b32ad
commit 47b7645046
3 changed files with 72 additions and 2 deletions

View File

@ -123,6 +123,9 @@ export class ConfigUI extends SceneFeature {
// Console RGB Toggle
createToggle('Console RGB Panel', 'consoleRGBEnabled');
// Gameboy Toggle
createToggle('Gameboy', 'gameboyEnabled');
// Guest Count Input
const guestRow = document.createElement('div');
guestRow.style.display = 'flex';
@ -358,6 +361,7 @@ export class ConfigUI extends SceneFeature {
sideScreensEnabled: true,
consoleRGBEnabled: true,
consoleEnabled: true,
gameboyEnabled: false,
guestCount: 150,
djHat: 'None'
};

View File

@ -142,6 +142,42 @@ export class DJ extends SceneFeature {
topHatGroup.visible = false;
this.head.add(topHatGroup);
this.hats['Top Hat'] = topHatGroup;
// --- Gameboy / Portable Console ---
const gbGroup = new THREE.Group();
// Body
const gbGeo = new THREE.BoxGeometry(0.2, 0.3, 0.05);
const gbMat = new THREE.MeshStandardMaterial({ color: 0x222222, roughness: 0.4 });
const gbBody = new THREE.Mesh(gbGeo, gbMat);
gbGroup.add(gbBody);
// Screen (Emissive)
const screenGeo = new THREE.PlaneGeometry(0.16, 0.12);
this.gbScreenMat = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const screen = new THREE.Mesh(screenGeo, this.gbScreenMat);
screen.position.set(0, 0.05, 0.026);
gbGroup.add(screen);
// Knobs/Buttons
const knobGeo = new THREE.CylinderGeometry(0.02, 0.02, 0.02, 8);
const knobMat = new THREE.MeshStandardMaterial({ color: 0xcccccc });
const k1 = new THREE.Mesh(knobGeo, knobMat);
k1.rotation.x = Math.PI/2;
k1.position.set(-0.05, -0.08, 0.026);
gbGroup.add(k1);
const k2 = new THREE.Mesh(knobGeo, knobMat);
k2.rotation.x = Math.PI/2;
k2.position.set(0.05, -0.08, 0.026);
gbGroup.add(k2);
// Attach to Left Arm (Hand position)
gbGroup.position.set(0, -0.9, 0.1);
gbGroup.rotation.x = -Math.PI / 4; // Tilted up
gbGroup.rotation.z = Math.PI; // Upside down
this.leftArm.add(gbGroup);
this.gameboy = gbGroup;
}
update(deltaTime) {
@ -162,9 +198,16 @@ export class DJ extends SceneFeature {
// Update Arm State
this.armTimer -= deltaTime;
if (this.armTimer <= 0) {
this.armState = Math.floor(Math.random() * 5);
this.armState = Math.floor(Math.random() * 4); // 0-3: Dance moves
this.armTimer = 2 + Math.random() * 4;
if (Math.random() < 0.3 && state.config.consoleEnabled) this.armState = 4; // Twiddling some more
const rand = Math.random();
// Gameboy Fiddling
if (state.config.gameboyEnabled && rand < 0.35) {
this.armState = 5;
} else if (state.config.consoleEnabled && rand < 0.65) {
this.armState = 4; // Console Twiddling
}
}
const upAngle = Math.PI * 0.85;
@ -182,6 +225,13 @@ export class DJ extends SceneFeature {
targetRightZ = 0.2;
targetLeftX = twiddleX;
targetRightX = twiddleX;
} else if (this.armState === 5 && state.config.gameboyEnabled) {
targetLeftZ = -0.3;
targetRightZ = -0.5; // Cross inwards
const timeRotX = Math.cos(time * 0.5) * 0.3;
const consoleRotX = state.config.consoleEnabled ? -0.5 : 0;
targetLeftX = -1.0 + timeRotX + consoleRotX; // Lift up
targetRightX = -1.1 + timeRotX + consoleRotX; // Lift up
} else {
targetLeftZ = (this.armState === 1 || this.armState === 3) ? upAngle : downAngle;
targetRightZ = (this.armState === 2 || this.armState === 3) ? upAngle : downAngle;
@ -198,6 +248,12 @@ export class DJ extends SceneFeature {
this.rightArm.rotation.z = this.currentRightAngle + Math.sin(t) * 0.05;
this.leftArm.rotation.x = this.currentLeftAngleX + Math.sin(t) * 0.1;
this.rightArm.rotation.x = this.currentRightAngleX + Math.cos(t) * 0.1;
} else if (this.armState === 5 && state.config.gameboyEnabled) {
const t = time * 20;
this.leftArm.rotation.z = -this.currentLeftAngle + Math.sin(t * 0.2) * 0.01;
this.rightArm.rotation.z = this.currentRightAngle + Math.sin(t) * 0.05;
this.leftArm.rotation.x = this.currentLeftAngleX + Math.cos(t * 0.2) * 0.01;
this.rightArm.rotation.x = this.currentRightAngleX + Math.cos(t) * 0.05;
} else {
const wave = Math.sin(time * 8) * 0.1;
const beatBounce = beatIntensity * 0.2;
@ -233,6 +289,15 @@ export class DJ extends SceneFeature {
for (const [name, mesh] of Object.entries(this.hats)) {
mesh.visible = (state.config.djHat === name);
}
// Update Gameboy
if (this.gameboy) {
this.gameboy.visible = state.config.gameboyEnabled;
if (this.gameboy.visible && state.music) {
const hue = (time * 0.5) % 1;
this.gbScreenMat.color.setHSL(hue, 1.0, 0.5);
}
}
}
onPartyStart() {

View File

@ -9,6 +9,7 @@ export function initState() {
sideScreensEnabled: true,
consoleRGBEnabled: true,
consoleEnabled: true,
gameboyEnabled: false,
guestCount: 150,
djHat: 'None' // 'None', 'Santa', 'Top Hat'
};