diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-06-03 16:24:10 -0400 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-06-03 16:24:28 -0400 |
| commit | 607f69c67a5b4dc72d2754192e3cdf67d0ad11d0 (patch) | |
| tree | 6556e7922c5bedb274bb1650e5dd100643a7895d /client/assets/javascripts/rectangles/models | |
| parent | d31259291d807c851de4396921e0c26b6dd8dce2 (diff) | |
partitioning client and serveR
Diffstat (limited to 'client/assets/javascripts/rectangles/models')
| -rw-r--r-- | client/assets/javascripts/rectangles/models/rect.js | 176 | ||||
| -rw-r--r-- | client/assets/javascripts/rectangles/models/room.js | 213 | ||||
| -rw-r--r-- | client/assets/javascripts/rectangles/models/tree.js | 37 | ||||
| -rw-r--r-- | client/assets/javascripts/rectangles/models/vec2.js | 99 | ||||
| -rw-r--r-- | client/assets/javascripts/rectangles/models/vec3.js | 5 | ||||
| -rw-r--r-- | client/assets/javascripts/rectangles/models/wall.js | 120 |
6 files changed, 650 insertions, 0 deletions
diff --git a/client/assets/javascripts/rectangles/models/rect.js b/client/assets/javascripts/rectangles/models/rect.js new file mode 100644 index 0000000..7a2ac6f --- /dev/null +++ b/client/assets/javascripts/rectangles/models/rect.js @@ -0,0 +1,176 @@ + +window.Rect = (function(){ + var Rect = function (x0,y0,x1,y1){ + if (x0 instanceof vec2) { + this.x = x0 + this.y = y0 + } + else if (x1 === undefined) { + this.x = new vec2(x0,x0) + this.y = new vec2(y0,y0) + } + else { + this.x = new vec2(x0,x1) + this.y = new vec2(y0,y1) + } + this.translation = new vec2(0,0) + this.sides = FRONT | BACK | LEFT | RIGHT + } + Rect.prototype.clone = function(){ + return new Rect( this.x.clone(), this.y.clone() ) + } + Rect.prototype.center = function(){ + return new vec2(this.x.midpoint(), this.y.midpoint()) + } + Rect.prototype.area = function(){ + return this.x.length() * this.y.length() + } + + Rect.prototype.mul = function(n){ + this.x.mul(n) + this.y.mul(n) + return this + } + Rect.prototype.div = function(n){ + this.x.div(n) + this.y.div(n) + return this + } + + Rect.prototype.translate = function(translation){ + var translation = translation || this.translation + this.x.abs().add(translation.a) + this.y.abs().add(translation.b) + this.translation.a = this.translation.b = 0 + return this + } + Rect.prototype.resize = function(translation, sides){ + var translation = translation || this.translation + sides = sides || translation.sides + + if (sides & LEFT) { + this.x.a += translation.a + } + if (sides & RIGHT) { + this.x.b += translation.a + } + if (sides & FRONT) { + this.y.a += translation.b + } + if (sides & BACK) { + this.y.b += translation.b + } + this.translation.a = this.translation.b = 0 + } + Rect.prototype.contains = function(x,y){ + return this.x.contains(x) && this.y.contains(y) + } + Rect.prototype.containsDisc = function(x,y,r){ + return this.x.containsDisc(x,r) && this.y.containsDisc(y,r) + } + Rect.prototype.intersects = function(r){ + return this.x.intersects(r.x) && this.y.intersects(r.y) + } + Rect.prototype.nearEdge = function (x, y, r) { + var edges = 0 + if (x < this.x.a+r) { + edges |= LEFT + } + else if (x > this.x.b-r) { + edges |= RIGHT + } + if (y < this.y.a+r) { + edges |= FRONT + } + else if (y > this.y.b-r) { + edges |= BACK + } + return edges + } + Rect.prototype.width = function(){ return this.x.length() } + Rect.prototype.height = function(){ return this.y.length() } + Rect.prototype.toString = function(){ + var sides = sidesToString(this.sides) + var s = "[" + this.x.toString() + " " + this.y.toString() + "] " + sides + return s + } + Rect.prototype.quantize = function(n){ + this.x.quantize(n) + this.y.quantize(n) + return this + } + Rect.prototype.split = function(r){ + var rz = this + var splits = [] + var split_contains = 0 + var x_intervals = [], y_intervals = [] + var sides = this.sides + + // Split vertically + if (this.x.contains(r.x.a) && r.x.contains(this.x.b)) { + x_intervals.push([ new vec2( this.x.a, r.x.a ), LEFT ]) + x_intervals.push([ new vec2( r.x.a, this.x.b ), RIGHT ]) + split_contains |= RIGHT + } + + else if (r.x.contains(this.x.a) && this.x.contains(r.x.b)) { + x_intervals.push([ new vec2( this.x.a, r.x.b ), LEFT ]) + x_intervals.push([ new vec2( r.x.b, this.x.b ), RIGHT ]) + split_contains |= LEFT + } + + else if (this.x.contains(r.x.a) && this.x.contains(r.x.b)) { + x_intervals.push([ new vec2( this.x.a, r.x.a ), LEFT ]) + x_intervals.push([ new vec2( r.x.a, r.x.b ), 0 ]) + x_intervals.push([ new vec2( r.x.b, this.x.b ), RIGHT ]) + split_contains |= LEFT | RIGHT + } + + else { // if (r.x.contains(this.x.a) && r.x.contains(r.x.b)) { + x_intervals.push([ new vec2( this.x.a, this.x.b ), LEFT | RIGHT ]) + split_contains |= LEFT | RIGHT + } + + // Split horizontally + if (this.y.contains(r.y.a) && r.y.contains(this.y.b)) { + y_intervals.push([ new vec2( this.y.a, r.y.a ), FRONT ]) + y_intervals.push([ new vec2( r.y.a, this.y.b ), BACK ]) + split_contains |= BACK + } + + else if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { + y_intervals.push([ new vec2( this.y.a, r.y.b ), FRONT ]) + y_intervals.push([ new vec2( r.y.b, this.y.b ), BACK ]) + split_contains |= FRONT + } + + else if (this.y.contains(r.y.a) && this.y.contains(r.y.b)) { + y_intervals.push([ new vec2( this.y.a, r.y.a ), FRONT ]) + y_intervals.push([ new vec2( r.y.a, r.y.b ), 0 ]) + y_intervals.push([ new vec2( r.y.b, this.y.b ), BACK ]) + split_contains |= FRONT | BACK + } + + else { // if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { + y_intervals.push([ new vec2( this.y.a, this.y.b ), FRONT | BACK ]) + split_contains |= FRONT | BACK + } + + x_intervals.forEach(function(x){ + y_intervals.forEach(function(y){ + var rn = new Rect(x[0], y[0]) + rn.id = rz.id + rn.sides = ((x[1] | y[1]) & sides) + if (r.intersects(rn)) { + rn.sides = 0 + } + rn.focused = rz.focused + splits.push(rn) + }) + }) + return splits + } + + return Rect + +})() diff --git a/client/assets/javascripts/rectangles/models/room.js b/client/assets/javascripts/rectangles/models/room.js new file mode 100644 index 0000000..731411c --- /dev/null +++ b/client/assets/javascripts/rectangles/models/room.js @@ -0,0 +1,213 @@ +window.Room = (function(){ + + var Room = function(opt){ + this.id = opt.id || Rooms.list.length + this.rect = opt.rect + this.regions = [] + this.walls = [] + this.floor = [] + this.ceiling = [] + + this.height = opt.height || 200 + this.focused = false + } + + Room.prototype.toString = function(){ + return this.rect.toString() + } + + Room.prototype.reset = function(){ + var copy = this.rect.clone() + copy.id = this.id + copy.sides = FRONT | BACK | LEFT | RIGHT + this.regions = [ copy ] + + this.intersects = [] + this.constructed = false + + this.walls = [] + + this.mx_walls = [] + this.mx_floor = [] + this.mx_ceiling = [] + } + + Room.prototype.bind = function(){ + var base = this + base.mx_walls.forEach(function(wall){ + $(wall.el).bind({ + mouseover: function(){ + }, + mousemove: function(e){ + var color = choice(window.palettes.colors) + base.mx_walls.forEach(function(wall){ + $(wall.el).css("background-color", color) + }) + }, + mousedown: function(){ + } + }) + }) + } + + Room.prototype.group_mx_walls = function(){ + var base = this + var side_groups = {}, walls = [] + + // group the walls by side + base.mx_walls.forEach(function(wall){ + + // ignore half-walls for now + var side = wall.side || wall.half_side + + if (side_groups[side]) { + side_groups[side].push(wall) + } + else { + side_groups[side] = [wall] + } + }) + + // sort the subgroups, and then combine mx objects under wall objects + pairs(side_groups).forEach(function(pair){ + var side = pair[0], els = pair[1] + + if (side & LEFT_RIGHT) { + els.sort(compare_x) + } + else if (side & FRONT_BACK) { + els.sort(compare_z) + } + + var wall + + els.forEach(function(el){ + if (el.half_side) { + wall = new_wall(el) + walls.push(wall) + wall = null + } + else if (! wall) { + wall = new_wall(el) + walls.push(wall) + } + else if (side & FRONT_BACK && wall.rect.x.b == el.rect.x.a) { + wall.rect.x.b = el.rect.x.b + wall.mx.push(el) + } + else if (side & LEFT_RIGHT && wall.rect.y.b == el.rect.y.a) { + wall.rect.y.b = el.rect.y.b + wall.mx.push(el) + } + else { + wall = new_wall(el) + walls.push(wall) + } + }) + }) + + function new_wall (el) { + return new Wall ({ + room: base.id, + side: el.side | el.half_side, + half_side: el.half_side, + rect: el.rect.clone(), + el: el, + }) + } + + return walls + } + + Room.prototype.clipTo = function(r){ + // for each of this rect's regions split the region if necessary + var regions = this.regions + var splits + for (var i = 0, len = regions.length; i < len; i++) { + if (regions[i] && regions[i].intersects(r)) { + splits = regions[i].split(r) + regions = regions.concat(splits) + regions[i] = null + } + } + this.regions = regions + } + + Room.prototype.collides = function(x,y){ + var collision = 0, wall_collision, contains_x, contains_y + this.regions.forEach(function(r){ + if (! r.sides) return + + wall_collision = 0 + + if ((r.sides & FRONT) && y < r.y.a) { + wall_collision |= FRONT + } + if ((r.sides & BACK) && r.y.b < y) { + wall_collision |= BACK + } + if ((r.sides & LEFT) && x < r.x.a) { + wall_collision |= LEFT + } + if ((r.sides & RIGHT) && r.x.b < x) { + wall_collision |= RIGHT + } + if (! wall_collision) return + + contains_y = r.y.contains(y) + contains_x = r.x.contains(x) + + if (contains_x) { + collision |= wall_collision & FRONT_BACK + } + else if (contains_y) { + collision |= wall_collision & LEFT_RIGHT + } + else if (bitcount(wall_collision) > 1) { + collision |= wall_collision + } + }) + return collision + } + + Room.prototype.collidesDisc = function(x,y,radius){ + var collision = 0, wall_collision, contains_x, contains_y + this.regions.forEach(function(r){ + if (! r.sides) return + + wall_collision = 0 + + if ((r.sides & FRONT) && y-radius < r.y.a) { + wall_collision |= FRONT + } + if ((r.sides & BACK) && r.y.b < y+radius) { + wall_collision |= BACK + } + if ((r.sides & LEFT) && x-radius < r.x.a) { + wall_collision |= LEFT + } + if ((r.sides & RIGHT) && r.x.b < x+radius) { + wall_collision |= RIGHT + } + if (! wall_collision) return + + contains_x = r.x.contains(x, radius) + contains_y = r.y.contains(y, radius) + + if (contains_x) { + collision |= wall_collision & FRONT_BACK + } + else if (contains_y) { + collision |= wall_collision & LEFT_RIGHT + } + else if (bitcount(wall_collision) > 1) { + collision |= wall_collision + } + }) + return collision + } + + return Room + +})() + diff --git a/client/assets/javascripts/rectangles/models/tree.js b/client/assets/javascripts/rectangles/models/tree.js new file mode 100644 index 0000000..8193988 --- /dev/null +++ b/client/assets/javascripts/rectangles/models/tree.js @@ -0,0 +1,37 @@ +var Tree = function(n, data){ + this.lo = null + this.hi = null + this.value = n + this.data = data +} +Tree.prototype.find = function(n){ + if (n == this.value) return this + if (n < this.value) return this.lo ? this.lo.find(n) : this + if (n > this.value) return this.hi ? this.hi.find(n) : this +} +Tree.prototype.add = function(n, data){ + var closest = this.find(n) + if (n == closest.value) return closest + if (n < closest.value) return closest.lo = new Tree(n, data) + if (n > closest.value) return closest.hi = new Tree(n, data) +} +Tree.prototype.toArray = function(){ + var a = [] + if (this.lo) a = a.concat(this.lo.toArray()) + a.push(this.data) + if (this.hi) a = a.concat(this.hi.toArray()) + return a +} +Tree.prototype.toString = function(){ + var s = ""; + if (this.lo) s += this.lo.toString() + s += this.value + "," + if (this.hi) s += this.hi.toString() + return s +} +Tree.prototype.depth = function(){ + if (this.lo && this.hi) return 1 + max(this.lo.depth(), this.hi.depth()) + else if (this.lo) return 1 + this.lo.depth() + else if (this.hi) return 1 + this.hi.depth() + else return 0 +} diff --git a/client/assets/javascripts/rectangles/models/vec2.js b/client/assets/javascripts/rectangles/models/vec2.js new file mode 100644 index 0000000..9b0447c --- /dev/null +++ b/client/assets/javascripts/rectangles/models/vec2.js @@ -0,0 +1,99 @@ +function vec2(a,b){ + this.a = a + this.b = b +} +vec2.prototype.magnitude = function(){ + return this.b-this.a +} +vec2.prototype.length = function(){ + return abs(this.b-this.a) +} +vec2.prototype.clone = function(){ + return new vec2(this.a, this.b) +} +vec2.prototype.abs = function(){ + if (this.b < this.a) { + this.invert() + } + return this +} +vec2.prototype.invert = function(){ + this.a = this.a ^ this.b + this.b = this.a ^ this.b + this.a = this.a ^ this.b + return this +} +vec2.prototype.midpoint = function(){ + return lerp(0.5, this.a, this.b) +} +vec2.prototype.eq = function(v){ + return this.a == v.a && this.b == v.b +} +vec2.prototype.add = function(n){ + this.a += n + this.b += n + return this +} +vec2.prototype.sub = function(n){ + this.a -= n + this.b -= n + return this +} +vec2.prototype.mul = function(n){ + this.a *= n + this.b *= n + return this +} +vec2.prototype.div = function(n){ + this.a /= n + this.b /= n + return this +} +vec2.prototype.normalize = function(){ + var dim = max(this.a, this.b) + this.a = this.a/dim + this.b = this.b/dim + return this +} +vec2.prototype.contains = function(n){ + return this.a <= n && n <= this.b +} +vec2.prototype.containsDisc = function(n,r){ + return this.a <= n-r && n+r <= this.b +} +vec2.prototype.clamp = function(n){ + return clamp(n, this.a, this.b) +} +vec2.prototype.clampDisc = function(n,r){ + return clamp(n, this.a+r, this.b-r) +} +vec2.prototype.intersects = function(v){ + if (this.a < v.a) { + return (v.a < this.b && this.b <= v.b) || (this.a < v.b && v.b <= this.b) + } + else if (this.a == v.a) { + return true + } + else if (this.a > v.a) { + return (this.a < v.b && v.b <= this.b) || (v.a < this.b && this.b <= v.b) + } +} +vec2.prototype.union = function(v){ + if (this.intersects(v)) { + return new vec2( min(this.a,v.a), max(this.b, v.b) ) + } +} +vec2.prototype.intersection = function(v){ + if (this.intersects(v)) { + return new vec2( max(this.a,v.a), min(this.b, v.b) ) + } +} +vec2.prototype.toString = function(){ + return "[" + ~~this.a + " " + ~~this.b + "]" +} +vec2.prototype.quantize = function(n){ + n = n || 10 + this.a = quantize(this.a, n) + this.b = quantize(this.b, n) +} + diff --git a/client/assets/javascripts/rectangles/models/vec3.js b/client/assets/javascripts/rectangles/models/vec3.js new file mode 100644 index 0000000..4e9f3cb --- /dev/null +++ b/client/assets/javascripts/rectangles/models/vec3.js @@ -0,0 +1,5 @@ +function vec3(a,b,c){ + this.a = a + this.b = b + this.c = c +} diff --git a/client/assets/javascripts/rectangles/models/wall.js b/client/assets/javascripts/rectangles/models/wall.js new file mode 100644 index 0000000..4270551 --- /dev/null +++ b/client/assets/javascripts/rectangles/models/wall.js @@ -0,0 +1,120 @@ +window.Wall = (function(){ + + var Wall = function(opt){ + this.id = opt.id + this.uid = Uid() + this.room = opt.room + this.rect = opt.rect || new Rect (0,0,0,0) + this.rect.sides = opt.side + this.side = opt.side + this.mx = [] + this.els = [] + if (opt.el) { + this.mx.push(opt.el) + } + } + + Wall.prototype.toString = function(){ + return this.rect.toString() + } + + Wall.prototype.reset = function(){ + } + + Wall.prototype.destroy = function(){ + this.mx.forEach(function(mx){ + mx.destroy && mx.destroy() + }) + this.room = this.rect = this.mx = this.els = null + } + + Wall.prototype.bind = function(){ + var base = this + base.$walls = $( this.mx.map(function(mx){ return mx.el }) ) + base.$walls.bind({ + mouseover: function(){ + }, + mouseenter: function(e){ + Scenery.mouse.mouseenter(e, base) + }, + mousemove: function(e){ + }, + mousedown: function(){ + base.randomize_colors() + console.log(sidesToString(base.side)) + } + }) + } + + Wall.prototype.bounds_for = function(img) { + var coord = this.side & FRONT_BACK ? this.rect.x : this.rect.y + return new Rect( new vec2( coord.a + img.width/2, coord.b - img.width/2 ), + new vec2( img.height/2, Rooms.list[this.room].height - img.height/2 ) ) + } + Wall.prototype.fits = function(img){ + if (this.side & FRONT_BACK && this.rect.x.length() < img.width) { + return false + } + if (this.side & LEFT_RIGHT && this.rect.y.length() < img.width) { + return false + } + return true + } + + Wall.prototype.center = function(offset){ + + offset = offset || 0 + + var major_axis, minor_axis + if (this.side & FRONT_BACK) { + major_axis = this.rect.x + minor_axis = this.rect.y + } + else { + major_axis = this.rect.y + minor_axis = this.rect.x + } + + switch (this.side) { + case FRONT: + x = major_axis.midpoint() + z = minor_axis.a + painting_distance_from_wall + offset + break + case BACK: + x = major_axis.midpoint() + z = minor_axis.b - painting_distance_from_wall + offset + break + case LEFT: + x = minor_axis.a + painting_distance_from_wall + offset + z = major_axis.midpoint() + break + case RIGHT: + x = minor_axis.b - painting_distance_from_wall + offset + z = major_axis.midpoint() + break + } + + return new vec2 (x, z) + } + + Wall.prototype.color = function(color){ + this.$walls && this.$walls.css("background-color", color) + } + + Wall.prototype.siblings = function(){ + var base = this + var match = base.side | base.half_side + var walls = Rooms.list[this.room].walls.filter(function(w){ + return (w.side | w.half_side) & match + }) + return walls; + } + + Wall.prototype.randomize_colors = function(){ + var color = choice(window.colors) + this.siblings().forEach(function(w){ w.color(color) }) + } + + return Wall + +})() |
