diff --git a/app/components/Gate.tsx b/app/components/Gate.tsx new file mode 100644 index 0000000..46ff35a --- /dev/null +++ b/app/components/Gate.tsx @@ -0,0 +1,62 @@ +"use client"; + +import React, { useRef, useMemo } from 'react'; +import { Canvas, useFrame } from '@react-three/fiber'; +import * as THREE from 'three'; + +function ParticleRing() { + const pointsRef = useRef(null); + const particleCount = 500; + + const positions = useMemo(() => { + const pos = new Float32Array(particleCount * 3); + const radius = 2.5; + for (let i = 0; i < particleCount; i++) { + const theta = Math.random() * Math.PI * 2; + const r = radius + (Math.random() - 0.5) * 0.5; + pos[i * 3] = Math.cos(theta) * r; + pos[i * 3 + 1] = (Math.random() - 0.5) * 0.5; + pos[i * 3 + 2] = Math.sin(theta) * r; + } + return pos; + }, []); + + useFrame((_, delta) => { + if (pointsRef.current) { + pointsRef.current.rotation.y += delta * 0.15; + pointsRef.current.rotation.x += delta * 0.05; + } + }); + + return ( + + + + + + + ); +} + +export default function Gate() { + return ( +
+ + + +
+ ); +} + diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..c24bdab --- /dev/null +++ b/app/globals.css @@ -0,0 +1,17 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --background: #0a0a0a; + --foreground: #ededed; +} + +body { + color: var(--foreground); + background: var(--background); + font-family: var(--font-geist-sans), Arial, Helvetica, sans-serif; + overflow: hidden; + margin: 0; + padding: 0; +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..83c08bd --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,34 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import "./globals.css"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "Pixel | Tor der Wandlerin", + description: "Pixel - Architektin der FaeBits-Anderswelt", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + + {children} + + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..6732e01 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,55 @@ +"use client"; + +import { Canvas } from "@react-three/fiber"; +import { OrbitControls, Stars } from "@react-three/drei"; +import { Suspense, useRef, useState } from "react"; +import * as THREE from "three"; + +// Einfache Partikel-Animation (WebGPU-Ersatz für jetzt) +function ParticleField() { + const count = 2000; + const meshRef = useRef(null); + const [dummy] = useState(() => new THREE.Object3D()); + + // Zufällige Positionen initialisieren + const positions = useRef( + Array.from({ length: count }, () => ({ + x: (Math.random() - 0.5) * 20, + y: (Math.random() - 0.5) * 20, + z: (Math.random() - 0.5) * 20, + speed: Math.random() * 0.02 + 0.01, + })) + ); + + return ( + + + + + ); +} + +import Gate from './components/Gate'; + +export default function Home() { + return ( +
+ + + + + + + + +
+ + +
+
+ ); +} diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..9edff1c --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +import "./.next/types/routes.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..cd1abbb --- /dev/null +++ b/next.config.js @@ -0,0 +1,10 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + output: 'export', // Statische Export-Dateien für einfachen Webserver + images: { + unoptimized: true, // Für statischen Export notwendig + }, +}; + +module.exports = nextConfig; diff --git a/package.json b/package.json new file mode 100644 index 0000000..5ac86fe --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "pixel-faebits", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "next": "16.0.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "@react-three/fiber": "^9.0.0", + "@react-three/drei": "^10.0.0", + "three": "^0.182.0" + }, + "devDependencies": { + "@types/node": "^22.0.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "typescript": "^5.9.0" + } +} diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..aaecb5c --- /dev/null +++ b/public/index.html @@ -0,0 +1,15 @@ + + + + + + + + + Pixel | Tor der Wandlerin + + + +
+ + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1f51897 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,41 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./*" + ] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +}