Permalink
Browse files

initial, gravity simulator - no constraints yet

  • Loading branch information...
0 parents commit e923be6661c7abe574a63a7f3ec3a4b00bfcc223 @dominictarr committed Jan 20, 2012
Showing with 308 additions and 0 deletions.
  1. +3 −0 .gitignore
  2. +145 −0 index.html
  3. +112 −0 lib/vector.js
  4. +11 −0 package.json
  5. +37 −0 readme.markdown
@@ -0,0 +1,3 @@
+node_modules
+node_modules/*
+npm_debug.log
@@ -0,0 +1,145 @@
+<html>
+
+<body>
+
+<canvas id=canvas width=2000 height=1600></canvas>
+</body>
+
+<script src="lib/vector.js"></script>
+<script>
+var canvas = document.getElementById('canvas')
+var context = canvas.getContext('2d');
+var center = new Vector(canvas.width/2,canvas.height/2)
+ //paint whole canvas black
+
+ var bodies = []
+ function randV() {
+ return Vector.random(canvas.width,canvas.height).iabs()
+ }
+ function randS() {
+ return ((Math.random()*50)+ 10)
+ }
+ function Body (v, r) {
+ this.origin = v || randV()
+ this.velocity = Vector.a2v(Math.random()*2*Math.PI).imul(10)
+ this._origin = this.origin.sub(this.velocity)
+ this.speed = this.velocity.length()
+ this.radius = r || randS()
+ }
+
+ function each(ary, iter) {
+ for(var i in ary) iter(ary[i],i,ary)
+ }
+ function times(n, iter) {
+ var i = 0; while (i < n) iter(i++, n)
+ }
+ function drawBody (b) {
+ context.strokeStyle = 'rgba(0,255,0,1)';
+ context.lineWidth = 1;
+ context.beginPath();
+ context.arc(b.origin.x, b.origin.y, b.radius, 0, Math.PI*2, false);
+ context.stroke()
+ }
+
+ function draw() {
+ context.fillStyle = 'rgba(40,40,40,0.1)';
+ context.fillRect(0, 0, canvas.width, canvas.height);
+ each(bodies, drawBody)
+ }
+
+ times(36, function () {bodies.push(new Body())})
+ draw()
+
+ var G = 150000;
+ function getGravity (a, b) {
+ var dir = a.sub(b)
+ var l = dir.length() //there are unnecessary Math.sqrt, since nor also gets length
+ return dir.nor().imul(G/(l*l))
+ }
+
+ function assert(test, message) {
+ if(!test) throw new Error(message)
+ }
+
+ /*
+ VERTLET INTEGRATION
+ it make a big difference which way around this is done.
+ I had it like this before:
+
+ body.origin
+ .imul(2).isub(_origin)
+ .iadd(getGravity(center, body.origin).imul(delta))
+
+ I noticed that all my planets would fall into the gravity well and be slingshot
+ out. some would then fall back into the well...
+ they where loosing energy. I changed it, so that I add the acceleration
+ due to gravity first -- and it looks right. more stable orbits.
+
+ another idea:
+ variable timeslices with euler integration
+ -- give faster moving slices more steps.
+
+ */
+ setInterval(function () {
+ var delta = 0.1 //seconds
+
+ //sort bodies by thier speed, decending
+ bodies.sort(function (a,b) {
+ return b.speed - a.speed
+ })
+ var totalSpeed = 0
+ console.log(bodies.map(function (b) {
+ var s = Math.round(b.speed)
+ totalSpeed += s
+ return s
+ }).join(','))
+
+
+ function step(body, delta) {
+ /*
+ // verlet integration (_origin is last tick's origin)
+ body.origin
+ .iadd(getGravity(center, body.origin).imul(delta))
+ .imul(2).isub(_origin)
+ */
+ body.velocity.iadd(getGravity(center, body.origin).imul(delta))
+ body.speed = body.velocity.length()
+ body.origin.iadd(body.velocity.mul(delta))
+ }
+
+ /*
+ give each body steps depending on the square of it's speed.
+ this works fairly well. getting lots of quite stable highly eliptical orbits.
+ interestingly, I'm not seeing many regular orbits.
+
+ bodies do have a tendency to fall into the gravity well eventually...(rounding errors?)
+
+ the body moves quickly at the perigee, but slowly at the apogee.
+ approximating the curve with many straight lines is more accurate when
+ you use more lines. the apogee uses many slices, since it's moving slowly.
+ I have made it use more slices at the perigee, but is it the same number
+ of steps per distance traveled?
+
+ also, note at the perigee the steps (thus the delta) is very small.
+ could this cause rounding error? at the apogee the speed is very small,
+ could this balance out the small delta at the perigee?
+
+ currently, I always doing at least one step per frame, maybe it would be better
+ to update steps per object independent of frames...
+ so that it does not loose energy.
+
+ another (heavy) approach would just be to use BigDecimals.
+ though, that will be much slower it would be better to just not care.
+ */
+
+ each(bodies, function (b) {
+ var steps = Math.round((b.speed*b.speed)/100) || 1
+ var l = steps
+ while(l --)
+ step(b,delta/steps)
+ })
+ draw()
+ }, 100)
+
+</script>
+</html>
@@ -0,0 +1,112 @@
+
+function v(x, y) {
+ return new Vector(x, y)
+}
+
+Vector.a2v = function (a) { return new Vector(Math.cos(a), Math.sin(a)) }
+function r() {
+ return Math.random()*2 - 1
+}
+Vector.random = function (x,y) {
+ return new Vector(r()*x, r()*y)
+}
+Vector.center = function () {
+ var c = new Vector(0,0)
+ for (var i = 0; i < arguments.length; i ++) {
+ c.iadd(arguments[i])
+ }
+ return c.idiv(arguments.length)
+}
+
+function Vector (x, y) {
+ if('object' === typeof x && x) {
+ this.x = x.x || 0;
+ this.y = x.y || 0;
+ } else {
+ this.x = x || 0;
+ this.y = y || 0;
+ }
+}
+
+Vector.prototype = {
+ dot: function (v) {
+ return this.x * v.x + this.y * v.y
+ },
+ length: function () {
+ return Math.sqrt(this.x*this.x + this.y*this.y)
+ },
+ iadd: function (v) {
+ this.x += v.x;
+ this.y += v.y;
+ return this;
+ },
+ isub: function (v) {
+ this.x -= v.x;
+ this.y -= v.y;
+ return this;
+ },
+ imul: function (scalar) {
+ this.x *= scalar;
+ this.y *= scalar;
+ return this;
+ },
+ idiv: function (scalar) {
+ this.x /= scalar;
+ this.y /= scalar;
+ return this;
+ },
+ izero: function () {
+ this.x = 0;
+ this.y = 0;
+ return this;
+ },
+ inor: function () {
+ var l = this.length();
+ this.x /= l;
+ this.y /= l;
+ return this;
+ },
+ iabs: function () {
+ this.x = Math.abs(this.x)
+ this.y = Math.abs(this.y)
+ return this
+ },
+ add: function (v) {
+ return new Vector(this).iadd(v);
+ },
+ sub: function (v) {
+ return new Vector(this).isub(v);
+ },
+ mul: function (v) {
+ return new Vector(this).imul(v);
+ },
+ div: function (v) {
+ return new Vector(this).idiv(v);
+ },
+ nor: function () {
+ return new Vector(this).inor();
+ },
+ abs: function () {
+ return new Vector(this).iabs();
+ },
+ //always positive
+ diff: function (v) {
+ return new Vector(
+ Math.abs(this.x - v.x),
+ Math.abs(this.y - v.y)
+ )
+ },
+ //distance between this and the other point.
+ dist: function (v) {
+ return this.diff(v).length()
+ },
+ angle: function () {
+ return Math.atan(this.x/this.y) * (this.x > 0 ? 1 : -1 )
+ },
+ clone: function () {
+ return new Vector(this)
+ },
+ toString: function () {
+ return '('+this.x+','+this.y+')'
+ }
+}
@@ -0,0 +1,11 @@
+{ "name": "phyxel"
+, "version": "0.0.0"
+, "description": ""
+, "homepage": "http://github.com/dominictarr/phyxel"
+, "repository":
+ { "type": "git"
+ , "url": "https://github.com/dominictarr/phyxel.git" }
+, "dependencies": {}
+, "devDependencies": {}
+, "author": "Dominic Tarr <dominic.tarr@gmail.com> (http://bit.ly/dominictarr)"
+, "scripts": { "test": "meta-test test/*.js" } }
@@ -0,0 +1,37 @@
+# Phyxel
+
+experimental voxel based 2d physics.
+
+
+THIS IS JUST A ORBIT SIMULATOR, FOR NOW
+
+
+CRAZY IDEA
+
+fluids:
+
+ gas light, non dense, possibly moving partices, not sticky.
+
+ liquids: denser, sticky, surface tension.
+
+solids:
+
+ solid: dense, stiffly stuck to other solid things, but can be flexible or brittle.
+ connections can have a direction, so a chain can have stiffness, and brittleness.
+
+advantages:
+
+ simpler simulation,
+ each phyxel has a few simple properties, that my affect neibouring phyxels. (say, 6)
+ instead of having alot of complicated rules and checks. just make every thing a circle.
+
+ideas:
+
+ would be cool to be able to freeze or melt parts of a game level,
+ freeze to make it brittle, then smash it. melt through things,
+ float on water or fly in the air maybe?
+
+ maybe it'll be better to make the phyxels "large"... and lift wont work right.
+ that is okay, also, the entities in the game might be werid. walking and stuff...
+ maybe should just have them roll sideways, hover, or allow a few 'magical' forces.
+

0 comments on commit e923be6

Please sign in to comment.