kaka.farm

Unnamed repository; edit this file 'description' to name the repository.
git clone https://kaka.farm/~git/kaka.farm
Log | Files | Refs | README

wtc_plaza_2001-09-11.js (8424B)


      1 'use strict';
      2 
      3 // Why is it not part of the standard yet?
      4 Math.TAU = 2 * Math.PI;
      5 
      6 (function() {
      7 	let audio_context;
      8 	let scream_audio_data;
      9 	let thump_audio_data;
     10 
     11 	let BLOOD_COLOR = (0, 0, 255, 255);
     12 	let STICK_FIGURE_COLOR = (0, 0, 0, 255);
     13 
     14 	function lerp(portion, start, stop) {
     15 		return portion * (stop - start) + start;
     16 	}
     17 
     18 	function make_random_direction() {
     19 	    let uniform = Math.random();
     20 	    return [
     21 		Math.cos(Math.TAU * uniform),
     22 		Math.sin(Math.TAU * uniform),
     23 	    ];
     24 	};
     25 
     26 	function add_random_position(original_position, distance) {
     27 	    let new_direction = make_random_direction();
     28 
     29 	    return [
     30 		    original_position[0] + distance * new_direction[0],
     31 		    original_position[1] + distance * new_direction[1],
     32 	    ];
     33 	}
     34 
     35 	function make_random_stick_figure_positions() {
     36 	    let head_neck_distance = 0.05;
     37 	    let elbow_neck_distance = 0.050;
     38 	    let arm_tip_elbow_distance = 0.050;
     39 	    let pelvis_neck_distance = 0.125;
     40 	    let knee_pelvis_distance = 0.075;
     41 	    let leg_tip_knee_distance = 0.075;
     42 
     43 	    let head_position = [Math.random(), Math.random()];
     44 
     45 	    let neck_position = add_random_position(head_position, head_neck_distance);
     46 
     47 	    let left_elbow_position = add_random_position(neck_position, elbow_neck_distance);
     48 	    let right_elbow_position = add_random_position(neck_position, elbow_neck_distance);
     49 
     50 	    let left_arm_tip_position = add_random_position(left_elbow_position, arm_tip_elbow_distance);
     51 	    let right_arm_tip_position = add_random_position(right_elbow_position, arm_tip_elbow_distance);
     52 
     53 	    let pelvis_position = add_random_position(neck_position, pelvis_neck_distance);
     54 
     55 	    let left_knee_position = add_random_position(pelvis_position, knee_pelvis_distance);
     56 	    let right_knee_position = add_random_position(pelvis_position, knee_pelvis_distance);
     57 
     58 	    let left_leg_top_position = add_random_position(left_knee_position, leg_tip_knee_distance);
     59 	    let right_leg_top_position = add_random_position(right_knee_position, leg_tip_knee_distance);
     60 
     61 	    return [
     62 		    head_position,
     63 		    neck_position,
     64 		    left_elbow_position,
     65 		    right_elbow_position,
     66 		    left_arm_tip_position,
     67 		    right_arm_tip_position,
     68 		    pelvis_position,
     69 		    left_knee_position,
     70 		    right_knee_position,
     71 		    left_leg_top_position,
     72 		    right_leg_top_position,
     73 	    ];
     74 	}
     75 
     76 
     77 
     78 
     79 	function make_blood_splatter_positions(stick_figure_positions) {
     80 	    let blood_splatter_positions = [];
     81 
     82 	    for (let i = 0; i < 3; i++) {
     83 		    blood_splatter_positions.push(
     84 			    add_random_position(stick_figure_positions[1], 0.05 * (i + 1))
     85 		    );
     86 	    }
     87 
     88 	    for (let i = 0; i < 3; i++) {
     89 		    blood_splatter_positions.push(
     90 			    add_random_position(stick_figure_positions[6], 0.05 * (i + 1))
     91 		    );
     92 	    }
     93 
     94 		return blood_splatter_positions;
     95 	}
     96 
     97 	function draw_blood_splatter(blood_splatter_positions) {
     98 		let canvas = document.getElementById('canvas');
     99 		let ctx = canvas.getContext('2d');
    100 
    101 		let image_width = ctx.canvas.width;
    102 		let image_height = ctx.canvas.height;
    103 
    104 	    let blood_splatter_positions_in_image = blood_splatter_positions.map(
    105 		    position => [
    106 			    Math.floor(position[0] * image_width),
    107 			    Math.floor(position[1] * image_height),
    108 		    ]
    109 	    );
    110 
    111 
    112 		ctx.fillStyle = '#f00';
    113 
    114 		ctx.beginPath();
    115 	    ctx.arc(blood_splatter_positions_in_image[0][0], blood_splatter_positions_in_image[0][1], 20, 0, Math.TAU);
    116 		ctx.fill();
    117 
    118 		ctx.beginPath();
    119 	    ctx.arc(blood_splatter_positions_in_image[1][0], blood_splatter_positions_in_image[1][1], 10, 0, Math.TAU);
    120 		ctx.fill();
    121 
    122 		ctx.beginPath();
    123 	    ctx.arc(blood_splatter_positions_in_image[2][0], blood_splatter_positions_in_image[2][1], 5, 0, Math.TAU);
    124 		ctx.fill();
    125 
    126 		ctx.beginPath();
    127 	    ctx.arc(blood_splatter_positions_in_image[3][0], blood_splatter_positions_in_image[3][1], 20, 0, Math.TAU);
    128 		ctx.fill();
    129 
    130 		ctx.beginPath();
    131 	    ctx.arc(blood_splatter_positions_in_image[4][0], blood_splatter_positions_in_image[4][1], 10, 0, Math.TAU);
    132 		ctx.fill();
    133 
    134 		ctx.beginPath();
    135 	    ctx.arc(blood_splatter_positions_in_image[5][0], blood_splatter_positions_in_image[5][1], 5, 0, Math.TAU);
    136 		ctx.fill();
    137 
    138 		ctx.fill()
    139 	}
    140 
    141 
    142 	function draw_stick_figure(stick_figure_positions) {
    143 		let canvas = document.getElementById('canvas');
    144 		let ctx = canvas.getContext('2d');
    145 
    146 	    let image_width = ctx.canvas.width;
    147 	    let image_height = ctx.canvas.height;
    148 
    149 	    let stick_figure_positions_in_image = stick_figure_positions.map(
    150 		    x => [
    151 			    Math.floor(x[0] * image_width),
    152 			    Math.floor(x[1] * image_height),
    153 		    ]
    154 	    );
    155 		console.debug(stick_figure_positions_in_image)
    156 
    157 		ctx.fillStyle = '#000';
    158 		ctx.strokeStyle = '#000';
    159 		ctx.lineWidth = 2;
    160 
    161 		ctx.beginPath();
    162 	    ctx.arc(
    163 		    stick_figure_positions_in_image[0][0],
    164 		    stick_figure_positions_in_image[0][1],
    165 		    15,
    166 		    0,
    167 		    Math.TAU,
    168 		    false);
    169 		ctx.fill();
    170 
    171 	    let connections = [
    172 		[0, 1],
    173 		[1, 2],
    174 		[1, 3],
    175 		[2, 4],
    176 		[3, 5],
    177 		[1, 6],
    178 		[7, 6],
    179 		[8, 6],
    180 		[7, 9],
    181 		[8, 10],
    182 	    ];
    183 		for (let i = 0; i < connections.length; i++) {
    184 			ctx.beginPath();
    185 			let origin_coordinates = stick_figure_positions_in_image[connections[i][0]];
    186 			let destination_coordinates = stick_figure_positions_in_image[connections[i][1]];
    187 			console.debug([origin_coordinates, destination_coordinates])
    188 			ctx.moveTo(origin_coordinates[0], origin_coordinates[1]);
    189 			ctx.lineTo(destination_coordinates[0], destination_coordinates[1]);
    190 			ctx.stroke();
    191 		}
    192 	}
    193 
    194 	function draw_jumper() {
    195 		let stick_figure_positions = make_random_stick_figure_positions();
    196 		let blood_splatter_positions = make_blood_splatter_positions(stick_figure_positions);
    197 
    198 		console.debug(stick_figure_positions);
    199 		console.debug(blood_splatter_positions);
    200 
    201 		draw_blood_splatter(blood_splatter_positions);
    202 		draw_stick_figure(stick_figure_positions);
    203 	}
    204 
    205 
    206 	function jump() {
    207 		let scream_rate_fraction = lerp(Math.random(), 0.90, 1.45);
    208 		let scream_audio_buffer = make_audio_buffer(scream_audio_data, scream_rate_fraction);
    209 		let scream_source = make_audio_buffer_source(scream_audio_buffer);
    210 		scream_source.start();
    211 
    212 		setTimeout(function() {
    213 			scream_source.stop();
    214 
    215 			let thump_audio_buffer = make_audio_buffer(thump_audio_data, 1);
    216 			let thump_audio_source = make_audio_buffer_source(thump_audio_buffer);
    217 
    218 			thump_audio_source.currentTime = 0.2;
    219 
    220 			thump_audio_source.start()
    221 
    222 			draw_jumper();
    223 		}, 1700.0 / scream_rate_fraction);
    224 	}
    225 
    226 	function clear_canvas() {
    227 		let canvas = document.getElementById('canvas');
    228 		let ctx = canvas.getContext('2d');
    229 
    230 		ctx.clearRect(0, 0, canvas.width, canvas.height);
    231 	}
    232 
    233 	async function get_audio_data(audio_file_path) {
    234 		let response = await fetch(audio_file_path);
    235 
    236 		let array_buffer = await response.arrayBuffer();
    237 
    238 		return await audio_context.decodeAudioData(array_buffer);
    239 	}
    240 
    241 	function make_audio_buffer(audio_data, sample_rate_fraction) {
    242 		let audio_buffer = audio_context.createBuffer(
    243 			audio_data.numberOfChannels,
    244 			audio_data.getChannelData(0).length,
    245 			audio_data.sampleRate * sample_rate_fraction,
    246 		);
    247 
    248 		for (let channel_number = 0; channel_number < audio_buffer.numberOfChannels; channel_number++) {
    249 			let current_buffer = audio_buffer.getChannelData(channel_number);
    250 			let audio_data_channel = audio_data.getChannelData(channel_number);
    251 
    252 			for (let sample_number = 0; sample_number < current_buffer.length; sample_number++) {
    253 				current_buffer[sample_number] = audio_data_channel[sample_number];
    254 			}
    255 		}
    256 
    257 		return audio_buffer;
    258 	}
    259 
    260 	function make_audio_buffer_source(audio_buffer) {
    261 		let buffer_source = audio_context.createBufferSource();
    262 
    263 		buffer_source.buffer = audio_buffer;
    264 
    265 		buffer_source.connect(audio_context.destination);
    266 
    267 		return buffer_source;
    268 	}
    269 
    270 	async function main() {
    271 		audio_context = new AudioContext();
    272 
    273 		let scream_audio_element = document.getElementById('scream_audio');
    274 		let thump_audio_element = document.getElementById('thump_audio');
    275 
    276 		scream_audio_data = await get_audio_data(scream_audio_element.src);
    277 		thump_audio_data = await get_audio_data(thump_audio_element.src);
    278 
    279 		let canvas = document.getElementById('canvas');
    280 		canvas.addEventListener('click', jump);
    281 
    282 		let jump_button = document.getElementById('jump_button');
    283 		jump_button.addEventListener('click', jump);
    284 
    285 		let clear_button = document.getElementById('clear_button');
    286 		clear_button.addEventListener('click', clear_canvas);
    287 	}
    288 
    289 	window.addEventListener('load', main);
    290 })();