diff --git a/libs/bluemath.js b/libs/bluemath.js new file mode 100644 index 0000000..7ee90b1 --- /dev/null +++ b/libs/bluemath.js @@ -0,0 +1,15 @@ +// bluemath.js +// This library adds advanced math objects + +class vector { + constructor(components) { + this.components = components; + } +} + +class tensor { + contructor(dimentions,rank) { + this.componants = Math.pow(rank,dimentions); + this.baseVectors = dimentions; + } +} diff --git a/libs/bluepixle.js b/libs/bluepixle.js new file mode 100644 index 0000000..fd5746f --- /dev/null +++ b/libs/bluepixle.js @@ -0,0 +1,797 @@ +// bluepixle.js +// This library is to help make using canvas tags easier + +function deg2rad (deg) { + return ((Math.PI*2)/360)*deg; +} + +function rad2deg (rad) { + return (1/deg2rad(1))*rad; +} + +function drift(object) { + if (object instanceof container) { + object.direction = "number" == typeof object.direction ? + object.direction : Math.floor(Math.random()*360); + object.speed = "number" == typeof object.speed ? object.speed : 1; + object.move(object.direction,object.speed); + } else { + return new TypeError("must provide a container object"); + } +} + +function getAngle(ax,ay,bx,by) { + var deltaX = bx - ax; + var deltaY = by - ay; + return rad2deg(Math.atan2(deltaY,deltaX)); +} + +function reflect(inAngle,surfaceAngle) { + var normal = surfaceAngle+90; + var theta1 = normal - inAngle; + var theta2 = normal + theta1; + return theta2; +} + +function bounce(object, surface, impactTime) { + object.direction = reflect(object.direction,surface.direction-90); + object.speed = object.speed; +} + +function valueBetween (value,low,high) { + var Tlow = low <= high ? low : high; + var Thigh = high >= low ? high : low; + if ( (value >= Tlow) & (value <= Thigh) ) { + return true; + } else { + return false; + } +} + +function pointInside (x,y,top,right,bottom,left) { + if ( valueBetween(x,left,right) & valueBetween(y,top,bottom) ) { + return true; + } else { + return false; + } +} + +function collide(objectA,objectB,callBackFunction) { + var ASpeed = Math.abs(objectA.speed); + var BSpeed = Math.abs(objectB.speed); + var simAX = ASpeed <= BSpeed ? objectA.x : objectB.x; + var simAY = ASpeed <= BSpeed ? objectA.y : objectB.y; + var simBX = ASpeed <= BSpeed ? objectB.x : objectA.x; + var simBY = ASpeed <= BSpeed ? objectB.y : objectA.y; + var simADir = ASpeed <= BSpeed ? objectA.direction : objectB.direction; + var simBDir = ASpeed <= BSpeed ? objectB.direction : objectA.direction; + var simASpeed = ASpeed <= BSpeed ? objectA.speed : objectB.speed; + var simBSpeed = ASpeed <= BSpeed ? objectB.speed : objectA.speed; + var simAheight = ASpeed <= BSpeed ? objectA.sizeX : objectB.sizeX; + var simBheight = ASpeed <= BSpeed ? objectB.sizeX : objectA.sizeX; + var simAwidth = ASpeed <= BSpeed ? objectA.sizeY : objectB.sizeY; + var simBwidth = ASpeed <= BSpeed ? objectB.sizeY : objectA.sizeY; + var thetaA = deg2rad(simADir); + var deltaAX = Math.cos(thetaA)*simASpeed; + var deltaAY = Math.sin(thetaA)*simASpeed; + var thetaB = deg2rad(simBDir); + var deltaBX = Math.cos(thetaB)*simBSpeed; + var deltaBY = Math.sin(thetaB)*simBSpeed; + var fastest = Math.max(Math.abs(objectA.speed),Math.abs(objectB.speed)); + for (var t = 0; t <= fastest; t++) { + var tFraction = t/(fastest+1); + var Atop = simAY+(tFraction * deltaAY); + var Abottom = simAY+(tFraction * deltaAY)+simAheight; + var Aleft = simAX+(tFraction * deltaAX); + var Aright = simAX+(tFraction * deltaAX)+simAwidth; + var Btop = simBY+(tFraction * deltaBY); + var Bbottom = simBY+(tFraction * deltaBY)+simBheight; + var Bleft = simBX+(tFraction * deltaBX); + var Bright = simBX+(tFraction * deltaBX)+simBwidth; + if ( + pointInside(Aleft,Atop,Btop,Bright,Bbottom,Bleft) | + pointInside(Aright,Atop,Btop,Bright,Bbottom,Bleft) | + pointInside(Aleft,Abottom,Btop,Bright,Bbottom,Bleft) | + pointInside(Aright,Abottom,Btop,Bright,Bbottom,Bleft) | + pointInside(Bleft,Btop,Atop,Aright,Abottom,Aleft) | + pointInside(Bright,Btop,Atop,Aright,Abottom,Aleft) | + pointInside(Bleft,Bbottom,Atop,Aright,Abottom,Aleft) | + pointInside(Bright,Bbottom,Atop,Aright,Abottom,Aleft) + ){ + return callBackFunction(objectA,objectB,t); + } + } + return false; +} + +function chase (source,target,max,minDis,acc) { + acc /= 100; + var sourceCenterX = source.x + (source.sizeX/2); + var sourceCenterY = source.y + (source.sizeY/2); + var targetCenterX = target.x + (target.sizeX/2); + var targetCenterY = target.y + (target.sizeY/2); + var deltaX = targetCenterX - sourceCenterX; + var deltaY = targetCenterY - sourceCenterY; + var theta = Math.atan2(deltaY,deltaX); + var dis = Math.sqrt(Math.pow(Math.abs(deltaX),2)+Math.pow(Math.abs(deltaY),2)); + var dir = theta; + if (dis > minDis) { + dis = dis <= max ? dis : max; + source.direction = rad2deg(dir); + source.speed = (dis-minDis)*acc; + source.move(source.direction,source.speed); + } +} + +function rect (ctx,xOrigin,yOrigin,width,height,fill,stroke,outlineWidth) { +// Save current defaults + var local = {}; + local.fillStyle = "string" == typeof ctx.fillStyle ? ctx.fillStyle : undefined; + local.strokeStyle = "string" == ctx.strokeStyle ? ctx.strokeStyle : undefined; + local.lineWidth = "number" == ctx.lineWidth ? ctx.lineWidth : undefined; +// Check inputs + ctx.fillStyle = "string" == typeof fill ? fill : local.fillStyle; + ctx.strokeStyle = "string" == typeof stroke ? stroke : "rgba(0,0,0,0)"; + ctx.lineWidth = "number" == typeof outlineWidth ? outlineWidth : 1; + ctx.fillRect(xOrigin,yOrigin,width,height); + ctx.strokeRect(xOrigin,yOrigin,width,height); +// restore context defaults + ctx.fillStyle = local.fillStyle; + ctx.strokeStyle = local.strokeStyle; + ctx.lineWidth = local.lineWidth; +} + +function elip (ctx,xOrigin,yOrigin,width,height,fill,stroke,outlineWidth) { +// Save current defaults + var local = {}; + local.fillStyle = ctx.fillStyle; + local.strokeStyle = ctx.strokeStyle; + local.lineWidth = ctx.lineWidth; +// Check inputs + ctx.fillStyle = "string" == typeof fill ? fill : local.fillStyle; + ctx.strokeStyle = "string" == typeof stroke ? stroke : "rgba(0,0,0,0)"; + ctx.lineWidth = "number" == typeof outlineWidth ? outlineWidth : 1; + ctx.beginPath(); + ctx.ellipse(xOrigin,yOrigin,width,height,0,0,360); + ctx.stroke(); + ctx.fill(); +// restore context defaults + ctx.fillStyle = local.fillStyle; + ctx.strokeStyle = local.strokeStyle; + ctx.lineWidth = local.lineWidth; +} + +function drawPixel (ctx, x, y, r, g, b, a) { + // Always validate your input + if (false == ctx instanceof CanvasRenderingContext2D) { + return new TypeError("ctx must be a 2D rendering context for canvas."); + } + x = x <= ctx.canvas.width ? x : ctx.canvas.width; + y = y <= ctx.canvas.height ? y : ctx.canvas.height; + r = r <= 255 ? r : 255; + r = r >= 0 ? r : 0; + g = g <= 255 ? g : 255; + g = g >= 0 ? g : 0; + b = b <= 255 ? b : 255; + b = b >= 0 ? b : 0; + a = a <= 255 ? a : 255; + a = a >= 0 ? a : 0; + // Do the thing + ctx.putImageData(new ImageData(new Uint8ClampedArray([r,g,b,a]),1,1),x,y); +} + +class matrix { + constructor(m,n,matrixArray) { + if (matrixArray.length != m*n) { + return new RangeError("the size of the array does not match the size of the matrix!"); + } else { + this.array = []; + for (var row = 0; row < m; row++) { + this.array[row] = []; + for (var col = 0; col < n; col++) { + this.array[row][col] = matrixArray[n*row+col]; + } + } + this.m = m; + this.n = n; + } + } + + log() { + var string = ""; + for (var row = 0; row < this.m; row++) { + string += "["; + for( var col = 0; col < this.n; col++) { + string += this.array[row][col]; + string += ","; + } + string += "]"; + console.log(string); + string = ""; + } + } + + add(matrixb) { + if ( + matrixb.m == this.m && + matrixb.n == this.n + ) { + matrixb.array.forEach( function(row,rowIndex) { + row.forEach( function(col,colIndex) { + this.array[rowIndex][colIndex] += col; + }); + }); + } else { + throw new RangeError("cannot add matricies of different dimentions."); + } + } + + scalarMult(scalar) { + var data = this.array; + data.forEach( function(row,rI) { + row.forEach( function(col,cI) { + data[rI][cI] *= scalar; + }); + }); + } + + transpose() { + var tArray = []; + for (var row = 0; row < this.n; row++) { tArray[row] = []; } + for (var row = 0; row < this.m; row++) { + for (var col = 0; col < this.n; col++) { + tArray[col][row] = this.array[row][col]; + } + } + var rawArray = []; + tArray.forEach(function (row,rI) { + row.forEach( function(col,cI) { + rawArray.push(tArray[rI][cI]); + }); + }); + return new matrix(this.n,this.m,rawArray); + } + + multiply(matrixb) { + if (matrixb.m == this.n) { + var m = this.m; + var n = this.n; + var p = matrixb.n; + var A = this; + var B = matrixb; + var newMatrix = []; + for (var i = 0; i < m; i++) { + newMatrix[i] = []; + for (var j = 0; j < p; j++) { + var sum = 0; + for (var k = 0; k < n; k++) { + sum += A.array[i][k] * B.array[k][j]; + } + newMatrix[i][j] = sum; + } + } + var rawArray = []; + newMatrix.forEach(function (row,rI) { + row.forEach( function (col,cI) { + rawArray.push(newMatrix[rI][cI]); + }); + }); + return new matrix(m,p,rawArray); + } else { + return undefined; + } + } +} + +class point { + constructor(x,y) { + this.x = "number" == typeof x ? x : 0; + this.y = "number" == typeof y ? y : 0; + } + + getCoords() { + return [this.x,this.y]; + } + + setCoords(x,y) { + this.x = "number" == typeof x ? x : 0; + this.y = "number" == typeof y ? y : 0; + } + + setX(x) { + this.x = "number" == typeof x ? x : 0; + } + + setY(y) { + this.y = "number" == typeof y ? y : 0; + } + +} +class vector { + constructor(direction,magnitude) { + this.direction = "number" == typeof direction ? + 0 <= direction ? + 360 >= direction ? direction : 360 : 0 : 0; + this.magnitude = "number" == typeof magnitude ? magnitude : 0; + } + + getXYcomponents() { + var theta = deg2rad(this.direction); + var deltaX = Math.cos(theta)*this.magnitude; + var deltaY = Math.sin(theta)*this.magnitude; + return {"dx":deltaX,"dy":deltaY}; + } + + adjustMag(value) { + this.magnitude += "number" == typeof value ? value : 0; + } + + setMag(value) { + this.magnitude = "number" == typeof value ? value : this.magnitude; + } + + adjustDir(value) { + value = 0 <= value ? 360 >= value ? value: 360 : 0; + this.direction += value; + } + + setDir(value) { + this.direction = 0 <= value ? 360 >= value ? value: 360 : 0; + } + + executeVector(x,y) { + var components = this.getXYcomponents(); + return new point(x+components.dx,y+components.dy); + } + + crossProduct(vectorB) { + if (vectorB instanceof vector) { + var V1 = this.executeVector(0,0); + var V2 = vectorB.executeVector(0,0); + return (Math.sin(V1.x) * Math.cos(V2.y)) + - (Math.cos(V1.y) * Math.sin(V2.x)); + } else { + throw new TypeError("object is not a vector"); + } + } + +} + +class lineSeg { + constructor(x1,y1,x2,y2) { + this.pointA = new point(x1,y1); + this.pointB = new point(x2,y2); + this.center = new point((x1+x2)/2,(y1+y2)/2); + this.length = Math.sqrt( + Math.pow(Math.abs(x2-x1),2) + +Math.pow(Math.abs(y2-y1),2) + ); + this.angle = getAngle(x1,y1,x2,y2); + } + + adjustA(length) { + length = "number" == typeof length ? length : 0; + var vecC2A = new vector(getAngle( + this.center.x, + this.center.y, + this.pointA.x, + this.pointA.y), + this.length/2); + vecC2A.adjustMag(length); + this.pointA = vecC2A.executeVector(this.center.x,this.center.y); + this.center.setCoords( + (this.pointA.x+this.pointB.x)/2, + (this.pointA.y+this.pointB.y)/2); + this.length += length; + } + + adjustB(length) { + length = "number" == typeof length ? length : 0; + var vecC2B = new vector( + getAngle( + this.center.x, + this.center.y, + this.pointB.x, + this.pointB.y), + this.length/2); + vecC2B.adjustMag(length); + this.pointB = vecC2B.executeVector(this.center.x,this.center.y); + this.center.setCoords( + (this.pointA.x+this.pointB.x)/2, + (this.pointA.y+this.pointB.y)/2); + this.length += length; + } + + adjustCenter(length) { + adjustA(length/2); + adjustB(length/2); + } + + rotateA(deg) { + var abVec = new vector( + getAngle( + this.pointA.x, + this.pointA.y, + this.pointB.x, + this.pointB.y), + this.length); + abVec.adjustDir(deg); + this.pointB = abVec.executeVector(this.pointA.x,this.pointA.y); + this.center.setCoords( + (this.pointA.x+this.pointB.x)/2, + (this.pointA.y+this.pointB.y)/2); + } + + rotateB(deg) { + var baVec = new vector( + getAngle( + this.pointB.x, + this.pointB.y, + this.pointA.x, + this.pointA.y), + this.length); + baVec.adjustDir(deg); + this.pointA = baVec.executeVector(this.pointB.x,this.pointB.y); + this.center.setCoords( + (this.pointA.x+this.pointB.x)/2, + (this.pointA.y+this.pointB.y)/2); + } + + rotateCenter(deg) { + var vecC2A = new vector( + getAngle( + this.center.x, + this.center.y, + this.pointA.x, + this.pointA.y), + this.length/2); + var vecC2B = new vector( + getAngle( + this.center.x, + this.center.y, + this.pointB.x, + this.pointB.y), + this.length/2); + vecC2A.adjust(deg); + vecC2B.adjust(deg); + this.pointA = vecC2A.executeVector(this.center.x,this.center.y); + this.pointB = vecC2B.executeVector(this.center.x,this.center.y); + } + + getPerp() { + this.rotateCenter(90); + var newline = new lineSeg( + this.pointA.x, + this.pointA.y, + this.pointB.x, + this.pointB.y); + this.rotateCenter(-90); + return newline; + } + + slope() { + var deltaX = this.pointB.x - this.pointA.x; + var deltaY = this.pointB.y - this.pointA.y; + return deltaY / deltaX; + } + + xIntercept() { + return -this.yIntercept()/this.slope(); + } + + yIntercept() { + var slope = this.slope(); + if (Math.abs(slope) != Infinity) { + return -(slope*this.pointA.x)+this.pointA.y; + } else { + return this.pointA.x; + } + } + + intersect(line) { + if (line instanceof lineSeg) { + var x1 = this.pointA.x; + var x2 = this.pointB.x; + var x3 = line.pointA.x; + var x4 = line.pointB.x; + + var y1 = this.pointA.y; + var y2 = this.pointB.y; + var y3 = line.pointA.y; + var y4 = line.pointB.y; + + var deltaAX = x1 - x2; + var deltaBX = x3 - x4; + var deltaAY = y1 - y2; + var deltaBY = y3 - y4; + + // I don't know wtf to call these + var ground = deltaAX*deltaBY-deltaAY*deltaBX; + var Across = x1*y2 - y1*x2; + var Bcross = x3*y4 - y3*x4; + + var x = (Across*deltaBX-deltaAX*Bcross)/ground; + var y = (Across*deltaBY-deltaAY*Bcross)/ground; + + if ( + valueBetween(x,this.pointA.x,this.pointB.x) && + valueBetween(x,line.pointA.x,line.pointB.x) && + valueBetween(y,this.pointA.y,this.pointB.y) && + valueBetween(y,line.pointA.y,line.pointB.y)) { + return new point(x,y); + } else { + return false; + } + + } else { + throw new TypeError("must check against line"); + } + } + +} + +class shape { + constructor(type,x,y,sizeX,sizeY,fColor,bColor,bStyle,extraObject) { + this.type = "string" == typeof type ? type : "rect"; + this.x = "number" == typeof x ? x : 0; + this.y = "number" == typeof y ? y : 0; + this.sizeX = "number" == typeof sizeX ? sizeX : 1; + this.sizeY = "number" == typeof sizeY ? sizeY : 1; + this.fColor = "string" == typeof fColor ? fColor : undefined; + this.bColor = "string" == typeof bColor ? bColor : undefined; + this.bStyle = "number" == typeof bStyle ? bStyle : undefined; + this.extraObject = "object" == typeof extraObject ? extraObject : {}; + + if ("rect" == this.type) { + this.render = function (ctx,xPos,yPos) { + rect( + ctx, + this.x+xPos, + this.y+yPos, + this.sizeX, + this.sizeY, + this.fColor, + this.bColor, + this.bStyle); + } + } else if ("elipse" == this.type) { + this.render = function (ctx,xPos,yPos) { + var centerX = this.x+xPos+(this.sizeX/2); + var centerY = this.y+yPos+(this.sizeY/2); + elip( + ctx, + centerX, + centerY, + (this.sizeX/2), + (this.sizeY/2), + this.fColor, + this.bColor, + this.bStyle); + } + } else if ("image" == this.type) { + this.imageData = + this.extraObject.imageData instanceof ImageData ? + this.extraObject.imageData : + new ImageData( + new Uint8ClampedArray([ + 255,0,0,255, + 0,0,0,0, + 255,0,0,255, + 0,0,0,0, + 255,0,0,255, + 0,0,0,0, + 255,0,0,255, + 0,0,0,0, + 255,0,0,255 + ]),3,3); + this.image = createImageBitmap(this.imageData); + this.render = function (ctx,xPos,yPos) { + var x = this.x; + var y = this.y; + var sizeX = this.sizeX; + var sizeY = this.sizeY; + var contextBlur = ctx.imageSmoothingEnabled; + this.image.then(function (image) { + ctx.imageSmoothingEnabled = false; + ctx.drawImage(image,x+xPos,y+yPos,sizeX,sizeY); + ctx.imageSmoothingEnabled = contextBlur; + }); + } + } else { + console.log("no valid type defined for shape, defalting to 'rect'"); + this.render = function (ctx,xPos,yPos) { + rect( + ctx, + this.x+xPos, + this.y+yPos, + this.sizeX, + this.sizeY, + this.fColor, + this.bColor, + this.bStyle); + } + } + } + + grow (amp) { + this.sizeX+=amp; + this.sizeY+=amp; + } +} + +class container { + constructor(x,y,height,width,speed,direction) { + this.x = x; + this.y = y; + this.sizeY = height; + this.sizeX = width; + this.speed = "number" == typeof speed ? speed : 0; + this.direction = "number" == typeof direction ? direction : 0; + // Vectors are the future + this.netMovementVector = new vector( + this.direction, + this.speed); + } + + setShape(myShape) { + if (myShape instanceof shape) { + this.shape = myShape; + } else { + throw new TypeError("addShape Method must be given a shape object"); + } + } + + nestContainer() { + this.containerArray = []; + this.addShape = function (newShape) { + if (newShape instanceof shape) { + var containerIndex = this.containerArray.push( + new container(0,0,this.sizeY,this.sizeX)); + this.containerArray[containerIndex-1].setShape(newShape); + return this.containerArray[containerIndex-1]; + } else { + throw new TypeError("addShape Method must be given a shape object"); + } + }; + if (this.shape instanceof shape) { this.addShape(me.shape); } + this.shape = undefined; + this.setShape = undefined; + } + + move(direction,amplitude) { + this.direction = direction; + this.speed = amplitude; + var theta = deg2rad(direction); + this.x += Math.cos(theta) * amplitude; + this.y += Math.sin(theta) * amplitude; + } + + renderContainer(ctx,xPos,yPos) { + var refX = this.x + ("number" == typeof xPos ? xPos : 0); + var refY = this.y + ("number" == typeof yPos ? yPos : 0); + if ("object" == typeof this.shape) { + this.shape.render(ctx,refX,refY); + } else if ("object" == typeof this.containerArray) { + this.containerArray.forEach( + function (container) { + container.renderContainer(ctx,refX,refY); + }); + } else { + console.log("Container is empty!!!"); + } + } + + grow(amp) { + amp = "number"== typeof amp ? amp : 1; + this.x -= amp; + this.y -= amp; + if ("object" == typeof this.shape) { + this.shape.grow(amp); + } else if ("object" == typeof this.containerArray) { + this.containerArray.forEach( + function (container) { container.grow(amp); }); + } + } + +} + +class frameBuffer { + constructor(ctx, height, width) { + this.ctx = ctx; + this.height = height; + this.width = width; + this.containerArray = []; + } + + addContainer(containerObject) { //might change this to auto create containers. + if (containerObject instanceof container) { + var index = this.containerArray.push(containerObject); + return this.containerArray[ index - 1]; + } else { + throw new TypeError("addContainer Method must be given a container object"); + } + } + + pushFrame() { + var ctx = this.ctx; + ctx.clearRect(0,0,this.width,this.height); + this.containerArray.forEach( + function (container) { container.renderContainer(ctx,0,0); }); + } + +} + +class starfield { + constructor (buffer,boundWidth,boundHeight,centerX,centerY,starCount,starLife,starSpeed) { + //Validate things + this.centerX = centerX; + this.centerY = centerY; + this.starLife = starLife; + this.starSpeed = starSpeed; + //Math the things + this.topBound = centerY - (boundHeight/2); + this.bottomBound = centerY + (boundHeight/2); + this.leftBound = centerX - (boundWidth/2); + this.rightBound = centerX + (boundWidth/2); + this.stars = []; + this.container = buffer.addContainer( + new container(this.centerX,this.centerY,0,0,0)); + this.container.nestContainer(); + for (var count = 1; count <= starCount; count++) { + var star = this.container.addShape( + new shape( + "rect", + ((Math.random()*boundWidth)-(boundWidth/2)), + ((Math.random()*boundHeight)-(boundHeight/2)), + 1,1, + "#ffffff", + "#ffffff", + 1)); + this.stars.push({ + "container":star, + "life":this.starLife, + "speed":this.starSpeed}); + } + } + + forward() { + var me = this; + this.stars.forEach(function (star) { + if ( + (star.life > 0) & + (star.container.shape.x > me.leftBound - me.centerX) & + (star.container.shape.x < me.rightBound - me.centerX) & + (star.container.shape.y > me.topBound - me.centerY) & + (star.container.shape.y < me.bottomBound - me.centerY)) { + var xOffset = star.container.shape.x; + var yOffset = star.container.shape.y; + star.life--; + var c = 255*((me.starLife-star.life)/me.starLife)*4; + star.container.grow(5/me.starLife); + star.container.shape.fColor = "rgb("+c+","+c+","+c+")"; + star.container.shape.bColor = "rgb("+c+","+c+","+c+")"; + star.speed+=me.starSpeed; + star.container.shape.x += + star.speed*((xOffset/me.centerX)*0.5); + star.container.shape.y += + star.speed*((yOffset/me.centerY)*0.5); + } else { + star.container.x = 0; + star.container.y = 0; + star.life = me.starLife; + star.speed = me.starSpeed; + star.container.shape.sizeX = 1; + star.container.shape.sizeY = 1; + star.container.shape.fColor = "rgb(0,0,0)"; + star.container.shape.bColor = "rgb(0,0,0)"; + star.container.shape.x = + (Math.random()*(me.rightBound-me.leftBound)) + -(me.centerX); + star.container.shape.y = + (Math.random()*(me.bottomBound-me.topBound)) + -(me.centerY); + } + }); + } +} +