kaka.farm

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

main.js (5918B)


      1 'use strict;'
      2 
      3 Math.TAU = 2 * Math.PI;
      4 
      5 (function() {
      6 	let start_time;
      7 	let elapsed_time;
      8 	let previous_timestamp;
      9 
     10 	let polygons_vertices = [];
     11 	let polygon_velocity = [];
     12 
     13 	let hsv_values = [[0, 1, 0.7]];
     14 	let color_wheel_velocity = 0.01;
     15 
     16 	let wanted_number_of_polygons = 50;
     17 	let pixels_per_step = 10;
     18 
     19 	function hsv_to_rgb(hue, saturation, value) {
     20 		// https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB
     21 		// H in [0, 1] (position on the color wheel)
     22 		// S in [0, 1]
     23 		// V in [0, 1]
     24 
     25 		let chroma = value * saturation;
     26 
     27 		let hue_tag = hue * 6;
     28 
     29 		let x = chroma * (1 - Math.abs((hue_tag % 2) - 1));
     30 
     31 		let [red_1, green_1, blue_1] = ((hue_tag, chroma, x)=>{
     32 			if (hue_tag >= 0 && hue_tag < 1) { return [chroma, x, 0];
     33 			} else if (hue_tag >= 1 && hue_tag < 2) { return [x, chroma, 0];
     34 			} else if (hue_tag >= 2 && hue_tag < 3) { return [0, chroma, x];
     35 			} else if (hue_tag >= 3 && hue_tag < 4) { return [0, x, chroma];
     36 			} else if (hue_tag >= 4 && hue_tag < 5) { return [x, 0, chroma];
     37 			} else if (hue_tag >= 5 && hue_tag < 6) { return [chroma, 0, x];
     38 			}
     39 		})(hue_tag, chroma, x);
     40 
     41 		let m = value - chroma;
     42 
     43 		return [red_1 + m, green_1 + m, blue_1 + m];
     44 	}
     45 
     46 	function move_and_bounce_1d(position, velocity, maximum_value) {
     47 		let new_position = position + velocity;
     48 
     49 		if (new_position > maximum_value) {
     50 			return [2 * maximum_value - new_position, -Math.abs(velocity)];
     51 		} else if (new_position < 0) {
     52 			return [Math.abs(new_position), Math.abs(velocity)];
     53 		} else {
     54 			return [new_position, velocity];
     55 		};
     56 
     57 	}
     58 
     59 	function move_and_bounce_2d(position, velocity, width, height) {
     60 		let [position_x, velocity_x] = move_and_bounce_1d(position[0], velocity[0], width);
     61 		let [position_y, velocity_y] = move_and_bounce_1d(position[1], velocity[1], height);
     62 
     63 		return [
     64 			[position_x, position_y],
     65 			[velocity_x, velocity_y],
     66 		];
     67 	}
     68 
     69 	function move_polygon(polygon_vertices, polygon_velocity) {
     70 		for (let vertex_number = 0; vertex_number < polygon_vertices.length; vertex_number++) {
     71 			let [new_position, new_velocity] = move_and_bounce_2d(
     72 				polygon_vertices[vertex_number],
     73 				polygon_velocity[vertex_number],
     74 				canvas.width,
     75 				canvas.height,
     76 			);
     77 
     78 			polygon_vertices[vertex_number] = new_position;
     79 			polygon_velocity[vertex_number] = new_velocity;
     80 		}
     81 	};
     82 
     83 	function draw_polygon(ctx, polygon_vertices, rgb) {
     84 		ctx.beginPath();
     85 
     86 		ctx.strokeStyle = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`;
     87 
     88 		ctx.moveTo(polygon_vertices[0][0], polygon_vertices[0][1]);
     89 
     90 		for (let vertex_number = 1; vertex_number < polygon_vertices.length; vertex_number++) {
     91 			ctx.lineTo(polygon_vertices[vertex_number][0], polygon_vertices[vertex_number][1]);
     92 		}
     93 
     94 		ctx.closePath();
     95 		ctx.stroke();
     96 	}
     97 
     98 	function uniform_random_direction() {
     99 		let uniform = Math.random();
    100 		let direction_vector = [
    101 			Math.cos(uniform * Math.TAU),
    102 			Math.sin(uniform * Math.TAU),
    103 		];
    104 		return direction_vector;
    105 	}
    106 
    107 	function step_polygons() {
    108 		if (polygons_vertices.length >= wanted_number_of_polygons) {
    109 			// Remove oldest polygon, the one at position 0.
    110 			polygons_vertices = polygons_vertices.slice(1, polygons_vertices.length);
    111 		}
    112 
    113 		// Get the newest polygon at position n-1.
    114 		let current_polygon_vertices = polygons_vertices[polygons_vertices.length - 1];
    115 
    116 		// Clone our latest polygon.
    117 		let new_polygon_vertices = current_polygon_vertices.map(vertex => vertex.map(axis => axis));
    118 
    119 		move_polygon(new_polygon_vertices, polygon_velocity);
    120 
    121 		polygons_vertices.push(new_polygon_vertices);
    122 	}
    123 
    124 	function step_hsv_values() {
    125 		if (hsv_values.length >= wanted_number_of_polygons) {
    126 			// Remove oldest hsv value, the one at position 0.
    127 			hsv_values = hsv_values.slice(1, hsv_values.length);
    128 		}
    129 
    130 		// Get the newest hsv_value at position n-1.
    131 		let current_hsv_value = hsv_values[hsv_values.length - 1];
    132 
    133 		// Clone.
    134 		let new_hsv_value = current_hsv_value.map(axis => axis);
    135 
    136 		// Spin the hue around in the color wheel.
    137 		new_hsv_value[0] = (new_hsv_value[0] + color_wheel_velocity) % 1;
    138 
    139 		hsv_values.push(new_hsv_value);
    140 	}
    141 
    142 	function draw_polygons(ctx, polygons_vertices, hsv_values) {
    143 		for (let current_polygon = 0; current_polygon < polygons_vertices.length; current_polygon++) {
    144 			let rgb = hsv_to_rgb(
    145 				hsv_values[current_polygon][0],
    146 				hsv_values[current_polygon][1],
    147 				hsv_values[current_polygon][2],
    148 			).map(x => 255 * x);
    149 			draw_polygon(ctx, polygons_vertices[current_polygon], rgb);
    150 		}
    151 	}
    152 
    153 	function step(timestamp) {
    154 		if (start_time === undefined) {
    155 			start_time = timestamp;
    156 		}
    157 
    158 		elapsed_time = timestamp - start_time;
    159 
    160 		delta_time = timestamp - previous_timestamp;
    161 
    162 		let canvas = document.getElementById('canvas');
    163 		let ctx = canvas.getContext('2d');
    164 
    165 		ctx.clearRect(0, 0, canvas.width, canvas.height);
    166 
    167 		step_polygons();
    168 		step_hsv_values();
    169 
    170 		draw_polygons(ctx, polygons_vertices, hsv_values);
    171 
    172 		previous_timestamp = timestamp;
    173 
    174 		window.requestAnimationFrame(step)
    175 	}
    176 
    177 	function resize_window() {
    178 		// https://stackoverflow.com/a/32119392
    179 
    180 		let canvas = document.getElementById('canvas');
    181 
    182 		canvas.width = window.innerWidth;
    183 		canvas.style.width = window.innerWidth;
    184 		canvas.height = window.innerHeight;
    185 		canvas.style.height = window.innerHeight;
    186 	}
    187 
    188 	function reset_world() {
    189 		polygons_vertices = [[
    190 			[canvas.width / 2, canvas.height / 3],
    191 			[2 * canvas.width / 3, 2 * canvas.height / 3],
    192 			[canvas.width / 3, 2 * canvas.height / 3],
    193 		]];
    194 
    195 		polygon_velocity = [
    196 			uniform_random_direction(),
    197 			uniform_random_direction(),
    198 			uniform_random_direction(),
    199 		].map(vertex => vertex.map(axis => pixels_per_step * axis));
    200 	}
    201 
    202 	function main() {
    203 		let canvas = document.getElementById('canvas');
    204 		let ctx = canvas.getContext('2d');
    205 
    206 		resize_window();
    207 		reset_world();
    208 
    209 		canvas.addEventListener('click', reset_world);
    210 
    211 		window.addEventListener('resize', resize_window)
    212 
    213 		window.requestAnimationFrame(step);
    214 	}
    215 
    216 	window.addEventListener('load', main);
    217 })();