gradio-game / app.py
akhaliq's picture
akhaliq HF staff
Update app.py
4552af7 verified
raw
history blame
11 kB
import gradio as gr
demo = gr.Blocks()
with demo:
gr.HTML("""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hugging Face Game with Sound</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
#win-message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 48px;
color: white;
background: rgba(0, 0, 0, 0.7);
padding: 20px;
display: none;
font-family: Arial, sans-serif;
}
#gpu-counter {
position: absolute;
top: 10px;
left: 10px;
font-size: 24px;
color: white;
background: rgba(0, 0, 0, 0.7);
padding: 10px;
font-family: Arial, sans-serif;
}
#controls {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 20px;
color: white;
background: rgba(0, 0, 0, 0.8);
padding: 20px;
font-family: Arial, sans-serif;
text-align: center;
transition: opacity 1s;
}
</style>
</head>
<body>
<div id="win-message">You Win!</div>
<div id="gpu-counter">GPUs Collected: 0 / 10</div>
<div id="controls">
<p>Controls:</p>
<p>W / Up Arrow: Forward</p>
<p>S / Down Arrow: Backward</p>
<p>A / Left Arrow: Left</p>
<p>D / Right Arrow: Right</p>
<p>Spacebar: Up</p>
<p>Shift: Down</p>
<p>Collect all GPUs to win!</p>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r134/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Morning lighting
const directionalLight = new THREE.DirectionalLight(0xffe0b2, 1);
directionalLight.position.set(1, 1, 0.5).normalize();
scene.add(directionalLight);
const ambientLight = new THREE.AmbientLight(0x87ceeb, 0.5);
scene.add(ambientLight);
// Morning background
scene.background = new THREE.Color(0x87ceeb);
scene.fog = new THREE.Fog(0x87ceeb, 10, 100);
// Ground
const groundGeometry = new THREE.PlaneGeometry(100, 100);
const groundMaterial = new THREE.MeshLambertMaterial({ color: 0x8c8c8c });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// Realistic Buildings
const buildings = [];
const numBuildings = 50;
for (let i = 0; i < numBuildings; i++) {
const width = Math.random() * 5 + 2;
const height = Math.random() * 20 + 10;
const depth = Math.random() * 5 + 2;
const buildingGeometry = new THREE.BoxGeometry(width, height, depth);
const buildingMaterial = new THREE.MeshLambertMaterial({ color: 0xb0b0b0 });
const building = new THREE.Mesh(buildingGeometry, buildingMaterial);
building.position.x = Math.random() * 80 - 40;
building.position.y = height / 2;
building.position.z = Math.random() * 80 - 40;
scene.add(building);
buildings.push(building);
}
// Hugging Face Emoji
const emojiCanvas = document.createElement('canvas');
emojiCanvas.width = 256;
emojiCanvas.height = 256;
const emojiCtx = emojiCanvas.getContext('2d');
emojiCtx.font = '128px Arial';
emojiCtx.textAlign = 'center';
emojiCtx.textBaseline = 'middle';
emojiCtx.fillText('🤗', 128, 128);
const emojiTexture = new THREE.CanvasTexture(emojiCanvas);
const faceGeometry = new THREE.SphereGeometry(1, 32, 32);
const faceMaterial = new THREE.MeshLambertMaterial({ map: emojiTexture });
const face = new THREE.Mesh(faceGeometry, faceMaterial);
face.position.set(0, 5, 0);
scene.add(face);
face.velocity = new THREE.Vector3(0, 0, 0);
face.maxSpeed = 25;
face.acceleration = new THREE.Vector3(0, 0, 0);
face.friction = 0.95;
// "GPU" Texts
const canvas = document.createElement('canvas');
canvas.width = 128;
canvas.height = 128;
const ctx = canvas.getContext('2d');
ctx.font = '48px Arial';
ctx.fillStyle = 'white';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('GPU', 64, 64);
const texture = new THREE.CanvasTexture(canvas);
const gpuSprites = [];
const totalGPUs = 10;
let collectedGPUs = 0;
for (let i = 0; i < totalGPUs; i++) {
const spriteMaterial = new THREE.SpriteMaterial({ map: texture });
const sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(2, 2, 1);
sprite.position.set(Math.random() * 80 - 40, Math.random() * 20 + 10, Math.random() * 80 - 40);
scene.add(sprite);
gpuSprites.push(sprite);
}
// Sound setup (Web Audio API)
const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
// Background music (simple looping oscillator)
const bgOscillator = audioCtx.createOscillator();
const bgGain = audioCtx.createGain();
bgOscillator.type = 'sine';
bgOscillator.frequency.setValueAtTime(220, audioCtx.currentTime); // Low hum
bgGain.gain.setValueAtTime(0.1, audioCtx.currentTime); // Quiet volume
bgOscillator.connect(bgGain);
bgGain.connect(audioCtx.destination);
bgOscillator.start();
// GPU collect sound
function playCollectSound() {
const oscillator = audioCtx.createOscillator();
const gain = audioCtx.createGain();
oscillator.type = 'square';
oscillator.frequency.setValueAtTime(880, audioCtx.currentTime); // High pitch
gain.gain.setValueAtTime(0.3, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.2);
oscillator.connect(gain);
gain.connect(audioCtx.destination);
oscillator.start();
oscillator.stop(audioCtx.currentTime + 0.2);
}
// Clock for smooth animation
const clock = new THREE.Clock();
// Win condition and counter
const winMessage = document.getElementById('win-message');
const gpuCounter = document.getElementById('gpu-counter');
let gameWon = false;
// Controls instructions
const controlsDiv = document.getElementById('controls');
let controlsVisible = true;
setTimeout(() => {
if (controlsVisible) {
controlsDiv.style.opacity = '0';
setTimeout(() => controlsDiv.style.display = 'none', 1000);
controlsVisible = false;
}
}, 5000); // Hide after 5 seconds
// Keyboard controls
const keys = {};
window.addEventListener('keydown', (e) => {
keys[e.key] = true;
if (controlsVisible) {
controlsDiv.style.opacity = '0';
setTimeout(() => controlsDiv.style.display = 'none', 1000);
controlsVisible = false;
}
});
window.addEventListener('keyup', (e) => { keys[e.key] = false; });
function handleControls(deltaTime) {
const accel = 50;
face.acceleration.set(0, 0, 0);
if (keys['w'] || keys['ArrowUp']) face.acceleration.z = -accel;
if (keys['s'] || keys['ArrowDown']) face.acceleration.z = accel;
if (keys['a'] || keys['ArrowLeft']) face.acceleration.x = -accel;
if (keys['d'] || keys['ArrowRight']) face.acceleration.x = accel;
if (keys[' ']) face.acceleration.y = accel;
if (keys['Shift']) face.acceleration.y = -accel;
// Apply acceleration and friction
face.velocity.add(face.acceleration.clone().multiplyScalar(deltaTime));
face.velocity.multiplyScalar(face.friction);
face.velocity.clampLength(0, face.maxSpeed);
// Update position
face.position.add(face.velocity.clone().multiplyScalar(deltaTime));
// Face direction of movement
if (face.velocity.length() > 0.1) {
face.lookAt(face.position.clone().add(face.velocity));
}
// Keep within bounds
face.position.x = Math.max(-50, Math.min(50, face.position.x));
face.position.z = Math.max(-50, Math.min(50, face.position.z));
face.position.y = Math.max(1, Math.min(50, face.position.y));
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const deltaTime = clock.getDelta();
if (!gameWon) {
// Handle player controls
handleControls(deltaTime);
// Check for "GPU" collisions
gpuSprites.forEach((gpu, index) => {
if (face.position.distanceTo(gpu.position) < 1) {
scene.remove(gpu);
gpuSprites.splice(index, 1);
collectedGPUs++;
gpuCounter.textContent = `GPUs Collected: ${collectedGPUs} / ${totalGPUs}`;
playCollectSound(); // Play sound on collection
if (collectedGPUs === totalGPUs) {
gameWon = true;
winMessage.style.display = 'block';
face.velocity.set(0, 0, 0);
bgOscillator.stop(); // Stop background music
}
}
});
}
// Update camera
camera.position.set(face.position.x, face.position.y + 5, face.position.z - 10);
camera.lookAt(face.position);
// Render
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>""")
demo.launch()