examples/pacman-unicode/unicodetiles/unicodetiles.js
File `unicodetiles.js` has 271 lines of code (exceeds 250 allowed). Consider refactoring./// File: unicodetiles.js/// This file contains the main tile engine namespace./// All coordinates are assumed to be integers - behaviour is undefined/// if you feed in floats (or anything other) as x and y (or similar) parameters. /*jshint browser:true devel:true trailing:true latedef:true undef:true unused:true newcap:true */ if (!window.console) { window.console = { log: function(){}, warn: function(){}, error: function(){} }} /// Namespace: ut/// Container namespace.var ut = ut || {}; /// Constants: Semi-internal constants for ut namespace/// VERSION - Version of the library as string./// NULLCHAR - Character used when none is specified otherwise./// CSSCLASS - The CSS class name used for the tile engine element./// NULLTILE - The tile used as placeholder for empty tile.ut.VERSION = "2.1";ut.NULLCHAR = " ";ut.CSSCLASS = "unicodetiles";ut.NULLTILE = {}; // Initialized properly after ut.Tile is defined /// Class: Tile/// Represents a unicode character tile with various attributes. /// Constructor: Tile/// Constructs a new Tile object.////// Parameters:/// ch - a character to display for this tile/// r - (optional) red foregorund color component 0-255/// g - (optional) green foreground color component 0-255/// b - (optional) blue foreground color component 0-255/// br - (optional) red background color component 0-255/// bg - (optional) green background color component 0-255/// bb - (optional) blue background color component 0-255Function `Tile` has 7 arguments (exceeds 4 allowed). Consider refactoring.ut.Tile = function(ch, r, g, b, br, bg, bb) { "use strict"; this.ch = ch || ut.NULLCHAR; this.r = r; this.g = g; this.b = b; this.br = br; this.bg = bg; this.bb = bb;}; /// Function: getChar /// Returns the character of this tile. ut.Tile.prototype.getChar = function() { return this.ch; }; /// Function: setChar /// Sets the character of this tile. ut.Tile.prototype.setChar = function(ch) { this.ch = ch; }; /// Function: setColor /// Sets the foreground color of this tile.Similar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.setColor = function(r, g, b) { this.r = r; this.g = g; this.b = b; }; /// Function: setGrey /// Sets the foreground color to the given shade (0-255) of grey. ut.Tile.prototype.setGrey = function(grey) { this.r = grey; this.g = grey; this.b = grey; }; /// Function: setBackground /// Sets the background color of this tile.Similar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.setBackground = function(r, g, b) { this.br = r; this.bg = g; this.bb = b; }; /// Function: resetColor /// Clears the color of this tile / assigns default color.Similar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.resetColor = function() { this.r = this.g = this.b = undefined; }; /// Function: resetBackground /// Clears the background color of this tile.Similar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.resetBackground = function() { this.br = this.bg = this.bb = undefined; }; /// Function: getColorHex /// Returns the hexadecimal representation of the colorSimilar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.getColorHex = function() { if (this.r !== undefined && this.g !== undefined && this.b !== undefined) return "#" + this.r.toString(16) + this.g.toString(16) + this.b.toString(16); else return ""; }; /// Function: getBackgroundHex /// Returns the hexadecimal representation of the background colorSimilar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.getBackgroundHex = function() { if (this.br !== undefined && this.bg !== undefined && this.bb !== undefined) return "#" + this.br.toString(16) + this.bg.toString(16) + this.bb.toString(16); else return ""; }; /// Function: getColorRGB /// Returns the CSS rgb(r,g,b) representation of the colorSimilar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.getColorRGB = function() { if (this.r !== undefined && this.g !== undefined && this.b !== undefined) return 'rgb('+this.r+','+this.g+','+this.b+')'; else return ""; }; /// Function: getBackgroundRGB /// Returns the CSS rgb(r,g,b) representation of the background colorSimilar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.getBackgroundRGB = function() { if (this.br !== undefined && this.bg !== undefined && this.bb !== undefined) return 'rgb('+this.br+','+this.bg+','+this.bb+')'; else return ""; }; /// Function: getColorJSON /// Returns the JSON representation of the color, i.e. object { r, g, b }Similar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.getColorJSON = function() { if (this.r !== undefined && this.g !== undefined && this.b !== undefined) return { "r": this.r, "g": this.g, "b": this.b }; else return {}; }; /// Function: getBackgroundJSON /// Returns the JSON representation of the background color, i.e. object { r, g, b }Similar blocks of code found in 2 locations. Consider refactoring. ut.Tile.prototype.getBackgroundJSON = function() { if (this.r !== undefined && this.g !== undefined && this.b !== undefined) return { "r": this.br, "g": this.bg, "b": this.bb }; else return {}; }; /// Function: copy /// Makes this tile identical to the one supplied. Custom properties are not copied. ut.Tile.prototype.copy = function(other) { this.ch = other.ch; this.r = other.r; this.g = other.g; this.b = other.b; this.br = other.br; this.bg = other.bg; this.bb = other.bb; }; /// Function: clone /// Returns a new copy of this tile. Custom properties are not cloned. ut.Tile.prototype.clone = function() { return new ut.Tile(this.ch, this.r, this.g, this.b, this.br, this.bg, this.bb); }; ut.NULLTILE = new ut.Tile(); /// Class: Viewport/// The tile engine viewport / window. Takes care of initializing a proper renderer. /// Constructor: Viewport/// Constructs a new Viewport object./// If you wish to display a player character at the center, you should use odd sizes.////// Parameters:/// elem - the DOM element which shall be transformed into the tile engine/// w - (integer) width in tiles/// h - (integer) height in tiles/// renderer - (optional) choose rendering engine, see <Viewport.setRenderer>, defaults to "auto"./// squarify - (optional) set to true to force the tiles square; may break some box drawingFunction `Viewport` has a Cognitive Complexity of 21 (exceeds 5 allowed). Consider refactoring.
Function `Viewport` has 52 lines of code (exceeds 25 allowed). Consider refactoring.
Function `Viewport` has 5 arguments (exceeds 4 allowed). Consider refactoring.ut.Viewport = function(elem, w, h, renderer, squarify) { "use strict"; this.elem = elem; this.elem.innerHTML = ""; this.w = w; this.h = h; this.renderer = null; // setRenderer() is called later this.squarify = squarify; this.cx = Math.floor(w/2); this.cy = Math.floor(h/2); // Add CSS class if not added already if (elem.className.indexOf(ut.CSSCLASS) === -1) { if (elem.className.length === 0) elem.className = ut.CSSCLASS; else elem.className += " " + ut.CSSCLASS; } // Create two 2-dimensional array to hold the viewport tiles this.buffer = new Array(h); for (var j = 0; j < h; ++j) { this.buffer[j] = new Array(w); for (var i = 0; i < w; ++i) { this.buffer[j][i] = new ut.Tile(); } } /// Function: updateStyle /// If the style of the parent element is modified, this needs to be called. this.updateStyle = function(updateRenderer) { var s = window.getComputedStyle(this.elem, null); this.defaultColor = s.color; this.defaultBackground = s.backgroundColor; if (updateRenderer !== false) this.renderer.updateStyle(s); }; /// Function: setRenderer /// Switch renderer at runtime. All methods fallback to "dom" if unsuccesful. /// Possible values: /// * "webgl" - Use WebGL with an HTML5 <canvas> element /// * "canvas" - Use HTML5 <canvas> element /// * "dom" - Use regular HTML element manipulation through DOM /// * "auto" - Use best available, i.e. try the above in order, picking the first that works this.setRenderer = function(newrenderer) { this.elem.innerHTML = "";Similar blocks of code found in 2 locations. Consider refactoring. if (newrenderer === "auto" || newrenderer === "webgl") { try { this.renderer = new ut.WebGLRenderer(this); } catch (e) { console.error(e); newrenderer = "canvas"; this.elem.innerHTML = ""; } }Similar blocks of code found in 2 locations. Consider refactoring. if (newrenderer === "canvas") { try { this.renderer = new ut.CanvasRenderer(this); } catch (e) { console.error(e); newrenderer = "dom"; this.elem.innerHTML = ""; } } if (newrenderer === "dom") { this.renderer = new ut.DOMRenderer(this); } this.updateStyle(false); }; this.setRenderer(renderer || "auto");}; /// Function: getRendererString /// Gets the currently used renderer. /// /// Returns: /// One of "webgl", "canvas", "dom", "". ut.Viewport.prototype.getRendererString = function() { if (this.renderer instanceof ut.WebGLRenderer) return "webgl"; if (this.renderer instanceof ut.CanvasRenderer) return "canvas"; if (this.renderer instanceof ut.DOMRenderer) return "dom"; return ""; }; /// Function: put /// Puts a tile to the given coordinates. /// Checks bounds and does nothing if invalid coordinates are given. /// /// Parameters: /// tile - the tile to put /// x - (integer) x coordinate /// y - (integer) y coordinate ut.Viewport.prototype.put = function(tile, x, y) { if (x < 0 || y < 0 || x >= this.w || y >= this.h) return; this.buffer[y][x] = tile; }; /// Function: unsafePut /// Puts a tile to the given coordinates. /// Does *not* check bounds; throws exception if invalid coordinates are given. /// /// Parameters: /// tile - the tile to put /// x - (integer) x coordinate /// y - (integer) y coordinate ut.Viewport.prototype.unsafePut = function(tile, x, y) { this.buffer[y][x] = tile; }; /// Function: putString /// Creates a row of tiles with the chars of the given string. /// Wraps to next line if it can't fit the chars on one line. /// /// Parameters: /// str - (string) the string to put /// x - (integer) x coordinate (column) /// y - (integer) y coordinate (row) /// r - (optional) red foregorund color component 0-255 /// g - (optional) green foreground color component 0-255 /// b - (optional) blue foreground color component 0-255 /// br - (optional) red background color component 0-255 /// bg - (optional) green background color component 0-255 /// bb - (optional) blue background color component 0-255Function `putString` has 9 arguments (exceeds 4 allowed). Consider refactoring.
Function `putString` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. ut.Viewport.prototype.putString = function(str, x, y, r, g, b, br, bg, bb) { var len = str.length; var tile; if (x < 0 || y < 0) return; for (var i = 0; i < len; ++i) { if (x >= this.w) { x = 0; ++y;} if (y >= this.h) return; tile = new ut.Tile(str[i], r, g, b, br, bg, bb); this.unsafePut(tile, x, y); ++x; } }; /// Function: get /// Returns the tile in the given coordinates. /// Checks bounds and returns empty tile if invalid coordinates are given. /// /// Parameters: /// x - (integer) x coordinate /// y - (integer) y coordinate /// /// Returns: /// The tile. ut.Viewport.prototype.get = function(x, y) { if (x < 0 || y < 0 || x >= this.w || y >= this.h) return ut.NULLTILE; return this.buffer[y][x]; }; /// Function: clear /// Clears the viewport buffer by assigning empty tiles. ut.Viewport.prototype.clear = function() { for (var j = 0; j < this.h; ++j) { for (var i = 0; i < this.w; ++i) { this.buffer[j][i] = ut.NULLTILE; } } this.renderer.clear(); }; /// Function: render /// Renders the buffer as html to the element specified at construction. ut.Viewport.prototype.render = function() { this.renderer.render(); }; /// Class: Engine/// The tile engine itself. /// Constructor: Engine/// Constructs a new Engine object. If width or height is given,/// it will not attempt to fetch tiles outside the boundaries./// In that case 0,0 is assumed as the upper-left corner of the world,/// but if no width/height is given also negative coords are valid.////// Parameters:/// vp - the <Viewport> instance to use as the viewport/// func - the function used for fetching tiles/// w - (integer) (optional) world width in tiles/// h - (integer) (optional) world height in tilesut.Engine = function(vp, func, w, h) { "use strict"; this.viewport = vp; this.tileFunc = func; this.w = w; this.h = h; this.refreshCache = true; this.cacheEnabled = false; this.transitionTimer = null; this.transitionDuration = 0; this.transition = null; this.cachex = 0; this.cachey = 0; this.tileCache = new Array(vp.h); this.tileCache2 = new Array(vp.h); for (var j = 0; j < vp.h; ++j) { this.tileCache[j] = new Array(vp.w); this.tileCache2[j] = new Array(vp.w); }}; /// Function: setTileFunc /// Sets the function to be called with coordinates to fetch each tile. /// Optionally can apply a transition effect. Effects are: /// "boxin", "boxout", "circlein", "circleout", "random" /// /// Parameters: /// func - function taking parameters (x, y) and returning an ut.Tile /// effect - (string) (optional) name of effect to use (see above for legal values) /// duration - (integer) (optional) how many milliseconds the transition effect should lastFunction `setTileFunc` has a Cognitive Complexity of 39 (exceeds 5 allowed). Consider refactoring.
Function `setTileFunc` has 40 lines of code (exceeds 25 allowed). Consider refactoring. ut.Engine.prototype.setTileFunc = function(func, effect, duration) { "use strict"; if (effect) { this.transition = undefined; if (typeof effect === "string") {Function `transition` has 7 arguments (exceeds 4 allowed). Consider refactoring. if (effect === "boxin") this.transition = function(x, y, w, h, new_t, old_t, factor) { var halfw = w * 0.5, halfh = h * 0.5; x -= halfw; y -= halfh;Similar blocks of code found in 2 locations. Consider refactoring. if (Math.abs(x) < halfw * factor && Math.abs(y) < halfh * factor) return new_t; else return old_t; };Function `transition` has 7 arguments (exceeds 4 allowed). Consider refactoring. else if (effect === "boxout") this.transition = function(x, y, w, h, new_t, old_t, factor) { var halfw = w * 0.5, halfh = h * 0.5; x -= halfw; y -= halfh; factor = 1.0 - factor;Avoid deeply nested control flow statements.
Similar blocks of code found in 2 locations. Consider refactoring. if (Math.abs(x) < halfw * factor && Math.abs(y) < halfh * factor) return old_t; else return new_t; };Function `transition` has 7 arguments (exceeds 4 allowed). Consider refactoring.
Avoid deeply nested control flow statements. else if (effect === "circlein") this.transition = function(x, y, w, h, new_t, old_t, factor) { var halfw = w * 0.5, halfh = h * 0.5; x -= halfw; y -= halfh; if (x*x + y*y < (halfw*halfw + halfh*halfh) * factor) return new_t; else return old_t; };Function `transition` has 7 arguments (exceeds 4 allowed). Consider refactoring. else if (effect === "circleout") this.transition = function(x, y, w, h, new_t, old_t, factor) { var halfw = w * 0.5, halfh = h * 0.5; x -= halfw; y -= halfh; factor = 1.0 - factor; if (x*x + y*y > (halfw*halfw + halfh*halfh) * factor) return new_t; else return old_t; };Function `transition` has 7 arguments (exceeds 4 allowed). Consider refactoring. else if (effect === "random") this.transition = function(x, y, w, h, new_t, old_t, factor) { if (Math.random() > factor) return old_t; else return new_t; }; } if (this.transition) { this.transitionTimer = (new Date()).getTime(); this.transitionDuration = duration || 500; } } this.tileFunc = func; }; /// Function: setMaskFunc /// Sets the function to be called to fetch mask information according to coordinates. /// If mask function returns false to some coordinates, then that tile is not rendered. /// /// Parameters: /// func - function taking parameters (x, y) and returning a true if the tile is visible ut.Engine.prototype.setMaskFunc = function(func) { this.maskFunc = func; }; /// Function: setShaderFunc /// Sets the function to be called to post-process / shade each visible tile. /// Shader function is called even if caching is enabled, see <Engine.setCacheEnabled>. /// /// Parameters: /// func - function taking parameters (tile, x, y) and returning an ut.Tile ut.Engine.prototype.setShaderFunc = function(func) { this.shaderFunc = func; }; /// Function: setWorldSize /// Tiles outside of the range x = [0,width[; y = [0,height[ are not fetched. /// Set to undefined in order to make the world infinite. /// /// Parameters: /// width - (integer) new world width /// height - (integer) new world height ut.Engine.prototype.setWorldSize = function(width, height) { this.w = width; this.h = height; }; /// Function: setCacheEnabled /// Enables or disables the usage of tile cache. This means that /// extra measures are taken to not call the tile function unnecessarily. /// This means that all animating must be done in a shader function, /// see <Engine.setShaderFunc>. /// Cache is off by default, but should be enabled if the tile function /// does more computation than a simple array look-up. /// /// Parameters: /// mode - true to enable, false to disable ut.Engine.prototype.setCacheEnabled = function(mode) { this.cacheEnabled = mode; this.refreshCache = true; }; /// Function: update /// Updates the viewport according to the given player coordinates. /// The algorithm goes as follows: /// * Record the current time /// * For each viewport tile: /// * Check if the tile is visible by testing the mask /// * If not visible, continue to the next tile in the viewport /// * Otherwise, if cache is enabled try to fetch the tile from there /// * Otherwise, call the tile function and check for shader function presence /// * If there is shader function, apply it to the tile, passing the recorded time /// * Put the tile to viewport /// /// Parameters: /// x - (integer) viewport center x coordinate in the tile world /// y - (integer) viewport center y coordinate in the tile worldFunction `update` has a Cognitive Complexity of 29 (exceeds 5 allowed). Consider refactoring.
Function `update` has 42 lines of code (exceeds 25 allowed). Consider refactoring. ut.Engine.prototype.update = function(x, y) { "use strict"; x = x || 0; y = y || 0; // World coords of upper left corner of the viewport var xx = x - this.viewport.cx; var yy = y - this.viewport.cy; var timeNow = (new Date()).getTime(); // For passing to shaderFunc var transTime; if (this.transition) transTime = (timeNow - this.transitionTimer) / this.transitionDuration; if (transTime >= 1.0) this.transition = undefined; var tile; // For each tile in viewport... for (var j = 0; j < this.viewport.h; ++j) { for (var i = 0; i < this.viewport.w; ++i) { var ixx = i+xx, jyy = j+yy; // Check horizontal bounds if requested if (this.w && (ixx < 0 || ixx >= this.w)) { tile = ut.NULLTILE; // Check vertical bounds if requested } else if (this.h && (jyy < 0 || jyy >= this.w)) { tile = ut.NULLTILE; // Check mask } else if (this.maskFunc && !this.maskFunc(ixx, jyy)) { tile = ut.NULLTILE; // Check transition effect } else if (this.transition && !this.refreshCache) { tile = this.transition(i, j, this.viewport.w, this.viewport.h, this.tileFunc(ixx, jyy), this.tileCache[j][i], transTime); // Check cache } else if (this.cacheEnabled && !this.refreshCache) { var lookupx = ixx - this.cachex; var lookupy = jyy - this.cachey; if (lookupx >= 0 && lookupx < this.viewport.w && lookupy >= 0 && lookupy < this.viewport.h) { tile = this.tileCache[lookupy][lookupx];Avoid deeply nested control flow statements. if (tile === ut.NULLTILE) tile = this.tileFunc(ixx, jyy); } else // Cache miss tile = this.tileFunc(ixx, jyy); // If all else fails, call tileFunc } else tile = this.tileFunc(ixx, jyy); // Save the tile to cache (always due to transition effects) this.tileCache2[j][i] = tile; // Apply shader function if (this.shaderFunc && tile !== ut.NULLTILE) tile = this.shaderFunc(tile, ixx, jyy, timeNow); // Put shaded tile to viewport this.viewport.unsafePut(tile, i, j); } } // Cache stuff is enabled always, because it is also required by transitions // Save the new cache origin this.cachex = xx; this.cachey = yy; // Swap cache buffers var tempCache = this.tileCache; this.tileCache = this.tileCache2; this.tileCache2 = tempCache; this.refreshCache = false; };