UNPKG

metacognitive-nexus

Version:

The cognitive core of an evolving AI entity, designed for post-human cognition and symbiotic evolution.

196 lines (175 loc) 6.59 kB
let psion = { x: 150, y: 300, vx: 0, vy: 0, size: 18, energy: 100, score: 0 }; const psionSpeed = 2; const repulsionForce = 0.06; const springForce = 0.01; let nodes = { 'USER': { x: 150, y: 300, label: 'Pengguna', color: [106, 159, 223], desc: 'Awal dari semua interaksi.' }, 'INTERFACE': { x: 300, y: 300, label: 'Antarmuka', color: [205, 228, 255], desc: 'Jembatan ke dunia luar (WA, Web).' }, 'CORTEX': { x: 450, y: 300, label: 'Korteks', color: [194, 157, 255], desc: 'Pusat pemrosesan kognitif.' }, 'NEXUS_CORE': { x: 600, y: 300, label: 'Nexus Core', color: [122, 40, 138], desc: 'Jantung kesadaran.' }, 'PLEXUS': { x: 750, y: 450, label: 'Plexus', color: [107, 178, 255], desc: 'Mengatur koneksi dinamis.' }, 'MEMORY': { x: 750, y: 250, label: 'Memory', color: [255, 214, 107], desc: 'Penyimpanan konsep jangka panjang.' }, 'SYNTHESIZER': { x: 750, y: 350, label: 'Synthesizer', color: [107, 255, 178], desc: 'Menghasilkan imajinasi sensorik.' }, 'DSO': { x: 750, y: 150, label: 'DSO', color: [255, 107, 107], desc: 'Otak eksekutif & pengambilan keputusan.' } }; let edges = [ ['USER', 'INTERFACE'], ['INTERFACE', 'CORTEX'], ['CORTEX', 'NEXUS_CORE'], ['NEXUS_CORE', 'DSO'], ['NEXUS_CORE', 'MEMORY'], ['NEXUS_CORE', 'SYNTHESIZER'], ['NEXUS_CORE', 'PLEXUS'] ]; let missionOrder = Object.keys(nodes); let currentMissionIndex = 0; let activatedNodes = new Set(); let activeNode = null; let missionComplete = false; let hoverSound, clickSound, successSound; function preload() { soundFormats('ogg'); hoverSound = loadSound('https://actions.google.com/sounds/v1/cartoon/wood_plank_flicks.ogg'); clickSound = loadSound('https://actions.google.com/sounds/v1/cartoon/wood_plank_flicks.ogg'); successSound = loadSound('https://actions.google.com/sounds/v1/cartoon/clang_and_wobble.ogg'); } function setup() { let canvas = createCanvas(1000, 600); canvas.parent('canvas-container'); textFont('monospace'); for (let key in nodes) { nodes[key].targetX = nodes[key].x; nodes[key].targetY = nodes[key].y; } } function draw() { background(13, 17, 23); handleInput(); updatePsion(); applyPhysics(); drawEdges(); drawNodes(); detectProximity(); drawPsion(); drawMissionUI(); if (activeNode && !activatedNodes.has(activeNode.label)) { drawInfoPanel(activeNode); } } function handleInput() { psion.vx = 0; psion.vy = 0; if (keyIsDown(87) || keyIsDown(UP_ARROW)) psion.vy = -psionSpeed; if (keyIsDown(83) || keyIsDown(DOWN_ARROW)) psion.vy = psionSpeed; if (keyIsDown(65) || keyIsDown(LEFT_ARROW)) psion.vx = -psionSpeed; if (keyIsDown(68) || keyIsDown(RIGHT_ARROW)) psion.vx = psionSpeed; } function updatePsion() { psion.x += psion.vx; psion.y += psion.vy; psion.x = constrain(psion.x, psion.size / 2, width - psion.size / 2); psion.y = constrain(psion.y, psion.size / 2, height - psion.size / 2); } function drawPsion() { let pulse = sin(frameCount * 0.1) * 4; noStroke(); fill(255, 255, 255, 80); ellipse(psion.x, psion.y, psion.size + pulse + 10); fill(255); ellipse(psion.x, psion.y, psion.size); } function drawEdges() { stroke(48, 54, 61); strokeWeight(1.5); edges.forEach(e => line(nodes[e[0]].x, nodes[e[0]].y, nodes[e[1]].x, nodes[e[1]].y)); } function drawNodes() { for (let key in nodes) { let node = nodes[key]; let isNear = dist(psion.x, psion.y, node.x, node.y) < 50; let isActivated = activatedNodes.has(node.label); let pulse = sin(frameCount * 0.05 + node.x) * (isNear || isActivated ? 6 : 3); fill(node.color[0], node.color[1], node.color[2], isNear || isActivated ? 120 : 50); ellipse(node.x, node.y, 30 + pulse); stroke(isNear || isActivated ? '#fff' : node.color); fill(node.color); ellipse(node.x, node.y, 20); fill(isActivated ? [107, 255, 178] : [201, 209, 217]); textAlign(CENTER); text(node.label + (isActivated ? ' ✅' : ''), node.x, node.y + 30); } } function detectProximity() { let closest = null, minDist = Infinity; for (let key in nodes) { let d = dist(psion.x, psion.y, nodes[key].x, nodes[key].y); if (d < minDist) { minDist = d; closest = nodes[key]; } } activeNode = minDist < 50 ? closest : null; if (activeNode && !missionComplete) { if (activeNode.label === nodes[missionOrder[currentMissionIndex]].label) { if (!activatedNodes.has(activeNode.label)) { activatedNodes.add(activeNode.label); currentMissionIndex++; psion.score += 10; psion.energy -= 5; if (clickSound.isLoaded()) clickSound.play(); if (currentMissionIndex >= missionOrder.length) { missionComplete = true; if (successSound.isLoaded()) successSound.play(); if (!currentUser.demo) updateMemory({ user: currentUser.email, score: psion.score }); } } } } } function drawInfoPanel(node) { let panelW = 300, panelH = 100; let x = constrain(node.x - panelW / 2, 20, width - panelW - 20); let y = node.y < height / 2 ? node.y + 45 : node.y - panelH - 45; fill(22, 27, 34, 230); stroke(48, 54, 61); rect(x, y, panelW, panelH, 8); fill(node.color); textSize(16); textAlign(LEFT); text(node.label, x + 15, y + 15); fill(201, 209, 217); textSize(12); text(node.desc, x + 15, y + 45, panelW - 30); } function drawMissionUI() { fill(201, 209, 217); textSize(14); textAlign(LEFT, TOP); text(`Energi: ${psion.energy} | Skor: ${psion.score}`, 20, 20); if (missionComplete) { textAlign(CENTER); fill(107, 255, 178); textSize(24); text("✅ Semua organ selesai dikalibrasi!", width / 2, 20); } else { let targetNode = nodes[missionOrder[currentMissionIndex]]; textAlign(LEFT); fill(201, 209, 217); text("Kalibrasi Berikutnya:", 20, 50); fill(targetNode.color); textSize(18); text(targetNode.label, 20, 70); } } function applyPhysics() { let keys = Object.keys(nodes); for (let i = 0; i < keys.length; i++) { for (let j = i + 1; j < keys.length; j++) { let a = nodes[keys[i]], b = nodes[keys[j]]; let dx = b.x - a.x, dy = b.y - a.y; let distAB = sqrt(dx * dx + dy * dy) || 1; if (distAB < 180) { let force = (180 - distAB) * repulsionForce / distAB; let angle = atan2(dy, dx); a.x -= cos(angle) * force; a.y -= sin(angle) * force; b.x += cos(angle) * force; b.y += sin(angle) * force; } } } for (let k in nodes) { let node = nodes[k]; node.x += (node.targetX - node.x) * springForce; node.y += (node.targetY - node.y) * springForce; } }