diff --git a/Makefile b/Makefile index 6219e160..35964f4a 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,8 @@ SOURCES = src/rot.js \ src/lighting.js \ src/path/path.js \ src/path/dijkstra.js \ - src/path/astar.js + src/path/astar.js \ + src/image/image.js NODE_VERSION = "$(shell head -1 < NODE_VERSION)" NODE_PRE_SOURCES = node/node-shim.js diff --git a/README.md b/README.md index 66c46356..d0cddbb5 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,39 @@ -rot.js -====== +rot.js _(with ASCIIart support)_ +================================ -ROguelike Toolkit in JavaScript. For more info, see http://ondras.github.com/rot.js. +**RO**guelike **T**oolkit in **J**ava**S**cript. For more info, see https://github.com/mdtrooper/rot.js. To install `rot.js`, pick one: - clone this repository to gain full source code access; - - download just the [minified rot.min.js file](https://github.com/ondras/rot.js/blob/master/rot.min.js) to include it in your project; + - download just the [minified rot.min.js file](https://github.com/mdtrooper/rot.js/blob/master/rot.min.js) to include it in your project; - use `bower install rot.js`, if you prefer Bower for package management; RogueBasin page (with links to some rot.js-based games): http://www.roguebasin.roguelikedevelopment.org/index.php?title=Rot.js + +ASCIIart support +---------------- +This fork has a support for [ASCIIart (link to wikipedia)](http://en.wikipedia.org/wiki/ASCII_art) for you use the image files in native format (jpg, png…) and the game shows a pretty ASCIIart. + +It is very easy to use. + +```javascript +var image = new ROT.Image(); + +image.strResolution = "medium"; +image.bBlock = false; +image.load("combat.png"); + +var display = new ROT.Display({width:w, height:h, fontSize:10}); + +image.paint(display, 0, 0); +``` + +The image methods are: +* load(url): get a image from url and convert to ASCIIart. +* blit(display, display_x, display_y, image_x, image_y, rect_w, rect_h): paint a part of ASCIIart into the display. +* paint(display, offset_x, offset_y): paint the entire ASCIIart into a position in the display. + +And the config attributes are: +* bBlock: for to paint blocks instead characters. +* bColor: ASCIIart in color or not. +* strResolution: (low, medium, high) the ASCII art resolution. diff --git a/examples/combat.html b/examples/combat.html new file mode 100644 index 00000000..2ff5fad3 --- /dev/null +++ b/examples/combat.html @@ -0,0 +1,35 @@ + + + test + + + + + + + + + + \ No newline at end of file diff --git a/examples/combat.png b/examples/combat.png new file mode 100644 index 00000000..286e34de Binary files /dev/null and b/examples/combat.png differ diff --git a/examples/src b/examples/src new file mode 120000 index 00000000..e057607e --- /dev/null +++ b/examples/src @@ -0,0 +1 @@ +../src/ \ No newline at end of file diff --git a/examples/title.html b/examples/title.html new file mode 100644 index 00000000..557297ae --- /dev/null +++ b/examples/title.html @@ -0,0 +1,34 @@ + + + test + + + + + + + + + + \ No newline at end of file diff --git a/examples/title.png b/examples/title.png new file mode 100644 index 00000000..2b555d98 Binary files /dev/null and b/examples/title.png differ diff --git a/rot.js b/rot.js index 79df9a8e..3280624d 100644 --- a/rot.js +++ b/rot.js @@ -1,6 +1,6 @@ /* This is rot.js, the ROguelike Toolkit in JavaScript. - Version 0.7~dev, generated on Tue Aug 30 12:08:59 CEST 2016. + Version 0.7~dev, generated on mié nov 2 00:54:29 CET 2016. */ /** * @namespace Top-level ROT namespace @@ -1712,6 +1712,17 @@ ROT.EventQueue.prototype.get = function() { return this._events.splice(0, 1)[0]; } +/** + * Get the time associated with the given event + * @param {?} event + * @returns {number} time + */ +ROT.EventQueue.prototype.getEventTime = function(event) { + var index = this._events.indexOf(event); + if (index == -1) { return undefined } + return this._eventTimes[index]; +} + /** * Remove an event from the queue * @param {?} event @@ -1757,6 +1768,15 @@ ROT.Scheduler.prototype.add = function(item, repeat) { return this; } +/** + * Get the time the given item is scheduled for + * @param {?} item + * @returns {number} time + */ +ROT.Scheduler.prototype.getTimeOf = function(item) { + return this._queue.getEventTime(item); +} + /** * Clear all items */ @@ -1829,10 +1849,11 @@ ROT.Scheduler.Speed.extend(ROT.Scheduler); /** * @param {object} item anything with "getSpeed" method * @param {bool} repeat + * @param {number} [time=1/item.getSpeed()] * @see ROT.Scheduler#add */ -ROT.Scheduler.Speed.prototype.add = function(item, repeat) { - this._queue.add(item, 1/item.getSpeed()); +ROT.Scheduler.Speed.prototype.add = function(item, repeat, time) { + this._queue.add(item, time !== undefined ? time : 1/item.getSpeed()); return ROT.Scheduler.prototype.add.call(this, item, repeat); } @@ -5305,3 +5326,204 @@ ROT.Path.AStar.prototype._distance = function(x, y) { throw new Error("Illegal topology"); } +/** + * @class Base image (as ASCII art) converter + */ + + //BASED IN THE WORK OF: + /* + * jsAscii 0.1 + * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/ + * MIT License [http://www.nihilogic.dk/licenses/mit-license.txt] + */ +ROT.Image = function() { + this.aDefaultCharList = (" .,:;i1tfLCG08@").split(""); + this.aDefaultColorCharList = (" CGO08@").split(""); + this.strFont = "courier new"; + this.bBlock = true; + this.bAlpha = false; + this.bColor = true; + this.strResolution = "medium"; + + this.ascii_art = ""; + this.ascii_art_array = null; + this.height = 0; + this.width = 0; +}; + +ROT.Image.prototype.loadASCII = function() { + var aCharList = this.aDefaultCharList; + var bBlock = this.bBlock; + var bAlpha = this.bAlpha; + var bColor = this.bColor; + + var oCanvas = document.createElement("canvas"); + if (!oCanvas.getContext) { + return; + } + var oCtx = oCanvas.getContext("2d"); + if (!oCtx.getImageData) { + return; + } + + var strResolution = this.strResolution; + + var fResolution = 0.5; + + switch (strResolution) { + case "low" : fResolution = 0.25; break; + case "medium" : fResolution = 0.5; break; + case "high" : fResolution = 1; break; + } + + var iWidth = Math.round(parseInt(this.img.width) * fResolution); + var iHeight = Math.round(parseInt(this.img.height) * fResolution); + this.width = iWidth; + this.height = iHeight; + + oCanvas.width = iWidth; + oCanvas.height = iHeight; + //oCanvas.style.display = "none"; + oCanvas.style.width = iWidth; + oCanvas.style.height = iHeight; + + oCtx.drawImage(this.img, 0, 0, iWidth, iHeight); + + var oImgData = oCtx.getImageData(0, 0, iWidth, iHeight).data; + + var strChars = ""; + var array_chars = []; + + var iterator_y = 0; + for (var y=0;y" + strThisChar + ""; + + array_chars[iterator_y][x] = {'r': iRed, 'g' : iGreen, 'b' : iBlue, 'char': unscape_char}; + } + else { + strChars += strThisChar; + array_chars[iterator_y][x] = {'char': unscape_char}; + } + } + iterator_y++; + strChars += "
"; + } + + this.height = iterator_y; + + this.ascii_art_array = array_chars; + + return strChars; +}; + +ROT.Image.prototype.load = function(image_url, callback_load_complete) { + this.img = new Image(); + this.img.setAttribute('crossOrigin', ''); + this.img.src = image_url; + + var self = this; + + if (this.img.complete) { + this.ascii_art = this.loadASCII(); + + return true; + } + else { + this.img.onload = function() { + self.ascii_art = self.loadASCII(); + + if (typeof(callback_load_complete) != "undefined") + callback_load_complete(); + } + + return false; + } +}; + +ROT.Image.prototype.get = function(xin, yin) { + return this.ascii_art_array[yin][xin]; +}; + +ROT.Image.prototype.blit = function(display, display_x, display_y, image_x, image_y, rect_w, rect_h) { + var i = 0; + + for (var y = image_y; y < rect_h; y++) { + var j = 0; + for (var x = image_x; x < rect_w; x++) { + if (this.bColor) { + var color = "#" + + this.ascii_art_array[y][x]['r'].toString(16) + + this.ascii_art_array[y][x]['g'].toString(16) + + this.ascii_art_array[y][x]['b'].toString(16); + if (this.bBlock) { + display.draw(display_x + j, display_y + i, this.ascii_art_array[y][x]['char'], color, color); + } + else { + display.draw(display_x + j, display_y + i, this.ascii_art_array[y][x]['char'], color); + } + } + else { + display.draw(display_x + j, display_y + i, this.ascii_art_array[y][x]['char']); + } + j++; + } + i++; + } +}; + +ROT.Image.prototype.paint = function(display, offset_x, offset_y) { + var i = 0; + + for (var y = 0; y < this.height; y++) { + var j = 0; + for (var x = 0; x < this.width; x++) { + if (this.bColor) { + var color = "#" + + this.ascii_art_array[y][x]['r'].toString(16) + + this.ascii_art_array[y][x]['g'].toString(16) + + this.ascii_art_array[y][x]['b'].toString(16); + if (this.bBlock) { + display.draw(offset_x + j, offset_y + i, this.ascii_art_array[y][x]['char'], color, color); + } + else { + display.draw(offset_x + j, offset_y + i, this.ascii_art_array[y][x]['char'], color); + } + } + else { + display.draw(offset_x + j, offset_y + i, this.ascii_art_array[y][x]['char']); + } + j++; + } + i++; + } +}; \ No newline at end of file diff --git a/rot.min.js b/rot.min.js index cafd2161..9940312f 100644 --- a/rot.min.js +++ b/rot.min.js @@ -3,7 +3,7 @@ VK_HOME:36,VK_LEFT:37,VK_UP:38,VK_RIGHT:39,VK_DOWN:40,VK_PRINTSCREEN:44,VK_INSER VK_NUMPAD0:96,VK_NUMPAD1:97,VK_NUMPAD2:98,VK_NUMPAD3:99,VK_NUMPAD4:100,VK_NUMPAD5:101,VK_NUMPAD6:102,VK_NUMPAD7:103,VK_NUMPAD8:104,VK_NUMPAD9:105,VK_MULTIPLY:106,VK_ADD:107,VK_SEPARATOR:108,VK_SUBTRACT:109,VK_DECIMAL:110,VK_DIVIDE:111,VK_F1:112,VK_F2:113,VK_F3:114,VK_F4:115,VK_F5:116,VK_F6:117,VK_F7:118,VK_F8:119,VK_F9:120,VK_F10:121,VK_F11:122,VK_F12:123,VK_F13:124,VK_F14:125,VK_F15:126,VK_F16:127,VK_F17:128,VK_F18:129,VK_F19:130,VK_F20:131,VK_F21:132,VK_F22:133,VK_F23:134,VK_F24:135,VK_NUM_LOCK:144, VK_SCROLL_LOCK:145,VK_CIRCUMFLEX:160,VK_EXCLAMATION:161,VK_DOUBLE_QUOTE:162,VK_HASH:163,VK_DOLLAR:164,VK_PERCENT:165,VK_AMPERSAND:166,VK_UNDERSCORE:167,VK_OPEN_PAREN:168,VK_CLOSE_PAREN:169,VK_ASTERISK:170,VK_PLUS:171,VK_PIPE:172,VK_HYPHEN_MINUS:173,VK_OPEN_CURLY_BRACKET:174,VK_CLOSE_CURLY_BRACKET:175,VK_TILDE:176,VK_COMMA:188,VK_PERIOD:190,VK_SLASH:191,VK_BACK_QUOTE:192,VK_OPEN_BRACKET:219,VK_BACK_SLASH:220,VK_CLOSE_BRACKET:221,VK_QUOTE:222,VK_META:224,VK_ALTGR:225,VK_WIN:91,VK_KANA:21,VK_HANGUL:21, VK_EISU:22,VK_JUNJA:23,VK_FINAL:24,VK_HANJA:25,VK_KANJI:25,VK_CONVERT:28,VK_NONCONVERT:29,VK_ACCEPT:30,VK_MODECHANGE:31,VK_SELECT:41,VK_PRINT:42,VK_EXECUTE:43,VK_SLEEP:95,Text:{RE_COLORS:/%([bc]){([^}]*)}/g,TYPE_TEXT:0,TYPE_NEWLINE:1,TYPE_FG:2,TYPE_BG:3,measure:function(a,b){for(var c={width:0,height:1},d=this.tokenize(a,b),e=0,f=0;fb){for(g=-1;;){var h=f.value.indexOf(" ",g+1);if(-1==h)break;if(d+h>b)break;g=h}-1!=g?f.value=this._breakInsideToken(a,c,g,!0):-1!=e?(f=a[e],c=f.value.lastIndexOf(" "),f.value=this._breakInsideToken(a,e,c,!0),c= e):f.value=this._breakInsideToken(a,c,b-d,!1)}else d+=f.value.length,-1!=f.value.indexOf(" ")&&(e=c);c++}else a.splice(c,1)}}a.push({type:ROT.Text.TYPE_NEWLINE});d=null;for(c=0;cthis._options.order?a=a.slice(-this._options.order):a.lengthb){c=d;break}this._events.splice(c,0,a);this._eventTimes.splice(c,0,b)};ROT.EventQueue.prototype.get=function(){if(!this._events.length)return null;var a=this._eventTimes.splice(0,1)[0];if(0q;q++)if(g=e+2*n[q][0],h=f+2*n[q][1],this._isFree(d,g,h,b,c)){d[g][h]=0;d[e+n[q][0]][f+n[q][1]]= @@ -115,7 +116,7 @@ ROT.Map.Feature.Corridor.prototype.isValid=function(a,b){var c=this._startX,d=th e,this._endY+f);return(c||h)&&this._endsWithAWall?!1:!0};ROT.Map.Feature.Corridor.prototype.create=function(a){var b=this._startX,c=this._startY,d=this._endX-b,e=this._endY-c,f=1+Math.max(Math.abs(d),Math.abs(e));d&&(d/=Math.abs(d));e&&(e/=Math.abs(e));for(var g=0;gr?(t=1,u=0):(t=0,u=1);var w=p-t+f,x=r-u+f,n=p-1+2*f,f=r-1+2*f,q=q.mod(e),e=m.mod(e),v=.5-p*p-r*r;0<=v&&(v*=v,m=d[q+c[e]],m=this._gradients[m],g=v*v*(m[0]*p+m[1]*r));p=.5-w*w-x*x;0<=p&&(p*=p,m=d[q+t+c[e+u]],m=this._gradients[m],h=p*p*(m[0]*w+m[1]*x));p=.5-n*n-f*f;0<=p&&(p*=p,m=d[q+1+c[e+1]], +ROT.Noise.Simplex.prototype.get=function(a,b){var c=this._perms,d=this._indexes,e=c.length/2,f=this._G2,g=0,h=0,l=0,m,n=(a+b)*this._F2,q=Math.floor(a+n);m=Math.floor(b+n);var n=(q+m)*f,p=a-(q-n),r=b-(m-n),t,u;p>r?(t=1,u=0):(t=0,u=1);var x=p-t+f,v=r-u+f,n=p-1+2*f,f=r-1+2*f,q=q.mod(e),e=m.mod(e),w=.5-p*p-r*r;0<=w&&(w*=w,m=d[q+c[e]],m=this._gradients[m],g=w*w*(m[0]*p+m[1]*r));p=.5-x*x-v*v;0<=p&&(p*=p,m=d[q+t+c[e+u]],m=this._gradients[m],h=p*p*(m[0]*x+m[1]*v));p=.5-n*n-f*f;0<=p&&(p*=p,m=d[q+1+c[e+1]], m=this._gradients[m],l=p*p*(m[0]*n+m[1]*f));return 70*(g+h+l)};ROT.FOV=function(a,b){this._lightPasses=a;this._options={topology:8};for(var c in b)this._options[c]=b[c]};ROT.FOV.prototype.compute=function(a,b,c,d){}; ROT.FOV.prototype._getCircle=function(a,b,c){var d=[],e,f,g;switch(this._options.topology){case 4:f=1;g=[0,1];e=[ROT.DIRS[8][7],ROT.DIRS[8][1],ROT.DIRS[8][3],ROT.DIRS[8][5]];break;case 6:e=ROT.DIRS[6];f=1;g=[-1,1];break;case 8:e=ROT.DIRS[4],f=2,g=[-1,1]}a+=g[0]*c;b+=g[1]*c;for(g=0;g=q;){var q=q+1,u=a+q*g+p*h,w=b+q*l+p*m,x=(q-.5)/(p+.5),v=(q+.5)/(p-.5);if(!(v>d)){if(x=q;){var q=q+1,u=a+q*g+p*h,x=b+q*l+p*m,v=(q-.5)/(p+.5),w=(q+.5)/(p-.5);if(!(w>d)){if(vc;c++)b[c+1]+=16*b[c],b.splice(c,1);else b=(c=a.match(/rgb\(([0-9, ]+)\)/i))?c[1].split(/\s*,\s*/).map(function(a){return parseInt(a)}):[0,0,0];this._cache[a]=b}return b.slice()},add:function(a,b){for(var c=a.slice(),d=0;3>d;d++)for(var e=1;ec;c++)for(var d=1;dd;d++){for(var e=1;ec;c++){for(var d=1;darguments.length&&(c=.5);for(var d=a.slice(),e=0;3>e;e++)d[e]= Math.round(d[e]+c*(b[e]-a[e]));return d},interpolateHSL:function(a,b,c){3>arguments.length&&(c=.5);for(var d=this.rgb2hsl(a),e=this.rgb2hsl(b),f=0;3>f;f++)d[f]+=c*(e[f]-d[f]);return this.hsl2rgb(d)},randomize:function(a,b){b instanceof Array||(b=Math.round(ROT.RNG.getNormal(0,b)));for(var c=a.slice(),d=0;3>d;d++)c[d]+=b instanceof Array?Math.round(ROT.RNG.getNormal(0,b[d])):b;return c},rgb2hsl:function(a){var b=a[0]/255,c=a[1]/255;a=a[2]/255;var d=Math.max(b,c,a),e=Math.min(b,c,a),f,g=(d+e)/2;if(d== @@ -151,3 +152,9 @@ ROT.Path.Dijkstra.prototype._add=function(a,b,c){c={x:a,y:b,prev:c};this._comput ROT.Path.AStar.prototype.compute=function(a,b,c){this._todo=[];this._done={};this._fromX=a;this._fromY=b;for(this._add(this._toX,this._toY,null);this._todo.length;){var d=this._todo.shift();if(d.x==a&&d.y==b)break;for(var e=this._getNeighbors(d.x,d.y),f=0;f"+v+"",l[m][q]={r:r,g:t,b:u,"char":w}):(f+=v,l[m][q]={"char":w})}m++;f+="
"}this.height=m;this.ascii_art_array= +l;return f}}};ROT.Image.prototype.load=function(a,b){this.img=new Image;this.img.setAttribute("crossOrigin","");this.img.src=a;var c=this;if(this.img.complete)return this.ascii_art=this.loadASCII(),!0;this.img.onload=function(){c.ascii_art=c.loadASCII();"undefined"!=typeof b&&b()};return!1};ROT.Image.prototype.get=function(a,b){return this.ascii_art_array[b][a]}; +ROT.Image.prototype.blit=function(a,b,c,d,e,f,g){for(var h=0;e" + strThisChar + ""; + + array_chars[iterator_y][x] = {'r': iRed, 'g' : iGreen, 'b' : iBlue, 'char': unscape_char}; + } + else { + strChars += strThisChar; + array_chars[iterator_y][x] = {'char': unscape_char}; + } + } + iterator_y++; + strChars += "
"; + } + + this.height = iterator_y; + + this.ascii_art_array = array_chars; + + return strChars; +}; + +ROT.Image.prototype.load = function(image_url, callback_load_complete) { + this.img = new Image(); + this.img.setAttribute('crossOrigin', ''); + this.img.src = image_url; + + var self = this; + + if (this.img.complete) { + this.ascii_art = this.loadASCII(); + + return true; + } + else { + this.img.onload = function() { + self.ascii_art = self.loadASCII(); + + if (typeof(callback_load_complete) != "undefined") + callback_load_complete(); + } + + return false; + } +}; + +ROT.Image.prototype.get = function(xin, yin) { + return this.ascii_art_array[yin][xin]; +}; + +ROT.Image.prototype.blit = function(display, display_x, display_y, image_x, image_y, rect_w, rect_h) { + var i = 0; + + for (var y = image_y; y < rect_h; y++) { + var j = 0; + for (var x = image_x; x < rect_w; x++) { + if (this.bColor) { + var color = "#" + + this.ascii_art_array[y][x]['r'].toString(16) + + this.ascii_art_array[y][x]['g'].toString(16) + + this.ascii_art_array[y][x]['b'].toString(16); + if (this.bBlock) { + display.draw(display_x + j, display_y + i, this.ascii_art_array[y][x]['char'], color, color); + } + else { + display.draw(display_x + j, display_y + i, this.ascii_art_array[y][x]['char'], color); + } + } + else { + display.draw(display_x + j, display_y + i, this.ascii_art_array[y][x]['char']); + } + j++; + } + i++; + } +}; + +ROT.Image.prototype.paint = function(display, offset_x, offset_y) { + var i = 0; + + for (var y = 0; y < this.height; y++) { + var j = 0; + for (var x = 0; x < this.width; x++) { + if (this.bColor) { + var color = "#" + + this.ascii_art_array[y][x]['r'].toString(16) + + this.ascii_art_array[y][x]['g'].toString(16) + + this.ascii_art_array[y][x]['b'].toString(16); + if (this.bBlock) { + display.draw(offset_x + j, offset_y + i, this.ascii_art_array[y][x]['char'], color, color); + } + else { + display.draw(offset_x + j, offset_y + i, this.ascii_art_array[y][x]['char'], color); + } + } + else { + display.draw(offset_x + j, offset_y + i, this.ascii_art_array[y][x]['char']); + } + j++; + } + i++; + } +}; \ No newline at end of file