├── README.md ├── CSS └── style.css ├── .gitattributes ├── JS ├── index.js ├── canvas-toBlob.js ├── filesaver.js └── gameoflife.js ├── index.html └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | Game of Life 2 | ======= 3 | Conway's Game of Life 4 | - Random 5 | - Glider 6 | - Lightweight Spaceship 7 | - Pulsar 8 | - Glider Gun 9 | - Image 10 | 11 | License 12 | ====== 13 | [MIT license] (http://opensource.org/licenses/MIT) -------------------------------------------------------------------------------- /CSS/style.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | font-size: 2em; 3 | font-weight: bold; 4 | text-align:center; 5 | } 6 | 7 | #stop { 8 | display:none; 9 | } 10 | 11 | #canvas { 12 | margin-top:10px; 13 | } 14 | 15 | #image,#img_image { 16 | display:none; 17 | } 18 | 19 | #files { 20 | display:none; 21 | } 22 | 23 | 24 | .button { 25 | margin:5px 0px 0px 15px; 26 | background-color:#fb0; 27 | color: black; 28 | border-radius: 3px; 29 | padding:10px; 30 | width:auto; 31 | display:inline-block; 32 | cursor:pointer; 33 | } 34 | 35 | 36 | .save { 37 | 38 | width:100px; 39 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /JS/index.js: -------------------------------------------------------------------------------- 1 | var ctx = document.getElementById('canvas').getContext("2d"); 2 | var gameoflife = new GoL(ctx); 3 | 4 | var id_config = document.getElementById('config'); 5 | id_config.onchange = function() { 6 | if (id_config.value == "Image") { 7 | document.getElementById("files").style.display = "inline"; 8 | } else { 9 | document.getElementById("files").style.display = "none"; 10 | } 11 | } 12 | 13 | function start() { 14 | var width = document.getElementById("canvas").offsetWidth; 15 | var height = document.getElementById("canvas").offsetHeight; 16 | 17 | 18 | var timeout = document.getElementById("timeout").value; 19 | var alive = document.getElementById("alive").value; 20 | var config = document.getElementById("config").value; 21 | if (timeout > 0 && ((config == "Random" && alive > 0 && alive <= Math.floor(width/4)*Math.floor(height/4)) || config !== "Random")) { 22 | gameoflife.create_GoL(width,height,timeout,alive,config); 23 | document.getElementById("user_input").style.display = "none"; 24 | document.getElementById("stop").style.display = "inline"; 25 | } else { 26 | alert("Both (timeout and alive) must be > 0 and alive must be <= "+Math.floor(width/4)*Math.floor(height/4)); 27 | } 28 | } 29 | function stop() { 30 | gameoflife.set_stop(); 31 | document.getElementById("user_input").style.display = "inline"; 32 | document.getElementById("stop").style.display = "none"; 33 | } 34 | 35 | /* Save diagram */ 36 | function save() { 37 | var canvas = document.getElementById("canvas"); 38 | canvas.toBlob(function(blob) { 39 | saveAs(blob, "GoL.png"); 40 | }); 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Game of Life 5 | 6 | 7 | 8 | 9 | 10 | Fork me on GitHub 11 |

Game of Life

12 |
13 | Timeout(ms): Number of alive cells (only for random): 14 |
23 | 24 |
Start 25 |
26 | Stop 28 |
29 |
30 |
Save as png
31 | 32 |
33 | 34 | 35 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /JS/canvas-toBlob.js: -------------------------------------------------------------------------------- 1 | /* canvas-toBlob.js 2 | * A canvas.toBlob() implementation. 3 | * 2011-07-13 4 | * 5 | * By Eli Grey, http://eligrey.com and Devin Samarin, https://github.com/eboyjr 6 | * License: X11/MIT 7 | * See LICENSE.md 8 | */ 9 | 10 | /*global self */ 11 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, 12 | plusplus: true */ 13 | 14 | /*! @source http://purl.eligrey.com/github/canvas-toBlob.js/blob/master/canvas-toBlob.js */ 15 | 16 | (function(view) { 17 | "use strict"; 18 | var 19 | Uint8Array = view.Uint8Array 20 | , HTMLCanvasElement = view.HTMLCanvasElement 21 | , is_base64_regex = /\s*;\s*base64\s*(?:;|$)/i 22 | , base64_ranks 23 | , decode_base64 = function(base64) { 24 | var 25 | len = base64.length 26 | , buffer = new Uint8Array(len / 4 * 3 | 0) 27 | , i = 0 28 | , outptr = 0 29 | , last = [0, 0] 30 | , state = 0 31 | , save = 0 32 | , rank 33 | , code 34 | , undef 35 | ; 36 | while (len--) { 37 | code = base64.charCodeAt(i++); 38 | rank = base64_ranks[code-43]; 39 | if (rank !== 255 && rank !== undef) { 40 | last[1] = last[0]; 41 | last[0] = code; 42 | save = (save << 6) | rank; 43 | state++; 44 | if (state === 4) { 45 | buffer[outptr++] = save >>> 16; 46 | if (last[1] !== 61 /* padding character */) { 47 | buffer[outptr++] = save >>> 8; 48 | } 49 | if (last[0] !== 61 /* padding character */) { 50 | buffer[outptr++] = save; 51 | } 52 | state = 0; 53 | } 54 | } 55 | } 56 | // 2/3 chance there's going to be some null bytes at the end, but that 57 | // doesn't really matter with most image formats. 58 | // If it somehow matters for you, truncate the buffer up outptr. 59 | return buffer.buffer; 60 | } 61 | ; 62 | if (Uint8Array) { 63 | base64_ranks = new Uint8Array([ 64 | 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1 65 | , -1, -1, 0, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 66 | , 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 67 | , -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 68 | , 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 69 | ]); 70 | } 71 | if (HTMLCanvasElement && !HTMLCanvasElement.prototype.toBlob) { 72 | HTMLCanvasElement.prototype.toBlob = function(callback, type /*, ...args*/) { 73 | if (!type) { 74 | type = "image/png"; 75 | } if (this.mozGetAsFile) { 76 | callback(this.mozGetAsFile("canvas", type)); 77 | return; 78 | } 79 | var 80 | args = Array.prototype.slice.call(arguments, 1) 81 | , dataURI = this.toDataURL.apply(this, args) 82 | , header_end = dataURI.indexOf(",") 83 | , data = dataURI.substring(header_end + 1) 84 | , is_base64 = is_base64_regex.test(dataURI.substring(0, header_end)) 85 | , blob 86 | ; 87 | if (Blob.fake) { 88 | // no reason to decode a data: URI that's just going to become a data URI again 89 | blob = new Blob 90 | if (is_base64) { 91 | blob.encoding = "base64"; 92 | } else { 93 | blob.encoding = "URI"; 94 | } 95 | blob.data = data; 96 | blob.size = data.length; 97 | } else if (Uint8Array) { 98 | if (is_base64) { 99 | blob = new Blob([decode_base64(data)], {type: type}); 100 | } else { 101 | blob = new Blob([decodeURIComponent(data)], {type: type}); 102 | } 103 | } 104 | callback(blob); 105 | }; 106 | } 107 | }(self)); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /JS/filesaver.js: -------------------------------------------------------------------------------- 1 | /* FileSaver.js 2 | * A saveAs() FileSaver implementation. 3 | * 2013-01-23 4 | * 5 | * By Eli Grey, http://eligrey.com 6 | * License: X11/MIT 7 | * See LICENSE.md 8 | */ 9 | 10 | /*global self */ 11 | /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, 12 | plusplus: true */ 13 | 14 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ 15 | 16 | var saveAs = saveAs 17 | || (navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator)) 18 | || (function(view) { 19 | "use strict"; 20 | var 21 | doc = view.document 22 | // only get URL when necessary in case BlobBuilder.js hasn't overridden it yet 23 | , get_URL = function() { 24 | return view.URL || view.webkitURL || view; 25 | } 26 | , URL = view.URL || view.webkitURL || view 27 | , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a") 28 | , can_use_save_link = !view.externalHost && "download" in save_link 29 | , click = function(node) { 30 | var event = doc.createEvent("MouseEvents"); 31 | event.initMouseEvent( 32 | "click", true, false, view, 0, 0, 0, 0, 0 33 | , false, false, false, false, 0, null 34 | ); 35 | node.dispatchEvent(event); 36 | } 37 | , webkit_req_fs = view.webkitRequestFileSystem 38 | , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem 39 | , throw_outside = function (ex) { 40 | (view.setImmediate || view.setTimeout)(function() { 41 | throw ex; 42 | }, 0); 43 | } 44 | , force_saveable_type = "application/octet-stream" 45 | , fs_min_size = 0 46 | , deletion_queue = [] 47 | , process_deletion_queue = function() { 48 | var i = deletion_queue.length; 49 | while (i--) { 50 | var file = deletion_queue[i]; 51 | if (typeof file === "string") { // file is an object URL 52 | URL.revokeObjectURL(file); 53 | } else { // file is a File 54 | file.remove(); 55 | } 56 | } 57 | deletion_queue.length = 0; // clear queue 58 | } 59 | , dispatch = function(filesaver, event_types, event) { 60 | event_types = [].concat(event_types); 61 | var i = event_types.length; 62 | while (i--) { 63 | var listener = filesaver["on" + event_types[i]]; 64 | if (typeof listener === "function") { 65 | try { 66 | listener.call(filesaver, event || filesaver); 67 | } catch (ex) { 68 | throw_outside(ex); 69 | } 70 | } 71 | } 72 | } 73 | , FileSaver = function(blob, name) { 74 | // First try a.download, then web filesystem, then object URLs 75 | var 76 | filesaver = this 77 | , type = blob.type 78 | , blob_changed = false 79 | , object_url 80 | , target_view 81 | , get_object_url = function() { 82 | var object_url = get_URL().createObjectURL(blob); 83 | deletion_queue.push(object_url); 84 | return object_url; 85 | } 86 | , dispatch_all = function() { 87 | dispatch(filesaver, "writestart progress write writeend".split(" ")); 88 | } 89 | // on any filesys errors revert to saving with object URLs 90 | , fs_error = function() { 91 | // don't create more object URLs than needed 92 | if (blob_changed || !object_url) { 93 | object_url = get_object_url(blob); 94 | } 95 | if (target_view) { 96 | target_view.location.href = object_url; 97 | } else { 98 | window.open(object_url, "_blank"); 99 | } 100 | filesaver.readyState = filesaver.DONE; 101 | dispatch_all(); 102 | } 103 | , abortable = function(func) { 104 | return function() { 105 | if (filesaver.readyState !== filesaver.DONE) { 106 | return func.apply(this, arguments); 107 | } 108 | }; 109 | } 110 | , create_if_not_found = {create: true, exclusive: false} 111 | , slice 112 | ; 113 | filesaver.readyState = filesaver.INIT; 114 | if (!name) { 115 | name = "download"; 116 | } 117 | if (can_use_save_link) { 118 | object_url = get_object_url(blob); 119 | save_link.href = object_url; 120 | save_link.download = name; 121 | click(save_link); 122 | filesaver.readyState = filesaver.DONE; 123 | dispatch_all(); 124 | return; 125 | } 126 | // Object and web filesystem URLs have a problem saving in Google Chrome when 127 | // viewed in a tab, so I force save with application/octet-stream 128 | // http://code.google.com/p/chromium/issues/detail?id=91158 129 | if (view.chrome && type && type !== force_saveable_type) { 130 | slice = blob.slice || blob.webkitSlice; 131 | blob = slice.call(blob, 0, blob.size, force_saveable_type); 132 | blob_changed = true; 133 | } 134 | // Since I can't be sure that the guessed media type will trigger a download 135 | // in WebKit, I append .download to the filename. 136 | // https://bugs.webkit.org/show_bug.cgi?id=65440 137 | if (webkit_req_fs && name !== "download") { 138 | name += ".download"; 139 | } 140 | if (type === force_saveable_type || webkit_req_fs) { 141 | target_view = view; 142 | } 143 | if (!req_fs) { 144 | fs_error(); 145 | return; 146 | } 147 | fs_min_size += blob.size; 148 | req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) { 149 | fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) { 150 | var save = function() { 151 | dir.getFile(name, create_if_not_found, abortable(function(file) { 152 | file.createWriter(abortable(function(writer) { 153 | writer.onwriteend = function(event) { 154 | target_view.location.href = file.toURL(); 155 | deletion_queue.push(file); 156 | filesaver.readyState = filesaver.DONE; 157 | dispatch(filesaver, "writeend", event); 158 | }; 159 | writer.onerror = function() { 160 | var error = writer.error; 161 | if (error.code !== error.ABORT_ERR) { 162 | fs_error(); 163 | } 164 | }; 165 | "writestart progress write abort".split(" ").forEach(function(event) { 166 | writer["on" + event] = filesaver["on" + event]; 167 | }); 168 | writer.write(blob); 169 | filesaver.abort = function() { 170 | writer.abort(); 171 | filesaver.readyState = filesaver.DONE; 172 | }; 173 | filesaver.readyState = filesaver.WRITING; 174 | }), fs_error); 175 | }), fs_error); 176 | }; 177 | dir.getFile(name, {create: false}, abortable(function(file) { 178 | // delete file if it already exists 179 | file.remove(); 180 | save(); 181 | }), abortable(function(ex) { 182 | if (ex.code === ex.NOT_FOUND_ERR) { 183 | save(); 184 | } else { 185 | fs_error(); 186 | } 187 | })); 188 | }), fs_error); 189 | }), fs_error); 190 | } 191 | , FS_proto = FileSaver.prototype 192 | , saveAs = function(blob, name) { 193 | return new FileSaver(blob, name); 194 | } 195 | ; 196 | FS_proto.abort = function() { 197 | var filesaver = this; 198 | filesaver.readyState = filesaver.DONE; 199 | dispatch(filesaver, "abort"); 200 | }; 201 | FS_proto.readyState = FS_proto.INIT = 0; 202 | FS_proto.WRITING = 1; 203 | FS_proto.DONE = 2; 204 | 205 | FS_proto.error = 206 | FS_proto.onwritestart = 207 | FS_proto.onprogress = 208 | FS_proto.onwrite = 209 | FS_proto.onabort = 210 | FS_proto.onerror = 211 | FS_proto.onwriteend = 212 | null; 213 | 214 | view.addEventListener("unload", process_deletion_queue, false); 215 | return saveAs; 216 | }(self)); 217 | 218 | if (typeof module !== 'undefined') module.exports = saveAs; -------------------------------------------------------------------------------- /JS/gameoflife.js: -------------------------------------------------------------------------------- 1 | window.GoL = function(context) { 2 | var ctx = context; 3 | var GoL_array = new Array(); 4 | var next_GoL_array = new Array(); 5 | var width; 6 | var height; 7 | var steps = 100000; 8 | var stop; 9 | var timeout; 10 | 11 | this.create_GoL = function(w,h,tout,alive,config) { 12 | stop = false; 13 | timeout = tout; 14 | width = w; 15 | height = h; 16 | ctx.fillStyle = '#FFF'; 17 | 18 | ctx.fillRect(0,0,width,height); 19 | for (var x=0; x < Math.floor(width/4); x++) { 20 | GoL_array[x] = new Array(); 21 | next_GoL_array[x] = new Array(); 22 | for (var y=0; y < Math.floor(height/4); y++) { 23 | GoL_array[x][y] = 0; 24 | next_GoL_array[x][y] = 0; 25 | } 26 | } 27 | 28 | 29 | 30 | var grid = create_grid(); 31 | 32 | switch (config) { 33 | case "Random": 34 | var rand_alive = random_alive(alive); 35 | break; 36 | case "Glider": 37 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)); 38 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)+1); 39 | set_alive(Math.floor(width/8),Math.floor(height/8)+1); 40 | set_alive(Math.floor(width/8)-1,Math.floor(height/8)+1); 41 | set_alive(Math.floor(width/8),Math.floor(height/8)-1); 42 | show_state(); 43 | break; 44 | case "LWSS": 45 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)); 46 | set_alive(Math.floor(width/8)+2,Math.floor(height/8)); 47 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)+1); 48 | set_alive(Math.floor(width/8),Math.floor(height/8)+1); 49 | set_alive(Math.floor(width/8)-1,Math.floor(height/8)+1); 50 | set_alive(Math.floor(width/8)-2,Math.floor(height/8)+1); 51 | set_alive(Math.floor(width/8),Math.floor(height/8)+2); 52 | set_alive(Math.floor(width/8)-1,Math.floor(height/8)+2); 53 | set_alive(Math.floor(width/8)-1,Math.floor(height/8)); 54 | set_alive(Math.floor(width/8)-2,Math.floor(height/8)); 55 | set_alive(Math.floor(width/8),Math.floor(height/8)-1); 56 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)-1); 57 | break; 58 | case "Pulsar": 59 | for (var i = -4; i <= 4; i++) { 60 | if (i <= -2 || i >= 2) { 61 | set_alive(Math.floor(width/8)+i,Math.floor(height/8)-1); 62 | set_alive(Math.floor(width/8)+i,Math.floor(height/8)+1); 63 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)+i); 64 | set_alive(Math.floor(width/8)-1,Math.floor(height/8)+i); 65 | 66 | set_alive(Math.floor(width/8)+i,Math.floor(height/8)-6); 67 | set_alive(Math.floor(width/8)+i,Math.floor(height/8)+6); 68 | set_alive(Math.floor(width/8)+6,Math.floor(height/8)+i); 69 | set_alive(Math.floor(width/8)-6,Math.floor(height/8)+i); 70 | } 71 | } 72 | break; 73 | case "Gun": 74 | set_alive(Math.floor(width/8)-13,Math.floor(height/8)); 75 | set_alive(Math.floor(width/8)-14,Math.floor(height/8)); 76 | set_alive(Math.floor(width/8)-13,Math.floor(height/8)-1); 77 | set_alive(Math.floor(width/8)-14,Math.floor(height/8)-1); 78 | 79 | 80 | set_alive(Math.floor(width/8)-4,Math.floor(height/8)-1); 81 | set_alive(Math.floor(width/8)-4,Math.floor(height/8)); 82 | set_alive(Math.floor(width/8)-4,Math.floor(height/8)+1); 83 | set_alive(Math.floor(width/8)-3,Math.floor(height/8)-2); 84 | set_alive(Math.floor(width/8)-3,Math.floor(height/8)+2); 85 | set_alive(Math.floor(width/8)-2,Math.floor(height/8)-3); 86 | set_alive(Math.floor(width/8)-2,Math.floor(height/8)+3); 87 | set_alive(Math.floor(width/8)-1,Math.floor(height/8)-3); 88 | set_alive(Math.floor(width/8)-1,Math.floor(height/8)+3); 89 | 90 | set_alive(Math.floor(width/8),Math.floor(height/8)); 91 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)-2); 92 | set_alive(Math.floor(width/8)+1,Math.floor(height/8)+2); 93 | set_alive(Math.floor(width/8)+2,Math.floor(height/8)-1); 94 | set_alive(Math.floor(width/8)+2,Math.floor(height/8)); 95 | set_alive(Math.floor(width/8)+2,Math.floor(height/8)+1); 96 | set_alive(Math.floor(width/8)+3,Math.floor(height/8)); 97 | 98 | 99 | 100 | set_alive(Math.floor(width/8)+6,Math.floor(height/8)-1); 101 | set_alive(Math.floor(width/8)+6,Math.floor(height/8)-2); 102 | set_alive(Math.floor(width/8)+6,Math.floor(height/8)-3); 103 | set_alive(Math.floor(width/8)+7,Math.floor(height/8)-1); 104 | set_alive(Math.floor(width/8)+7,Math.floor(height/8)-2); 105 | set_alive(Math.floor(width/8)+7,Math.floor(height/8)-3); 106 | 107 | set_alive(Math.floor(width/8)+8,Math.floor(height/8)); 108 | set_alive(Math.floor(width/8)+8,Math.floor(height/8)-4); 109 | set_alive(Math.floor(width/8)+10,Math.floor(height/8)); 110 | set_alive(Math.floor(width/8)+10,Math.floor(height/8)+1); 111 | set_alive(Math.floor(width/8)+10,Math.floor(height/8)-4); 112 | set_alive(Math.floor(width/8)+10,Math.floor(height/8)-5); 113 | 114 | 115 | 116 | set_alive(Math.floor(width/8)+20,Math.floor(height/8)-3); 117 | set_alive(Math.floor(width/8)+20,Math.floor(height/8)-2); 118 | set_alive(Math.floor(width/8)+21,Math.floor(height/8)-3); 119 | set_alive(Math.floor(width/8)+21,Math.floor(height/8)-2); 120 | 121 | break; 122 | case "Stripes": 123 | for (var i = 0; i < Math.floor(width/4); i=i+2) { 124 | for (var j = 0; j < Math.floor(height/4); j++) { 125 | set_alive(i,j); 126 | } 127 | } 128 | break; 129 | case "Image": 130 | 131 | var img = new Image(); 132 | img.onload = function() { 133 | document.getElementById("image").getContext("2d").drawImage(img,0,0, Math.floor(width/4), Math.floor(height/4)); 134 | 135 | var imageData = document.getElementById("image").getContext("2d").getImageData(0, 0, Math.floor(width/4), Math.floor(height/4)); 136 | 137 | var lightness_max = 0; 138 | var lightness_min = 255; 139 | var lightness_array = new Array(Math.floor(width/4)); 140 | 141 | for (var x = 0; x < Math.floor(width/4); x++) { 142 | lightness_array[x] = new Array(Math.floor(height/4)); 143 | for (var y = 0; y < Math.floor(height/4); y++) { 144 | var lightness = 0; 145 | var index = (y*imageData.width + x) * 4; 146 | var red = parseInt(imageData.data[index]); 147 | var green = parseInt(imageData.data[index + 1]); 148 | var blue = parseInt(imageData.data[index + 2]); 149 | lightness = parseInt((0.2126*red) + (0.7152*green) + (0.0722*blue)); 150 | if (lightness > lightness_max) { lightness_max = lightness; } 151 | if (lightness < lightness_min) { lightness_min = lightness; } 152 | lightness_array[x][y] = lightness; 153 | } 154 | } 155 | med_lightness = 0.5*(lightness_max+lightness_min); 156 | 157 | for (var x = 0; x < Math.floor(width/4); x++) { 158 | for (var y = 0; y < Math.floor(height/4); y++) { 159 | if (lightness_array[x][y] <= med_lightness) { 160 | set_alive(x,y); 161 | } 162 | } 163 | } 164 | 165 | }; 166 | img.src = document.getElementById("img_image").src; 167 | } 168 | 169 | 170 | var i = 0; 171 | setTimeout(function () { 172 | get_next_step(1); 173 | }, timeout); 174 | 175 | } 176 | 177 | 178 | 179 | this.set_stop = function() { 180 | stop = true; 181 | } 182 | 183 | function create_grid() { 184 | ctx.strokeStyle = '#eee'; 185 | ctx.lineWidth = 1; 186 | ctx.beginPath(); 187 | //vertical 188 | for(var i = 0; i <= Math.floor(width/4); i++) { 189 | ctx.moveTo(i*4,0); 190 | ctx.lineTo(i*4,500); 191 | ctx.stroke(); 192 | } 193 | //horizontal 194 | for(var i = 0; i <= Math.floor(width/4); i++) { 195 | ctx.moveTo(0,i*4); 196 | ctx.lineTo(1000,i*4); 197 | ctx.stroke(); 198 | } 199 | ctx.closePath(); 200 | } 201 | 202 | function random_alive(nr) { 203 | var i = 0; 204 | while (i < nr) { 205 | var xrand = Math.floor(Math.random() * (Math.floor(width/4))); 206 | var yrand = Math.floor(Math.random() * (Math.floor(height/4))); 207 | if (GoL_array[xrand][yrand] == 0) { 208 | set_alive(xrand,yrand); 209 | i++; 210 | } 211 | } 212 | } 213 | 214 | function set_alive(x,y) { 215 | ctx.fillStyle = '#000000'; 216 | GoL_array[x][y] = 1; 217 | ctx.fillRect(x*4+1,y*4+1,2,2); 218 | } 219 | 220 | function set_dead(x,y) { 221 | ctx.fillStyle = '#FFFFFF'; 222 | GoL_array[x][y] = 0; 223 | ctx.fillRect(x*4+1,y*4+1,2,2); 224 | } 225 | 226 | 227 | function get_next_step(step) { 228 | if (stop === false && step < steps) { 229 | for (var x=0; x < Math.floor(width/4); x++) { 230 | for (var y=0; y < Math.floor(height/4); y++) { 231 | var c_dead = 0; 232 | 233 | for (var sx=x-1; sx<=x+1; sx++) { 234 | for (var sy=y-1; sy<=y+1; sy++) { 235 | if (sx == -1 || sx == Math.floor(width/4) || sy == -1 || sy == Math.floor(height/4)) { 236 | c_dead++; 237 | }else { 238 | if (GoL_array[sx][sy] == 0) { c_dead++; } 239 | } 240 | } 241 | } 242 | 243 | state = GoL_array[x][y]; 244 | switch (state) { 245 | case 0: // dead 246 | c_dead--; 247 | if (c_dead == 5) { // exactly 3 alive 248 | next_GoL_array[x][y] = 1; 249 | } 250 | break; 251 | case 1: // alive 252 | if (c_dead >= 7 || c_dead < 5) { // <2 alive or >3 253 | next_GoL_array[x][y] = 0; 254 | } 255 | if (c_dead == 5 || c_dead == 6) { 256 | next_GoL_array[x][y] = 1; 257 | } 258 | break; 259 | } 260 | 261 | } 262 | 263 | } 264 | 265 | for (var x=0; x < Math.floor(width/4); x++) { 266 | for (var y=0; y < Math.floor(height/4); y++) { 267 | GoL_array[x][y] = next_GoL_array[x][y]; 268 | } 269 | } 270 | 271 | show_state(); 272 | step++; 273 | setTimeout(function () { 274 | get_next_step(step); 275 | }, timeout); 276 | } 277 | } 278 | 279 | function show_state() { 280 | var alive = 0; 281 | for (var x=0; x < Math.floor(width/4); x++) { 282 | for (var y=0; y < Math.floor(height/4); y++) { 283 | if (GoL_array[x][y] == 0) { 284 | set_dead(x,y); 285 | } else { 286 | set_alive(x,y); 287 | alive++; 288 | } 289 | } 290 | } 291 | } 292 | } --------------------------------------------------------------------------------