PageSourceSearch

https://signalsmedia.github.io/sketch.js

js signalsmedia.github.io collected 2026-10-03 09:57:09 UTC 15,300 bytes, 601 lines download raw bytes

1
2
3
4///// CONSTANTS /////
5const SIGNALS = {'0':'NEUTRAL','1':'A','2':'B','3':'C','4':'D','40':'E','48':'F','56':'G','10':'H','11':'I','52':'J','33':'K','41':'L','49':'M','57':'N','26':'O','34':'P','42':'Q','50':'R','58':'S','35':'T','43':'U','60':'V','53':'W','61':'X','51':'Y','55':'Z','15':'SPACE','44':'NUMBERS','59':'CANCEL'}
6const NUMBERS = {'1':'1','2':'2','3':'3','4':'4','40':'5','48':'6','56':'7','10':'8','11':'9','52':'LETTERS','33':'0','15':'SPACE','59':'CANCEL'}
7
8const SIGNALS_ORDERED = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','SPACE','NUMBERS','CANCEL']
9
10const SIGNALS_ICONS = {'1':'A','2':'B','3':'C','4':'D','40':'E','48':'F','56':'G','10':'H','11':'I','52':'J','33':'K','41':'L','49':'M','57':'N','26':'O','34':'P','42':'Q','50':'R','58':'S','35':'T','43':'U','60':'V','53':'W','61':'X','51':'Y','55':'Z','15':'_','44':'#','59':'⌫ '}
11const NUMBERS_ICONS = {'1':'1','2':'2','3':'3','4':'4','40':'5','48':'6','56':'7','10':'8','11':'9','52':'🔤','33':'0','15':'_','59':'⌫ '}
12
13const ALL_STATES = [DebugState, LoadingState, IntroMenuState, MainMenuState, GameAMenuState, GameState]
14
15Object.freeze(SIGNALS);
16Object.freeze(NUMBERS);
17Object.freeze(SIGNALS_ORDERED);
18Object.freeze(SIGNALS_ICONS);
19Object.freeze(NUMBERS_ICONS);
20Object.freeze(ALL_STATES);
21
22const TIME_THRESHOLD = 1200; // Milliseconds
23const DELTA_MAX = 160
24const LOCAL_DEBUG = false;
25const DEBUG_TEXT = "Q - Flip Camera & Guides\nW - Toggle Word Mode\nE - Toggle Flag Type\nR - Toggle Asyncronous Mode\nT - Return to Main Menu"
26
27var RED;
28var GREEN;
29var BLUE;
30var YELLOW;
31var MAGENTA;
32var CYAN;
33var BLACK;
34var WHITE;
35
36var LGRAY;
37var LRED;
38var LBLUE;
39
40var DGRAY;
41
42var Canvas;
43
44var streamRefreshMillis;
45
46var debugFrame = 0;
47
48var mainRegion=
49{
50	size: undefined,
51	origin: undefined,
52	innerSize: undefined,
53	innerOrigin: undefined,
54	
55	center: undefined,
56	
57	idealSize: 720,
58	scale: undefined,
59}
60
61var margin;
62
63// TODO: MAKE GAME-DEPENDENT ONLY
64var lowerRegion=
65{
66	size: undefined,
67	origin: undefined,
68}
69var overflowRegion=
70{
71	size: undefined,
72	origin: undefined,
73}
74
75// var leftRegion=
76// {
77	// size: undefined,
78	// origin: undefined,
79// }
80// var rightRegion=
81// {
82	// size: undefined,
83	// origin: undefined,
84// }
85
86
87
88var cutoffAspect = 
89{
90	max: 2.3,
91	min: 0,
92}
93
94// var mainRegion.size;
95// var mainRegion.origin;
96
97// var mainRegion.innerSize;
98// var mainRegion.innerOrigin;
99
100// var mainRegion.center;
101
102var inModelPipeline = false;
103var flip = true;
104
105var drawStage = 'pre';
106
107var state = LoadingState;
108
109var paused;
110var tabPaused;
111
112// p5.disableFriendlyErrors = !LOCAL_DEBUG
113p5.disableFriendlyErrors = true;
114
115window.onbeforeunload = function (e) 
116{
117  Model.disposeAll();
118};
119
120var introDone = false;
121var preloadDone = false;
122
123var ready = false;
124
125function animationEnd(event)
126{
127	if(preloadDone) fadeLoader();
128	introDone = true;
129}
130
131function fadeLoader()
132{
133	// loadingDiv.onwebkitanimationend = endLoader;
134	// loadingDiv.onanimationend = endLoader;
135	// loadingDiv.onmozanimationend = endLoader;
136	// loadingDiv.onmsanimationend = endLoader;
137	
138	loadingDiv.style.display = 'none';
139	ready = true;
140	// loadingDiv.style.animation = "fade 1s ease-in-out reverse";
141	// loadingDiv.style.webkitAnimation = "fade 1s ease-in-out reverse";
142	// loadingDiv.style.mozAnimation = "fade 1s ease-in-out reverse";
143	// loadingDiv.style.msAnimation = "fade 1s ease-in-out reverse";
144	
145	// Canvas.elt.style.animation = "fade 1s ease-in-out";
146	// Canvas.elt.style.webkitAnimation = "fade 1s ease-in-out";
147	// Canvas.elt.style.mozAnimation = "fade 1s ease-in-out";
148	// Canvas.elt.style.msAnimation = "fade 1s ease-in-out";
149	
150	// Canvas.style("animation", "fade 1s ease-in-out");
151	// Canvas.style("webkitAnimation", "fade 1s ease-in-out");
152	// Canvas.style("mozAnimation", "fade 1s ease-in-out");
153	// Canvas.style("msAnimation", "fade 1s ease-in-out");
154	
155	//ready = 0;
156	
157	
158}
159
160// function endLoader()
161// {
162	// loadingDiv.style.display = 'none';
163	// ready = 1;
164// }
165
166var loadingDiv = document.getElementById('loading_circ');
167loadingDiv.onwebkitanimationend = animationEnd;
168loadingDiv.onanimationend = animationEnd;
169loadingDiv.onmozanimationend = animationEnd;
170loadingDiv.onmsanimationend = animationEnd;
171
172///// P5 FUNCTIONS /////
173function preload()
174{
175	//introEnd = millis()+1000;
176	WebcamView.preload();
177	Game.preload();
178	GuideCards.preload();
179	
180	ALL_STATES.forEach((s)=>
181	{
182		if(s.preload) s.preload();
183	});
184}
185
186var linkSpan;
187var ppolSpan;// = document.getElementById('ppol');
188var gitSpan
189
190function setup() 
191{
192	document.oncontextmenu = function() { return false; }
193	
194	if(introDone) fadeLoader();
195	preloadDone = true;
196	
197	Canvas = createCanvas(windowWidth,windowHeight, P2D);
198	
199	// let s = createSpan('<a href="https://www.iubenda.com/privacy-policy/91430819" class="iubend
199a-white iubenda-embed" title="Privacy Policy ">Privacy Policy</a><script type="text/javascript">(function (w,d) {var loader = function () {var s = d.createElement("script"), tag = d.getElementsByTagName("script")[0]; s.src="https://cdn.iubenda.com/iubenda.js"; tag.parentNode.insertBefore(s,tag);}; if(w.addEventListener){w.addEventListener("load", loader, false);}else if(w.attachEvent){w.attachEvent("onload", loader);}else{w.onload = loader;}})(window, document);</script>');
200	// s.id("ppol");
201	
202	linkSpan = createSpan('Developed for <a href="https://www.signals.org.uk/">Signals</a> by Ben Tilbury');
203	linkSpan.id("reflink")
204	linkSpan.hide();
205	
206	ppolSpan = createSpan('<a href="https://www.iubenda.com/privacy-policy/91430819">Privacy Policy</a>');
207	ppolSpan.id("ppol")
208	ppolSpan.hide();
209	
210	gitSpan = createSpan('<a href="https://github.com/signalsmedia/signalsmedia.github.io">Source Code</a>');
211	gitSpan.id("git")
212	gitSpan.hide();
213
214	// if(!LOCAL_DEBUG) noCursor();
215	
216	textFont("Dosis", 64);
217	textStyle(BOLD)
218	strokeJoin(ROUND);
219	
220	RED = color(255,0,0);
221	GREEN = color(0,255,0);
222	BLUE = color(0,0,255);
223	YELLOW = color(255,255,0);
224	MAGENTA = color(255,0,255);
225	CYAN = color(0,255,255);
226	BLACK = color(0,0,0);
227	WHITE = color(255,255,255);
228	LGRAY = color(160,160,160);
229	DGRAY = color(100,100,100);
230	
231	LRED = color(255,60,60);
232	LBLUE = color(60,60,255);
233	
234	windowResized();
235	
236	WebcamView.init();
237	Model.init();
238	Flag.init();
239	UI.init();
240		
241	if(state.onEnter) state.onEnter();
242}
243
244// var freq = 600;
245// var numPoints = 200;
246// var theta = 0.0;
247// var speed = 0.005;
248// var amp = 0.4;
249// var T = 0.004
250// var D = 0.01
251
252var mouseWait = 0;
253var mouseVisible = true;
254
255function draw() 
256{
257	let m = millis();
258	
259	if(!ready) return;
260	
261	//// UPDATE ////
262	deltaTime = min(deltaTime,DELTA_MAX);
263	if(!state.ignoreModel) Model.update();
264	if(state.update) state.update();
265	
266	//// DRAW ////
267	clear();
268	// Background //
269	drawStage = 'pre';
270	if(state.preDraw) state.preDraw();
271	// Flippabled //
272	drawStage = 'flip';
273	push();
274	if(flip)
275	{
276	  translate(width/2,0);
277	  scale(-1,1);
278	  translate(-width/2,0);
279	}
280	if(!state.ignoreWebcam) WebcamView.draw();
281	if(state.flipDraw) state.flipDraw();
282	if(!state.ignoreFlags && !paused) Flag.draw();
283	pop();
284	// Foreground //
285	drawStage = 'post';
286	if(state.postDraw) state.postDraw();
287	
288	//drawStage = 'flag';
289	//if(!state.ignoreFlags) Flag.draw();
290
291	drawStage = 'overlay';
292	if(paused) UI.showOptions();
293	else if(UI.helpVisible()) UI.showHelp();
294	
295	//Model.debug();
296	
297	if ((mouseX != pmouseX) || (mouseY != pmouseY)) 
298	{
299		if (!mouseVisible) 
300		{
301			//cursor();
302			document.body.style.cursor = 'auto';
303			Canvas.style("cursor","auto")
304			mouseVisible = true;
305		}
306		
307		if (mouseWait < m + 2000) mouseWait = m + 2000; 
308	} 
309	else 
310	{
311		if (mouseVisible && m > mouseWait) 
312		{
313			//noCursor(); 
314			document.body.style.cursor = 'none';
315			Canvas.style("cursor","none")
316			mouseVisible = false;
317		}
318	}
319	
320	// if(ready>=0 && ready < 1)
321	// {
322		// ready += deltaTime*0.001
323		
324		// Canvas.canvas.style.opacity = Math.min(1,ready);
325		// Canvas.canvas.style.webkitOpacity = Math.min(1,ready);
326	// }
327	// // // theta += speed;
328	// let step = windowWidth/numPoints
329	// let dx = (TWO_PI/freq) * step;
330	// let s = lowerRegion.size.y*amp;
331	// fill(BLUE);
332	// noStroke();
333	// let x = theta;
334	// beginShape();
335	// vertex(0,windowHeight)
336	// for(let i = 0; i<numPoints; i++)
337	// {
338		// curveVertex(i*step+mouseX,lowerRegion.origin.y+Math.sin(x)*s+mouseY);
339		// x+=dx;
340	// }
341	// // //to avoid Runge phenememon
342	// vertex(windowWidth,lowerRegion.origin.y+Math.sin(x)*s)
343	// vertex(windowWidth+20,lowerRegion.origin.y+Math.sin(x)*s)
344	// vertex(windowWidth,windowHeight)
345	// endShape(CLOSE)
346	
347	
348	// let step = windowWidth / Q;
349	// let s = lowerRegion.size.y;
350	// fill(BLUE);
351	// noStroke();
352	// beginShape();
353	// vertex(windowWidth,lowerRegion.origin.y+noise(millis()*T)*s)
354	// vertex(windowWidth,windowHeight)
355	// vertex(0,windowHeight)
356	// vertex(0,lowerRegion.origin.y+noise(Q*D+millis()*T)*s);
357	// for(let i = 0; i<Q-1; i++)
358	// {
359		// curveVertex(i*step,lowerRegion.origin.y+noise(i*D+millis()*T)*s);
360	// }
361	// // //+noise(i,millis()*0.0005)
362	// endShape(CLOSE)
363	
364	// fill(CYAN);
365	// noStroke();
366	// beginShape();
367	// vertex(windowWidth,lowerRegion.origin.y+noise(millis()*T+0.5)*s+s/3);
368	// vertex(windowWidth,windowHeight)
369	// vertex(0,windowHeight)
370	// vertex(0,lowerRegion.origin.y+noise(Q*D+millis()*T+0.5)*s+s/3);
371	// for(let i = 0; i<Q-1; i++)
372	// {
373		// curveVertex(i*step,lowerRegion.origin.y+noise(i*D+millis()*T+0.5)*s+s/3);
374	// }
375	// endShape(CLOSE)
376	
377	// strokeWeight(16);
378	// stroke(RED);
379	// line(lowerRegion.origin.x,lowerRegion.origin.y,windowWidth,lowerRegion.origin.y);
380	// stroke(BLUE)
381	// line(overflowRegion.origin.x,overflowRegion.origin.y,windowWidth,overflowRegion.origin.y)
382}
383// var T = 0.0004;
384// var D = 0.4
385// var Q = 100;
386
387var DEBUG_DRAW_REGIONS = false;
388
389function keyPressed()
390{
391	/// DEBUG ///
392	if(key=='1' && state!=DebugState) 
393	{
394		nextState(DebugState, state);
395		return;
396	}
397	else if(key=='2') DEBUG_DRAW_REGIONS = !DEBUG_DRAW_REGIONS;
398	/////////////
399	if(state.onKeyPressed) state.onKeyPressed();
400}
401
402function pause(yesText, yesAction, noText, noAction)
403{
404	paused = true;
405	UI.setOptions({text:yesText, action:yesAction},{text:noText, action:noAction}, 'PAUSED');
406}
407
408
409
410function nextState(newState, params)
411{
412	if(state.onExit) state.onExit();
413	state = newState;
414	
415	// Model.resetTimes();
416	
417	// Initialize if first time entering.
418	if(!state.initialized && state.init) state.init();
419	
420	// Update dimensions if required, needs to be done after first time initialize but before onEnter
421	if(state.updateDimensionsPending && state.updateDimensions) state.updateDimensions();
422	
423	if(state.onEnter) state.onEnter(params);
424	
425	state.updateDimensionsPending = false;
426	state.initialized = true;
427	
428	Flag.rightFlag.confirmValue = 0;
429	Flag.leftFlag.confirmValue = 0;
430}
431
432function windowResized()
433{
434	resizeCanvas(windowWidth,windowHeight)
435	
436	if(state.overrideRegion) state.overrideMainRegion();
437	else
438	{
439		mainRegion.size = createVector(min(windowWidth/2,(windowHeight/2.6)*cutoffAspect.max),min(windowWidth/2,(windowHeight/2.6)*cutoffAspect.max));
440		//mainRegion.origin = createVector(windowWidth/2 - mainRegion.size.x/2, 0);
441		
442		
443		mainRegion.origin = createVector(windowWidth/2 - mainRegion.size.x/2, (windowHeight-mainRegion.size.y)/3);
444		
445		mainRegion.innerSize = createVector(2*mainRegion.size.x/3,2*mainRegion.size.y/3);
446		mainRegion.innerOrigin = createVector(mainRegion.origin.x+mainRegion.innerSize.x/4,mainRegion.origin.y+mainRegion.innerSize.y/4);
447		mainRegion.center = createVector(mainRegion.origin.x+mainRegion.size.x/2,mainReg
447ion.origin.y+mainRegion.size.y/2);
448		mainRegion.scale = mainRegion.size.x / mainRegion.idealSize
449		
450		lowerRegion.origin = createVector(0,windowHeight);
451		lowerRegion.size = createVector(windowWidth,0);
452	}
453	
454	margin = 32*mainRegion.scale;//createVector(windowWidth/32,windowHeight/32);
455	
456	// lowerRegion.origin = createVector(0,max(mainRegion.size.y,(windowHeight*2/3+mainRegion.size.y)/2));
457	// lowerRegion.size = createVector(windowWidth,min(mainRegion.size.y/4,windowHeight-lowerRegion.origin.y));
458	
459	// overflowRegion.origin = createVector(0,lowerRegion.origin.y+lowerRegion.size.y);
460	// overflowRegion.size = createVector(windowWidth,windowHeight-overflowRegion.origin.y);
461	
462	
463	
464	overflowRegion.origin = createVector(0,lowerRegion.origin.y+lowerRegion.size.y);
465	overflowRegion.size = createVector(windowWidth,windowHeight-overflowRegion.origin.y);
466	
467	/// DEBUG ///
468	// leftRegion = {
469		// origin: createVector(margin,margin),
470		// size: createVector(mainRegion.origin.x-margin*2,lowerRegion.origin.y-margin*2)
471	// }
472	// rightRegion = {
473		// origin: createVector(mainRegion.origin.x+mainRegion.size.x+margin,margin),
474		// size: createVector(windowWidth-(mainRegion.origin.x+mainRegion.size.x+margin*2),lowerRegion.origin.y-margin*2)
475	// }
476	/////////////
477	
478	Flag.updateDimensions();
479	UI.updateDimensions();
480	
481	ALL_STATES.forEach((s)=>s.updateDimensionsPending=true);
482	if(state.updateDimensions) state.updateDimensions();
483	state.updateDimensionsPending = false;
484	
485	textSize(windowWidth*0.01);
486	let h = textWidth("Developed for Signals by Ben Tilbury");
487	linkSpan.position(windowWidth/2-h/2-windowWidth*0.005,windowHeight-windowWidth*0.02)
488	linkSpan.show()
489	
490	textSize(windowWidth*0.01);
491	h = textWidth("Privacy Policy");
492	ppolSpan.position(windowWidth-h-windowWidth*0.015,windowHeight-windowWidth*0.02);
493	ppolSpan.show();
494	
495	gitSpan.position(windowWidth*0.01,windowHeight-windowWidth*0.02);
496	gitSpan.show();
497}
498
499function angleToIndex(angle) { return (round(angle*8/(PI*2))+6) % 8 }
500
501function anglesFromLetter(letter)
502{
503	let num = Object.keys(SIGNALS).find(key => SIGNALS[key] === letter);
504	num = parseInt(num);
505	let l = floor(num/8)
506	let r = num - l*8
507	
508	r = indexToAngle(r)
509	l = indexToAngle(l)
510	
511	return [r, l];
512}
513
514function indexToAngle(index, mode)
515{
516	return ((index)/8)*PI*2 + PI/2;
517}
518
519function vectorsFromLetter(letter)
520{
521	const [r,l] = anglesFromLetter(letter);
522	return [p5.Vector.fromAngle(r), p5.Vector.fromAngle(l)]
523}
524
525function randomTriangular(lower,upper,mode)
526{
527	let U = Math.random()
528	if(U<(mode-lower)/(upper-lower)) return lower+Math.sqrt(U*(upper-lower)*(mode-lower));
529	else return upper-Math.sqrt((1-U)*(upper-lower)*(upper-mode));
530}
531
532function inputDebug()
533{
534	// Flip
535	if(key.toUpperCase() === 'Q')
536	{
537		flip = !flip;
538		//document.getElementById("guideA").src = flip ? "assets/bacfaceA.png" : "assets/forfaceA.png"
539		//document.getElementById("guideB").src = flip ? "assets/bacfaceB.png" : "assets/forfaceB.png"
540	}
541	
542	// Toggle Word Mode
543	if(key.toUpperCase() === 'W' && state!=GameState)
544	{
545		state.wordMode = !state.wordMode
546		state.sentence = "";
547	}
548	
549	// Toggle Two Tone Flags
550	if(key.toUpperCase() === 'E')
551	{
552		Flag.twoTone = !Flag.twoTone;
553	}
554	
555	// Toggle Aync Mode
556	if(key.toUpperCase() === 'R')
557	{
558		Model.toggleAsync();
559		Flag.resetAdapto();
560	}
561	
562	if(key.toUpperCase() === 'T') 
563	{
564		nextState(MainMenuState)
565	}
566}
567
568// function shuffle(array) 
569// {
570  // var m = array.length, t, i;
571  
572  // while (m) {
573
574    // i = Math.floor(Math.random() * m--);
575
576    // t = array[m];
577    // array[m] = array[i];
578    // array[i] = t;
579  // }
580
581  // return array;
582// }
583
584///// DOCUMENT FUNCTIONS /////
585document.addEventListener('visibilitychange', function() 
586{
587    if(document.hidden && !paused) 
588	{
589		tabPaused = true;
590	}
591	else if(!document.hidden && !paused)
592	{
593		tabPaused = false;
594	}
595});
596
597
598// window.onbeforeunload = function (e) 
599// {
600  // Model.disposeAll();
601// };

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.