function Intro(){
var SCREEN_X = 160;
var SCREEN_Y = 100;
function getStyle(index) {
return [
c_filters[0]*128 * (1 + Math.sin(c_cycles[0]*offset/16 + c_multipliers[0]*index*Math.PI)),
c_filters[1]*128 * (1 - Math.cos(c_cycles[1]*offset/16 + c_multipliers[1]*index*Math.PI)),
c_filters[2]*128 * (1 - Math.sin(c_cycles[2]*offset/16 + c_multipliers[2]*index*Math.PI)),
];
}
function draw(weights) {
var ctx = document.getElementById("canvas").getContext("2d");
var screen = ctx.getImageData(0, 0, SCREEN_X, SCREEN_Y);
var imgData = screen.data;
var sin_offset_64th = Math.sin(offset/64),
cos_offset_64th = Math.cos(offset/64),
sin_offset_32th = Math.sin(offset/32),
cos_offset_32th = Math.cos(offset/32),
cos_offset_16th = Math.cos(offset/16);
var cx1 = SCREEN_X/2 + SCREEN_Y *(sin_offset_64th),
cy1 = SCREEN_Y/2 - SCREEN_Y *(cos_offset_64th);
var cx2 = SCREEN_X/2 - SCREEN_Y *((1 - sin_offset_64th))*cos_offset_32th,
cy2 = SCREEN_Y/2 + SCREEN_Y *((1 - cos_offset_64th))*sin_offset_32th;
var sinVal1, sinVal2, cosVal1, cosVal2, val, pixel_start, style;
for (var i = 0; i < SCREEN_Y; i++) {
for (var j = 0; j < SCREEN_X; j++) {
sinVal1 = Math.sin((j/16) + offset/16 * cos_offset_64th );
sinVal2 = Math.sin( (2*j * sin_offset_32th + 2*i * cos_offset_16th)/16 + offset/16 );
cosVal1 = Math.cos(0.4*(Math.sqrt(((j-cx1) * (j-cx1)) + ((i-cy1) * (i-cy1))))-offset);
cosVal2 = Math.cos(0.4*(Math.sqrt(((j-cx2) * (j-cx2)) + ((i-cy2) * (i-cy2))))-offset);
val = (weights[0]*sinVal1 + weights[1]*sinVal2 + weights[2]*cosVal1 + weights[3]*cosVal2) / 4;
pixel_start = (i*SCREEN_X + j)*4;
style = getStyle(val);
imgData[pixel_start]=style[0];
imgData[pixel_start+1]=style[1];
imgData[pixel_start+2]=style[2];
imgData[pixel_start+3]=255;
}
}
ctx.putImageData(screen, 0, 0);
}
var PERIOD = Math.PI*256;
var PERIOD_DURATION_MS = 26600;
function render(timestamp) {
var elapsed_total = Math.max(timestamp - started, 0);
var elapsed_cycle = Math.max(timestamp - cycle_started, 0);
draw(weights);
offset = PERIOD * elapsed_cycle / PERIOD_DURATION_MS; //(offset + 0.51);
if (Math.floor(elapsed_total / PERIOD_DURATION_MS)% steps.length != step){
// console.log("reset! "+ (timestamp - cycle_started) + " ms");
offset = 0;
periodStart();
}
if (!stopped){
window.requestAnimationFrame(render);
}
}
function start(){
showText('');
offset = 0;
started = performance.now();
weights = [0,0,0,0];
c_cycles = [0,0,0];
c_multipliers = [0,0,0];
c_filters = [0,0,0];
step = -1;
stopped = false;
setSize();
periodStart();
doPlasmaTransition();
window.requestAnimationFrame(render);
}
function stop(){
stopped = true;
stopAudio();
showText('');
}
function periodStart(){
cycle_started = performance.now();
step = (step + 1) % steps.length;
// console.log("step: "+step);
startTextScript();
if (step == 0){
var audio_scheduled_at = performance.now();
setTimeout(function(){
if (!stopped && audio_scheduled_at >= started){
startAudio();
} else {
console.log("Outdated audio timer");
}
}, 8500);
}
}
function _adjust(valueList, goalList, delta){
for (var i=0; i<=Math.min(valueList.length, goalList.length); i++){
if (valueList[i] < goalList[i]){
valueList[i] += delta;
valueList[i] = Math.min(goalList[i], valueList[i]);
} else if (valueList[i] > goalList[i]){
valueList[i] -= delta;
valueList[i] = Math.max(goalList[i], valueList[i]);
}
}
}
function doPlasmaTransition(){
var delta = 0.025;
_adjust(weights, steps[step][0], delta);
_adjust(c_cycles, steps[step][1], delta);
_adjust(c_multipliers, steps[step][2], delta);
_adjust(c_filters, steps[step][3], delta);
schedule(doPlasmaTransition, 100);
}
var offset = 0;
var started, cycle_started;
var stopped = true;
var steps = [ // plasma composition, cycles, multipliers, filters:
[[1,0,0,0], [0,0,0], [1,1,1], [0,0,1]], // blue vertical bars
[[0.5,1,0,0], [0,0,0], [1,2,2], [0,1,1]], // blue-green fabric
//[[0.4,0.5,0,0.2], [0,0,0], [4,4,4], [1,1,1]], // orange-blue circular waves
[[0.15,0,0,1], [0,0,0], [2,2,-2], [1,1,1]], // magenta-green circles
[[0.8,0.2,0.1,0.1], [3,3,3], [4,3,4], [1,1,1]], // saturated waves
[[1,1,1,1], [1,0,0], [1,1,1], [1,1,1]], // pallette cycles
[[0,0,1,1], [0,0,0], [1,0,-1], [1,1,1]], // magenta waves
];
var weights = [0,0,0,0]; // steps[0][0];
var c_cycles = [0,0,0]; // steps[0][1]; // color waves (0=none)
var c_multipliers = [0,0,0]; // steps[0][2]; // number of stripes
var c_filters = [0,0,0]; // steps[0][3]; // color opacity (0-1)
var step = -1;
function setSize(){
var size = calculateSize();
document.getElementById("plasma").style.width=""+size[0]+"px";
document.getElementById("plasma").style.height=""+size[1]+"px";
document.getElementById("marquee").style.top=""+Math.floor(size[1]/2)+"px";
document.getElementById("marquee").style['font-size']=""+Math.floor(size[1]/6)+"px";
}
function calculateSize(){
var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
var vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0);
var from_width = [vw, Math.floor(vw * SCREEN_Y / SCREEN_X)];
var from_height = [Math.floor(vh * SCREEN_X / SCREEN_Y), vh];
return from_width[0] < from_height[0]? from_width : from_height;
}
// Marquee
function showText(text){
var el = document.getElementById('text');
el.textContent=text;
el.style.animation = 'none';
el.style['moz-animation'] = 'none';
el.style['webkit-animation'] = 'none';
el.style.animation = 'none';
el.offsetHeight; /* trigger reflow */
el.style.animation = null;
el.style['moz-animation'] = null;
el.style['webkit-animation'] = null;
}
function startTextScript(){
var texts = [
['FHC presents...', '::: BYOD :::'],
['(c) n-n 2015-2020','Interactive Fiction'],
['Game + Walkthrough', 'An IFComp entry'],
['Intro: Brutal', 'Music: E-Mantra'],
['Greetings to:', 'All scene groups'],
['Contact Us!', '(ESC to exit)'],
];
var current_txt = 0;
var total_ms = 25000; // just under avg plasma cycle
var scheduled_at = performance.now();
if (step < texts.length){
schedule(null, total_ms, function(){
if (!stopped && scheduled_at >= started){
showText(texts[step][current_txt++]);
} else {
console.log("Outdated timer (started: "+started+", scheduled_at:"+scheduled_at);
}
}, total_ms / (texts[step].length + 1), true);
}
}
// Audio
var audio = new Audio('res/intro.mp3');
function startAudio(){
audio.play();
}
function stopAudio(){
audio.pause();
audio.currentTime = 0;
}
// Timer management
function schedule(timeoutCallback, timeoutMs, stepCallback, timeoutStepMs){
var init = performance.now();
if (timeoutCallback) {
setTimeout(timeoutCallback, timeoutMs);
}
if (!!stepCallback){
var wrapper = function(){
stepCallback();
var now = performance.now();
if (now < init + timeoutMs){
var timer = setTimeout(wrapper, timeoutStepMs);
} else {
// console.log("Done after "+timeoutMs);
}
};
setTimeout(wrapper, timeoutStepMs);
}
}
function setup(element_id){
window.addEventListener("resize", setSize);
document.getElementById(element_id).innerHTML =
'<div class="plasma" id="plasma">' +
'<div class="marquee" id="marquee">' +
'<div class="text" id="text"></div>' +
'</div>' +
'<canvas style="width:100%" id="canvas" width="160" height="100"></canvas>' +
'</div>';
return this;
}
return {
setup: setup,
setSize: setSize,
start: start,
stop: stop
}
}
// vim: set ai expandtab tabstop=2 shiftwidth=2