UNPKG

d-zone

Version:

An ambient life simulation driven by the user activity within a Discord server

165 lines (161 loc) 8.42 kB
'use strict'; var BetterCanvas = require('./../common/bettercanvas.js'); var charSets = { upper: { y: 0, height: 8, xSpacing: 1, chars: [ ['A',5], ['B',5], ['C',5], ['D',5], ['E',4], ['F',4], ['G',5], ['H',5], ['I',3], ['J',5], ['K',5], ['L',4], ['M',5], ['N',5], ['O',5], ['P',5], ['Q',5], ['R',5], ['S',5], ['T',5], ['U',5], ['V',5], ['W',5], ['X',5], ['Y',5], ['Z',5] ] }, lower: { y: 8, height: 11, xSpacing: 1, chars: [ ['a',5], ['b',4], ['c',4], ['d',4], ['e',4], ['f',4], ['g',4], ['h',4], ['i',1], ['j',2], ['k',4], ['l',1], ['m',5], ['n',4], ['o',4], ['p',4], ['q',4], ['r',4], ['s',4], ['t',4], ['u',4], ['v',5], ['w',5], ['x',4], ['y',4], ['z',4], [' ',4] ] }, numsAndSymbols: { y: 19, xSpacing: 1, height: 8, chars: [ ['0',4], ['1',3], ['2',4], ['3',4], ['4',4], ['5',4], ['6',4], ['7',4], ['8',4], ['9',4], ['`',2],['~',6],['!',1],['@',7],['#',7],['$',4],['%',5],['^',5],['&',6],['*',3],['(',2], [')',2],['_',5],['=',5],['-',5],['+',5],['|',1],[',',2],['.',1],['<',5],['>',5],['?',4], ['/',3],['\\',3],[';',1],[':',1],["'",1],['"',3],['[',2],[']',2],['{',3],['}',3] ] }, icons: { count: 4, y: 27, height: 12, chars: [ [':icon-npm:',12],[':icon-github:',12],[':icon-lock:',12],[':icon-lock-small:',12] ] }, accented1: { y: 39, xSpacing: 1, height: 13, oy: -2, chars: [ ['á',5], ['Á',5], ['à',5], ['À',5], ['â',5], ['Â',5], ['ä',5], ['Ä',5], ['ã',5], ['Ã',5], ['å',5], ['Å',5], ['æ',7], ['Æ',7], ['ç',4], ['Ç',5], ['é',4], ['É',4], ['è',4], ['È',4], ['ê',4], ['Ê',4], ['ë',4], ['Ë',4], ['í',2], ['Í',3], ['ì',2], ['Ì',3], ['î',3], ['Î',3], ['ï',3], ['Ï',3] ] }, accented2: { y: 52, xSpacing: 1, height: 10, oy: -2, chars: [ ['ñ',4], ['Ñ',5], ['ó',4], ['Ó',5], ['ò',4], ['Ò',5], ['ô',4], ['Ô',5], ['ö',4], ['Ö',5], ['õ',4], ['Õ',5], ['ø',4], ['Ø',5], ['œ',7], ['Œ',8], ['ß',5], ['ú',4], ['Ú',5], ['ù',4], ['Ù',5], ['û',4], ['Û',5], ['ü',4], ['Ü',5] ] } }; var fontMap = {}; for(var csKey in charSets) { if(!charSets.hasOwnProperty(csKey)) continue; var charSet = charSets[csKey], rx = 0; for(var c = 0; c < charSet.chars.length; c++) { var char = charSet.chars[c][0], width = charSet.chars[c][1]+(charSet.xSpacing || 0); fontMap[char] = { x: rx, y: charSet.y, w: width, h: charSet.height, char: char, oy: charSet.oy }; rx += width; } } var padding = { x: 4, y: 3 }; var vertOffset = 1; var image; module.exports = { loadImage: function(img) { image = img; }, blot: function(options) { var x = options.x || 0, y = options.y || 0; var metrics = options.metrics || this.calculateMetrics(options); var lineStart = options.lineStart ? options.lineStart : 0; var lineCount = options.lineCount ? Math.min(metrics.lines.length, options.lineCount) : metrics.lines.length; var canvas = options.canvas || new BetterCanvas( padding.x * 2 + x + metrics.w - 1, padding.y * 2 + y + lineCount * 10 ); if(options.bg) canvas.fill(options.bg); var charCount = 0; for(var l = lineStart; l < Math.min(metrics.lines.length, lineStart + lineCount); l++) { var maxChars = metrics.lines[l].chars.length; if(options.maxChars) maxChars = Math.min(maxChars,options.maxChars - charCount); for(var c = 0; c < maxChars; c++) { var char = metrics.lines[l].chars[c]; if(char.char.text == ' ') continue; canvas.drawImage(image, char.char.x, char.char.y, char.w, char.char.h, padding.x + x + char.x, padding.y + y + (l - lineStart) * 10 + (char.oy || 0) + vertOffset, char.w, char.char.h); } charCount += metrics.lines[l].chars.length; } return canvas.canvas; }, transition: function(options) { var metrics = options.metrics || this.calculateMetrics(options); var canvas = options.canvas || new BetterCanvas( metrics.w + padding.x * 2, (options.lineCount || metrics.lines.length) * 10 + padding.y * 2 ); var fillWidth = Math.max(2,Math.max(0, options.progress - 0.25) / 0.75 * canvas.canvas.width); var fillHeight = Math.min(1, options.progress * 4) * canvas.canvas.height * -1; canvas.fillRect(options.bg, (canvas.canvas.width - fillWidth) / 2, canvas.canvas.height, fillWidth, fillHeight); return canvas.canvas; }, calculateMetrics: function(options) { // TODO: Normalize line lengths so there are no single-word remainders var text = options.text; var lines = []; var words = text.split(' '); var space = fontMap[' ']; var lineWidth = 0, lineChars = [], maxLineWidth = 0; for(var w = 0; w < words.length; w++) { var word = words[w]; if(word == '') continue; // Skip empty words var wordWidth = 0; var wordChars = []; if(lineChars.length > 0) { // Add space before word unless starting a line wordChars.push({ x: lineWidth, char: space, w: space.w }); wordWidth += space.w; } if(word.length > 1 && fontMap[word]) { // Icon codes wordChars.push({ x: lineWidth + wordWidth, char: fontMap[word], w: fontMap[word].w, oy: -2 }); wordWidth += fontMap[word].w; } else { for(var a = 0; a < word.length; a++) { var ltr = fontMap[word[a]] || space; wordChars.push({ x: lineWidth + wordWidth, char: ltr, w: ltr.w, oy: ltr.oy }); wordWidth += ltr.w; } } if(options.maxWidth && lineWidth + wordWidth > options.maxWidth) { if(wordWidth > options.maxWidth) { // Word is longer than maxWidth, won't fit any line if(lineWidth > 0) { lines.push({ w: lineWidth, chars: lineChars }); maxLineWidth = Math.max(lineWidth, maxLineWidth); lineWidth = 0; lineChars = []; } wordChars = []; wordWidth = 0; for(var b = 0; b < word.length; b++) { var ltrB = fontMap[word[b]] || space; if(lineWidth + wordWidth + ltrB.w < options.maxWidth) { wordChars.push({ x: lineWidth + wordWidth, char: ltrB, w: ltrB.w, oy: ltrB.oy }); wordWidth += ltrB.w; } else { var trimWidth = (lineWidth + wordWidth + ltrB.w) - options.maxWidth; wordChars.push({ x: lineWidth + wordWidth, char: ltrB, w: ltrB.w - trimWidth, oy: ltrB.oy }); wordWidth += ltrB.w - trimWidth; break; } } lineWidth += wordWidth; lineChars = lineChars.concat(wordChars); } else { // Word can be pushed to next line w--; } lines.push({ w: lineWidth, chars: lineChars }); maxLineWidth = Math.max(lineWidth, maxLineWidth); lineWidth = 0; lineChars = []; } else { // Word fits on line lineWidth += wordWidth; lineChars = lineChars.concat(wordChars); if(w == words.length - 1) { lines.push({ w: lineWidth, chars: lineChars }); maxLineWidth = Math.max(lineWidth, maxLineWidth); } } } return { lines: lines, text: text, w: maxLineWidth }; }, fontMap: fontMap };