Created
March 15, 2015 17:50
-
-
Save bylatt/4b1f24ec991c9e8bad39 to your computer and use it in GitHub Desktop.
Trees
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <head> | |
| <title>Canvas Trees</title> | |
| <script type="text/javascript" src="http://code.jquery.com/jquery-1.3.2.min.js"></script> | |
| <script type="text/javascript" src="canvastree.js"></script> | |
| <style> | |
| body { | |
| text-align: center; | |
| /* background-color: #abcdef; */ | |
| } | |
| canvas#canvastree { | |
| position: relative; | |
| margin-left: auto; | |
| margin-right: auto; | |
| width: 750px; | |
| height: 400px; | |
| border-bottom: 1px solid black; | |
| } | |
| a { | |
| color: black; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <canvas id="canvastree"></canvas> | |
| <div><a href="http://kennethjorgensen.com/blog">blog</a></div> | |
| <!-- <div id="info-container"> | |
| <div id="info"></div> | |
| <div id="fps"></div> | |
| </div> --> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Snake = function(canvas) { | |
| this.setCanvas(canvas); | |
| this.x = this.canvasWidth/2; | |
| this.y = this.canvasHeight; | |
| this.radius = 10; | |
| this.speed = this.canvasWidth/500; | |
| this.angle = Math.PI/2; | |
| this.angleDiversion = | |
| this.fillStyle = "#000000"; | |
| this.shadowColor = "#000000"; | |
| this.shadowBlur = 2; | |
| this.generation = 0; | |
| this.lifespan = 0; | |
| this.totalDistance = 0; | |
| this.distance = 0; | |
| }; | |
| Snake.prototype = { | |
| setCanvas: function(canvas) { | |
| this.canvas = canvas; | |
| this.context = canvas.getContext("2d"); | |
| this.$canvas = jQuery(canvas); | |
| this.canvasWidth = $canvas.width(); | |
| this.canvasHeight = $canvas.height(); | |
| }, | |
| next: function() { | |
| this.draw(); | |
| this.iterate(); | |
| this.randomize(); | |
| // this.limitSpeed(); | |
| // this.reset(context); | |
| this.split(); | |
| this.lifespan++; | |
| this.die(); | |
| }, | |
| draw: function() { | |
| var context = this.context; | |
| context.save(); | |
| context.fillStyle = this.fillStyle; | |
| context.shadowColor = this.shadowColor; | |
| context.shadowBlur = this.shadowBlur; | |
| context.beginPath(); | |
| context.moveTo(this.x, this.y); | |
| context.arc(this.x, this.y, this.radius, 0, 2*Math.PI, true); | |
| context.closePath(); | |
| context.fill(); | |
| context.restore(); | |
| }, | |
| iterate: function() { | |
| var lastX = this.x; | |
| var lastY = this.y; | |
| this.x += this.speed * Math.cos(this.angle); | |
| this.y += this.speed * -Math.sin(this.angle); | |
| this.radius *= (0.99 - this.generation/250); // minus 0.004 per generation | |
| var deltaDistance = Math.sqrt(Math.abs(lastX-this.x) + Math.abs(lastY-this.y)); | |
| this.distance += deltaDistance; | |
| this.totalDistance += deltaDistance; | |
| if (this.speed > this.radius*2) | |
| this.speed = this.radius*2; | |
| }, | |
| randomize: function() { | |
| this.angle += Math.random()/5 - 1/5/2; | |
| }, | |
| reset: function(context) { | |
| var $canvas = jQuery(context.canvas); | |
| var margin = 30+this.radius; | |
| var width = $canvas.width(); | |
| var height = $canvas.height(); | |
| if (this.x < -margin || this.x > width+margin || this.y < -margin || this.y > height+margin) { | |
| // this.x = width/2; | |
| this.y = height; | |
| // New color | |
| var grey = Math.floor(Math.random()*255).toString(16); | |
| this.fillStyle = "#" + grey + grey + grey; | |
| this.shadowColor = this.fillStyle; | |
| } | |
| }, | |
| split: function() { | |
| // Calculate split chance | |
| var splitChance = 0; | |
| // Trunk | |
| if (this.generation == 0) | |
| splitChance = (this.distance-this.canvasHeight/5)/100; | |
| // Branch | |
| else if (this.generation < 3) | |
| splitChance = (this.distance-this.canvasHeight/10)/100; | |
| // Split if we are allowed | |
| if (Math.random() < splitChance) { | |
| var n = 2+Math.round(Math.random()*2); | |
| for (var i=0 ; i<n ; i++) { | |
| var snake = new Snake(this.canvas); | |
| snake.x = this.x; | |
| snake.y = this.y; | |
| snake.angle = this.angle; | |
| snake.speed = this.speed; | |
| snake.radius = this.radius * 0.9; | |
| snake.generation = this.generation + 1; | |
| snake.fillStyle = this.fillStyle; | |
| snake.shadowColor = this.shadowColor; | |
| snake.shadowBlur = this.shadowBlur; | |
| snake.totalDistance = this.totalDistance; | |
| this.collection.add(snake); | |
| } | |
| this.collection.remove(this); | |
| } | |
| }, | |
| die: function() { | |
| if (this.radius < 0.2) { | |
| this.collection.remove(this); | |
| // console.log(this.distance); | |
| } | |
| } | |
| } | |
| SnakeCollection = function() { | |
| this.canvas = canvas; | |
| this.snakes = []; | |
| } | |
| SnakeCollection.prototype = { | |
| next: function() { | |
| n = this.snakes.length; | |
| for (var s in this.snakes) { | |
| var snake = this.snakes[s]; | |
| if (this.snakes[s]) | |
| this.snakes[s].next(); | |
| } | |
| }, | |
| add: function(snake) { | |
| this.snakes.push(snake); | |
| snake.collection = this; | |
| }, | |
| remove: function(snake) { | |
| for (var s in this.snakes) | |
| if (this.snakes[s] === snake) | |
| this.snakes.splice(s, 1); | |
| } | |
| } | |
| function randHex() { | |
| var num = Math.round(Math.random() * 255).toString(16); | |
| if (num.length == 1) | |
| num = "0"+num; | |
| return num; | |
| } | |
| jQuery(function() { | |
| // Convenience | |
| $canvas = jQuery("canvas#canvastree"); | |
| canvas = $canvas[0]; | |
| context = canvas.getContext("2d"); | |
| // Dimensions | |
| var width = $canvas.width(); | |
| var height = $canvas.height(); | |
| // Set actual canvas size to match css | |
| $canvas.attr("width", width); | |
| $canvas.attr("height", height); | |
| // Information | |
| jQuery("#info").html("Size: "+canvas.width+"x"+canvas.height); | |
| // Frame rate | |
| var frame = 0; | |
| // Snakes | |
| var n = 2+Math.random()*3; | |
| var initialRadius = width/50; | |
| snakes = new SnakeCollection(); | |
| for (var i=0 ; i<n ; i++) { | |
| var snake = new Snake(canvas); | |
| snake.x = width/2 - initialRadius + i*initialRadius*2/n; | |
| snake.radius = initialRadius; | |
| snakes.add(snake); | |
| } | |
| // Frame drawer | |
| var interval = setInterval(function() { | |
| snakes.next(); | |
| frame++; | |
| }, 0); | |
| // fps | |
| // var fpsInterval = setInterval(function() { | |
| // jQuery("#fps").html(frame+" fps<br/>"+snakes.snakes.length+" branches running"); | |
| // frame = 0; | |
| // if (snakes.snakes.length == 0) { | |
| // clearInterval(interval); | |
| // clearInterval(fpsInterval); | |
| // var delay = 1500; | |
| // jQuery("#info-container").fadeOut(1500, function(){ | |
| // jQuery("#info-container").html("Refresh for more delicious trees :)").fadeIn(delay, function() { | |
| // setTimeout(function() { | |
| // jQuery("#info-container").fadeOut(delay); | |
| // }, delay*3) | |
| // }); | |
| // }); | |
| // } | |
| // }, 1000); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment