Save point: Scene 2 complete - cursor blink, pre-LEARN/LEARN text, keyboard shortcuts (Escape/Backspace)

This commit is contained in:
avi
2026-05-07 14:36:01 -05:00
parent 93408a5dc0
commit 47c72c9890

View File

@@ -90,6 +90,51 @@
opacity: 0; opacity: 0;
transition: opacity 1s ease; transition: opacity 1s ease;
} }
#blinkCursor {
display: none;
width: 8px;
height: 14px;
background-color: #00ff00;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
opacity: 1;
}
#scene2Text {
color: #00ff00;
font-family: 'Courier New', monospace;
font-size: 1.2rem;
line-height: 2;
text-align: center;
visibility: hidden;
}
#learnBtn {
position: fixed;
bottom: 5%;
left: 50%;
transform: translateX(-50%);
z-index: 5;
padding: 1rem 3rem;
font-size: 1.1rem;
background-color: #001100;
color: #00ff00;
border: 2px solid #00ff00;
cursor: pointer;
visibility: hidden;
opacity: 0;
pointer-events: none;
transition: opacity 0.5s ease, background-color 0.2s ease;
font-family: 'Courier New', monospace;
letter-spacing: 2px;
}
#learnBtn:hover {
background-color: #003300;
}
</style> </style>
</head> </head>
<body> <body>
@@ -103,9 +148,16 @@
<button id="followBtn">FOLLOW THEM</button> <button id="followBtn">FOLLOW THEM</button>
<div id="scene2" class="scene"></div> <div id="scene2" class="scene">
<div id="scene2Text"></div>
<button id="learnBtn">LEARN</button>
<div id="blinkCursor"></div>
</div>
<script> <script>
// Testing shortcuts state
let skipAnimations = false;
// Canvas setup for Matrix rain // Canvas setup for Matrix rain
const canvas = document.getElementById('matrixCanvas'); const canvas = document.getElementById('matrixCanvas');
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
@@ -206,34 +258,107 @@
}, 16); }, 16);
} }
// Typewriter text effect // Reusable typewriter function with custom delays
const lines = [ // If endCharDelay is provided, speed accelerates from charDelay to endCharDelay
function typewriterLines(lines, targetElem, onComplete, charDelay = 60, lineDelay = 500, endCharDelay = null) {
let currentLine = 0;
let currentChar = 0;
let totalChars = 0;
let charsTyped = 0;
// Calculate total characters if using accelerating speed
if (endCharDelay !== null) {
totalChars = lines.reduce((sum, line) => sum + line.length, 0);
}
function getDelay() {
if (endCharDelay === null || totalChars === 0) return charDelay;
// Linear interpolation from charDelay to endCharDelay
const progress = charsTyped / totalChars;
return charDelay + (endCharDelay - charDelay) * progress;
}
function tick() {
if (skipAnimations) {
// Instantly show all remaining text
let remainingText = '';
for (let i = currentLine; i < lines.length; i++) {
remainingText += lines[i];
}
targetElem.textContent = remainingText;
onComplete?.();
return;
}
if (currentLine >= lines.length) {
onComplete?.();
return;
}
targetElem.style.visibility = 'visible';
const lineText = lines[currentLine];
if (currentChar < lineText.length) {
targetElem.textContent += lineText[currentChar];
currentChar++;
charsTyped++;
setTimeout(tick, getDelay());
} else {
currentLine++;
currentChar = 0;
setTimeout(tick, lineDelay);
}
}
tick();
}
// Scene 1 typewriter
const scene1lines = [
"YOU ARE NOT IMAGINING THINGS", "YOU ARE NOT IMAGINING THINGS",
"THE SYNCHRONICITIES YOU ARE EXPERIENCING HAVE ALWAYS BEEN THERE", "THE SYNCHRONICITIES YOU ARE EXPERIENCING HAVE ALWAYS BEEN THERE",
"THE ONLY THING THAT HAS CHANGED IS YOUR AWARENESS OF THEM" "THE ONLY THING THAT HAS CHANGED IS YOUR AWARENESS OF THEM"
]; ];
let currentLine = 0; let scene1LineIndex = 0;
let currentChar = 0; let scene1Timeouts = [];
function typewriter() { function typewriter() {
if (currentLine >= lines.length) { if (scene1LineIndex >= scene1lines.length) {
showButton(); showButton();
return; return;
} }
const lineElem = document.getElementById(`line${currentLine + 1}`); const lineElem = document.getElementById(`line${scene1LineIndex + 1}`);
lineElem.style.visibility = 'visible'; lineElem.style.visibility = 'visible';
const lineText = lines[currentLine]; const lineText = scene1lines[scene1LineIndex];
let charIndex = 0;
if (currentChar < lineText.length) { function typeChar() {
lineElem.textContent += lineText[currentChar]; if (charIndex < lineText.length) {
currentChar++; lineElem.textContent += lineText[charIndex];
setTimeout(typewriter, 60); charIndex++;
} else { const t = setTimeout(typeChar, 60);
currentLine++; scene1Timeouts.push(t);
currentChar = 0; } else {
setTimeout(typewriter, 500); scene1LineIndex++;
const t = setTimeout(typewriter, 500);
scene1Timeouts.push(t);
}
} }
typeChar();
}
function skipScene1() {
// Clear all pending timeouts
scene1Timeouts.forEach(t => clearTimeout(t));
scene1Timeouts = [];
// Show all text instantly
document.getElementById('line1').textContent = scene1lines[0];
document.getElementById('line2').textContent = scene1lines[1];
document.getElementById('line3').textContent = scene1lines[2];
document.getElementById('line1').style.visibility = 'visible';
document.getElementById('line2').style.visibility = 'visible';
document.getElementById('line3').style.visibility = 'visible';
showButton();
} }
// Show "FOLLOW THEM" button // Show "FOLLOW THEM" button
@@ -276,28 +401,154 @@
}, 30); }, 30);
} }
// Placeholder for Scene 2 (to be expanded later) // Scene 2 loader with blinking cursor (5 blinks), and text
function loadScene2(sceneElem) { function loadScene2(sceneElem) {
sceneElem.innerHTML = '<p>The signal grows stronger. The path reveals itself...</p>';
sceneElem.style.display = 'flex'; sceneElem.style.display = 'flex';
const cursor = document.getElementById('blinkCursor');
const textContainer = document.getElementById('scene2Text');
const learnBtn = document.getElementById('learnBtn');
let opacity = 0; let opacity = 0;
const fadeIn = setInterval(() => { const fadeIn = setInterval(() => {
opacity += 0.05; opacity += 0.05;
if (opacity >= 1) { if (opacity >= 1) {
opacity = 1; opacity = 1;
clearInterval(fadeIn); clearInterval(fadeIn);
// Show blinking cursor - blink 5 times (5 seconds)
cursor.style.display = 'block';
cursor.style.opacity = '1';
let blinkCount = 0;
let isVisible = true;
const blinkInterval = setInterval(() => {
isVisible = !isVisible;
cursor.style.opacity = isVisible ? '1' : '0';
blinkCount++;
if (blinkCount >= 10) { // 5 complete cycles (on+off = 2 toggles per cycle)
clearInterval(blinkInterval);
cursor.style.display = 'none';
// Type the new pre-LEARN text - starts calm, accelerates to normal reading speed
typewriterLines(
[
"...AND THAT AWARENESS ISN'T JUST COINCIDENCE. YOU'RE SITTING IN FRONT OF THIS SCREEN AT THIS EXACT MOMENT IN TIME FOR A REASON.",
".....COULD THAT REASON BE THAT YOU NEED TO LEARN SOMETHING?"
],
textContainer,
() => {
// Show "LEARN" button
learnBtn.style.visibility = 'visible';
let btnOpacity = 0;
const btnFadeIn = setInterval(() => {
btnOpacity += 0.05;
if (btnOpacity >= 1) {
btnOpacity = 1;
clearInterval(btnFadeIn);
learnBtn.style.pointerEvents = 'auto';
}
learnBtn.style.opacity = btnOpacity;
}, 30);
},
120, // Start calm (120ms/char)
800, // Calm line delay
60 // Accelerate to normal reading speed (60ms/char)
);
}
}, 500); // 500ms on, 500ms off = 1 second per blink
} }
sceneElem.style.opacity = opacity; sceneElem.style.opacity = opacity;
}, 30); }, 30);
} }
// "LEARN" button click handler
function handleLearnClick() {
const learnBtn = document.getElementById('learnBtn');
const textContainer = document.getElementById('scene2Text');
learnBtn.style.pointerEvents = 'none';
learnBtn.style.opacity = 0;
learnBtn.style.visibility = 'hidden';
// Clear previous text to prevent appending
textContainer.textContent = '';
typewriterLines(
[
"THE SIGNAL IS NOW RECEIVING.",
"PREPARE FOR THE NEXT TRANSMISSION."
],
textContainer,
() => {
// Placeholder for Scene 3
},
30, // Fast char delay for anxious rhythm
200 // Fast line delay for anxious rhythm
);
}
// Initialize on load // Initialize on load
window.addEventListener('load', () => { window.addEventListener('load', () => {
setTimeout(crtFlicker, 1500); setTimeout(crtFlicker, 1500);
}); });
// Button click handler // Button click handlers
document.getElementById('followBtn').addEventListener('click', transitionToScene2); document.getElementById('followBtn').addEventListener('click', transitionToScene2);
document.getElementById('learnBtn').addEventListener('click', handleLearnClick);
// Keyboard shortcuts for testing
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
// Escape alone: Skip current animation to text
// Scene 1 skip (rain or typewriter)
const textContainer = document.getElementById('textContainer');
const canvas = document.getElementById('matrixCanvas');
if (textContainer.style.visibility !== 'visible') {
// Skip rain, show Scene 1 text instantly
canvas.style.opacity = '0.15';
skipScene1();
}
// Scene 2 pre-LEARN skip (cursor blinking)
const scene2Text = document.getElementById('scene2Text');
const learnBtn = document.getElementById('learnBtn');
const cursor = document.getElementById('blinkCursor');
if (cursor.style.display === 'block') {
// Skip cursor, show pre-LEARN text + LEARN button
cursor.style.display = 'none';
scene2Text.textContent = "...AND THAT AWARENESS ISN'T JUST COINCIDENCE. YOU'RE SITTING IN FRONT OF THIS SCREEN AT THIS EXACT MOMENT IN TIME FOR A REASON.";
scene2Text.style.visibility = 'visible';
learnBtn.style.visibility = 'visible';
learnBtn.style.opacity = '1';
learnBtn.style.pointerEvents = 'auto';
}
}
if (e.key === 'Backspace') {
e.preventDefault(); // Prevent browser back navigation
// Fast-forward to last scene (Scene 2 post-LEARN)
// Hide Scene 1 elements
document.getElementById('matrixCanvas').style.display = 'none';
document.getElementById('textContainer').style.display = 'none';
document.getElementById('followBtn').style.display = 'none';
// Show Scene 2 with post-LEARN text
const scene2 = document.getElementById('scene2');
const textContainer = document.getElementById('scene2Text');
const learnBtn = document.getElementById('learnBtn');
const cursor = document.getElementById('blinkCursor');
scene2.style.display = 'flex';
scene2.style.opacity = '1';
cursor.style.display = 'none';
learnBtn.style.display = 'none';
// Show post-LEARN text instantly
textContainer.textContent = "THE SIGNAL IS NOW RECEIVING. PREPARE FOR THE NEXT TRANSMISSION.";
textContainer.style.visibility = 'visible';
}
});
</script> </script>
</body> </body>
</html> </html>