Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Byte-Sized Universe Birth</title>
- <style>
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
- body {
- font-family: 'Courier New', monospace;
- background: linear-gradient(135deg, #000428 0%, #004e92 100%);
- color: #e0f7fa;
- display: flex;
- justify-content: center;
- align-items: center;
- min-height: 100vh;
- overflow: hidden;
- }
- .container {
- text-align: center;
- padding: 20px;
- background: rgba(0, 0, 0, 0.7);
- border-radius: 20px;
- box-shadow: 0 0 40px rgba(0, 255, 255, 0.3);
- }
- h1 {
- font-size: 2.5em;
- margin-bottom: 10px;
- background: linear-gradient(45deg, #00ffff, #ff00ff, #ffff00);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- animation: glow 3s ease-in-out infinite;
- }
- @keyframes glow {
- 0%, 100% { filter: brightness(1); }
- 50% { filter: brightness(1.3); }
- }
- .subtitle {
- color: #80deea;
- margin-bottom: 20px;
- font-size: 0.9em;
- }
- canvas {
- border: 2px solid #00ffff;
- border-radius: 10px;
- cursor: crosshair;
- box-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
- image-rendering: pixelated;
- image-rendering: crisp-edges;
- }
- .controls {
- margin-top: 20px;
- display: flex;
- gap: 15px;
- justify-content: center;
- flex-wrap: wrap;
- }
- button {
- padding: 10px 20px;
- background: linear-gradient(45deg, #1a237e, #3949ab);
- color: #fff;
- border: none;
- border-radius: 25px;
- cursor: pointer;
- font-size: 14px;
- transition: all 0.3s;
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
- }
- button:hover {
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(0, 255, 255, 0.4);
- background: linear-gradient(45deg, #283593, #5c6bc0);
- }
- button:active {
- transform: translateY(0);
- }
- .info {
- margin-top: 20px;
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
- gap: 10px;
- font-size: 12px;
- }
- .info-item {
- padding: 8px;
- background: rgba(255, 255, 255, 0.1);
- border-radius: 10px;
- border: 1px solid rgba(0, 255, 255, 0.3);
- }
- .info-label {
- color: #80deea;
- display: block;
- margin-bottom: 3px;
- }
- .info-value {
- color: #ffff00;
- font-weight: bold;
- font-size: 16px;
- }
- .preset-seeds {
- margin-top: 15px;
- display: flex;
- gap: 10px;
- justify-content: center;
- flex-wrap: wrap;
- }
- .preset-btn {
- padding: 5px 12px;
- font-size: 12px;
- background: linear-gradient(45deg, #00695c, #00897b);
- }
- .preset-btn:hover {
- background: linear-gradient(45deg, #00796b, #009688);
- }
- .speed-control {
- margin-top: 15px;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 10px;
- }
- input[type="range"] {
- width: 150px;
- height: 5px;
- background: rgba(255, 255, 255, 0.2);
- outline: none;
- border-radius: 5px;
- }
- input[type="range"]::-webkit-slider-thumb {
- appearance: none;
- width: 15px;
- height: 15px;
- background: #00ffff;
- cursor: pointer;
- border-radius: 50%;
- box-shadow: 0 0 10px rgba(0, 255, 255, 0.8);
- }
- .legend {
- margin-top: 15px;
- font-size: 11px;
- display: flex;
- gap: 15px;
- justify-content: center;
- flex-wrap: wrap;
- }
- .legend-item {
- display: flex;
- align-items: center;
- gap: 5px;
- }
- .color-box {
- width: 15px;
- height: 15px;
- border-radius: 3px;
- border: 1px solid rgba(255, 255, 255, 0.3);
- }
- </style>
- </head>
- <body>
- <div class="container">
- <h1>Byte-Sized Universe Birth</h1>
- <div class="subtitle">Click to seed • Watch galaxies bloom • Entropy awaits</div>
- <canvas id="universe"></canvas>
- <div class="controls">
- <button id="clearBtn">Clear Universe</button>
- <button id="randomBtn">Random Seed</button>
- <button id="pauseBtn">Pause</button>
- <button id="stepBtn">Single Step</button>
- </div>
- <div class="preset-seeds">
- <button class="preset-btn" data-preset="glider">Glider</button>
- <button class="preset-btn" data-preset="pulsar">Pulsar</button>
- <button class="preset-btn" data-preset="galaxy">Galaxy</button>
- <button class="preset-btn" data-preset="nebula">Nebula</button>
- <button class="preset-btn" data-preset="supernova">Supernova</button>
- </div>
- <div class="speed-control">
- <span>Speed:</span>
- <input type="range" id="speedSlider" min="1" max="20" value="10">
- <span id="speedValue">10</span>
- </div>
- <div class="info">
- <div class="info-item">
- <span class="info-label">Generation</span>
- <span class="info-value" id="generation">0</span>
- </div>
- <div class="info-item">
- <span class="info-label">Active Bytes</span>
- <span class="info-value" id="population">0</span>
- </div>
- <div class="info-item">
- <span class="info-label">Entropy</span>
- <span class="info-value" id="entropy">0%</span>
- </div>
- <div class="info-item">
- <span class="info-label">Peak Bytes</span>
- <span class="info-value" id="peak">0</span>
- </div>
- </div>
- <div class="legend">
- <div class="legend-item">
- <div class="color-box" style="background: #00ffff;"></div>
- <span>Young Star</span>
- </div>
- <div class="legend-item">
- <div class="color-box" style="background: #ff00ff;"></div>
- <span>Nebula</span>
- </div>
- <div class="legend-item">
- <div class="color-box" style="background: #ffff00;"></div>
- <span>Supernova</span>
- </div>
- <div class="legend-item">
- <div class="color-box" style="background: #ff6b6b;"></div>
- <span>Red Giant</span>
- </div>
- </div>
- </div>
- <script>
- const canvas = document.getElementById('universe');
- const ctx = canvas.getContext('2d');
- const CELL_SIZE = 4;
- const GRID_WIDTH = 150;
- const GRID_HEIGHT = 100;
- canvas.width = GRID_WIDTH * CELL_SIZE;
- canvas.height = GRID_HEIGHT * CELL_SIZE;
- let grid = [];
- let nextGrid = [];
- let generation = 0;
- let population = 0;
- let peakPopulation = 0;
- let isPaused = false;
- let speed = 10;
- let entropyLevel = 0;
- let cellAge = [];
- // Initialize grids
- function initializeGrid() {
- grid = Array(GRID_HEIGHT).fill().map(() => Array(GRID_WIDTH).fill(0));
- nextGrid = Array(GRID_HEIGHT).fill().map(() => Array(GRID_WIDTH).fill(0));
- cellAge = Array(GRID_HEIGHT).fill().map(() => Array(GRID_WIDTH).fill(0));
- generation = 0;
- population = 0;
- peakPopulation = 0;
- entropyLevel = 0;
- updateStats();
- }
- // Count neighbors with different weights for varied patterns
- function countNeighbors(x, y) {
- let count = 0;
- let pattern = { young: 0, old: 0, dying: 0 };
- for (let dy = -1; dy <= 1; dy++) {
- for (let dx = -1; dx <= 1; dx++) {
- if (dx === 0 && dy === 0) continue;
- const nx = (x + dx + GRID_WIDTH) % GRID_WIDTH;
- const ny = (y + dy + GRID_HEIGHT) % GRID_HEIGHT;
- if (grid[ny][nx] === 1) {
- count++;
- const age = cellAge[ny][nx];
- if (age < 5) pattern.young++;
- else if (age < 15) pattern.old++;
- else pattern.dying++;
- }
- }
- }
- return { count, pattern };
- }
- // Update rules with entropy and varied evolution
- function updateCell(x, y) {
- const { count, pattern } = countNeighbors(x, y);
- const current = grid[y][x];
- const age = cellAge[y][x];
- // Add entropy factor
- const entropyFactor = Math.random() < (entropyLevel / 1000);
- if (current === 1) {
- // Living cell rules
- cellAge[y][x]++;
- // Death by entropy or age
- if (entropyFactor || age > 30) {
- return 0;
- }
- // Classic Conway rules with modifications
- if (count < 2 || count > 3) {
- // Higher chance of survival if surrounded by young cells
- if (pattern.young >= 2 && Math.random() < 0.3) {
- return 1;
- }
- return 0;
- }
- return 1;
- } else {
- // Dead cell rules
- if (count === 3) {
- cellAge[y][x] = 0;
- return 1;
- } else if (count === 2 && pattern.young >= 2 && Math.random() < 0.1) {
- // Small chance of spontaneous birth near young cells
- cellAge[y][x] = 0;
- return 1;
- }
- return 0;
- }
- }
- // Single evolution step
- function evolve() {
- population = 0;
- for (let y = 0; y < GRID_HEIGHT; y++) {
- for (let x = 0; x < GRID_WIDTH; x++) {
- nextGrid[y][x] = updateCell(x, y);
- if (nextGrid[y][x] === 1) population++;
- }
- }
- // Swap grids
- [grid, nextGrid] = [nextGrid, grid];
- generation++;
- entropyLevel = Math.min(100, generation * 0.5 + (peakPopulation - population) * 0.1);
- if (population > peakPopulation) {
- peakPopulation = population;
- }
- updateStats();
- }
- // Get color based on cell age and state
- function getCellColor(x, y) {
- if (grid[y][x] === 0) return null;
- const age = cellAge[y][x];
- if (age < 3) {
- return '#00ffff'; // Young star - cyan
- } else if (age < 8) {
- return '#ff00ff'; // Nebula - magenta
- } else if (age < 15) {
- return '#ffff00'; // Supernova - yellow
- } else if (age < 25) {
- return '#ff6b6b'; // Red giant
- } else {
- return '#4a148c'; // Dying star - deep purple
- }
- }
- // Draw the universe
- function draw() {
- ctx.fillStyle = '#000014';
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- // Draw grid lines (subtle)
- ctx.strokeStyle = 'rgba(255, 255, 255, 0.03)';
- ctx.lineWidth = 0.5;
- for (let x = 0; x <= GRID_WIDTH; x++) {
- ctx.beginPath();
- ctx.moveTo(x * CELL_SIZE, 0);
- ctx.lineTo(x * CELL_SIZE, canvas.height);
- ctx.stroke();
- }
- for (let y = 0; y <= GRID_HEIGHT; y++) {
- ctx.beginPath();
- ctx.moveTo(0, y * CELL_SIZE);
- ctx.lineTo(canvas.width, y * CELL_SIZE);
- ctx.stroke();
- }
- // Draw cells with glow effect
- for (let y = 0; y < GRID_HEIGHT; y++) {
- for (let x = 0; x < GRID_WIDTH; x++) {
- const color = getCellColor(x, y);
- if (color) {
- // Add glow
- const age = cellAge[y][x];
- const glowSize = age < 5 ? 2 : 1;
- ctx.shadowColor = color;
- ctx.shadowBlur = glowSize * 2;
- ctx.fillStyle = color;
- ctx.fillRect(
- x * CELL_SIZE,
- y * CELL_SIZE,
- CELL_SIZE,
- CELL_SIZE
- );
- ctx.shadowBlur = 0;
- }
- }
- }
- }
- // Update statistics
- function updateStats() {
- document.getElementById('generation').textContent = generation;
- document.getElementById('population').textContent = population;
- document.getElementById('entropy').textContent = Math.floor(entropyLevel) + '%';
- document.getElementById('peak').textContent = peakPopulation;
- }
- // Preset patterns
- const presets = {
- glider: [
- [0, 1], [1, 2], [2, 0], [2, 1], [2, 2]
- ],
- pulsar: [
- [2,4],[2,5],[2,6],[2,10],[2,11],[2,12],
- [4,2],[5,2],[6,2],[4,7],[5,7],[6,7],[4,9],[5,9],[6,9],[4,14],[5,14],[6,14],
- [7,4],[7,5],[7,6],[7,10],[7,11],[7,12],
- [9,4],[9,5],[9,6],[9,10],[9,11],[9,12],
- [10,2],[11,2],[12,2],[10,7],[11,7],[12,7],[10,9],[11,9],[12,9],[10,14],[11,14],[12,14],
- [14,4],[14,5],[14,6],[14,10],[14,11],[14,12]
- ],
- galaxy: function() {
- const pattern = [];
- for (let i = 0; i < 50; i++) {
- const angle = (i / 50) * Math.PI * 2;
- const radius = i * 0.5;
- const x = Math.floor(GRID_WIDTH / 2 + Math.cos(angle) * radius);
- const y = Math.floor(GRID_HEIGHT / 2 + Math.sin(angle) * radius);
- if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT) {
- pattern.push([y, x]);
- }
- }
- return pattern;
- },
- nebula: function() {
- const pattern = [];
- const cx = GRID_WIDTH / 2;
- const cy = GRID_HEIGHT / 2;
- for (let i = 0; i < 100; i++) {
- const angle = Math.random() * Math.PI * 2;
- const radius = Math.random() * 20;
- const x = Math.floor(cx + Math.cos(angle) * radius);
- const y = Math.floor(cy + Math.sin(angle) * radius);
- if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT) {
- pattern.push([y, x]);
- }
- }
- return pattern;
- },
- supernova: function() {
- const pattern = [];
- const cx = GRID_WIDTH / 2;
- const cy = GRID_HEIGHT / 2;
- for (let r = 5; r < 15; r += 3) {
- for (let a = 0; a < Math.PI * 2; a += 0.3) {
- const x = Math.floor(cx + Math.cos(a) * r);
- const y = Math.floor(cy + Math.sin(a) * r);
- if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT) {
- pattern.push([y, x]);
- }
- }
- }
- return pattern;
- }
- };
- // Place preset pattern
- function placePreset(name) {
- initializeGrid();
- const pattern = typeof presets[name] === 'function' ? presets[name]() : presets[name];
- const offsetX = Math.floor((GRID_WIDTH - 20) / 2);
- const offsetY = Math.floor((GRID_HEIGHT - 20) / 2);
- for (const [y, x] of pattern) {
- const nx = x + offsetX;
- const ny = y + offsetY;
- if (nx >= 0 && nx < GRID_WIDTH && ny >= 0 && ny < GRID_HEIGHT) {
- grid[ny][nx] = 1;
- cellAge[ny][nx] = 0;
- }
- }
- draw();
- }
- // Canvas click handler
- canvas.addEventListener('click', (e) => {
- const rect = canvas.getBoundingClientRect();
- const x = Math.floor((e.clientX - rect.left) / CELL_SIZE);
- const y = Math.floor((e.clientY - rect.top) / CELL_SIZE);
- // Create a small cluster for better effect
- for (let dy = -1; dy <= 1; dy++) {
- for (let dx = -1; dx <= 1; dx++) {
- const nx = x + dx;
- const ny = y + dy;
- if (nx >= 0 && nx < GRID_WIDTH && ny >= 0 && ny < GRID_HEIGHT) {
- if (Math.random() < 0.6) {
- grid[ny][nx] = 1;
- cellAge[ny][nx] = 0;
- }
- }
- }
- }
- draw();
- });
- // Control buttons
- document.getElementById('clearBtn').addEventListener('click', () => {
- initializeGrid();
- draw();
- });
- document.getElementById('randomBtn').addEventListener('click', () => {
- initializeGrid();
- for (let y = 0; y < GRID_HEIGHT; y++) {
- for (let x = 0; x < GRID_WIDTH; x++) {
- if (Math.random() < 0.15) {
- grid[y][x] = 1;
- cellAge[y][x] = Math.floor(Math.random() * 5);
- }
- }
- }
- draw();
- });
- document.getElementById('pauseBtn').addEventListener('click', () => {
- isPaused = !isPaused;
- document.getElementById('pauseBtn').textContent = isPaused ? 'Resume' : 'Pause';
- });
- document.getElementById('stepBtn').addEventListener('click', () => {
- evolve();
- draw();
- });
- // Preset buttons
- document.querySelectorAll('.preset-btn').forEach(btn => {
- btn.addEventListener('click', (e) => {
- placePreset(e.target.dataset.preset);
- });
- });
- // Speed control
- document.getElementById('speedSlider').addEventListener('input', (e) => {
- speed = parseInt(e.target.value);
- document.getElementById('speedValue').textContent = speed;
- });
- // Animation loop
- let frameCount = 0;
- function animate() {
- if (!isPaused) {
- frameCount++;
- if (frameCount >= (21 - speed)) {
- evolve();
- draw();
- frameCount = 0;
- }
- }
- requestAnimationFrame(animate);
- }
- // Initialize
- initializeGrid();
- draw();
- animate();
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment