anycoder-f24770c8 / index.html
kirikir13's picture
Upload folder using huggingface_hub
a8fefcd verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Game-Unknown | 3D Sandbox</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Rajdhani:wght@300;500;700&display=swap" rel="stylesheet">
<!-- Three.js and Addons -->
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.160.0/examples/jsm/"
}
}
</script>
<style>
:root {
--primary: #00f260;
--secondary: #0575e6;
--glass: rgba(255, 255, 255, 0.1);
--glass-border: rgba(255, 255, 255, 0.2);
--text: #ffffff;
--bg-gradient: linear-gradient(135deg, #0f0c29, #302b63, #24243e);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
font-family: 'Rajdhani', sans-serif;
background: var(--bg-gradient);
color: var(--text);
overflow: hidden;
height: 100vh;
width: 100vw;
}
/* --- Canvas --- */
#game-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
display: none; /* Hidden until start */
}
/* --- UI Overlay --- */
#ui-layer {
position: relative;
z-index: 10;
width: 100%;
height: 100%;
pointer-events: none; /* Let clicks pass to canvas when locked */
display: flex;
flex-direction: column;
justify-content: space-between;
}
/* --- Header --- */
header {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(to bottom, rgba(0,0,0,0.8), transparent);
pointer-events: auto;
}
.logo {
font-family: 'Orbitron', sans-serif;
font-size: 1.5rem;
font-weight: 700;
background: linear-gradient(to right, var(--primary), var(--secondary));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-transform: uppercase;
letter-spacing: 2px;
}
.anycoder-link {
font-size: 0.9rem;
color: rgba(255,255,255,0.7);
text-decoration: none;
border-bottom: 1px solid var(--primary);
transition: 0.3s;
}
.anycoder-link:hover { color: var(--primary); }
/* --- Setup Screen (Modal) --- */
#setup-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(15, 12, 41, 0.9);
backdrop-filter: blur(10px);
display: flex;
justify-content: center;
align-items: center;
z-index: 20;
pointer-events: auto;
transition: opacity 0.5s ease;
}
.panel {
background: var(--glass);
border: 1px solid var(--glass-border);
padding: 40px;
border-radius: 20px;
width: 90%;
max-width: 500px;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
}
h2 {
font-family: 'Orbitron', sans-serif;
margin-bottom: 20px;
text-align: center;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 700;
color: var(--primary);
}
input[type="text"], select, input[type="file"] {
width: 100%;
padding: 12px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid var(--glass-border);
color: white;
border-radius: 8px;
font-family: 'Rajdhani', sans-serif;
font-size: 1.1rem;
outline: none;
transition: 0.3s;
}
input:focus, select:focus {
border-color: var(--primary);
box-shadow: 0 0 10px rgba(0, 242, 96, 0.3);
}
.btn {
width: 100%;
padding: 15px;
border: none;
border-radius: 8px;
background: linear-gradient(90deg, var(--secondary), var(--primary));
color: #000;
font-family: 'Orbitron', sans-serif;
font-weight: 700;
font-size: 1.2rem;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
text-transform: uppercase;
}
.btn:hover {
transform: scale(1.02);
box-shadow: 0 0 20px rgba(0, 242, 96, 0.6);
}
/* --- HUD --- */
#hud {
display: none; /* Hidden initially */
padding: 20px;
pointer-events: auto;
}
.hud-top {
display: flex;
justify-content: space-between;
font-size: 1.2rem;
font-weight: 700;
}
.crosshair {
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
pointer-events: none;
}
.crosshair::before, .crosshair::after {
content: '';
position: absolute;
background: var(--primary);
}
.crosshair::before { top: 9px; left: 0; width: 20px; height: 2px; }
.crosshair::after { top: 0; left: 9px; width: 2px; height: 20px; }
.controls-hint {
text-align: center;
font-size: 0.9rem;
opacity: 0.7;
margin-top: 10px;
}
/* --- Notifications --- */
#notifications {
position: fixed;
bottom: 20px;
right: 20px;
display: flex;
flex-direction: column;
gap: 10px;
z-index: 30;
}
.toast {
background: rgba(0,0,0,0.8);
border-left: 4px solid var(--primary);
padding: 15px;
border-radius: 4px;
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
/* Weapon Model */
#weapon-container {
position: absolute;
bottom: 0;
right: 20%;
width: 200px;
height: 200px;
display: none; /* Hidden until game starts */
pointer-events: none;
}
/* Loading Spinner */
.loader {
border: 4px solid rgba(255, 255, 255, 0.1);
border-left-color: var(--primary);
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto;
display: none;
}
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
</style>
</head>
<body>
<!-- 3D Canvas -->
<canvas id="game-canvas"></canvas>
<!-- UI Layer -->
<div id="ui-layer">
<header>
<div class="logo">Game-Unknown</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with AnyCoder</a>
</header>
<!-- HUD -->
<div id="hud">
<div class="hud-top">
<div id="player-health">HP: 100%</div>
<div id="world-name">World: Greek City</div>
</div>
<div class="crosshair"></div>
<div class="controls-hint">WASD to Move | SPACE to Jump | CLICK to Shoot | ESC to Pause</div>
</div>
</div>
<!-- Weapon Overlay (3D Model attached to camera later) -->
<div id="weapon-container"></div>
<!-- Setup Screen -->
<div id="setup-screen">
<div class="panel">
<h2>Mission Init</h2>
<div class="form-group">
<label>HF Token (Authentication)</label>
<input type="text" id="hf-token" placeholder="Enter HuggingFace Token...">
</div>
<div class="form-group">
<label>Load Custom Model (.glb / .gltf)</label>
<input type="file" id="model-upload" accept=".glb, .gltf">
<div style="text-align: center; margin: 5px 0; font-size: 0.8rem;">OR</div>
<select id="preset-model">
<option value="default">Select Preset: Soldier</option>
<option value="wizard">Preset: Wizard</option>
<option value="cyborg">Preset: Cyborg</option>
</select>
</div>
<div class="form-group">
<label>World Environment</label>
<select id="world-select">
<option value="greek">Greek City (Ruins)</option>
<option value="warehouse">Abandoned Warehouse</option>
<option value="cyber">Neon Cyber Field</option>
</select>
</div>
<div class="loader" id="loader"></div>
<button class="btn" id="enter-btn">ENTER SIMULATION</button>
</div>
</div>
<div id="notifications"></div>
<script type="module">
import * as THREE from 'three';
import { PointerLockControls } from 'three/addons/controls/PointerLockControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
// --- State & Config ---
const state = {
moveForward: false,
moveBackward: false,
moveLeft: false,
moveRight: false,
canJump: false,
velocity: new THREE.Vector3(),
direction: new THREE.Vector3(),
isPlaying: false,
world: 'greek'
};
// --- Scene Setup ---
const canvas = document.querySelector('#game-canvas');
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x050510);
scene.fog = new THREE.FogExp2(0x050510, 0.02);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.y = 1.6; // Eye level
const renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
// --- Lighting ---
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6);
scene.add(hemiLight);
const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
dirLight.position.set(10, 20, 10);
dirLight.castShadow = true;
dirLight.shadow.camera.top = 50;
dirLight.shadow.camera.bottom = -50;
dirLight.shadow.camera.left = -50;
dirLight.shadow.camera.right = 50;
scene.add(dirLight);
// --- Controls ---
const controls = new PointerLockControls(camera, document.body);
// --- Weapon Visuals (Procedural Gun) ---
const weaponGeo = new THREE.BoxGeometry(0.2, 0.2, 0.6);
const weaponMat = new THREE.MeshStandardMaterial({ color: 0x333333, roughness: 0.2, metalness: 0.8 });
const weapon = new THREE.Mesh(weaponGeo, weaponMat);
weapon.position.set(0.3, -0.3, -0.5);
camera.add(weapon);
scene.add(camera); // Add camera to scene so weapon renders
// --- Physics / Movement Logic ---
let prevTime = performance.now();
const onKeyDown = function (event) {
switch (event.code) {
case 'ArrowUp': case 'KeyW': state.moveForward = true; break;
case 'ArrowLeft': case 'KeyA': state.moveLeft = true; break;
case 'ArrowDown': case 'KeyS': state.moveBackward = true; break;
case 'ArrowRight': case 'KeyD': state.moveRight = true; break;
case 'Space': if (state.canJump === true) state.velocity.y += 350; state.canJump = false; break;
}
};
const onKeyUp = function (event) {
switch (event.code) {
case 'ArrowUp': case 'KeyW': state.moveForward = false; break;
case 'ArrowLeft': case 'KeyA': state.moveLeft = false; break;
case 'ArrowDown': case 'KeyS': state.moveBackward = false; break;
case 'ArrowRight': case 'KeyD': state.moveRight = false; break;
}
};
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
// --- Mouse Click (Shoot) ---
document.addEventListener('mousedown', () => {
if (state.isPlaying && controls.isLocked) {
// Visual Recoil
weapon.position.z = -0.3;
setTimeout(() => { weapon.position.z = -0.5; }, 100);
// Simple Raycast to see if we hit the 'enemies'
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(new THREE.Vector2(0,0), camera);
// Find targets
const intersects = raycaster.intersectObjects(enemies.children);
if(intersects.length > 0) {
const hitObj = intersects[0].object;
// "Kill" effect
hitObj.material.color.setHex(0xff0000);
scene.remove(hitObj);
notify("Target Eliminated");
}
}
});
// --- World Generation ---
const enemies = new THREE.Group();
scene.add(enemies);
function createEnvironment(type) {
// Clear previous
while(scene.children.length > 0){
const obj = scene.children[0];
if(obj.type === "Mesh" || obj.type === "Group") {
if(obj !== camera && obj !== enemies) scene.remove(obj);
}
}
enemies.clear();
// Floor
let floorGeo, floorMat;
if(type === 'cyber') {
floorGeo = new THREE.PlaneGeometry(200, 200, 100, 100);
floorMat = new THREE.MeshStandardMaterial({ color: 0x000000, wireframe: true, emissive: 0x0575e6, emissiveIntensity: 0.5 });
} else {
floorGeo = new THREE.PlaneGeometry(200, 200);
floorMat = new THREE.MeshStandardMaterial({ color: 0x222222, roughness: 0.8 });
}
const floor = new THREE.Mesh(floorGeo, floorMat);
floor.rotation.x = - Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);
// Procedural Props based on World Type
if (type === 'greek') {
for(let i=0; i<50; i++) {
const colGeo = new THREE.CylinderGeometry(1, 1, 10, 6);
const colMat = new THREE.MeshStandardMaterial({ color: 0xdddddd });
const column = new THREE.Mesh(colGeo, colMat);
column.position.set((Math.random()-0.5)*100, 5, (Math.random()-0.5)*100);
column.castShadow = true;
column.receiveShadow = true;
scene.add(column);
// Spawn Enemy nearby
spawnEnemy(column.position);
}
} else if (type === 'warehouse') {
for(let i=0; i<20; i++) {
const boxGeo = new THREE.BoxGeometry(5, 5, 5);
const boxMat = new THREE.MeshStandardMaterial({ color: 0x555555 });
const box = new THREE.Mesh(boxGeo, boxMat);
box.position.set((Math.random()-0.5)*80, 2.5, (Math.random()-0.5)*80);
box.castShadow = true;
scene.add(box);
spawnEnemy(box.position);
}
} else {
// Cyber / Generic
for(let i=0; i<40; i++) {
const geo = new THREE.TorusGeometry(2, 0.5, 8, 20);
const mat = new THREE.MeshStandardMaterial({ color: 0x00f260, emissive: 0x00f260, emissiveIntensity: 0.8 });
const ring = new THREE.Mesh(geo, mat);
ring.position.set((Math.random()-0.5)*100, 3, (Math.random()-0.5)*100);
ring.rotation.x = Math.PI / 2;
scene.add(ring);
spawnEnemy(ring.position);
}
}
}
function spawnEnemy(refPos) {
const geo = new THREE.SphereGeometry(1, 32, 32);
const mat = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const enemy = new THREE.Mesh(geo, mat);
// Random position near reference
enemy.position.set(
refPos.x + (Math.random()-0.5)*20,
2,
refPos.z + (Math.random()-0.5)*20
);
enemy.userData = { moveDir: Math.random() };
enemies.add(enemy);
}
// --- Model Loading Logic ---
function loadPlayerModel(source, file = null) {
// Remove existing child (default camera child is weapon, we want to attach model to a group parented to camera)
// For this demo, we will just change the camera height or simple geometry
// Implementing full GLTF loading requires actual file URLs.
// Since this is a text response, we simulate the upload process.
if (file) {
const url = URL.createObjectURL(file);
const loader = new GLTFLoader();
loader.load(url, function (gltf) {
const model = gltf.scene;
model.scale.set(1, 1, 1); // Adjust scale
// Ideally attach to a wrapper group at camera position
notify("Custom Model Loaded Successfully");
}, undefined, function (error) {
console.error(error);
notify("Error loading model. Using Default.");
});
} else {
notify(`Loaded Preset: ${source}`);
}
}
// --- UI Interactions ---
const setupScreen = document.getElementById('setup-screen');
const hud = document.getElementById('hud');
const enterBtn = document.getElementById('enter-btn');
const worldSelect = document.getElementById('world-select');
const modelUpload = document.getElementById('model-upload');
const presetModel = document.getElementById('preset-model');
const loader = document.getElementById('loader');
enterBtn.addEventListener('click', () => {
const token = document.getElementById('hf-token').value;
if(!token) {
alert("Please enter a HuggingFace Token (or any text to proceed).");
return;
}
loader.style.display = 'block';
enterBtn.style.opacity = '0.5';
// Simulate Loading
setTimeout(() => {
state.world = worldSelect.value;
loadPlayerModel(presetModel.value, modelUpload.files[0]);
createEnvironment(state.world);
loader.style.display = 'none';
setupScreen.style.opacity = '0';
setTimeout(() => {
setupScreen.style.display = 'none';
hud.style.display = 'block';
canvas.style.display = 'block';
controls.lock();
state.isPlaying = true;
}, 500);
}, 1500);
});
// Handle Pointer Lock Events
controls.addEventListener('lock', function () {
state.isPlaying = true;
});
controls.addEventListener('unlock', function () {
state.isPlaying = false;
// Show pause menu logic could go here
notify("Paused - Click to Resume");
});
function notify(msg) {
const container = document.getElementById('notifications');
const el = document.createElement('div');
el.className = 'toast';
el.innerText = msg;
container.appendChild(el);
setTimeout(() => el.remove(), 3000);
}
// --- Main Loop ---
function animate() {
requestAnimationFrame(animate);
if (state.isPlaying) {
const time = performance.now();
const delta = (time - prevTime) / 1000;
// Movement Physics
state.velocity.x -= state.velocity.x * 10.0 * delta;
state.velocity.z -= state.velocity.z * 10.0 * delta;
state.velocity.y -= 9.8 * 100.0 * delta; // Gravity
state.direction.z = Number(state.moveForward) - Number(state.moveBackward);
state.direction.x = Number(state.moveRight) - Number(state.moveLeft);
state.direction.normalize();
if (state.moveForward || state.moveBackward) state.velocity.z -= state.direction.z * 400.0 * delta;
if (state.moveLeft || state.moveRight) state.velocity.x -= state.direction.x * 400.0 * delta;
controls.moveRight(- state.velocity.x * delta);
controls.moveForward(- state.velocity.z * delta);
camera.position.y += (state.velocity.y * delta); // Simple gravity
// Floor Collision
if (camera.position.y < 1.6) {
state.velocity.y = 0;
camera.position.y = 1.6;
state.canJump = true;
}
// Animate Enemies (Bobbing)
enemies.children.forEach((child, idx) => {
child.position.y = 2 + Math.sin(time * 0.003 + idx) * 0.5;
child.rotation.y += 0.01;
});
prevTime = time;
}
renderer.render(scene, camera);
}
// Window Resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
animate();
</script>
</body>
</html>