Terminal Style.
A Pen by Benedikt Wolters on CodePen.
| <input type='text' id="ghost" /><span id="info">WOPR | |
| by <a href='https://mightyuhu.github.io/'> Benedikt Wolters</a></span> | |
| <canvas width="512" height="512" id="source"></canvas> | |
| <canvas width="512" height="512" id="projection"></canvas> |
| window.requestAnimFrame = (function(){ | |
| return window.requestAnimationFrame || | |
| window.webkitRequestAnimationFrame || | |
| window.mozRequestAnimationFrame || | |
| function( callback ){ | |
| window.setTimeout(callback, 1000 / 60); | |
| }; | |
| })(); | |
| // usage: | |
| // instead of setInterval(render, 16) .... | |
| var redraw = true; | |
| $("#ghost").focus(); | |
| (function($) { | |
| $.fn.getCursorPosition = function() { | |
| var input = this.get(0); | |
| if (!input) return; // No (input) element found | |
| if ('selectionStart' in input) { | |
| // Standard-compliant browsers | |
| return input.selectionStart; | |
| } else if (document.selection) { | |
| // IE | |
| input.focus(); | |
| var sel = document.selection.createRange(); | |
| var selLen = document.selection.createRange().text.length; | |
| sel.moveStart('character', -input.value.length); | |
| return sel.text.length - selLen; | |
| } | |
| } | |
| })(jQuery); | |
| var strbadd= function(str,strb){ | |
| strb+=str; | |
| for(i=0;i<41-(str.length % 41);i++){ | |
| strb += " "; | |
| } | |
| if(strb.length > (25*41)){ | |
| strb = strb.slice(strb.length-(25*41), strb.length); | |
| } | |
| return strb; | |
| } | |
| var strb = ""; | |
| strb = strbadd(" ",strb); | |
| strb = strbadd("GREETINGS PROFESSOR FALKEN",strb); | |
| strb = strbadd(" ",strb); | |
| strb = strbadd("SHALL WE PLAY A GAME?",strb); | |
| strb = strbadd(" ",strb); | |
| strb = strbadd("Game List",strb); | |
| strb = strbadd(" ",strb); | |
| strb = strbadd("FALKENS'S MAZE",strb); | |
| strb = strbadd("CHESS",strb); | |
| strb = strbadd("POKER",strb); | |
| strb = strbadd("FIGHTER COMBAT",strb); | |
| strb = strbadd("GUERILLA ENGAGEMENT",strb); | |
| strb = strbadd("DESERT WARFARE",strb); | |
| strb = strbadd("AIR-TO-GROUND ACTIONS",strb); | |
| strb = strbadd("THEATERWIDE TACTICAL WARFARE",strb); | |
| strb = strbadd("THEATERWIDE TACTICAL BIOTOXIC AND CHEMICAL WARFARE",strb); | |
| strb = strbadd(" ",strb); | |
| strb = strbadd("GLOBAL THERMONUCLEAR WAR",strb); | |
| strbp = strb; | |
| strbp = strbadd('▊',strb); | |
| var lc = ""; | |
| textCheck = function(){ | |
| if(settings.stickfocus){ | |
| $("#ghost").focus(); | |
| } | |
| if($("#ghost").getCursorPosition() != lc){ | |
| //strb = strbadd($("#ghost").val(),strb); | |
| lc =$("#ghost").getCursorPosition(); | |
| strbp = strbadd($("#ghost").val().slice(0,lc)+'▊'+$("#ghost").val().slice(lc,$("#ghost").val().length),strb); | |
| redraw = true; | |
| } | |
| }; | |
| $(window).on('keydown keyup',function(){ | |
| textCheck(); | |
| }); | |
| //sentinel = setInterval(textCheck,.2 ) | |
| $("#ghost").keyup(function (e) { | |
| if (e.keyCode == 13) { | |
| strb = strbadd($("#ghost").val(),strb); | |
| strb = strbadd("Unknow Command: \""+$("#ghost").val()+"\"",strb); | |
| strbp = strb; | |
| strbp = strbadd($("#ghost").val().slice(0,lc)+'▊'+$("#ghost").val().slice(lc,$("#ghost").val().length),strb); | |
| $("#ghost").val(""); | |
| redraw = true; | |
| //draw(); | |
| //generateMapping(); | |
| } | |
| }); | |
| var width = 512; | |
| var height = 512; | |
| var spherize = function (px, py) { | |
| var x = px - width / 2; | |
| var y = py - height / 2; | |
| var r = Math.sqrt(x * x + y * y); | |
| var maxr = width / settings.maxRadius; | |
| if (r > maxr) return { | |
| 'x': px, | |
| 'y': py | |
| } | |
| var a = Math.atan2(y, x) * settings.atanscale; | |
| var k = (r / maxr) * (r / maxr) * settings.k + 0.2; | |
| var dx = Math.cos(a * settings.xscale) * r * k * settings.oxscale; | |
| var dy = Math.sin(a * settings.yscale) * r * k * settings.oyscale; | |
| return { | |
| 'x': dx + width / 2, | |
| 'y': dy + height / 2 | |
| } | |
| } | |
| var src = document.getElementById('source'); | |
| var dst = document.getElementById('projection'); | |
| var input = src.getContext('2d'); | |
| var output = dst.getContext('2d'); | |
| var draw = function(){ | |
| //input.fillStyle="#262737"; | |
| input.fillRect(0, 0, 512, 512); | |
| input.font = '20px Monospace'; | |
| input.fillStyle = '#74F9FF'; | |
| input.shadowBlur = 30; | |
| // Specify the shadow colour. | |
| input.shadowColor = "blue"; | |
| // Specify the shadow offset. | |
| input.shadowOffsetX = 0; | |
| input.shadowOffsetY = 0; | |
| for(i = 0;i<(25*41);i+=41){ | |
| console.log(strbp.slice(i,i+41)) | |
| input.fillText(strbp.slice(i,i+41), 10, ((i+41)/41) * 20); | |
| } | |
| input.shadowBlur = 0; | |
| // Specify the shadow offset. | |
| input.shadowOffsetX = 0; | |
| input.shadowOffsetY = 0; | |
| input.shadowColor = "black"; | |
| input.fillStyle = 'black'; | |
| for (var i = 2; i < width; i += 1.5) { | |
| input.beginPath() | |
| input.moveTo(i * 2, 2); | |
| input.lineTo(i * 2, 512); | |
| input.lineWidth = 0.8; | |
| input.strokeStyle = 'hsl(0,0%,0%)'; | |
| input.stroke(); | |
| input.beginPath() | |
| input.moveTo(2, i * 2); | |
| input.lineTo(512, i * 2); | |
| input.lineWidth = 0.8; | |
| input.strokeStyle = 'hsl(0,0%,0%)'; | |
| input.stroke(); | |
| } | |
| input.shadowBlur = 0; | |
| // Specify the shadow offset. | |
| input.shadowOffsetX = 0; | |
| input.shadowOffsetY = 0; | |
| } | |
| draw(); | |
| generateMapping = function () { | |
| output.fillRect(0, 0, 512, 512); | |
| var bitmap = input.getImageData(0, 0, 512, 512); | |
| var texture = input.getImageData(0, 0, 512, 512); | |
| var map = []; | |
| for (var y = 0; y < height; y++) { | |
| for (var x = 0; x < width; x++) { | |
| var t = spherize(x, y); | |
| map[(x + y * height) * 2 + 0] = Math.max(Math.min(t.x, width ), 0); | |
| map[(x + y * height) * 2 + 1] = Math.max(Math.min(t.y, height ), 0); | |
| } | |
| } | |
| var colorat = function (x, y, channel) { | |
| return texture.data[(x + y * height) * 4 + channel]; | |
| } | |
| for (var j = 0; j < height; j++) { | |
| for (var i = 0; i < width; i++) { | |
| var u = map[(i + j * height) * 2]; | |
| var v = map[(i + j * height) * 2 + 1]; | |
| var x = Math.floor(u); | |
| var y = Math.floor(v); | |
| var kx = u - x; | |
| var ky = v - y; | |
| for (var c = 0; c < 4; c++) { | |
| bitmap.data[(i + j * height) * 4 + c] = (colorat(x, y, c) * (1 - kx) + colorat(x + 1, y, c) * kx) * (1 - ky) + (colorat(x, y + 1, c) * (1 - kx) + colorat(x + 1, y + 1, c) * kx) * (ky); | |
| } | |
| } | |
| } | |
| output.putImageData(bitmap, 0, 0); | |
| }; | |
| settings = { | |
| maxRadius: 0.561, | |
| k: 0.115, | |
| atanscale: 1, | |
| xscale: 1, | |
| yscale: 1, | |
| oxscale: 4.7, | |
| oyscale: 4.7, | |
| stickfocus: true, | |
| applyMapping: function () { | |
| generateMapping(); | |
| } | |
| }; | |
| var gui = new dat.GUI(); | |
| gui.add(settings, 'maxRadius', 0.01, 1.51).onChange(function (value) { | |
| generateMapping(); | |
| }); | |
| gui.add(settings, 'atanscale', 0.01, 10.0).onChange(function (value) { | |
| generateMapping(); | |
| }); | |
| gui.add(settings, 'oxscale', 0.01, 10.0).onChange(function (value) { | |
| generateMapping(); | |
| }); | |
| gui.add(settings, 'oyscale', 0.01, 10.0).onChange(function (value) { | |
| generateMapping(); | |
| }); | |
| //gui.add(settings, 'xscale', 0.01, 10.0).onChange(function (value) { | |
| // generateMapping(); | |
| //}); | |
| //gui.add(settings, 'yscale', 0.01, 10.0).onChange(function (value) { | |
| // generateMapping(); | |
| //}); | |
| gui.add(settings, 'stickfocus'); | |
| gui.add(settings, 'k', 0.001, 2.010).onChange(function (value) { | |
| generateMapping(); | |
| }); | |
| gui.add(settings, 'applyMapping'); | |
| (function animloop(){ | |
| requestAnimFrame(animloop); | |
| if(redraw){ | |
| redraw = false; | |
| draw(); | |
| generateMapping(); | |
| } | |
| })(); |
Terminal Style.
A Pen by Benedikt Wolters on CodePen.
| @import url(http://fonts.googleapis.com/css?family=Open+Sans|Maven+Pro:500); | |
| A, A:link, A:visited, A:active { | |
| text-decoration:none; | |
| color:#b00b00; | |
| } | |
| body, html { | |
| font-family:'Open Sans'; | |
| background: #000; | |
| min-height: 100%; | |
| font-size:10px; | |
| font-family:'Open Sans'; | |
| background-attachment: fixed; | |
| color: white; | |
| font-size:10/1px; | |
| font-family:monospace; | |
| } | |
| span#info{ | |
| position:fixed; | |
| } | |
| canvas#source{ | |
| display:none; | |
| } | |
| canvas#projection{ | |
| margin-top:5px; | |
| display:block; | |
| width:512px; | |
| margin:0 auto; | |
| } | |
| input#ghost{ | |
| position: fixed; | |
| width: 100%; | |
| color: transparent; | |
| background-color: transparent; | |
| border: 0; | |
| outline: none; | |
| border:none; | |
| } |