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>Dream Weaver Web</title>
- <style>
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
- body {
- font-family: 'Georgia', serif;
- background: radial-gradient(ellipse at center, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
- overflow: hidden;
- height: 100vh;
- position: relative;
- }
- .dream-canvas {
- width: 100%;
- height: 100vh;
- position: relative;
- cursor: crosshair;
- }
- .thought-node {
- position: absolute;
- width: 140px;
- height: 90px;
- border-radius: 25px;
- backdrop-filter: blur(15px);
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: grab;
- transition: all 0.4s ease;
- color: white;
- text-align: center;
- font-size: 12px;
- font-weight: 500;
- padding: 12px;
- box-shadow: 0 8px 32px rgba(0,0,0,0.4);
- border: 2px solid;
- animation: gentle-float 6s ease-in-out infinite;
- user-select: none;
- }
- .thought-node.positive {
- background: linear-gradient(135deg, rgba(100,255,150,0.15) 0%, rgba(50,200,255,0.1) 100%);
- border-color: rgba(100,255,150,0.4);
- box-shadow: 0 8px 32px rgba(100,255,150,0.2);
- }
- .thought-node.negative {
- background: linear-gradient(135deg, rgba(255,100,100,0.15) 0%, rgba(200,50,50,0.1) 100%);
- border-color: rgba(255,100,100,0.4);
- box-shadow: 0 8px 32px rgba(255,100,100,0.2);
- }
- .thought-node.neutral {
- background: linear-gradient(135deg, rgba(200,200,255,0.15) 0%, rgba(150,150,200,0.1) 100%);
- border-color: rgba(200,200,255,0.4);
- box-shadow: 0 8px 32px rgba(200,200,255,0.2);
- }
- .thought-node:hover {
- transform: scale(1.1);
- filter: brightness(1.2);
- }
- .thought-node.dragging {
- cursor: grabbing;
- z-index: 1000;
- transform: scale(1.2);
- filter: brightness(1.3);
- }
- .thought-node.connected {
- filter: brightness(1.1) saturate(1.2);
- animation: connected-pulse 4s ease-in-out infinite;
- }
- .thought-node.nightmare {
- background: linear-gradient(135deg, rgba(255,0,0,0.3) 0%, rgba(150,0,0,0.2) 100%);
- border-color: rgba(255,0,0,0.7);
- animation: nightmare-shake 0.5s ease-in-out infinite;
- }
- @keyframes gentle-float {
- 0%, 100% { transform: translateY(0px) rotate(0deg); }
- 33% { transform: translateY(-8px) rotate(0.5deg); }
- 66% { transform: translateY(-4px) rotate(-0.5deg); }
- }
- @keyframes connected-pulse {
- 0%, 100% { filter: brightness(1.1) saturate(1.2); }
- 50% { filter: brightness(1.3) saturate(1.4); }
- }
- @keyframes nightmare-shake {
- 0%, 100% { transform: translateX(0); }
- 25% { transform: translateX(-2px); }
- 75% { transform: translateX(2px); }
- }
- .connection-svg {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- pointer-events: none;
- z-index: -1;
- }
- .connection-line {
- stroke-width: 3;
- fill: none;
- filter: drop-shadow(0 0 8px currentColor);
- animation: energy-flow 2s ease-in-out infinite;
- }
- .positive-connection {
- stroke: rgba(100,255,150,0.8);
- }
- .negative-connection {
- stroke: rgba(255,100,100,0.8);
- }
- .neutral-connection {
- stroke: rgba(200,200,255,0.6);
- }
- .nightmare-connection {
- stroke: rgba(255,0,0,0.9);
- stroke-width: 4;
- stroke-dasharray: 8,4;
- animation: nightmare-flow 1s linear infinite, energy-flow 2s ease-in-out infinite;
- }
- @keyframes energy-flow {
- 0%, 100% { opacity: 0.6; }
- 50% { opacity: 1; }
- }
- @keyframes nightmare-flow {
- 0% { stroke-dashoffset: 0; }
- 100% { stroke-dashoffset: 12; }
- }
- .temp-line {
- stroke: rgba(255,255,255,0.8);
- stroke-width: 2;
- fill: none;
- stroke-dasharray: 5,5;
- }
- .ui-panel {
- position: fixed;
- top: 20px;
- left: 20px;
- background: rgba(0,0,0,0.8);
- padding: 25px;
- border-radius: 20px;
- color: white;
- backdrop-filter: blur(15px);
- border: 2px solid rgba(255,255,255,0.2);
- min-width: 280px;
- }
- .score-section {
- margin-bottom: 15px;
- }
- .score-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin: 8px 0;
- font-size: 16px;
- }
- .score-value {
- font-weight: bold;
- color: #4fc3f7;
- }
- .combo-indicator {
- background: linear-gradient(135deg, #ff6b6b, #feca57);
- color: white;
- padding: 5px 12px;
- border-radius: 15px;
- font-size: 14px;
- margin-top: 10px;
- text-align: center;
- display: none;
- }
- .legend {
- margin-top: 20px;
- padding-top: 15px;
- border-top: 1px solid rgba(255,255,255,0.3);
- }
- .legend-item {
- display: flex;
- align-items: center;
- margin: 5px 0;
- font-size: 12px;
- }
- .legend-color {
- width: 15px;
- height: 15px;
- border-radius: 3px;
- margin-right: 8px;
- border: 1px solid rgba(255,255,255,0.3);
- }
- .positive-color { background: rgba(100,255,150,0.6); }
- .negative-color { background: rgba(255,100,100,0.6); }
- .neutral-color { background: rgba(200,200,255,0.6); }
- .progress-bar {
- width: 200px;
- height: 8px;
- background: rgba(255,255,255,0.2);
- border-radius: 4px;
- overflow: hidden;
- margin: 8px 0;
- }
- .progress-fill {
- height: 100%;
- background: linear-gradient(90deg, #4fc3f7, #29b6f6);
- transition: width 0.5s ease;
- border-radius: 4px;
- }
- .completion-modal {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background: rgba(0,0,0,0.95);
- padding: 40px;
- border-radius: 25px;
- color: white;
- text-align: center;
- backdrop-filter: blur(25px);
- border: 3px solid rgba(255,255,255,0.3);
- max-width: 600px;
- display: none;
- z-index: 2000;
- }
- .completion-modal h2 {
- color: #4fc3f7;
- margin-bottom: 20px;
- font-size: 28px;
- }
- .final-score {
- font-size: 24px;
- color: #feca57;
- margin: 15px 0;
- }
- .new-game-btn {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- border: none;
- padding: 15px 35px;
- border-radius: 30px;
- color: white;
- cursor: pointer;
- font-size: 18px;
- transition: transform 0.3s ease;
- margin-top: 20px;
- }
- .new-game-btn:hover {
- transform: scale(1.05);
- }
- .floating-particles {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- pointer-events: none;
- z-index: -2;
- }
- .particle {
- position: absolute;
- width: 3px;
- height: 3px;
- background: rgba(255,255,255,0.4);
- border-radius: 50%;
- animation: float-particle 20s linear infinite;
- }
- @keyframes float-particle {
- 0% {
- transform: translateY(100vh) translateX(0);
- opacity: 0;
- }
- 10% {
- opacity: 1;
- }
- 90% {
- opacity: 1;
- }
- 100% {
- transform: translateY(-50px) translateX(50px);
- opacity: 0;
- }
- }
- .spawn-effect {
- animation: spawn-in 1s ease-out;
- }
- @keyframes spawn-in {
- 0% {
- transform: scale(0) rotate(180deg);
- opacity: 0;
- }
- 100% {
- transform: scale(1) rotate(0deg);
- opacity: 1;
- }
- }
- .reward-popup {
- position: absolute;
- background: rgba(255,215,0,0.9);
- color: #333;
- padding: 8px 16px;
- border-radius: 20px;
- font-weight: bold;
- pointer-events: none;
- z-index: 1500;
- animation: reward-float 2s ease-out forwards;
- }
- @keyframes reward-float {
- 0% {
- transform: translateY(0) scale(0);
- opacity: 0;
- }
- 20% {
- transform: translateY(-10px) scale(1.2);
- opacity: 1;
- }
- 100% {
- transform: translateY(-60px) scale(1);
- opacity: 0;
- }
- }
- </style>
- </head>
- <body>
- <div class="floating-particles" id="particles"></div>
- <div class="dream-canvas" id="canvas">
- <svg class="connection-svg" id="svg">
- <defs>
- <filter id="glow">
- <feGaussianBlur stdDeviation="4" result="coloredBlur"/>
- <feMerge>
- <feMergeNode in="coloredBlur"/>
- <feMergeNode in="SourceGraphic"/>
- </feMerge>
- </filter>
- </defs>
- </svg>
- </div>
- <div class="ui-panel">
- <div class="score-section">
- <div class="score-item">
- <span>Dream Score:</span>
- <span class="score-value" id="score">0</span>
- </div>
- <div class="score-item">
- <span>Harmony Bonus:</span>
- <span class="score-value" id="harmony">0</span>
- </div>
- <div class="score-item">
- <span>Connections:</span>
- <span class="score-value" id="connections">0</span>
- </div>
- <div class="combo-indicator" id="combo">Harmony Streak!</div>
- </div>
- <div>Dream Progress:</div>
- <div class="progress-bar">
- <div class="progress-fill" id="progress" style="width: 0%"></div>
- </div>
- <div class="legend">
- <div class="legend-item">
- <div class="legend-color positive-color"></div>
- <span>Positive Dreams (+50 pts)</span>
- </div>
- <div class="legend-item">
- <div class="legend-color negative-color"></div>
- <span>Nightmares (-25 pts)</span>
- </div>
- <div class="legend-item">
- <div class="legend-color neutral-color"></div>
- <span>Neutral (+20 pts)</span>
- </div>
- </div>
- <div style="margin-top: 15px; font-size: 11px; opacity: 0.9;">
- 🎯 Connect <strong>Positive to Positive</strong> for huge bonuses!<br>
- ⚡ Avoid connecting opposite emotions<br>
- 🌟 Build harmony streaks for multipliers
- </div>
- </div>
- <div class="completion-modal" id="modal">
- <h2 id="modalTitle">Dream Complete!</h2>
- <div class="final-score">Final Score: <span id="finalScore">0</span></div>
- <p id="modalText"></p>
- <button class="new-game-btn" onclick="newGame()">Weave Another Dream</button>
- </div>
- <script>
- class DreamWeaver {
- constructor() {
- this.canvas = document.getElementById('canvas');
- this.svg = document.getElementById('svg');
- this.nodes = [];
- this.connections = [];
- this.isDragging = false;
- this.dragNode = null;
- this.tempLine = null;
- this.score = 0;
- this.harmonyBonus = 0;
- this.harmonyStreak = 0;
- this.gameComplete = false;
- this.targetConnections = 15;
- // Enhanced dream content with clear emotional categories
- this.dreamContent = {
- positive: [
- "Soaring through starlight", "Childhood laughter echoing", "Warm golden meadows",
- "Dancing with butterflies", "Gentle ocean waves", "Rainbow bridge pathway",
- "Singing crystal fountains", "Floating flower gardens", "Sunlit forest clearing",
- "Angels whispering hope", "Peaceful mountain vista", "Luminous healing light"
- ],
- negative: [
- "Falling into darkness", "Endless maze of mirrors", "Screaming silent winds",
- "Shadowy figures lurking", "Bleeding crimson sky", "Frozen in terror",
- "Drowning in black water", "Thorns piercing flesh", "Empty hollow voices",
- "Crumbling stone walls", "Suffocating dense fog", "Eyes watching always"
- ],
- neutral: [
- "Clock ticking steadily", "Empty white corridors", "Floating geometric shapes",
- "Mechanical gears turning", "Gray misty landscapes", "Silent library halls",
- "Drifting paper planes", "Reflecting still water", "Ancient stone circles",
- "Distant city lights", "Wandering endless roads", "Spinning compass needles"
- ]
- };
- this.dreamEndings = {
- transcendent: "Your harmonious dream web ascends into pure light, each connection a note in the symphony of consciousness. You have achieved perfect dream mastery.",
- balanced: "Your dream tapestry weaves together light and shadow in perfect balance, creating a masterpiece of subconscious artistry.",
- chaotic: "Your dream fragments scatter like broken glass, each piece reflecting a different reality. Beautiful chaos reigns in your sleeping mind.",
- nightmare: "The shadows have consumed your dream web, leaving only whispers of what might have been. Even nightmares teach us about ourselves.",
- incomplete: "Your dream fades before completion, leaving mysterious fragments that hint at deeper truths waiting to be discovered."
- };
- this.init();
- }
- init() {
- this.createParticles();
- this.createInitialNodes();
- this.setupEventListeners();
- this.gameLoop();
- }
- createParticles() {
- const particleContainer = document.getElementById('particles');
- for (let i = 0; i < 25; i++) {
- const particle = document.createElement('div');
- particle.className = 'particle';
- particle.style.left = Math.random() * 100 + '%';
- particle.style.animationDelay = Math.random() * 20 + 's';
- particle.style.animationDuration = (15 + Math.random() * 10) + 's';
- particleContainer.appendChild(particle);
- }
- }
- createInitialNodes() {
- // Start with just 5 well-spaced nodes
- const positions = [
- { x: 200, y: 150 },
- { x: 600, y: 200 },
- { x: 400, y: 400 },
- { x: 800, y: 350 },
- { x: 300, y: 600 }
- ];
- positions.forEach((pos, i) => {
- setTimeout(() => {
- this.createNode(pos.x, pos.y);
- }, i * 300);
- });
- }
- createNode(x, y) {
- // Random emotional type with balanced distribution
- const types = ['positive', 'negative', 'neutral'];
- const weights = [0.4, 0.3, 0.3]; // Slightly favor positive
- const type = this.weightedRandom(types, weights);
- const node = document.createElement('div');
- node.className = `thought-node ${type} spawn-effect`;
- node.textContent = this.getRandomText(type);
- // Better positioning - ensure nodes stay within visible area
- const finalX = x || (100 + Math.random() * (window.innerWidth - 300));
- const finalY = y || (100 + Math.random() * (window.innerHeight - 200));
- node.style.left = finalX + 'px';
- node.style.top = finalY + 'px';
- node.style.animationDelay = Math.random() * 6 + 's';
- node.dataset.id = this.nodes.length;
- node.dataset.type = type;
- node.dataset.connections = '0';
- node.dataset.x = finalX + 70; // center point
- node.dataset.y = finalY + 45; // center point
- this.canvas.appendChild(node);
- this.nodes.push(node);
- this.setupNodeEvents(node);
- }
- weightedRandom(items, weights) {
- const random = Math.random();
- let sum = 0;
- for (let i = 0; i < weights.length; i++) {
- sum += weights[i];
- if (random <= sum) return items[i];
- }
- return items[items.length - 1];
- }
- getRandomText(type) {
- const texts = this.dreamContent[type];
- return texts[Math.floor(Math.random() * texts.length)];
- }
- setupNodeEvents(node) {
- node.addEventListener('mousedown', (e) => this.startDrag(e, node));
- node.addEventListener('mouseup', (e) => this.endDrag(e, node));
- }
- setupEventListeners() {
- this.canvas.addEventListener('mousemove', (e) => this.onMouseMove(e));
- this.canvas.addEventListener('mouseup', (e) => this.onMouseUp(e));
- this.canvas.addEventListener('contextmenu', (e) => e.preventDefault());
- }
- startDrag(e, node) {
- e.preventDefault();
- this.isDragging = true;
- this.dragNode = node;
- node.classList.add('dragging');
- this.tempLine = document.createElementNS('http://www.w3.org/2000/svg', 'line');
- this.tempLine.setAttribute('class', 'temp-line');
- this.tempLine.setAttribute('x1', node.dataset.x);
- this.tempLine.setAttribute('y1', node.dataset.y);
- this.tempLine.setAttribute('x2', e.clientX);
- this.tempLine.setAttribute('y2', e.clientY);
- this.svg.appendChild(this.tempLine);
- }
- onMouseMove(e) {
- if (this.isDragging && this.tempLine) {
- this.tempLine.setAttribute('x2', e.clientX);
- this.tempLine.setAttribute('y2', e.clientY);
- }
- }
- endDrag(e, targetNode) {
- if (this.isDragging && this.dragNode && targetNode !== this.dragNode) {
- this.createConnection(this.dragNode, targetNode);
- }
- this.onMouseUp(e);
- }
- onMouseUp(e) {
- if (this.isDragging) {
- this.isDragging = false;
- if (this.dragNode) {
- this.dragNode.classList.remove('dragging');
- this.dragNode = null;
- }
- if (this.tempLine) {
- this.svg.removeChild(this.tempLine);
- this.tempLine = null;
- }
- }
- }
- createConnection(node1, node2) {
- const id1 = parseInt(node1.dataset.id);
- const id2 = parseInt(node2.dataset.id);
- // Check if connection already exists
- const existingConnection = this.connections.find(conn =>
- (conn.node1 === id1 && conn.node2 === id2) ||
- (conn.node1 === id2 && conn.node2 === id1)
- );
- if (existingConnection) return;
- const type1 = node1.dataset.type;
- const type2 = node2.dataset.type;
- const { score, connectionType, isHarmony } = this.calculateConnectionScore(type1, type2);
- // Create visual connection
- const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
- line.setAttribute('x1', node1.dataset.x);
- line.setAttribute('y1', node1.dataset.y);
- line.setAttribute('x2', node2.dataset.x);
- line.setAttribute('y2', node2.dataset.y);
- line.setAttribute('class', `connection-line ${connectionType}-connection`);
- line.setAttribute('filter', 'url(#glow)');
- this.svg.appendChild(line);
- // Update node connections
- const conn1 = parseInt(node1.dataset.connections) + 1;
- const conn2 = parseInt(node2.dataset.connections) + 1;
- node1.dataset.connections = conn1;
- node2.dataset.connections = conn2;
- node1.classList.add('connected');
- node2.classList.add('connected');
- // Handle scoring and effects
- this.score += score;
- if (isHarmony) {
- this.harmonyStreak++;
- const bonus = this.harmonyStreak * 10;
- this.harmonyBonus += bonus;
- this.showRewardPopup(node1, `+${score + bonus} Harmony!`);
- this.showCombo();
- } else {
- this.harmonyStreak = 0;
- this.hideCombo();
- if (score < 0) {
- this.showRewardPopup(node1, `${score} Nightmare!`);
- } else {
- this.showRewardPopup(node1, `+${score}`);
- }
- }
- // Check for nightmare tangles (too many connections)
- if (conn1 > 4 || conn2 > 4) {
- this.createNightmareTangle(conn1 > 4 ? node1 : node2);
- }
- // Store connection
- this.connections.push({
- node1: id1,
- node2: id2,
- type: connectionType,
- line: line,
- score: score
- });
- this.updateUI();
- this.checkWinCondition();
- // Spawn new nodes strategically
- if (this.connections.length % 3 === 0 && this.nodes.length < 12) {
- setTimeout(() => this.createNode(), 1000);
- }
- }
- calculateConnectionScore(type1, type2) {
- if (type1 === 'positive' && type2 === 'positive') {
- return { score: 50, connectionType: 'positive', isHarmony: true };
- } else if (type1 === 'negative' && type2 === 'negative') {
- return { score: 30, connectionType: 'negative', isHarmony: true };
- } else if (type1 === 'neutral' && type2 === 'neutral') {
- return { score: 40, connectionType: 'neutral', isHarmony: true };
- } else if ((type1 === 'positive' && type2 === 'negative') || (type1 === 'negative' && type2 === 'positive')) {
- return { score: -25, connectionType: 'nightmare', isHarmony: false };
- } else {
- // Mixed neutral connections
- return { score: 20, connectionType: 'neutral', isHarmony: false };
- }
- }
- showRewardPopup(node, text) {
- const popup = document.createElement('div');
- popup.className = 'reward-popup';
- popup.textContent = text;
- popup.style.left = node.style.left;
- popup.style.top = (parseInt(node.style.top) - 20) + 'px';
- this.canvas.appendChild(popup);
- setTimeout(() => {
- if (popup.parentNode) {
- popup.parentNode.removeChild(popup);
- }
- }, 2000);
- }
- showCombo() {
- const combo = document.getElementById('combo');
- combo.textContent = `${this.harmonyStreak}x Harmony Streak!`;
- combo.style.display = 'block';
- }
- hideCombo() {
- document.getElementById('combo').style.display = 'none';
- }
- createNightmareTangle(node) {
- node.classList.add('nightmare');
- this.score -= 50;
- this.showRewardPopup(node, '-50 Tangle!');
- }
- updateUI() {
- document.getElementById('score').textContent = Math.max(0, this.score);
- document.getElementById('harmony').textContent = this.harmonyBonus;
- document.getElementById('connections').textContent = this.connections.length;
- const progress = Math.min(100, (this.connections.length / this.targetConnections) * 100);
- document.getElementById('progress').style.width = progress + '%';
- }
- checkWinCondition() {
- if (this.connections.length >= this.targetConnections) {
- setTimeout(() => this.endGame(), 1000);
- }
- }
- endGame() {
- if (this.gameComplete) return;
- this.gameComplete = true;
- const finalScore = this.score + this.harmonyBonus;
- let endingType;
- if (finalScore > 800 && this.harmonyStreak > 5) {
- endingType = 'transcendent';
- } else if (finalScore > 400) {
- endingType = 'balanced';
- } else if (finalScore > 0) {
- endingType = 'chaotic';
- } else {
- endingType = 'nightmare';
- }
- const modal = document.getElementById('modal');
- const title = document.getElementById('modalTitle');
- const text = document.getElementById('modalText');
- const finalScoreElement = document.getElementById('finalScore');
- title.textContent = this.getEndingTitle(endingType);
- text.textContent = this.dreamEndings[endingType];
- finalScoreElement.textContent = finalScore;
- modal.style.display = 'block';
- }
- getEndingTitle(type) {
- const titles = {
- transcendent: '✨ Dream Transcendence ✨',
- balanced: '🌟 Harmonious Dreams 🌟',
- chaotic: '🌪️ Beautiful Chaos 🌪️',
- nightmare: '👻 Shadow Realm 👻',
- incomplete: '💭 Mysterious Fragments 💭'
- };
- return titles[type] || 'Dream Complete';
- }
- gameLoop() {
- // Gentle node movement
- this.nodes.forEach((node, index) => {
- if (!node.classList.contains('dragging')) {
- const time = Date.now() * 0.0005;
- const driftX = Math.sin(time + index) * 0.3;
- const driftY = Math.cos(time + index * 1.3) * 0.2;
- const currentX = parseFloat(node.style.left);
- const currentY = parseFloat(node.style.top);
- node.style.left = (currentX + driftX) + 'px';
- node.style.top = (currentY + driftY) + 'px';
- node.dataset.x = currentX + 70 + driftX;
- node.dataset.y = currentY + 45 + driftY;
- }
- });
- // Update connection lines
- this.connections.forEach(conn => {
- const node1 = this.nodes[conn.node1];
- const node2 = this.nodes[conn.node2];
- if (node1 && node2 && conn.line) {
- conn.line.setAttribute('x1', node1.dataset.x);
- conn.line.setAttribute('y1', node1.dataset.y);
- conn.line.setAttribute('x2', node2.dataset.x);
- conn.line.setAttribute('y2', node2.dataset.y);
- }
- });
- if (!this.gameComplete) {
- requestAnimationFrame(() => this.gameLoop());
- }
- }
- }
- function newGame() {
- location.reload();
- }
- // Initialize the game
- let dreamWeaver;
- window.addEventListener('DOMContentLoaded', () => {
- dreamWeaver = new DreamWeaver();
- });
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment