├── LICENSE ├── README.md ├── build ├── indexed.js ├── indexed.min.js ├── jsmin │ ├── __init__.py │ ├── __init__.pyc │ └── __main__.py ├── libs │ ├── playground-base.min.js │ └── twgl.min.js └── make.ps1 ├── examples ├── data │ └── basic.pal ├── drawing.html ├── images │ ├── glue.pcx │ ├── grad.pcx │ ├── lena.pcx │ ├── o1.pcx │ ├── pixelfont.pcx │ ├── shootemup.pcx │ ├── slices.pcx │ └── testsprite.pcx ├── index.php ├── lena.html ├── shootemup.html ├── somesprites.html └── sounds │ ├── enemy.ogg │ ├── explosion.ogg │ ├── hit.ogg │ ├── music.ogg │ └── shoot.ogg └── src └── indexed.render.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Diego F. Goberna 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Indexed 2 | (work in progress!) 3 | 4 | Javascript game framework emulating old 8-bit indexed color mode 5 | 6 | It supports both canvas 2D and WebGL (default, using __twgl__). 7 | 8 | Only PCX indexed image format supported yet, and PAL for palettes. 9 | 10 | * src/__indexed.render.js__: core classes for drawing: Stage, Buffer, Palette 11 | * __build__ folder: library packed together with playground and twgl 12 | 13 | Live examples: http://feiss.be/exp/indexed/examples/ 14 | 15 | MIT Licensed. [playground](http://github.com/rezoner/playground) by @rezoner, 16 | [twgl](http://github.com/greggman/twgl.js) by @greggman. 17 | 18 | Thanks to the above authors and Javier Campos for optimization tips. 19 | -------------------------------------------------------------------------------- /build/indexed.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/build/indexed.js -------------------------------------------------------------------------------- /build/indexed.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/build/indexed.min.js -------------------------------------------------------------------------------- /build/jsmin/__init__.py: -------------------------------------------------------------------------------- 1 | # This code is original from jsmin by Douglas Crockford, it was translated to 2 | # Python by Baruch Even. It was rewritten by Dave St.Germain for speed. 3 | # 4 | # The MIT License (MIT) 5 | # 6 | # Copyright (c) 2013 Dave St.Germain 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in 16 | # all copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | # THE SOFTWARE. 25 | 26 | 27 | import sys 28 | is_3 = sys.version_info >= (3, 0) 29 | if is_3: 30 | import io 31 | else: 32 | import StringIO 33 | try: 34 | import cStringIO 35 | except ImportError: 36 | cStringIO = None 37 | 38 | 39 | __all__ = ['jsmin', 'JavascriptMinify'] 40 | __version__ = '2.0.11' 41 | 42 | 43 | def jsmin(js): 44 | """ 45 | returns a minified version of the javascript string 46 | """ 47 | if not is_3: 48 | if cStringIO and not isinstance(js, unicode): 49 | # strings can use cStringIO for a 3x performance 50 | # improvement, but unicode (in python2) cannot 51 | klass = cStringIO.StringIO 52 | else: 53 | klass = StringIO.StringIO 54 | else: 55 | klass = io.StringIO 56 | ins = klass(js) 57 | outs = klass() 58 | JavascriptMinify(ins, outs).minify() 59 | return outs.getvalue() 60 | 61 | 62 | class JavascriptMinify(object): 63 | """ 64 | Minify an input stream of javascript, writing 65 | to an output stream 66 | """ 67 | 68 | def __init__(self, instream=None, outstream=None): 69 | self.ins = instream 70 | self.outs = outstream 71 | 72 | def minify(self, instream=None, outstream=None): 73 | if instream and outstream: 74 | self.ins, self.outs = instream, outstream 75 | 76 | self.is_return = False 77 | self.return_buf = '' 78 | 79 | def write(char): 80 | # all of this is to support literal regular expressions. 81 | # sigh 82 | if char in 'return': 83 | self.return_buf += char 84 | self.is_return = self.return_buf == 'return' 85 | self.outs.write(char) 86 | if self.is_return: 87 | self.return_buf = '' 88 | 89 | read = self.ins.read 90 | 91 | space_strings = "abcdefghijklmnopqrstuvwxyz"\ 92 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$\\" 93 | starters, enders = '{[(+-', '}])+-"\'' 94 | newlinestart_strings = starters + space_strings 95 | newlineend_strings = enders + space_strings 96 | do_newline = False 97 | do_space = False 98 | escape_slash_count = 0 99 | doing_single_comment = False 100 | previous_before_comment = '' 101 | doing_multi_comment = False 102 | in_re = False 103 | in_quote = '' 104 | quote_buf = [] 105 | 106 | previous = read(1) 107 | if previous == '\\': 108 | escape_slash_count += 1 109 | next1 = read(1) 110 | if previous == '/': 111 | if next1 == '/': 112 | doing_single_comment = True 113 | elif next1 == '*': 114 | doing_multi_comment = True 115 | previous = next1 116 | next1 = read(1) 117 | else: 118 | in_re = True # literal regex at start of script 119 | write(previous) 120 | elif not previous: 121 | return 122 | elif previous >= '!': 123 | if previous in "'\"": 124 | in_quote = previous 125 | write(previous) 126 | previous_non_space = previous 127 | else: 128 | previous_non_space = ' ' 129 | if not next1: 130 | return 131 | 132 | while 1: 133 | next2 = read(1) 134 | if not next2: 135 | last = next1.strip() 136 | if not (doing_single_comment or doing_multi_comment)\ 137 | and last not in ('', '/'): 138 | if in_quote: 139 | write(''.join(quote_buf)) 140 | write(last) 141 | break 142 | if doing_multi_comment: 143 | if next1 == '*' and next2 == '/': 144 | doing_multi_comment = False 145 | if previous_before_comment and previous_before_comment in space_strings: 146 | do_space = True 147 | next2 = read(1) 148 | elif doing_single_comment: 149 | if next1 in '\r\n': 150 | doing_single_comment = False 151 | while next2 in '\r\n': 152 | next2 = read(1) 153 | if not next2: 154 | break 155 | if previous_before_comment in ')}]': 156 | do_newline = True 157 | elif previous_before_comment in space_strings: 158 | write('\n') 159 | elif in_quote: 160 | quote_buf.append(next1) 161 | 162 | if next1 == in_quote: 163 | numslashes = 0 164 | for c in reversed(quote_buf[:-1]): 165 | if c != '\\': 166 | break 167 | else: 168 | numslashes += 1 169 | if numslashes % 2 == 0: 170 | in_quote = '' 171 | write(''.join(quote_buf)) 172 | elif next1 in '\r\n': 173 | if previous_non_space in newlineend_strings \ 174 | or previous_non_space > '~': 175 | while 1: 176 | if next2 < '!': 177 | next2 = read(1) 178 | if not next2: 179 | break 180 | else: 181 | if next2 in newlinestart_strings \ 182 | or next2 > '~' or next2 == '/': 183 | do_newline = True 184 | break 185 | elif next1 < '!' and not in_re: 186 | if (previous_non_space in space_strings \ 187 | or previous_non_space > '~') \ 188 | and (next2 in space_strings or next2 > '~'): 189 | do_space = True 190 | elif previous_non_space in '-+' and next2 == previous_non_space: 191 | # protect against + ++ or - -- sequences 192 | do_space = True 193 | elif self.is_return and next2 == '/': 194 | # returning a regex... 195 | write(' ') 196 | elif next1 == '/': 197 | if do_space: 198 | write(' ') 199 | if in_re: 200 | if previous != '\\' or (not escape_slash_count % 2) or next2 in 'gimy': 201 | in_re = False 202 | write('/') 203 | elif next2 == '/': 204 | doing_single_comment = True 205 | previous_before_comment = previous_non_space 206 | elif next2 == '*': 207 | doing_multi_comment = True 208 | previous_before_comment = previous_non_space 209 | previous = next1 210 | next1 = next2 211 | next2 = read(1) 212 | else: 213 | in_re = previous_non_space in '(,=:[?!&|;' or self.is_return # literal regular expression 214 | write('/') 215 | else: 216 | if do_space: 217 | do_space = False 218 | write(' ') 219 | if do_newline: 220 | write('\n') 221 | do_newline = False 222 | 223 | write(next1) 224 | if not in_re and next1 in "'\"": 225 | in_quote = next1 226 | quote_buf = [] 227 | 228 | previous = next1 229 | next1 = next2 230 | 231 | if previous >= '!': 232 | previous_non_space = previous 233 | 234 | if previous == '\\': 235 | escape_slash_count += 1 236 | else: 237 | escape_slash_count = 0 238 | -------------------------------------------------------------------------------- /build/jsmin/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/build/jsmin/__init__.pyc -------------------------------------------------------------------------------- /build/jsmin/__main__.py: -------------------------------------------------------------------------------- 1 | import sys, os, glob 2 | from jsmin import JavascriptMinify 3 | 4 | for f in sys.argv[1:]: 5 | with open(f, 'r') as js: 6 | minifier = JavascriptMinify(js, sys.stdout) 7 | minifier.minify() 8 | sys.stdout.write('\n') 9 | 10 | 11 | -------------------------------------------------------------------------------- /build/libs/playground-base.min.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/build/libs/playground-base.min.js -------------------------------------------------------------------------------- /build/libs/twgl.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license twgl.js 0.0.28 Copyright (c) 2015, Gregg Tavares All Rights Reserved. 3 | * Available via the MIT license. 4 | * see: http://github.com/greggman/twgl.js for details 5 | */ 6 | /** 7 | * @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. 8 | * Available via the MIT or new BSD license. 9 | * see: http://github.com/jrburke/almond for details 10 | */ 11 | !function(a,b){"function"==typeof define&&define.amd?define([],b):a.twgl=b()}(this,function(){var a,b,c;return function(d){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.slice(0,n.length-1).concat(a),k=0;k0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,b){return function(){var c=v.call(arguments,0);return"string"!=typeof c[0]&&1===c.length&&c.push(null),n.apply(d,c.concat([a,b]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var b=r[a];delete r[a],t[a]=!0,m.apply(d,b)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,b,c,f){var h,k,l,m,n,s,u=[],v=typeof c;if(f=f||a,"undefined"===v||"function"===v){for(b=!b.length&&c.length?["require","exports","module"]:b,n=0;n1&&"[0]"===c.name.substr(-3);if(f===a.FLOAT&&g)return function(b){a.uniform1fv(e,b)};if(f===a.FLOAT)return function(b){a.uniform1f(e,b)};if(f===a.FLOAT_VEC2)return function(b){a.uniform2fv(e,b)};if(f===a.FLOAT_VEC3)return function(b){a.uniform3fv(e,b)};if(f===a.FLOAT_VEC4)return function(b){a.uniform4fv(e,b)};if(f===a.INT&&g)return function(b){a.uniform1iv(e,b)};if(f===a.INT)return function(b){a.uniform1i(e,b)};if(f===a.INT_VEC2)return function(b){a.uniform2iv(e,b)};if(f===a.INT_VEC3)return function(b){a.uniform3iv(e,b)};if(f===a.INT_VEC4)return function(b){a.uniform4iv(e,b)};if(f===a.BOOL&&g)return function(b){a.uniform1iv(e,b)};if(f===a.BOOL)return function(b){a.uniform1i(e,b)};if(f===a.BOOL_VEC2)return function(b){a.uniform2iv(e,b)};if(f===a.BOOL_VEC3)return function(b){a.uniform3iv(e,b)};if(f===a.BOOL_VEC4)return function(b){a.uniform4iv(e,b)};if(f===a.FLOAT_MAT2)return function(b){a.uniformMatrix2fv(e,!1,b)};if(f===a.FLOAT_MAT3)return function(b){a.uniformMatrix3fv(e,!1,b)};if(f===a.FLOAT_MAT4)return function(b){a.uniformMatrix4fv(e,!1,b)};if((f===a.SAMPLER_2D||f===a.SAMPLER_CUBE)&&g){for(var h=[],i=0;ig;++g){var h=a.getActiveUniform(b,g);if(!h)break;var i=h.name;"[0]"===i.substr(-3)&&(i=i.substr(0,i.length-3));var j=c(b,h);e[i]=j}return e}function m(a,b){a=a.uniformSetters||a;for(var c=arguments.length,d=1;c>d;++d){var e=arguments[d];if(Array.isArray(e))for(var f=e.length,g=0;f>g;++g)m(a,e[g]);else for(var h in e){var i=a[h];i&&i(e[h])}}}function n(a,b){function c(b){return function(c){a.bindBuffer(a.ARRAY_BUFFER,c.buffer),a.enableVertexAttribArray(b),a.vertexAttribPointer(b,c.numComponents||c.size,c.type||a.FLOAT,c.normalize||!1,c.stride||0,c.offset||0)}}for(var d={},e=a.getProgramParameter(b,a.ACTIVE_ATTRIBUTES),f=0;e>f;++f){var g=a.getActiveAttrib(b,f);if(!g)break;var h=a.getAttribLocation(b,g.name);d[g.name]=c(h)}return d}function o(a,b){for(var c in b){var d=a[c];d&&d(b[c])}}function p(a,b,c){o(b.attribSetters||b,c.attribs),c.indices&&a.bindBuffer(a.ELEMENT_ARRAY_BUFFER,c.indices)}function q(a,b,c,d,e){b=b.map(function(a){var b=document.getElementById(a);return b?b.text:a});var f=j(a,b,c,d,e);if(!f)return null;var g=l(a,f),h=n(a,f);return{program:f,uniformSetters:g,attribSetters:h}}function r(a,b){b=b||1,b=Math.max(1,b);var c=a.clientWidth*b|0,d=a.clientHeight*b|0;return a.width!==c||a.height!==d?(a.width=c,a.height=d,!0):!1}function s(a,b,c,d){if(b instanceof WebGLBuffer)return b;c=c||a.ARRAY_BUFFER;var e=a.createBuffer();return a.bindBuffer(c,e),a.bufferData(c,b,d||a.STATIC_DRAW),e}function t(a){return"indices"===a}function u(a){if(a instanceof Int8Array)return ha;if(a instanceof Uint8Array)return ia;if(a instanceof Int16Array)return ja;if(a instanceof Uint16Array)return ka;if(a instanceof Int32Array)return la;if(a instanceof Uint32Array)return ma;if(a instanceof Float32Array)return na;throw"unsupported typed array type"}function v(a,b){switch(b){case a.BYTE:return Int8Array;case a.UNSIGNED_BYTE:return Uint8Array;case a.SHORT:return Int16Array;case a.UNSIGNED_SHORT:return Uint16Array;case a.INT:return Int32Array;case a.UNSIGNED_INT:return Uint32Array;case a.FLOAT:return Float32Array;default:throw"unknown gl type"}}function w(a){return a instanceof Int8Array?!0:a instanceof Uint8Array?!0:!1}function x(a){return a&&a.buffer&&a.buffer instanceof ArrayBuffer}function y(a,b){var c;if(c=a.indexOf("coord")>=0?2:a.indexOf("color")>=0?4:3,b%c>0)throw"can not guess numComponents. You should specify it.";return c}function z(a,b){if(x(a))return a;if(x(a.data))return a.data;Array.isArray(a)&&(a={data:a});var c=a.type;return c||(c="indices"===b?Uint16Array:Float32Array),new c(a.data)}function A(a,b){var c={};return Object.keys(b).forEach(function(d){if(!t(d)){var e=b[d],f=e.attrib||e.name||e.attribName||ea+d,g=z(e,d);c[f]={buffer:s(a,g,void 0,e.drawType),numComponents:e.numComponents||e.size||y(d),type:u(g),normalize:void 0!==e.normalize?e.normalize:w(g),stride:e.stride||0,offset:e.offset||0}}}),c}function B(a,b){var c={attribs:A(a,b)},d=b.indices;return d?(d=z(d,"indices"),c.indices=s(a,d,a.ELEMENT_ARRAY_BUFFER),c.numElements=d.length,c.elementType=d instanceof Uint32Array?a.UNSIGNED_INT:a.UNSIGNED_SHORT):c.numElements=Ja(b),c}function C(a,b){var c={};return Object.keys(b).forEach(function(d){var e="indices"===d?a.ELEMENT_ARRAY_BUFFER:a.ARRAY_BUFFER,f=z(b[d],d);c[d]=s(a,f,e)}),c}function D(a,b,c,d,e){var f=c.indices,g=void 0===d?c.numElements:d;e=void 0===e?0:e,f?a.drawElements(b,g,void 0===c.elementType?a.UNSIGNED_SHORT:c.elementType,e):a.drawArrays(b,e,g)}function E(a,b){var c=null,d=null;b.forEach(function(b){if(b.active!==!1){var e=b.programInfo,f=b.bufferInfo,g=!1;e!==c&&(c=e,a.useProgram(e.program),g=!0),(g||f!==d)&&(d=f,p(a,e,f)),m(e,b.uniforms),D(a,b.type||a.TRIANGLES,f,b.count,b.offset)}})}function F(a,b){void 0!==b.colorspaceConversion&&(Ka.colorSpaceConversion=a.getParameter(a.UNPACK_COLORSPACE_CONVERSION_WEBGL)),void 0!==b.premultiplyAlpha&&(Ka.premultiplyAlpha=a.getParameter(a.UNPACK_PREMULTIPLY_ALPHA_WEBGL)),void 0!==b.flipY&&(Ka.flipY=a.getParameter(a.UNPACK_FLIP_Y_WEBGL))}function G(a,b){void 0!==b.colorspaceConversion&&a.pixelStorei(a.UNPACK_COLORSPACE_CONVERSION_WEBGL,Ka.colorSpaceConversion),void 0!==b.premultiplyAlpha&&a.pixelStorei(a.UNPACK_PREMULTIPLY_ALPHA_WEBGL,Ka.premultiplyAlpha),void 0!==b.flipY&&a.pixelStorei(a.UNPACK_FLIP_Y_WEBGL,Ka.flipY)}function H(a,b,c){var d=c.target||a.TEXTURE_2D;a.bindTexture(d,b),c.min&&a.texParameteri(d,a.TEXTURE_MIN_FILTER,c.min),c.mag&&a.texParameteri(d,a.TEXTURE_MAG_FILTER,c.mag),c.wrap&&(a.texParameteri(d,a.TEXTURE_WRAP_S,c.wrap),a.texParameteri(d,a.TEXTURE_WRAP_T,c.wrap)),c.wrapS&&a.texParameteri(d,a.TEXTURE_WRAP_S,c.wrapS),c.wrapT&&a.texParameteri(d,a.TEXTURE_WRAP_T,c.wrapT)}function I(a){return a=a||fa,x(a)?a:new Uint8Array([255*a[0],255*a[1],255*a[2],255*a[3]])}function J(a){return 0===(a&a-1)}function K(a,b,c,d,e){c=c||ga;var f=c.target||a.TEXTURE_2D;d=d||c.width,e=e||c.height,a.bindTexture(f,b),J(d)&&J(e)?a.generateMipmap(f):(a.texParameteri(f,a.TEXTURE_MIN_FILTER,a.LINEAR),a.texParameteri(f,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(f,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE))}function L(a,b){return b=b||{},b.cubeFaceOrder||[a.TEXTURE_CUBE_MAP_POSITIVE_X,a.TEXTURE_CUBE_MAP_NEGATIVE_X,a.TEXTURE_CUBE_MAP_POSITIVE_Y,a.TEXTURE_CUBE_MAP_NEGATIVE_Y,a.TEXTURE_CUBE_MAP_POSITIVE_Z,a.TEXTURE_CUBE_MAP_NEGATIVE_Z]}function M(a,b){var c=L(a,b),d=c.map(function(a,b){return{face:a,ndx:b}});return d.sort(function(a,b){return a.face-b.face}),d}function N(a){var b={};return Object.keys(a).forEach(function(c){b[c]=a[c]}),b}function O(){}function P(a,b){b=b||O;var c=new Image;return c.onerror=function(){var d="couldn't load image: "+a;da(d),b(d,c)},c.onload=function(){b(null,c)},c.src=a,c}function Q(a,b,c){c=c||ga;var d=c.target||a.TEXTURE_2D;if(a.bindTexture(d,b),c.color!==!1){var e=I(c.color);if(d===a.TEXTURE_CUBE_MAP)for(var f=0;6>f;++f)a.texImage2D(a.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,a.RGBA,1,1,0,a.RGBA,a.UNSIGNED_BYTE,e);else a.texImage2D(d,0,a.RGBA,1,1,0,a.RGBA,a.UNSIGNED_BYTE,e)}}function R(a,b,c,d){d=d||O,c=c||ga,Q(a,b,c),c=N(c);var e=P(c.src,function(e,f){e?d(e,b,f):(La(a,b,f,c),d(null,b,f))});return e}function S(a,b,c,d){function e(e){return function(f,m){--k,f?l.push(f):m.width!==m.height?l.push("cubemap face img is not a square: "+m.src):(F(a,c),a.bindTexture(i,b),5===k?L(a).forEach(function(b){a.texImage2D(b,0,g,g,h,m)}):a.texImage2D(e,0,g,g,h,m),G(a,c),a.generateMipmap(i)),0===k&&d(l.length?l:void 0,j,b)}}d=d||O;var f=c.src;if(6!==f.length)throw"there must be 6 urls for a cubemap";var g=c.format||a.RGBA,h=c.type||a.UNSIGNED_BYTE,i=c.target||a.TEXTURE_2D;if(i!==a.TEXTURE_CUBE_MAP)throw"target must be TEXTURE_CUBE_MAP";Q(a,b,c),c=N(c);var j,k=6,l=[],m=L(a,c);j=f.map(function(a,b){return P(a,e(m[b]))})}function T(a){switch(a){case pa:case sa:return 1;case ta:return 2;case qa:return 3;case ra:return 4;default:throw"unknown type: "+a}}function U(a,b){return x(b)?u(b):a.UNSIGNED_BYTE}function V(a,b,c,d){d=d||ga;var e=d.target||a.TEXTURE_2D,f=d.width,g=d.height,h=d.format||a.RGBA,i=d.type||U(a,c),j=T(h),k=c.length/j;if(k%1)throw"length wrong size of format: "+Ha(a,h);if(f||g){if(g){if(!f&&(f=k/g,f%1))throw"can't guess width"}else if(g=k/f,g%1)throw"can't guess height"}else{var l=Math.sqrt(k/(e===a.TEXTURE_CUBE_MAP?6:1));l%1===0?(f=l,g=l):(f=k,g=1)}if(!x(c)){var m=v(a,i);c=new m(c)}if(a.pixelStorei(a.UNPACK_ALIGNMENT,d.unpackAlignment||1),F(a,d),e===a.TEXTURE_CUBE_MAP){var n=k/6*j;M(a,d).forEach(function(b){var d=n*b.ndx,e=c.subarray(d,d+n);a.texImage2D(b.face,0,h,f,g,0,h,i,e)})}else a.texImage2D(e,0,h,f,g,0,h,i,c);return G(a,d),{width:f,height:g}}function W(a,b,c){var d=c.target||a.TEXTURE_2D;a.bindTexture(d,b);var e=c.format||a.RGBA,f=c.type||a.UNSIGNED_BYTE;if(F(a,c),d===a.TEXTURE_CUBE_MAP)for(var g=0;6>g;++g)a.texImage2D(a.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,e,c.width,c.height,0,e,f,null);else a.texImage2D(d,0,e,c.width,c.height,0,e,f,null)}function X(a,b,c){c=c||O,b=b||ga;var d=a.createTexture(),e=b.target||a.TEXTURE_2D,f=b.width||1,g=b.height||1;a.bindTexture(e,d),e===a.TEXTURE_CUBE_MAP&&(a.texParameteri(e,a.TEXTURE_WRAP_S,a.CLAMP_TO_EDGE),a.texParameteri(e,a.TEXTURE_WRAP_T,a.CLAMP_TO_EDGE));var h=b.src;if(h)if("function"==typeof h&&(h=h(a,b)),"string"==typeof h)R(a,d,b,c);else if(x(h)||Array.isArray(h)&&("number"==typeof h[0]||Array.isArray(h[0])||x(h[0]))){var i=V(a,d,h,b);f=i.width,g=i.height}else if(Array.isArray(h)&&"string"==typeof h[0])S(a,d,b,c);else{if(!(h instanceof HTMLElement))throw"unsupported src type";La(a,d,h,b),f=h.width,g=h.height}else W(a,d,b);return b.auto!==!1&&K(a,d,b,f,g),H(a,d,b),d}function Y(a,b,c,d,e){d=d||c.width,e=e||c.height;var f=c.target||a.TEXTURE_2D;a.bindTexture(f,b);var g,h=c.format||a.RGBA,i=c.src;if(g=i&&(x(i)||Array.isArray(i)&&"number"==typeof i[0])?c.type||U(a,i):c.type||a.UNSIGNED_BYTE,f===a.TEXTURE_CUBE_MAP)for(var j=0;6>j;++j)a.texImage2D(a.TEXTURE_CUBE_MAP_POSITIVE_X+j,0,h,d,e,0,h,g,null);else a.texImage2D(f,0,h,d,e,0,h,g,null)}function Z(a){return"string"==typeof a||Array.isArray(a)&&"string"==typeof a[0]}function $(a,b,c){function d(){0===f&&setTimeout(function(){c(g.length?g:void 0,b)},0)}function e(a){--f,a&&g.push(a),d()}c=c||O;var f=0,g=[],h={};return Object.keys(b).forEach(function(c){var d=b[c],g=void 0;Z(d.src)&&(g=e,++f),h[c]=X(a,d,g)}),d(),h}function _(a){return Na[a]}function aa(a){return Oa[a]}function ba(a,b,c,d){var e=a.FRAMEBUFFER,f=a.createFramebuffer();a.bindFramebuffer(e,f),c=c||a.drawingBufferWidth,d=d||a.drawingBufferHeight,b=b||Ma;var g=0,h={framebuffer:f,attachments:[]};return b.forEach(function(b){var f=b.attachment,i=b.format,j=_(i);if(j||(j=Ba+g++),!f)if(aa(i))f=a.createRenderbuffer(),a.bindRenderbuffer(a.RENDERBUFFER,f),a.renderbufferStorage(a.RENDERBUFFER,i,c,d);else{var k=N(b);k.width=c,k.height=d,k.auto=void 0===b.auto?!1:b.auto,f=X(a,k)}if(f instanceof WebGLRenderbuffer)a.framebufferRenderbuffer(e,j,a.RENDERBUFFER,f);else{if(!(f instanceof WebGLTexture))throw"unknown attachment type";a.framebufferTexture2D(e,j,b.texTarget||a.TEXTURE_2D,f,b.level||0)}h.attachments.push(f)}),h}function ca(a,b,c,d,e){d=d||a.drawingBufferWidth,e=e||a.drawingBufferHeight,c=c||Ma,c.forEach(function(c,f){var g=b.attachments[f],h=c.format;if(g instanceof WebGLRenderbuffer)a.bindRenderbuffer(a.RENDERBUFFER,g),a.renderbufferStorage(a.RENDERBUFFER,h,d,e);else{if(!(g instanceof WebGLTexture))throw"unknown attachment type";Y(a,g,c,d,e)}})}var da=window.console&&window.console.error?window.console.error.bind(window.console):function(){},ea="",fa=new Uint8Array([128,192,255,255]),ga={},ha=5120,ia=5121,ja=5122,ka=5123,la=5124,ma=5125,na=5126,oa=6402,pa=6406,qa=6407,ra=6408,sa=6409,ta=6410,ua=32854,va=32855,wa=36194,xa=33189,ya=6401,za=36168,Aa=34041,Ba=36064,Ca=36096,Da=36128,Ea=33306,Fa=33071,Ga=9729,Ha=function(){function a(a){b||(b={},Object.keys(a).forEach(function(c){"number"==typeof a[c]&&(b[a[c]]=c)}))}var b;return function(c,d){return a(),b[d]||"0x"+d.toString(16)}}(),Ia=["VERTEX_SHADER","FRAGMENT_SHADER"],Ja=function(){var a=["position","positions","a_position"];return function(b){for(var c,d=0;d0)throw"numComponents "+g+" not correct for length "+f;return h}}(),Ka={},La=function(){var a=document.createElement("canvas").getContext("2d");return function(b,c,d,e){e=e||ga;var f=e.target||b.TEXTURE_2D,g=d.width,h=d.height,i=e.format||b.RGBA,j=e.type||b.UNSIGNED_BYTE;if(F(b,e),b.bindTexture(f,c),f===b.TEXTURE_CUBE_MAP){var k,l,m=d.width,n=d.height;if(m/6===n)k=n,l=[0,0,1,0,2,0,3,0,4,0,5,0];else if(n/6===m)k=m,l=[0,0,0,1,0,2,0,3,0,4,0,5];else if(m/3===n/2)k=m/3,l=[0,0,1,0,2,0,0,1,1,1,2,1];else{if(m/2!==n/3)throw"can't figure out cube map from element: "+(d.src?d.src:d.nodeName);k=m/2,l=[0,0,1,0,0,1,1,1,0,2,1,2]}a.canvas.width=k,a.canvas.height=k,g=k,h=k,M(b,e).forEach(function(c){var e=l[2*c.ndx+0]*k,f=l[2*c.ndx+1]*k;a.drawImage(d,e,f,k,k,0,0,k,k),b.texImage2D(c.face,0,i,i,j,a.canvas)}),a.canvas.width=1,a.canvas.height=1}else b.texImage2D(f,0,i,i,j,d);G(b,e),e.auto!==!1&&K(b,c,e,g,h),H(b,c,e)}}(),Ma=[{format:ra,type:ia,min:Ga,wrap:Fa},{format:Aa}],Na={};Na[Aa]=Ea,Na[ya]=Da,Na[za]=Da,Na[oa]=Ca,Na[xa]=Ca;var Oa={};return Oa[ua]=!0,Oa[va]=!0,Oa[wa]=!0,Oa[Aa]=!0,Oa[xa]=!0,Oa[ya]=!0,Oa[za]=!0,{createAttribsFromArrays:A,createBuffersFromArrays:C,createBufferInfoFromArrays:B,createAttributeSetters:n,createProgram:g,createProgramFromScripts:i,createProgramFromSources:j,createProgramInfo:q,createUniformSetters:l,drawBufferInfo:D,drawObjectList:E,getWebGLContext:d,resizeCanvasToDisplaySize:r,setAttributes:o,setAttributePrefix:b,setBuffersAndAttributes:p,setUniforms:m,createTexture:X,setEmptyTexture:W,setTextureFromArray:V,loadTextureFromUrl:R,setTextureFromElement:La,setTextureFilteringForSize:K,setTextureParameters:H,setDefaultTextureColor:a,createTextures:$,resizeTexture:Y,createFramebufferInfo:ba,resizeFramebufferInfo:ca}}),c("main",["twgl/twgl"],function(a){return a}),b(["main"],function(a){return a},void 0,!0),c("build/js/twgl-includer",function(){}),b("main")}); -------------------------------------------------------------------------------- /build/make.ps1: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "/** INDEXED 4 | *** indexed color mode for canvas, and powered by playground and twgl 5 | *** indexed module copyright 2015 Diego F. Goberna 6 | 7 | *** playground by rezoner (http://github.com/rezoner/playground) 8 | *** twgl by greggman (https://github.com/greggman/twgl.js) 9 | 10 | *** see http://github.com/feiss/indexed 11 | */" > indexed.min.js 12 | 13 | 14 | cat libs/playground-base.min.js >> indexed.min.js 15 | cat libs/twgl.min.js >> indexed.min.js 16 | echo "/** INDEXED 17 | *** indexed color mode for canvas, and powered by playground and twgl 18 | *** copyright 2015 Diego F. Goberna, MIT licensed 19 | *** see http://github.com/feiss/indexed 20 | */" >> indexed.min.js 21 | python -m jsmin ../src/indexed.render.js >> indexed.min.js 22 | 23 | 24 | 25 | echo "/** INDEXED 26 | *** indexed color mode for canvas, and powered by playground and twgl 27 | *** indexed module copyright 2015 Diego F. Goberna 28 | 29 | *** playground by rezoner (http://github.com/rezoner/playground) 30 | *** twgl by greggman (https://github.com/greggman/twgl.js) 31 | 32 | *** see http://github.com/feiss/indexed 33 | */" > indexed.js 34 | 35 | cat libs/playground-base.min.js >> indexed.js 36 | cat libs/twgl.min.js >> indexed.js 37 | cat ../src/indexed.render.js >> indexed.js 38 | -------------------------------------------------------------------------------- /examples/data/basic.pal: -------------------------------------------------------------------------------- 1 | JASC-PAL 2 | 0100 3 | 256 4 | 0 0 0 5 | 0 0 168 6 | 0 255 0 7 | 255 251 0 8 | 130 255 0 9 | 0 255 0 10 | 0 255 125 11 | 0 255 255 12 | 0 130 255 13 | 0 0 255 14 | 121 0 255 15 | 207 0 255 16 | 255 0 215 17 | 255 0 130 18 | 255 0 0 19 | 255 125 0 20 | 203 154 69 21 | 150 60 24 22 | 97 0 0 23 | 255 247 130 24 | 195 255 130 25 | 130 255 130 26 | 130 255 190 27 | 130 255 255 28 | 130 195 255 29 | 130 130 255 30 | 166 130 255 31 | 207 130 255 32 | 251 130 255 33 | 255 130 195 34 | 255 130 130 35 | 255 158 130 36 | 130 0 0 37 | 130 28 0 38 | 130 60 0 39 | 130 81 0 40 | 130 101 0 41 | 130 121 0 42 | 65 130 0 43 | 0 130 0 44 | 0 130 60 45 | 0 130 130 46 | 0 65 130 47 | 0 0 130 48 | 40 0 130 49 | 77 0 130 50 | 121 0 130 51 | 130 0 65 52 | 0 0 0 53 | 16 16 16 54 | 32 32 32 55 | 48 48 48 56 | 69 69 69 57 | 85 85 85 58 | 101 101 101 59 | 117 117 117 60 | 134 134 134 61 | 154 154 154 62 | 170 170 170 63 | 186 186 186 64 | 203 203 203 65 | 223 223 223 66 | 239 239 239 67 | 255 255 255 68 | 77 0 0 69 | 89 0 0 70 | 113 0 0 71 | 134 0 0 72 | 158 0 0 73 | 182 0 0 74 | 207 0 0 75 | 231 0 0 76 | 255 0 0 77 | 255 28 28 78 | 255 52 52 79 | 255 81 81 80 | 255 109 109 81 | 255 138 138 82 | 255 162 162 83 | 255 190 190 84 | 77 36 0 85 | 85 40 0 86 | 109 52 0 87 | 134 60 0 88 | 158 73 0 89 | 182 89 0 90 | 207 101 0 91 | 231 113 0 92 | 255 125 0 93 | 255 142 28 94 | 255 154 52 95 | 255 166 81 96 | 255 178 109 97 | 255 190 134 98 | 255 207 162 99 | 255 223 190 100 | 77 73 0 101 | 89 81 0 102 | 113 105 0 103 | 134 130 0 104 | 158 150 0 105 | 182 174 0 106 | 207 199 0 107 | 231 227 0 108 | 255 255 0 109 | 255 255 28 110 | 255 251 52 111 | 255 251 81 112 | 255 247 109 113 | 255 251 134 114 | 255 251 162 115 | 255 251 190 116 | 0 77 0 117 | 0 97 0 118 | 0 121 0 119 | 0 142 0 120 | 0 166 0 121 | 0 186 0 122 | 0 211 0 123 | 0 235 0 124 | 0 255 0 125 | 28 255 28 126 | 56 255 52 127 | 85 255 81 128 | 113 255 109 129 | 138 255 134 130 | 166 255 162 131 | 195 255 190 132 | 0 65 65 133 | 0 89 89 134 | 0 113 113 135 | 0 134 134 136 | 0 158 158 137 | 0 182 182 138 | 0 207 207 139 | 0 231 231 140 | 0 255 255 141 | 89 255 251 142 | 117 255 251 143 | 138 255 255 144 | 158 255 251 145 | 186 255 255 146 | 203 255 255 147 | 219 255 255 148 | 0 32 65 149 | 0 44 89 150 | 0 56 113 151 | 0 69 134 152 | 0 81 158 153 | 0 93 182 154 | 0 105 207 155 | 0 117 231 156 | 0 130 255 157 | 28 142 255 158 | 52 158 255 159 | 81 170 255 160 | 109 186 255 161 | 138 203 255 162 | 162 215 255 163 | 190 227 255 164 | 0 0 77 165 | 0 0 101 166 | 0 4 121 167 | 0 4 142 168 | 0 4 166 169 | 0 0 190 170 | 0 0 211 171 | 0 0 235 172 | 0 0 255 173 | 28 36 255 174 | 52 60 255 175 | 81 93 255 176 | 109 121 255 177 | 138 146 255 178 | 162 170 255 179 | 190 199 255 180 | 36 0 77 181 | 48 0 101 182 | 65 0 130 183 | 77 0 154 184 | 89 0 178 185 | 101 0 203 186 | 113 0 231 187 | 121 0 255 188 | 130 0 255 189 | 142 28 255 190 | 150 52 255 191 | 166 81 255 192 | 174 109 255 193 | 190 134 255 194 | 203 162 255 195 | 219 190 255 196 | 73 0 77 197 | 95 0 99 198 | 117 0 122 199 | 139 0 144 200 | 161 0 167 201 | 183 0 189 202 | 205 0 212 203 | 227 0 235 204 | 230 23 237 205 | 234 47 240 206 | 237 71 242 207 | 241 95 245 208 | 244 118 247 209 | 248 142 250 210 | 251 166 252 211 | 255 190 255 212 | 32 0 0 213 | 44 0 0 214 | 56 4 4 215 | 73 12 8 216 | 85 20 16 217 | 97 32 24 218 | 113 40 36 219 | 125 56 44 220 | 134 69 56 221 | 154 89 77 222 | 170 109 93 223 | 186 130 117 224 | 203 154 138 225 | 223 178 162 226 | 239 207 190 227 | 255 235 223 228 | 32 32 0 229 | 60 60 0 230 | 81 77 0 231 | 101 89 8 232 | 121 101 12 233 | 142 109 20 234 | 162 121 28 235 | 182 125 40 236 | 190 130 56 237 | 199 142 77 238 | 207 150 97 239 | 219 166 117 240 | 227 178 142 241 | 235 195 166 242 | 247 211 195 243 | 255 235 223 244 | 255 28 28 245 | 255 28 28 246 | 255 28 28 247 | 255 28 28 248 | 255 28 28 249 | 255 28 28 250 | 255 28 28 251 | 172 124 124 252 | 255 28 28 253 | 255 28 28 254 | 255 28 28 255 | 255 28 28 256 | 0 0 0 257 | 87 98 122 258 | 180 180 180 259 | 109 109 109 260 | -------------------------------------------------------------------------------- /examples/drawing.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 8-bit indexed color in webgl - Drawing test 9 | 27 | 28 | 29 | 30 |
click on canvas for next draw test
31 | View on GitHub
32 | 33 | 34 | 35 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /examples/images/glue.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/glue.pcx -------------------------------------------------------------------------------- /examples/images/grad.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/grad.pcx -------------------------------------------------------------------------------- /examples/images/lena.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/lena.pcx -------------------------------------------------------------------------------- /examples/images/o1.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/o1.pcx -------------------------------------------------------------------------------- /examples/images/pixelfont.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/pixelfont.pcx -------------------------------------------------------------------------------- /examples/images/shootemup.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/shootemup.pcx -------------------------------------------------------------------------------- /examples/images/slices.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/slices.pcx -------------------------------------------------------------------------------- /examples/images/testsprite.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/images/testsprite.pcx -------------------------------------------------------------------------------- /examples/index.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Indexed - Examples 6 | 7 | 8 | 9 |

Indexed examples

10 | 11 | read())) { 14 | if (substr($entry, -4)!='html') continue; 15 | echo "$entry
"; 16 | } 17 | $d->close(); 18 | ?> 19 | 20 |
21 | ← back to project 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/lena.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 8-bit indexed color in webgl 9 | 26 | 27 | 28 | 29 | 30 |
click to toggle palette cycling
31 | view in github.com
32 | 77 | 78 | -------------------------------------------------------------------------------- /examples/shootemup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 8-bit indexed color in webgl 9 | 26 | 27 | 28 | 29 | 30 |
Use your mouse and your aim
31 | view in github.com
32 | 392 | 393 | -------------------------------------------------------------------------------- /examples/somesprites.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 8-bit indexed color in webgl 9 | 32 | 33 | 34 | 35 |
36 |
    37 |
  • Move mouse around canvas
  • 38 |
  • [space] toggle palette cycling
  • 39 |
  • [click] Next test
  • 40 |
  • [ c ] Clear
  • 41 |
42 |
43 | View on GitHub
44 | 45 | 46 | 47 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /examples/sounds/enemy.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/sounds/enemy.ogg -------------------------------------------------------------------------------- /examples/sounds/explosion.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/sounds/explosion.ogg -------------------------------------------------------------------------------- /examples/sounds/hit.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/sounds/hit.ogg -------------------------------------------------------------------------------- /examples/sounds/music.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/sounds/music.ogg -------------------------------------------------------------------------------- /examples/sounds/shoot.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feiss/indexed/3e93d6cfd4dd3ce7accdd856d143f21828b9b6be/examples/sounds/shoot.ogg -------------------------------------------------------------------------------- /src/indexed.render.js: -------------------------------------------------------------------------------- 1 | /** INDEXED 2 | *** indexed color mode for canvas, and powered by playground and twgl 3 | *** copyright 2015 Diego F. Goberna, MIT licensed 4 | *** see http://github.com/feiss/indexed 5 | */ 6 | 7 | var Indexed= {}; 8 | 9 | Indexed.indexed_vert= "\ 10 | attribute vec4 position;\ 11 | void main() {\ 12 | gl_Position = position;\ 13 | }"; 14 | 15 | //todo: add optional postprocessing filters 16 | Indexed.indexed_frag="\ 17 | precision mediump float;\ 18 | uniform vec2 canvasratio;\ 19 | uniform vec2 resolution;\ 20 | uniform sampler2D fb;\ 21 | uniform sampler2D pal;\ 22 | void main() {\ 23 | vec2 uv = gl_FragCoord.xy / resolution * canvasratio;\ 24 | uv.y= canvasratio.y - uv.y;\ 25 | vec4 colindex= texture2D(fb, uv);\ 26 | vec4 color= texture2D(pal, colindex.xy);\ 27 | \ 28 | uv/= canvasratio;\ 29 | vec2 uv2 = uv * 2.0 - 1.0;\ 30 | color*= smoothstep(1.65, 1.65 - 0.75, length(uv2));\ 31 | gl_FragColor = color;\ 32 | }"; 33 | 34 | 35 | 36 | 37 | Indexed.Renderer= function (canvas_id, width, height, scale, forcecanvas){ 38 | scale= Math.floor(parseInt(scale)); 39 | if (!scale || scale<0) scale= 1; 40 | this.scale= scale; 41 | if (typeof canvas_id=='string'){ 42 | this.canvas= document.getElementById(canvas_id); 43 | } 44 | else this.canvas= canvas_id; 45 | if (!this.canvas) { 46 | this.canvas= document.createElement('canvas'); 47 | this.canvas.width= 256*scale; 48 | this.canvas.height= 256*scale; 49 | document.body.appendChild(this.canvas); 50 | } 51 | this.width= width || this.canvas.width/scale|0; 52 | this.height= height || this.canvas.height/scale|0; 53 | this.canvas.width= this.width*scale; 54 | this.canvas.height= this.height*scale; 55 | this.center= {x: this.width/2|0, y: this.height/2|0} 56 | this.fb= new Indexed.Buffer(this.width, this.height); 57 | this.palette= new Indexed.Palette(); 58 | 59 | var ctest= document.createElement('canvas'); 60 | var webgl_available = twgl.getWebGLContext(ctest); 61 | 62 | if (forcecanvas || !webgl_available){ 63 | this.gl= false; 64 | this.context= this.canvas.getContext("2d"); 65 | this.backcanvas= null; 66 | this.backcontext= null; 67 | if (scale!=1){ 68 | this.backcanvas= document.createElement('canvas'); 69 | this.backcanvas.width= this.width; 70 | this.backcanvas.height= this.height; 71 | this.backcontext= this.backcanvas.getContext("2d"); 72 | this.backcontext.fillRect(0,0, this.width, this.height); 73 | this.imagedata= this.backcontext.getImageData(0,0, this.width, this.height); 74 | } 75 | else{ 76 | this.context.fillRect(0,0, this.width*scale, this.height*scale); 77 | this.imagedata= this.context.getImageData(0,0, this.width, this.height); 78 | } 79 | this.prebuffer= new ArrayBuffer(this.imagedata.data.length); 80 | this.prebuffer8= new Uint8ClampedArray(this.prebuffer); 81 | this.prebuffer32= new Uint32Array(this.prebuffer); 82 | 83 | this.context.imageSmoothingEnabled= false; 84 | } 85 | else{ 86 | this.gl = twgl.getWebGLContext(this.canvas); 87 | this.programInfo = twgl.createProgramInfo(this.gl, [Indexed.indexed_vert, Indexed.indexed_frag]); 88 | 89 | //2 triangles 90 | this.bufferInfo = twgl.createBufferInfoFromArrays(this.gl, 91 | {position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0]}); 92 | 93 | //find power-2 texture sizes for this canvas size 94 | var twidth= Math.pow(2, Math.ceil(Math.log(this.width)/Math.log(2))); 95 | var theight= Math.pow(2, Math.ceil(Math.log(this.height)/Math.log(2))); 96 | var palwidth= Math.pow(2, Math.ceil(Math.log(this.palette.length)/Math.log(2))); 97 | this.textures= twgl.createTextures(this.gl, { 98 | pal: { 99 | min: this.gl.NEAREST, 100 | mag: this.gl.NEAREST, 101 | width: palwidth, 102 | height: 1, 103 | format: this.gl.RGBA, 104 | //src: this.palette.data, 105 | type: this.gl.UNSIGNED_BYTE, 106 | auto: false 107 | }, 108 | fb: { 109 | min: this.gl.NEAREST, 110 | mag: this.gl.NEAREST, 111 | format: this.gl.LUMINANCE, 112 | width: twidth, 113 | height: theight, 114 | //src: this.fb.data, 115 | type: this.gl.UNSIGNED_BYTE, 116 | auto: false 117 | } 118 | }); 119 | this.uniforms = { 120 | resolution: [this.gl.canvas.width, this.gl.canvas.height], 121 | canvasratio: [this.width/twidth, this.height/theight], 122 | fb: this.textures.fb, 123 | pal: this.textures.pal 124 | }; 125 | 126 | twgl.resizeCanvasToDisplaySize(this.gl.canvas); 127 | this.gl.viewport(0, 0, this.gl.canvas.width, this.gl.canvas.height); 128 | } 129 | 130 | this.updatePalette(); 131 | 132 | 133 | }; 134 | Indexed.Renderer.prototype= { 135 | setCursor: function(cursor){ 136 | this.canvas.style.cursor= cursor; 137 | }, 138 | clear: function(color){ 139 | this.fb.set(color); 140 | }, 141 | setPalette: function(pal){ 142 | if (pal instanceof Indexed.Palette) this.palette= pal; 143 | else this.palette.fromString(pal); 144 | this.updatePalette(); 145 | }, 146 | updatePalette: function(){ 147 | if (!this.gl) return; 148 | 149 | this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures.pal); 150 | // twgl.setTextureFromArray(this.gl, this.textures.pal, this.palette.data, {width: this.palette.length, height: 1, format: this.gl.RGB, type: this.gl.UNSIGNED_BYTE, update:true}); 151 | this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1); 152 | this.gl.texSubImage2D(this.gl.TEXTURE_2D, 0, 0, 0, this.palette.length, 1, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.palette.data8); 153 | }, 154 | flip: function(){ 155 | if (this.gl){ 156 | this.gl.bindTexture(this.gl.TEXTURE_2D, this.textures.fb); 157 | //twgl.setTextureFromArray(this.gl, this.textures.fb, this.fb.data, {format: this.gl.LUMINANCE, width: this.width, height: this.height, type: this.gl.UNSIGNED_BYTE, update: true}); 158 | this.gl.pixelStorei(this.gl.UNPACK_ALIGNMENT, 1); 159 | this.gl.texSubImage2D(this.gl.TEXTURE_2D, 0, 0, 0, this.width, this.height, this.gl.LUMINANCE, this.gl.UNSIGNED_BYTE, this.fb.data); 160 | 161 | this.gl.useProgram(this.programInfo.program); 162 | twgl.setBuffersAndAttributes(this.gl, this.programInfo, this.bufferInfo); 163 | twgl.setUniforms(this.programInfo, this.uniforms); 164 | twgl.drawBufferInfo(this.gl, this.gl.TRIANGLES, this.bufferInfo); 165 | } 166 | else{ 167 | var fbdata= this.fb.data, paldata= this.palette.data32, prebuffer= this.prebuffer32; 168 | for (var i=0, end=this.width*this.height; i< end; i++) { 169 | prebuffer[i]= paldata[ fbdata[i] ]; 170 | } 171 | this.imagedata.data.set(this.prebuffer8); 172 | if (this.backcanvas){ 173 | this.backcontext.putImageData(this.imagedata, 0, 0); 174 | this.context.drawImage(this.backcanvas, 0, 0, this.canvas.width, this.canvas.height); 175 | } 176 | else this.context.putImageData(this.imagedata, 0, 0); 177 | } 178 | } 179 | }; 180 | 181 | 182 | 183 | Indexed.Palette= function(a){ 184 | this.data= undefined; 185 | this.data8= undefined; 186 | this.data32= undefined; 187 | 188 | this.length= undefined; 189 | if (a===undefined) a= 256; 190 | if (parseInt(a)>0) this.init(a); 191 | else if (typeof a=='string') this.fromString(a); 192 | this.TRANSPARENT= 255; 193 | }; 194 | Indexed.Palette.prototype={ 195 | init: function(size){ 196 | if (size===undefined) size= 256*4; else size*=4; 197 | if (this['data']===undefined || this.data.length!==size){ 198 | this.data = new ArrayBuffer(size); 199 | this.data8= new Uint8Array(this.data); 200 | this.data32= new Uint32Array(this.data); 201 | 202 | this.length= size/4|0; 203 | } 204 | 205 | for (var i=0; i< this.length; i++){ 206 | this.data8[i*4 ]= i; 207 | this.data8[i*4+1]= i; 208 | this.data8[i*4+2]= i; 209 | this.data8[i*4+3]= 255; 210 | } 211 | }, 212 | fromString: function(str){ 213 | var lines= str.split('\n'); 214 | if (lines[0].trim()=='JASC-PAL'){ 215 | var size= parseInt(lines[2]); 216 | 217 | this.data = new ArrayBuffer(size*4); 218 | this.data8= new Uint8Array(this.data); 219 | this.data32= new Uint32Array(this.data); 220 | this.length= size; 221 | 222 | for (var i=0; i< size; i++){ 223 | var col= lines[i+3].split(' '); 224 | this.data8[i*4+0]= parseInt(col[0]); 225 | this.data8[i*4+1]= parseInt(col[1]); 226 | this.data8[i*4+2]= parseInt(col[2]); 227 | this.data8[i*4+3]= 255; 228 | } 229 | } 230 | }, 231 | initGrayscale: function(size){ 232 | if (size!==undefined && this.length!==size) this.init(size); 233 | this.makeGradient(0, this.length-1, [0,0,0], [255,255,255]); 234 | }, 235 | setTransparent: function(idx){ 236 | this.TRANSPARENT= Math.min(this.length, Math.max(0, idx)); 237 | }, 238 | makeGradient: function(start, end, colorstart, colorend){ 239 | var steps= end-start; 240 | var dr= (colorend[0]-colorstart[0])/steps; 241 | var dg= (colorend[1]-colorstart[1])/steps; 242 | var db= (colorend[2]-colorstart[2])/steps; 243 | 244 | for (var i= start, ii=i*4; i<= end; i++, ii+=4){ 245 | this.data8[ii ]= colorstart[0]|0; 246 | this.data8[ii+1]= colorstart[1]|0; 247 | this.data8[ii+2]= colorstart[2]|0; 248 | this.data8[ii+3]= 255; 249 | colorstart[0]+= dr; 250 | colorstart[1]+= dg; 251 | colorstart[2]+= db; 252 | } 253 | }, 254 | cycle: function(start, end, direction) { 255 | if (direction<0) { 256 | var aux= start; 257 | start= end; 258 | end= aux; 259 | direction= -1; 260 | } 261 | else direction= 1; 262 | 263 | for (var i= start, ii= i, ij; i!= end; i+= direction, ii=i){ 264 | ij= i+direction; 265 | this.data32[ii]= this.data32[ij]; 266 | } 267 | this.data32[end]= this.data32[start]; 268 | }, 269 | getColorIndex: function(r,g,b){ 270 | var col= (0xff000000)|(b<<16)|(g<<8)|r; 271 | for (var i=0, len=this.data32.length; i< len; i++){ 272 | if (this.data32[i]==col){ 273 | return i; 274 | } 275 | } 276 | return this.TRANSPARENT; 277 | }, 278 | setRGB: function(i,r,g,b){ 279 | this.data32[i]= (0xff000000)|(b<<16)|(g<<8)|r; 280 | }, 281 | shiftRGB: function(i,r,g,b){ 282 | this.data[i*3+0]= (this.data[i*3+0] + r)|0; 283 | this.data[i*3+1]= (this.data[i*3+1] + g)|0; 284 | this.data[i*3+2]= (this.data[i*3+2] + b)|0; 285 | } 286 | }; 287 | 288 | Indexed.Buffer= function(a, b){ 289 | this.data= undefined; 290 | this.palette= null; 291 | this.width= 0; 292 | this.height= 0; 293 | 294 | this.init= function(a,b,c){ 295 | this.data= undefined; 296 | this.width= 0; 297 | this.height= 0; 298 | if (a instanceof Image && b instanceof Indexed.Palette){ 299 | this.fromImage(a, b); 300 | } 301 | else if (a instanceof Uint8Array){ 302 | this.fromPCX(a, b); 303 | } 304 | else if (parseInt(a)>0 && parseInt(b)>0){ 305 | this.data= new Uint8Array(a*b); 306 | this.palette= new Indexed.Palette(); 307 | this.width= a; 308 | this.height= b; 309 | } 310 | } 311 | this.init(a,b); 312 | } 313 | Indexed.Buffer.prototype= { 314 | fromImage: function(img, pal){ 315 | if (this.data) this.data= null; 316 | this.data= new Uint8Array(img.width*img.height); 317 | var c= document.createElement('canvas'); 318 | c.width= img.width; 319 | c.height= img.height; 320 | this.width= img.width; 321 | this.height= img.height; 322 | var ctx= c.getContext('2d'); 323 | ctx.drawImage(img, 0,0); 324 | var imgdata= ctx.getImageData(0, 0, c.width, c.height).data; 325 | for (var i=0, len= imgdata.length, j=0; i< len; i+=4, j++){ 326 | this.data[j]= pal.getColorIndex(imgdata[i],imgdata[i+1],imgdata[i+2]); 327 | } 328 | this.palette= pal; 329 | }, 330 | fromPCX: function(img, readpalette){ 331 | var pcx= Indexed.PCXread(img, readpalette); 332 | this.width= pcx.width; 333 | this.height= pcx.height; 334 | this.data= pcx.data; 335 | this.palette= pcx.palette; 336 | }, 337 | set: function(color){ 338 | for (var i= 0, len= this.data.length; i W || y> H || x2 < 0 || y2 < 0) return null; 361 | if (x2> W) x2= W; 362 | if (y2> H) y2= H; 363 | var x1= x; 364 | w= x2-x; 365 | h= y2-y; 366 | var b= new Indexed.Buffer(w, h); 367 | for(j=0; y< y2; y++, j++){ 368 | for(i=0, x= x1; x< x2; x++, i++){ 369 | b.data[j*w+i]= this.data[y*W+x]; 370 | } 371 | } 372 | //FIX: shallow copy? hmmm nop nop! 373 | if (copypal) b.palette= this.palette; 374 | return b; 375 | }, 376 | drawBuffer: function(buffer, x, y){ 377 | var j= (y|0)*this.width+(x|0); 378 | var c; 379 | for (var i = 0, len= buffer.data.length; i < len;) { 380 | c= buffer.data[i]; 381 | if (c!=buffer.palette.TRANSPARENT){ 382 | this.data[j]= c;//Math.min(254, (this.data[j]+spr.pixels[i])); 383 | } 384 | i++; 385 | if(i%buffer.width==0) j+= this.width-buffer.width+1; else j++; 386 | }; 387 | }, 388 | drawSubBuffer: function(buffer, bx, by, bw, bh, x, y){ 389 | var i,j; 390 | var bx2= bx+bw, by2= by+bh; 391 | var W= buffer.width, H= buffer.height; 392 | if (bx > W || by> H || bx2 < 0 || by2 < 0) return null; 393 | if (bx2> W) bx2= W; 394 | if (by2> H) by2= H; 395 | var bx1= bx; 396 | bw= bx2-bx; 397 | bh= by2-by; 398 | var c; 399 | for(j=y; by< by2; by++, j++){ 400 | for(i=x, bx= bx1; bx< bx2; bx++, i++){ 401 | c= buffer.data[by*W+bx]; 402 | if (c!=buffer.palette.TRANSPARENT){ 403 | this.data[j*this.width+i]= c; 404 | } 405 | } 406 | } 407 | }, 408 | putPixel: function(col, x, y){ 409 | this.data[y*this.width+x]= col; 410 | }, 411 | getPixel: function(x, y){ 412 | return this.data[y*this.width+x]; 413 | }, 414 | drawRect: function(col, x, y, w, h, empty){ 415 | var i,j; 416 | var x2= x+w, y2= y+h; 417 | var W= this.width, H= this.height; 418 | if (x > W || y> H || x2 < 0 || y2 < 0) return; 419 | if (x2> W) x2= W; 420 | if (y2> H) y2= H; 421 | var x1= x; 422 | if (empty===true){ 423 | this.drawLine(col, x, y, x2, y); 424 | this.drawLine(col, x, y2, x2, y2); 425 | this.drawLine(col, x, y, x, y2); 426 | this.drawLine(col, x2, y, x2, y2); 427 | } 428 | else{ 429 | for(; y< y2; y++){ 430 | for(x= x1; x< x2; x++){ 431 | this.data[y*W+x]= col; 432 | } 433 | } 434 | } 435 | }, 436 | drawLine: function(col, x0, y0, x1, y1){ 437 | var W= this.width; 438 | var dx= Math.abs(x1-x0); 439 | var dy= Math.abs(y1-y0); 440 | var sx= (x0 < x1) ? 1 : -1; 441 | var sy= (y0 < y1) ? 1 : -1; 442 | var err = dx-dy; 443 | 444 | while(true){ 445 | this.data[y0*W+x0]= col; 446 | 447 | if ((x0==x1) && (y0==y1)) break; 448 | var e2 = 2*err; 449 | if (e2 >-dy){ err-= dy; x0+= sx; } 450 | if (e2 < dx){ err+= dx; y0+= sy; } 451 | } 452 | } 453 | } 454 | 455 | //fast and incomplete pcx reader. It assumes a lot of things by default. 456 | Indexed.PCXread= function(data, readpalette){ 457 | var pcx={width: 0, height: 0, data: null, palette: null}; 458 | 459 | var w= word(8); 460 | var h= word(10); 461 | if (!w || !h) return console.error('pcx dimensions wrong '+w+','+h); 462 | pcx.width= w+1; 463 | pcx.height= h+1; 464 | pcx.data= new Uint8Array(pcx.width*pcx.height); 465 | 466 | //rle 467 | var d, num, z=0; 468 | for (var i= 128, len=data.length-769; i < len; ) { 469 | d= data[i++]; 470 | num= 1; 471 | if((d & 0xc0) === 0xc0) { 472 | num= d&0x3f; 473 | d= data[i++]; 474 | } 475 | for(var j= 0; j < num; j++ ) { 476 | pcx.data[z++]= d; 477 | } 478 | } 479 | 480 | //palette 481 | if (readpalette===true){ 482 | pcx.palette= new Indexed.Palette(256); 483 | for (var i= data.length-768, j=0, len= data.length; i < len; ) { 484 | pcx.palette.data8[j++]= data[i++]; 485 | pcx.palette.data8[j++]= data[i++]; 486 | pcx.palette.data8[j++]= data[i++]; 487 | pcx.palette.data8[j++]= 255; 488 | } 489 | } 490 | 491 | return pcx; 492 | 493 | function word(offset){ 494 | return (data[offset+1]<<8)|data[offset]; 495 | } 496 | } 497 | 498 | 499 | 500 | 501 | 502 | /// plugin for playground 503 | if (window.PLAYGROUND){ 504 | 505 | PLAYGROUND.Renderer= function(app){ 506 | this.app= app; 507 | app.on('create', this.create.bind(this)); 508 | app.on('postrender', this.postrender.bind(this)); 509 | } 510 | PLAYGROUND.Renderer.plugin= true; 511 | PLAYGROUND.Renderer.prototype={ 512 | create: function(data){ 513 | this.app.layer= new Indexed.Renderer(this.app.container, this.app.width, this.app.height, this.app.scale, this.app.forcecanvas); 514 | }, 515 | postrender: function(){ 516 | this.app.layer.flip(); 517 | } 518 | }; 519 | 520 | PLAYGROUND.Application.prototype.loadPCX = function() { 521 | var promises = []; 522 | for (var i = 0; i < arguments.length; i++) { 523 | var arg = arguments[i]; 524 | if (typeof arg === "object") { 525 | for (var key in arg) promises = promises.concat(this.loadOnePCX(arg[key])); 526 | } 527 | else { 528 | promises.push(this.loadOnePCX(arg)); 529 | } 530 | } 531 | return Promise.all(promises); 532 | }; 533 | 534 | PLAYGROUND.Application.prototype.loadOnePCX = function(name) { 535 | if(!this.pcx) this.pcx = {}; 536 | var entry = this.getAssetEntry(name, "images", "pcx"); 537 | this.loader.add(); 538 | var self= this; 539 | 540 | var xobj = new XMLHttpRequest(); 541 | if (xobj.overrideMimeType) xobj.overrideMimeType("application/octet-stream"); 542 | xobj.responseType = 'arraybuffer'; 543 | xobj.open('GET', entry.url, true); 544 | xobj.onreadystatechange = function () { 545 | if (xobj.readyState == 4){ 546 | if (xobj.status == "200") { 547 | self.pcx[entry.key]= new Indexed.Buffer(new Uint8Array(xobj.response), true); 548 | self.loader.success(entry.url); 549 | } 550 | else{ 551 | self.loader.error("Could not load "+entry.url); 552 | } 553 | } 554 | }; 555 | xobj.send(null); 556 | }; 557 | 558 | 559 | } --------------------------------------------------------------------------------