mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-29 18:45:48 -05:00
Merge branch 'master' into production
This commit is contained in:
commit
727638b090
70 changed files with 616 additions and 96 deletions
|
@ -96,7 +96,9 @@ Aether.addGlobal('_', _);
|
|||
var serializedClasses = {
|
||||
"Thang": self.require('lib/world/thang'),
|
||||
"Vector": self.require('lib/world/vector'),
|
||||
"Rectangle": self.require('lib/world/rectangle')
|
||||
"Rectangle": self.require('lib/world/rectangle'),
|
||||
"Ellipse": self.require('lib/world/ellipse'),
|
||||
"LineSegment": self.require('lib/world/line_segment')
|
||||
};
|
||||
self.currentUserCodeMapCopy = "";
|
||||
self.currentDebugWorldFrame = 0;
|
||||
|
|
|
@ -181,12 +181,11 @@ module.exports = class Mark extends CocoClass
|
|||
buildDebug: ->
|
||||
@mark = new createjs.Shape()
|
||||
PX = 3
|
||||
[w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x]
|
||||
[w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x] # TODO: doesn't work with rotation
|
||||
@mark.alpha = 0.5
|
||||
@mark.graphics.beginFill '#abcdef'
|
||||
if @sprite.thang.shape in ['ellipsoid', 'disc']
|
||||
[w, h] = [Math.max(PX, w, h), Math.max(PX, w, h)]
|
||||
@mark.graphics.drawCircle 0, 0, w / 2
|
||||
@mark.graphics.drawEllipse -w / 2, -h / 2, w, h
|
||||
else
|
||||
@mark.graphics.drawRect -w / 2, -h / 2, w, h
|
||||
@mark.graphics.endFill()
|
||||
|
@ -259,7 +258,7 @@ module.exports = class Mark extends CocoClass
|
|||
|
||||
updateRotation: ->
|
||||
if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ['rectangle', 'box'])
|
||||
@mark.rotation = @sprite.thang.rotation * 180 / Math.PI
|
||||
@mark.rotation = -@sprite.thang.rotation * 180 / Math.PI
|
||||
|
||||
updateScale: ->
|
||||
if @name is 'bounds' and ((@sprite.thang.width isnt @lastWidth or @sprite.thang.height isnt @lastHeight) or (@sprite.thang.drawsBoundsIndex isnt @drawsBoundsIndex))
|
||||
|
|
174
app/lib/world/ellipse.coffee
Normal file
174
app/lib/world/ellipse.coffee
Normal file
|
@ -0,0 +1,174 @@
|
|||
Vector = require './vector'
|
||||
LineSegment = require './line_segment'
|
||||
Rectangle = require './rectangle'
|
||||
|
||||
class Ellipse
|
||||
@className: "Ellipse"
|
||||
|
||||
# TODO: add class methods for add, multiply, subtract, divide, rotate
|
||||
|
||||
isEllipse: true
|
||||
apiProperties: ['x', 'y', 'width', 'height', 'rotation', 'distanceToPoint', 'distanceSquaredToPoint', 'distanceToRectangle', 'distanceSquaredToRectangle', 'distanceToEllipse', 'distanceSquaredToEllipse', 'distanceToShape', 'distanceSquaredToShape', 'containsPoint', 'intersectsLineSegment', 'intersectsRectangle', 'intersectsEllipse', 'getPos', 'containsPoint', 'copy']
|
||||
|
||||
constructor: (@x=0, @y=0, @width=0, @height=0, @rotation=0) ->
|
||||
|
||||
copy: ->
|
||||
new Ellipse(@x, @y, @width, @height, @rotation)
|
||||
|
||||
getPos: ->
|
||||
new Vector(@x, @y)
|
||||
|
||||
rectangle: ->
|
||||
new Rectangle(@x, @y, @width, @height, @rotation)
|
||||
|
||||
axisAlignedBoundingBox: (rounded=true) ->
|
||||
@rectangle().axisAlignedBoundingBox()
|
||||
|
||||
distanceToPoint: (p) ->
|
||||
@rectangle().distanceToPoint p # TODO: actually implement ellipse ellipse-point distance
|
||||
|
||||
distanceSquaredToPoint: (p) ->
|
||||
# Doesn't handle rotation; just supposed to be faster than distanceToPoint.
|
||||
@rectangle().distanceSquaredToPoint p # TODO: actually implement ellipse-point distance
|
||||
|
||||
distanceToRectangle: (other) ->
|
||||
Math.sqrt @distanceSquaredToRectangle other
|
||||
|
||||
distanceSquaredToRectangle: (other) ->
|
||||
@rectangle().distanceSquaredToRectangle other # TODO: actually implement ellipse-rectangle distance
|
||||
|
||||
distanceToEllipse: (ellipse) ->
|
||||
Math.sqrt @distanceSquaredToEllipse ellipse
|
||||
|
||||
distanceSquaredToEllipse: (ellipse) ->
|
||||
@rectangle().distanceSquaredToEllipse ellipse # TODO: actually implement ellipse-ellipse distance
|
||||
|
||||
distanceToShape: (shape) ->
|
||||
Math.sqrt @distanceSquaredToShape shape
|
||||
|
||||
distanceSquaredToShape: (shape) ->
|
||||
if shape.isEllipse then @distanceSquaredToEllipse shape else @distanceSquaredToRectangle shape
|
||||
|
||||
containsPoint: (p, withRotation=true) ->
|
||||
[a, b] = [@width / 2, @height / 2]
|
||||
[h, k] = [@x, @y]
|
||||
[x, y] = [p.x, p.y]
|
||||
x2 = Math.pow(x, 2)
|
||||
a2 = Math.pow(a, 2)
|
||||
a4 = Math.pow(a, 4)
|
||||
b2 = Math.pow(b, 2)
|
||||
b4 = Math.pow(b, 4)
|
||||
h2 = Math.pow(h, 2)
|
||||
k2 = Math.pow(k, 2)
|
||||
if withRotation and @rotation
|
||||
sint = Math.sin(@rotation)
|
||||
sin2t = Math.sin(2 * @rotation)
|
||||
cost = Math.cos(@rotation)
|
||||
cos2t = Math.cos(2 * @rotation)
|
||||
numeratorLeft = (-a2 * h * sin2t) + (a2 * k * cos2t) + (a2 * k) + (a2 * x * sin2t)
|
||||
numeratorMiddle = Math.SQRT2 * Math.sqrt((a4 * b2 * cos2t) + (a4 * b2) - (a2 * b4 * cos2t) + (a2 * b4) - (2 * a2 * b2 * h2) + (4 * a2 * b2 * h * x) - (2 * a2 * b2 * x2))
|
||||
numeratorRight = (b2 * h * sin2t) - (b2 * k * cos2t) + (b2 * k) - (b2 * x * sin2t)
|
||||
denominator = (a2 * cos2t) + a2 - (b2 * cos2t) + b2
|
||||
solution1 = (numeratorLeft - numeratorMiddle + numeratorRight) / denominator
|
||||
solution2 = (numeratorLeft + numeratorMiddle + numeratorRight) / denominator
|
||||
if (not isNaN solution1) and (not isNaN solution2)
|
||||
[bigSolution, littleSolution] = if solution1 > solution2 then [solution1, solution2] else [solution2, solution1]
|
||||
if y > littleSolution and y < bigSolution
|
||||
return true
|
||||
else
|
||||
return false
|
||||
else
|
||||
return false
|
||||
else
|
||||
numeratorLeft = a2 * k
|
||||
numeratorRight = Math.sqrt((a4 * b2) - (a2 * b2 * h2) + (2 * a2 * b2 * h * x) - (a2 * b2 * x2))
|
||||
denominator = a2
|
||||
solution1 = (numeratorLeft + numeratorRight) / denominator
|
||||
solution2 = (numeratorLeft - numeratorRight) / denominator
|
||||
if (not isNaN solution1) and (not isNaN solution2)
|
||||
[bigSolution, littleSolution] = if solution1 > solution2 then [solution1, solution2] else [solution2, solution1]
|
||||
if y > littleSolution and y < bigSolution
|
||||
return true
|
||||
else
|
||||
return false
|
||||
else
|
||||
return false
|
||||
false
|
||||
|
||||
intersectsLineSegment: (p1, p2) ->
|
||||
[px1, py1, px2, py2] = [p1.x, p1.y, p2.x, p2.y]
|
||||
m = (py1 - py2) / (px1 - px2)
|
||||
m2 = Math.pow(m, 2)
|
||||
c = py1 - (m * px1)
|
||||
c2 = Math.pow(c, 2)
|
||||
[a, b] = [@width / 2, @height / 2]
|
||||
[h, k] = [@x, @y]
|
||||
a2 = Math.pow(a, 2)
|
||||
a4 = Math.pow(a, 2)
|
||||
b2 = Math.pow(b, 2)
|
||||
b4 = Math.pow(b, 4)
|
||||
h2 = Math.pow(h, 2)
|
||||
k2 = Math.pow(k, 2)
|
||||
sint = Math.sin(@rotation)
|
||||
sin2t = Math.sin(2 * @rotation)
|
||||
cost = Math.cos(@rotation)
|
||||
cos2t = Math.cos(2 * @rotation)
|
||||
if (not isNaN m) and m != Infinity and m != -Infinity
|
||||
numeratorLeft = (-a2 * c * m * cos2t) - (a2 * c * m) + (a2 * c * sin2t) - (a2 * h * m * sin2t) - (a2 * h * cos2t) + (a2 * h) + (a2 * k * m * cos2t) + (a2 * k * m) - (a2 * k * sin2t)
|
||||
numeratorMiddle = Math.SQRT2 * Math.sqrt((a4 * b2 * m2 * cos2t) + (a4 * b2 * m2) - (2 * a4 * b2 * m * sin2t) - (a4 * b2 * cos2t) + (a4 * b2) - (a2 * b4 * m2 * cos2t) + (a2 * b4 * m2) + (2 * a2 * b4 * m * sin2t) + (a2 * b4 * cos2t) + (a2 * b4) - (2 * a2 * b2 * c2) - (4 * a2 * b2 * c * h * m) + (4 * a2 * b2 * c * k) - (2 * a2 * b2 * h2 * m2) + (4 * a2 * b2 * h * k * m) - (2 * a2 * b2 * k2))
|
||||
numeratorRight = (b2 * c * m * cos2t) - (b2 * c * m) - (b2 * c * sin2t) + (b2 * h * m * sin2t) + (b2 * h * cos2t) + (b2 * h) - (b2 * k * m * cos2t) + (b2 * k * m) + (b2 * k * sin2t)
|
||||
denominator = (a2 * m2 * cos2t) + (a2 * m2) - (2 * a2 * m * sin2t) - (a2 * cos2t) + a2 - (b2 * m2 * cos2t) + (b2 * m2) + (2 * b2 * m * sin2t) + (b2 * cos2t) + b2
|
||||
solution1 = (-numeratorLeft - numeratorMiddle + numeratorRight) / denominator
|
||||
solution2 = (-numeratorLeft + numeratorMiddle + numeratorRight) / denominator
|
||||
if (not isNaN solution1) and (not isNaN solution2)
|
||||
[littleX, bigX] = if px1 < px2 then [px1, px2] else [px2, px1]
|
||||
if (littleX <= solution1 and bigX >= solution1) or (littleX <= solution2 and bigX >= solution2)
|
||||
return true
|
||||
if (not isNaN solution1) or (not isNaN solution2)
|
||||
solution = if not isNaN solution1 then solution1 else solution2
|
||||
[littleX, bigX] = if px1 < px2 then [px1, px2] else [px2, px1]
|
||||
if littleX <= solution and bigX >= solution
|
||||
return true
|
||||
else
|
||||
return false
|
||||
else
|
||||
x = px1
|
||||
x2 = Math.pow(x, 2)
|
||||
numeratorLeft = (-a2 * h * sin2t) + (a2 * k * cos2t) + (a2 * k) + (a2 * x * sin2t)
|
||||
numeratorMiddle = Math.SQRT2 * Math.sqrt((a4 * b2 * cos2t) + (a4 * b2) - (a2 * b4 * cos2t) + (a2 * b4) - (2 * a2 * b2 * h2) + (4 * a2 * b2 * h * x) - (2 * a2 * b2 * x2))
|
||||
numeratorRight = (b2 * h * sin2t) - (b2 * k * cos2t) + (b2 * k) - (b2 * x * sin2t)
|
||||
denominator = (a2 * cos2t) + a2 - (b2 * cos2t) + b2
|
||||
solution1 = (numeratorLeft - numeratorMiddle + numeratorRight) / denominator
|
||||
solution2 = (numeratorLeft + numeratorMiddle + numeratorRight) / denominator
|
||||
if (not isNaN solution1) or (not isNaN solution2)
|
||||
solution = if not isNaN solution1 then solution1 else solution2
|
||||
[littleY, bigY] = if py1 < py2 then [py1, py2] else [py2, py1]
|
||||
if littleY <= solution and bigY >= solution
|
||||
return true
|
||||
else
|
||||
return false
|
||||
false
|
||||
|
||||
intersectsRectangle: (rectangle) ->
|
||||
rectangle.intersectsEllipse @
|
||||
|
||||
intersectsEllipse: (ellipse) ->
|
||||
@rectangle().intersectsEllipse @ # TODO: actually implement ellipse-ellipse intersection
|
||||
#return true if @containsPoint ellipse.getPos()
|
||||
|
||||
intersectsShape: (shape) ->
|
||||
if shape.isEllipse then @intersectsEllipse shape else @intersectsRectangle shape
|
||||
|
||||
toString: ->
|
||||
return "{x: #{@x.toFixed(0)}, y: #{@y.toFixed(0)}, w: #{@width.toFixed(0)}, h: #{@height.toFixed(0)}, rot: #{@rotation.toFixed(3)}}"
|
||||
|
||||
serialize: ->
|
||||
{CN: @constructor.className, x: @x, y: @y, w: @width, h: @height, r: @rotation}
|
||||
|
||||
@deserialize: (o, world, classMap) ->
|
||||
new Ellipse o.x, o.y, o.w, o.h, o.r
|
||||
|
||||
serializeForAether: -> @serialize()
|
||||
@deserializeFromAether: (o) -> @deserialize o
|
||||
|
||||
module.exports = Ellipse
|
80
app/lib/world/line_segment.coffee
Normal file
80
app/lib/world/line_segment.coffee
Normal file
|
@ -0,0 +1,80 @@
|
|||
class LineSegment
|
||||
@className: "LineSegment"
|
||||
|
||||
constructor: (@a, @b) ->
|
||||
@slope = (@a.y - @b.y) / (@a.x - @b.x)
|
||||
@y0 = @a.y - (@slope * @a.x)
|
||||
@left = if @a.x < @b.x then @a else @b
|
||||
@right = if @a.x > @b.x then @a else @b
|
||||
@bottom = if @a.y < @b.y then @a else @b
|
||||
@top = if @a.y > @b.y then @a else @b
|
||||
|
||||
y: (x) ->
|
||||
(@slope * x) + @y0
|
||||
|
||||
x: (y) ->
|
||||
(y - @y0) / @slope
|
||||
|
||||
intersectsLineSegment: (lineSegment) ->
|
||||
if lineSegment.slope is @slope
|
||||
if lineSegment.y0 is @y0
|
||||
if lineSegment.left.x is @left.x or lineSegment.left.x is @right.x or lineSegment.right.x is @right.x or lineSegment.right.x is @left.x
|
||||
# segments are of the same line with shared start and/or end points
|
||||
return true
|
||||
else
|
||||
[left, right] = if lineSegment.left.x < @left.x then [lineSegment, @] else [@, lineSegment]
|
||||
if left.right.x > right.left.x
|
||||
# segments are of the same line and one is contained within the other
|
||||
return true
|
||||
else if Math.abs(@slope) isnt Infinity and Math.abs(lineSegment.slope) isnt Infinity
|
||||
x = (lineSegment.y0 - @y0) / (@slope - lineSegment.slope)
|
||||
if x >= @left.x and x <= @right.x and x >= lineSegment.left.x and x <= lineSegment.right.x
|
||||
return true
|
||||
else if Math.abs(@slope) isnt Infinity or Math.abs(lineSegment.slope) isnt Infinity
|
||||
[vertical, nonvertical] = if Math.abs(@slope) isnt Infinity then [lineSegment, @] else [@, lineSegment]
|
||||
x = vertical.a.x
|
||||
bottom = vertical.bottom.y
|
||||
top = vertical.top.y
|
||||
y = nonvertical.y(x)
|
||||
left = nonvertical.left.x
|
||||
right = nonvertical.right.x
|
||||
if y >= bottom and y <= top and x >= left and x <= right
|
||||
return true
|
||||
false
|
||||
|
||||
pointOnLine: (point, segment=true) ->
|
||||
if point.y is @y(point.x)
|
||||
if segment
|
||||
[littleY, bigY] = if @a.y < @b.y then [@a.y, @b.y] else [@b.y, @a.y]
|
||||
if littleY <= point.y and bigY >= point.y
|
||||
return true
|
||||
else
|
||||
return true
|
||||
false
|
||||
|
||||
distanceSquaredToPoint: (point) ->
|
||||
# http://stackoverflow.com/a/1501725/540620
|
||||
return @a.distanceSquared point if @a.equals @b
|
||||
res = Math.min point.distanceSquared(@a), point.distanceSquared(@b)
|
||||
lineMagnitudeSquared = @a.distanceSquared @b
|
||||
t = ((point.x - @a.x) * (@b.x - @a.x) + (point.y - @a.y) * (@b.y - @a.y)) / lineMagnitudeSquared
|
||||
return @a.distanceSquared point if t < 0
|
||||
return @b.distanceSquared point if t > 1
|
||||
point.distanceSquared x: @a.x + t * (@b.x - @a.x), y: @a.y + t * (@b.y - @a.y)
|
||||
|
||||
distanceToPoint: (point) ->
|
||||
Math.sqrt @distanceSquaredToPoint point
|
||||
|
||||
toString: ->
|
||||
"lineSegment(a=#{@a}, b=#{@b}, slope=#{@slope}, y0=#{@y0}, left=#{@left}, right=#{@right}, bottom=#{@bottom}, top=#{@top})"
|
||||
|
||||
serialize: ->
|
||||
{CN: @constructor.className, a: @a, b: @b}
|
||||
|
||||
@deserialize: (o, world, classMap) ->
|
||||
new LineSegment o.a, o.b
|
||||
|
||||
serializeForAether: -> @serialize()
|
||||
@deserializeFromAether: (o) -> @deserialize o
|
||||
|
||||
module.exports = LineSegment
|
|
@ -1,14 +1,16 @@
|
|||
Vector = require './vector'
|
||||
LineSegment = require './line_segment'
|
||||
|
||||
class Rectangle
|
||||
@className: 'Rectangle'
|
||||
# Class methods for nondestructively operating
|
||||
# Class methods for nondestructively operating - TODO: add rotate
|
||||
for name in ['add', 'subtract', 'multiply', 'divide']
|
||||
do (name) ->
|
||||
Rectangle[name] = (a, b) ->
|
||||
a.copy()[name](b)
|
||||
|
||||
apiProperties: ['x', 'y', 'width', 'height', 'rotation', 'getPos', 'vertices', 'touchesRect', 'touchesPoint', 'distanceToPoint', 'containsPoint', 'copy']
|
||||
isRectangle: true
|
||||
apiProperties: ['x', 'y', 'width', 'height', 'rotation', 'getPos', 'vertices', 'touchesRect', 'touchesPoint', 'distanceToPoint', 'distanceSquaredToPoint', 'distanceToRectangle', 'distanceSquaredToRectangle', 'distanceToEllipse', 'distanceSquaredToEllipse', 'distanceToShape', 'distanceSquaredToShape', 'containsPoint', 'copy', 'intersectsLineSegment', 'intersectsEllipse', 'intersectsRectangle', 'intersectsShape']
|
||||
|
||||
constructor: (@x=0, @y=0, @width=0, @height=0, @rotation=0) ->
|
||||
|
||||
|
@ -28,6 +30,14 @@ class Rectangle
|
|||
new Vector @x + (w2 * cos + h2 * sin), @y + (w2 * sin - h2 * cos)
|
||||
]
|
||||
|
||||
lineSegments: ->
|
||||
vertices = @vertices()
|
||||
lineSegment0 = new LineSegment vertices[0], vertices[1]
|
||||
lineSegment1 = new LineSegment vertices[1], vertices[2]
|
||||
lineSegment2 = new LineSegment vertices[2], vertices[3]
|
||||
lineSegment3 = new LineSegment vertices[3], vertices[0]
|
||||
[lineSegment0, lineSegment1, lineSegment2, lineSegment3]
|
||||
|
||||
touchesRect: (other) ->
|
||||
# Whether this rect shares part of any edge with other rect, for non-rotated, non-overlapping rectangles.
|
||||
# I think it says kitty-corner rects touch, but I don't think I want that.
|
||||
|
@ -62,25 +72,90 @@ class Rectangle
|
|||
box
|
||||
|
||||
distanceToPoint: (p) ->
|
||||
# Get p in rect's coordinate space, then operate in one quadrant
|
||||
# Get p in rect's coordinate space, then operate in one quadrant.
|
||||
p = Vector.subtract(p, @getPos()).rotate(-@rotation)
|
||||
dx = Math.max(Math.abs(p.x) - @width / 2, 0)
|
||||
dy = Math.max(Math.abs(p.y) - @height / 2, 0)
|
||||
Math.sqrt dx * dx + dy * dy
|
||||
|
||||
distanceSquaredToPoint: (p) ->
|
||||
# Doesn't handle rotation; just supposed to be faster than distanceToPoint
|
||||
# Doesn't handle rotation; just supposed to be faster than distanceToPoint.
|
||||
p = Vector.subtract(p, @getPos())
|
||||
dx = Math.max(Math.abs(p.x) - @width / 2, 0)
|
||||
dy = Math.max(Math.abs(p.y) - @height / 2, 0)
|
||||
dx * dx + dy * dy
|
||||
|
||||
distanceToRectangle: (other) ->
|
||||
Math.sqrt @distanceSquaredToRectangle other
|
||||
|
||||
distanceSquaredToRectangle: (other) ->
|
||||
return 0 if @intersectsRectangle other
|
||||
[firstVertices, secondVertices] = [@vertices(), other.vertices()]
|
||||
[firstEdges, secondEdges] = [@lineSegments(), other.lineSegments()]
|
||||
ans = Infinity
|
||||
for i in [0 ... 4]
|
||||
for j in [0 ... firstEdges.length]
|
||||
ans = Math.min ans, firstEdges[j].distanceSquaredToPoint(secondVertices[i])
|
||||
for j in [0 ... secondEdges.length]
|
||||
ans = Math.min ans, secondEdges[j].distanceSquaredToPoint(firstVertices[i])
|
||||
ans
|
||||
|
||||
distanceToEllipse: (ellipse) ->
|
||||
Math.sqrt @distanceSquaredToEllipse ellipse
|
||||
|
||||
distanceSquaredToEllipse: (ellipse) ->
|
||||
@distanceSquaredToRectangle ellipse.rectangle() # TODO: actually implement rectangle-ellipse distance
|
||||
|
||||
distanceToShape: (shape) ->
|
||||
Math.sqrt @distanceSquaredToShape shape
|
||||
|
||||
distanceSquaredToShape: (shape) ->
|
||||
if shape.isEllipse then @distanceSquaredToEllipse shape else @distanceSquaredToRectangle shape
|
||||
|
||||
containsPoint: (p, withRotation=true) ->
|
||||
if withRotation and @rotation
|
||||
not @distanceToPoint(p)
|
||||
else
|
||||
@x - @width / 2 < p.x < @x + @width / 2 and @y - @height / 2 < p.y < @y + @height / 2
|
||||
|
||||
intersectsLineSegment: (p1, p2) ->
|
||||
[px1, py1, px2, py2] = [p1.x, p1.y, p2.x, p2.y]
|
||||
m1 = (py1 - py2) / (px1 - px2)
|
||||
b1 = py1 - (m1 * px1)
|
||||
vertices = @vertices()
|
||||
lineSegments = [[vertices[0], vertices[1]], [vertices[1], vertices[2]], [vertices[2], vertices[3]], [vertices[3], vertices[0]]]
|
||||
for lineSegment in lineSegments
|
||||
[px1, py1, px2, py2] = [p1.x, p1.y, p2.x, p2.y]
|
||||
m2 = (py1 - py2) / (px1 - px2)
|
||||
b2 = py1 - (m * px1)
|
||||
if m1 isnt m2
|
||||
m = m1 - m2
|
||||
b = b2 - b1
|
||||
x = b / m
|
||||
[littleX, bigX] = if px1 < px2 then [px1, px2] else [px2, px1]
|
||||
if x >= littleX and x <= bigX
|
||||
y = (m1 * x) + b1
|
||||
[littleY, bigY] = if py1 < py2 then [py1, py2] else [py2, py1]
|
||||
if littleY <= solution and bigY >= solution
|
||||
return true
|
||||
false
|
||||
|
||||
intersectsRectangle: (rectangle) ->
|
||||
return true if @containsPoint rectangle.getPos()
|
||||
for thisLineSegment in @lineSegments()
|
||||
for thatLineSegment in rectangle.lineSegments()
|
||||
if thisLineSegment.intersectsLineSegment(thatLineSegment)
|
||||
return true
|
||||
false
|
||||
|
||||
intersectsEllipse: (ellipse) ->
|
||||
return true if @containsPoint ellipse.getPos()
|
||||
return true for lineSegment in @lineSegments() when ellipse.intersectsLineSegment lineSegment.a, lineSegment.b
|
||||
false
|
||||
|
||||
intersectsShape: (shape) ->
|
||||
if shape.isEllipse then @intersectsEllipse shape else @intersectsRectangle shape
|
||||
|
||||
subtract: (point) ->
|
||||
@x -= point.x
|
||||
@y -= point.y
|
||||
|
@ -102,10 +177,10 @@ class Rectangle
|
|||
@
|
||||
|
||||
isEmpty: () ->
|
||||
@width == 0 and @height == 0
|
||||
@width is 0 and @height is 0
|
||||
|
||||
invalid: () ->
|
||||
return (@x == Infinity) || isNaN(@x) || @y == Infinity || isNaN(@y) || @width == Infinity || isNaN(@width) || @height == Infinity || isNaN(@height) || @rotation == Infinity || isNaN(@rotation)
|
||||
return (@x is Infinity) || isNaN(@x) || @y is Infinity || isNaN(@y) || @width is Infinity || isNaN(@width) || @height is Infinity || isNaN(@height) || @rotation is Infinity || isNaN(@rotation)
|
||||
|
||||
toString: ->
|
||||
return "{x: #{@x.toFixed(0)}, y: #{@y.toFixed(0)}, w: #{@width.toFixed(0)}, h: #{@height.toFixed(0)}, rot: #{@rotation.toFixed(3)}}"
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
Vector = require './vector'
|
||||
Rectangle = require './rectangle'
|
||||
Ellipse = require './ellipse'
|
||||
LineSegment = require './line_segment'
|
||||
WorldFrame = require './world_frame'
|
||||
Thang = require './thang'
|
||||
ThangState = require './thang_state'
|
||||
|
@ -21,7 +23,7 @@ module.exports = class World
|
|||
apiProperties: ['age', 'dt']
|
||||
constructor: (@userCodeMap, classMap) ->
|
||||
# classMap is needed for deserializing Worlds, Thangs, and other classes
|
||||
@classMap = classMap ? {Vector: Vector, Rectangle: Rectangle, Thang: Thang}
|
||||
@classMap = classMap ? {Vector: Vector, Rectangle: Rectangle, Thang: Thang, Ellipse: Ellipse, LineSegment: LineSegment}
|
||||
Thang.resetThangIDs()
|
||||
|
||||
@userCodeMap ?= {}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
Vector = require './vector'
|
||||
Rectangle = require './rectangle'
|
||||
Ellipse = require './ellipse'
|
||||
LineSegment = require './line_segment'
|
||||
Grid = require './Grid'
|
||||
|
||||
module.exports.typedArraySupport = typedArraySupport = Float32Array? # Not in IE until IE 10; we'll fall back to normal arrays
|
||||
|
@ -36,7 +38,7 @@ module.exports.clone = clone = (obj, skipThangs=false) ->
|
|||
flags += 'y' if obj.sticky?
|
||||
return new RegExp(obj.source, flags)
|
||||
|
||||
if (obj instanceof Vector) or (obj instanceof Rectangle)
|
||||
if (obj instanceof Vector) or (obj instanceof Rectangle) or (obj instanceof Ellipse) or (obj instanceof LineSegment)
|
||||
return obj.copy()
|
||||
|
||||
if skipThangs and obj.isThang
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
|
|||
error_saving: "Chyba při ukládání"
|
||||
saved: "Změny uloženy"
|
||||
password_mismatch: "Hesla nesouhlasí."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
|
|||
error_saving: "Fejl under Gemning"
|
||||
saved: "Ændringer Gemt"
|
||||
password_mismatch: "Password matcher ikke."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
error_saving: "Fehler beim Speichern"
|
||||
saved: "Änderungen gespeichert"
|
||||
password_mismatch: "Passwörter stimmen nicht überein."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Jobprofil"
|
||||
job_profile_approved: "Dein Jobprofil wurde von CodeCombat freigegeben. Arbeitgeber können dieses solange einsehen, bis du es als inaktiv markiert oder wenn innerhalb von vier Wochen keine Änderung daran vorgenommen wurde."
|
||||
job_profile_explanation: "Hi! Fülle dies aus und wir melden uns bei dir bezüglich des Auffindens eines Jobs als Programmierer"
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Deutsch", englishDescription: "German", tra
|
|||
error_saving: "Fehler beim Speichern"
|
||||
saved: "Änderungen gespeichert"
|
||||
password_mismatch: "Passwörter stimmen nicht überein."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Jobprofil"
|
||||
job_profile_approved: "Dein Jobprofil wurde von CodeCombat freigegeben. Arbeitgeber können dieses solange einsehen, bis du es als inaktiv markiert oder wenn innerhalb von vier Wochen keine Änderung daran vorgenommen wurde."
|
||||
job_profile_explanation: "Hi! Fülle dies aus und wir melden uns bei dir bezüglich des Auffindens eines Jobs als Programmierer"
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "ελληνικά", englishDescription: "Gre
|
|||
error_saving: "Σφάλμα αποθήκευσης"
|
||||
saved: "Οι αλλαγές αποθηκεύτηκαν"
|
||||
password_mismatch: "Οι κωδικοί δεν ταιριάζουν"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
error_saving: "Error Saving"
|
||||
saved: "Changes Saved"
|
||||
password_mismatch: "Password does not match."
|
||||
password_repeat: "Please repeat your massword."
|
||||
password_repeat: "Please repeat your password."
|
||||
job_profile: "Job Profile"
|
||||
job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "español (América Latina)", englishDescrip
|
|||
error_saving: "Error al Guardar"
|
||||
saved: "Cambios Guardados"
|
||||
password_mismatch: "La contraseña no coincide."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Perfil de Trabajo"
|
||||
job_profile_approved: "Tu perfil de trabajo ha sido aprobado por CodeCombat. Los empleadores podrán verlo hasta que lo marques como inactivo o permanezca sin cambios por cuatro semanas."
|
||||
job_profile_explanation: "¡Hola! Llena esto, y te contactaremos acerca de encontrar un trabajo como desarrollador de software."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
|
|||
error_saving: "Error al guardar"
|
||||
saved: "Cambios guardados"
|
||||
password_mismatch: "La contraseña no coincide"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Perfil de trabajo"
|
||||
job_profile_approved: "Tu perfil de trabajo ha sido aprobado por CodeCombat. Los empleadores podrán verlo hasta que lo marques como inactivo o no haya sido cambiado durante cuatro semanas."
|
||||
job_profile_explanation: "¡Hola! Rellena esto y estaremos en contacto para hablar sobre encontrarte un trabajo como desarrollador de software."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "español", englishDescription: "Spanish", t
|
|||
error_saving: "Error al guardar"
|
||||
saved: "Cambios guardados"
|
||||
password_mismatch: "La contraseña no coincide"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
|
|||
error_saving: "Problème d'enregistrement"
|
||||
saved: "Changements sauvegardés"
|
||||
password_mismatch: "Le mot de passe ne correspond pas."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Profil d'emploi"
|
||||
job_profile_approved: "Votre profil d'emploi a été approuvé par CodeCombat. Les employeurs seront en mesure de voir votre profil jusqu'à ce que vous le marquez inactif ou qu'il n'a pas été changé pendant quatre semaines."
|
||||
job_profile_explanation: "Salut! Remplissez-le et nous prendrons contact pour vous trouver un emploi de développeur de logiciels."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
|
|||
error_saving: "בעיה בשמירה"
|
||||
saved: "השינויים נשמרו"
|
||||
password_mismatch: "סיסמאות לא זהות"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
|
|||
error_saving: "Hiba a mentés során"
|
||||
saved: "Változtatások elmentve"
|
||||
password_mismatch: "A jelszavak nem egyeznek."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Munkaköri leírás"
|
||||
job_profile_approved: "Munkaköri leírásodat a Codecombat jóváhagyta. Munkaadók mindaddig láthatják, amíg meg nem jelölöd inaktívként, vagy négy hétig, ha addig nem kerül megváltoztatásra."
|
||||
job_profile_explanation: "Szió! Töltsd ki ezt és majd kapcsolatba lépünk veled és keresünk neked egy szoftware fejlesztői állást."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
|
|||
error_saving: "Errore durante il salvataggio"
|
||||
saved: "Modifiche salvate"
|
||||
password_mismatch: "La password non corrisponde."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
|
|||
error_saving: "セーブ中にエラーが発生しました"
|
||||
saved: "変更しました"
|
||||
password_mismatch: "パスワードが違います"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "求職情報"
|
||||
job_profile_approved: "CodeCombatは、あなたの求職情報を承りました。無効にする、もしくは4週間の間変更をしなければ雇用者はあなたの求職情報を見ることができなくなります。"
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
|
|||
error_saving: "오류 저장"
|
||||
saved: "변경사항 저장 완료"
|
||||
password_mismatch: "비밀번호가 일치하지 않습니다."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
|
|||
error_saving: "Masalah menyimpan"
|
||||
saved: "Pengubahsuian disimpan"
|
||||
password_mismatch: "Kata-laluan tidak sama."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
|
|||
error_saving: "Lagring Feilet"
|
||||
saved: "Endringer Lagret"
|
||||
password_mismatch: "Passordene er ikke like."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
|
|||
error_saving: "Fout Tijdens Het Opslaan"
|
||||
saved: "Aanpassingen Opgeslagen"
|
||||
password_mismatch: "Het wachtwoord komt niet overeen."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Job Profiel"
|
||||
job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken."
|
||||
job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
|
|||
error_saving: "Fout Tijdens Het Opslaan"
|
||||
saved: "Aanpassingen Opgeslagen"
|
||||
password_mismatch: "Het wachtwoord komt niet overeen."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Job Profiel"
|
||||
job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken."
|
||||
job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Nederlands", englishDescription: "Dutch", t
|
|||
error_saving: "Fout Tijdens Het Opslaan"
|
||||
saved: "Aanpassingen Opgeslagen"
|
||||
password_mismatch: "Het wachtwoord komt niet overeen."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Job Profiel"
|
||||
job_profile_approved: "Jouw job profiel werd goedgekeurd door CodeCombat. Werkgevers zullen het kunnen bekijken totdat je het inactief zet of als er geen verandering in komt voor vier weken."
|
||||
job_profile_explanation: "Hey! Vul dit in en we zullen je contacteren om je een job als softwareontwikkelaar te helpen vinden."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
|
|||
error_saving: "Lagring Feilet"
|
||||
saved: "Endringer Lagret"
|
||||
password_mismatch: "Passordene er ikke like."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
|
|||
error_saving: "Błąd zapisywania"
|
||||
saved: "Zmiany zapisane"
|
||||
password_mismatch: "Hasła róznią się od siebie"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "português do Brasil", englishDescription:
|
|||
error_saving: "Erro no salvamento"
|
||||
saved: "Alterações Salvas"
|
||||
password_mismatch: "As senhas não estão iguais"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Perfil de trabalho"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
|
|||
error_saving: "Erro ao Guardar"
|
||||
saved: "Alterações Guardadas"
|
||||
password_mismatch: "As palavras-passe não coincidem."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Perfil de Emprego"
|
||||
job_profile_approved: "O seu perfil de emprego foi aprovado pelo CodeCombat. Os empregadores poderão vê-lo até que o defina como inativo ou não o tenha alterado à 4 semanas."
|
||||
job_profile_explanation: "Olá! Preencha isto e entraremos em contacto consigo sobre encontrar um emprego de desenvolvedor de software para si."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "português", englishDescription: "Portugues
|
|||
error_saving: "Erro no salvamento"
|
||||
saved: "Alterações Salvas"
|
||||
password_mismatch: "As senhas não estão iguais"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
|
|||
error_saving: "Salvare erori"
|
||||
saved: "Modificări salvate"
|
||||
password_mismatch: "Parola nu se potrivește."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
|
|||
error_saving: "Ошибка сохранения"
|
||||
saved: "Изменения сохранены"
|
||||
password_mismatch: "Пароли не совпадают."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Профиль соискателя"
|
||||
job_profile_approved: "Ваш профиль соискателя был одобрен CodeCombat. Работодатели смогут видеть его, пока вы не отметите его неактивным или он не будет изменен в течение четырёх недель."
|
||||
job_profile_explanation: "Привет! Заполните это, и мы свяжемся с вами при нахождении работы разработчика программного обеспечения для вас."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
|
|||
error_saving: "Chyba pri ukladaní"
|
||||
saved: "Zmeny uložené"
|
||||
password_mismatch: "Heslá nesedia."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
|
|||
error_saving: "Чување грешке..."
|
||||
saved: "Измене су сачуване"
|
||||
password_mismatch: "Шифре се не слажу."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
|
|||
error_saving: "Ett fel uppstod när ändringarna skulle sparas"
|
||||
saved: "Ändringar sparade"
|
||||
password_mismatch: "De angivna lösenorden stämmer inte överens."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
|
|||
error_saving: "บันทึกผิดพลาด"
|
||||
saved: "เปลี่ยนรหัสผ่าน"
|
||||
password_mismatch: "รหัสผ่านไม่ถูกต้อง"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
|
|||
error_saving: "Kayıt Esnasında Hata"
|
||||
saved: "Değişiklikler Kaydedildi"
|
||||
password_mismatch: "Şifreler Uyuşmuyor"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "українська мова", englishDesc
|
|||
error_saving: "Помилка при збереженні"
|
||||
saved: "Зміни збережено"
|
||||
password_mismatch: "Паролі не збігаються."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "Профіль роботи"
|
||||
job_profile_approved: "Ваш робочий пофіль буде затверджений CodeCombat. Роботодавці зможуть бачити його якщо він буде відмічений як активний, або він не зазнає змін протягом 4 тижнів."
|
||||
job_profile_explanation: "Привіт! Заповніть це і ми з Вами зв‘яжемось знайшовши для Вас роботу розробника ПЗ."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
|
|||
error_saving: "Lỗi lưu"
|
||||
saved: "Thay đổi được lưu"
|
||||
password_mismatch: "Mật khẩu không khớp."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
error_saving: "保存时出错"
|
||||
saved: "更改已保存"
|
||||
password_mismatch: "密码不匹配。"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "工作经历"
|
||||
job_profile_approved: "你填写的工作经历将由CodeCombat认证. 雇主将看到这些信息,除非你将它设置为不启用状态或者连续四周没有更新."
|
||||
job_profile_explanation: "你好! 填写这些信息, 我们将使用它帮你寻找一份软件开发的工作."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
|
|||
error_saving: "保存時發生錯誤"
|
||||
saved: "修改已儲存"
|
||||
password_mismatch: "密碼不正確。"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
|
|||
# error_saving: "Error Saving"
|
||||
# saved: "Changes Saved"
|
||||
# password_mismatch: "Password does not match."
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
|
|||
error_saving: "保存時出錯"
|
||||
saved: "保存起來哉"
|
||||
password_mismatch: "密碼弗合。"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
job_profile: "工作經歷"
|
||||
job_profile_approved: "爾填個工作經歷會讓CodeCombat來確認. 僱主會望着箇許訊息,除非爾畀渠調成望弗着狀態要勿粘牢四個星期朆改動。"
|
||||
job_profile_explanation: "爾好!填箇許訊息,我裏會用渠幫爾尋一份軟件開發個工作。"
|
||||
|
|
|
@ -186,7 +186,7 @@ module.exports = nativeDescription: "中文", englishDescription: "Chinese", tra
|
|||
error_saving: "保存失败"
|
||||
saved: "已保存"
|
||||
password_mismatch: "密码不对应"
|
||||
# password_repeat: "Please repeat your massword."
|
||||
# password_repeat: "Please repeat your password."
|
||||
# job_profile: "Job Profile"
|
||||
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
|
||||
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#test-view
|
||||
background-color: #eee
|
||||
margin: 0 20px
|
||||
padding: 0
|
||||
|
||||
h2
|
||||
background: #add8e6
|
||||
|
@ -11,4 +13,4 @@
|
|||
width: 78%
|
||||
|
||||
#test-nav
|
||||
width: 20%
|
||||
width: 20%
|
||||
|
|
|
@ -20,3 +20,5 @@ ol.breadcrumb
|
|||
span.spl= child.name
|
||||
if child.type == 'folder'
|
||||
strong (#{child.size})
|
||||
|
||||
.clearfix
|
|
@ -6,6 +6,8 @@ serializedClasses =
|
|||
Thang: require 'lib/world/thang'
|
||||
Vector: require 'lib/world/vector'
|
||||
Rectangle: require 'lib/world/rectangle'
|
||||
Ellipse: require 'lib/world/ellipse'
|
||||
LineSegment: require 'lib/world/line_segment'
|
||||
|
||||
module.exports = class DebugView extends View
|
||||
className: 'spell-debug-view'
|
||||
|
|
|
@ -14,7 +14,7 @@ describe 'Camera (Surface point of view)', ->
|
|||
|
||||
sup = cam.worldToSurface wop
|
||||
expect(sup.x).toBeCloseTo wop.x * Camera.PPM
|
||||
expect(sup.y).toBeCloseTo cam.surfaceHeight - (wop.y + wop.z * cam.z2y) * cam.y2x * Camera.PPM
|
||||
expect(sup.y).toBeCloseTo -(wop.y + wop.z * cam.z2y) * cam.y2x * Camera.PPM
|
||||
|
||||
cap = cam.worldToCanvas wop
|
||||
expect(cap.x).toBeCloseTo (sup.x - cam.surfaceViewport.x) * cam.zoom
|
||||
|
@ -83,47 +83,48 @@ describe 'Camera (Surface point of view)', ->
|
|||
testAngles = [0, Math.PI / 4, null, Math.PI / 2]
|
||||
testFOVs = [Math.PI / 6, Math.PI / 3, Math.PI / 2, Math.PI]
|
||||
|
||||
xit 'handles lots of different cases correctly', ->
|
||||
it 'handles lots of different cases correctly', ->
|
||||
for wop in testWops
|
||||
for size in testCanvasSizes
|
||||
for zoom in testZooms
|
||||
for target in testZoomTargets
|
||||
for angle in testAngles
|
||||
for fov in testFOVs
|
||||
cam = new Camera size.width, size.height, size.width * Camera.MPP, size.height * Camera.MPP, testLayer, zoom, null, angle, fov
|
||||
cam = new Camera {attr: (attr) -> if 'attr' is 'width' then size.width else size.height}, angle, fov
|
||||
checkCameraPos cam, wop
|
||||
cam.zoomTo target, zoom, 0
|
||||
checkConversionsFromWorldPos wop, cam
|
||||
checkCameraPos cam, wop
|
||||
|
||||
it 'works at 90 degrees', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
|
||||
cam = new Camera {attr: (attr) -> 100}, Math.PI / 2
|
||||
expect(cam.x2y).toBeCloseTo 1
|
||||
expect(cam.x2z).toBeGreaterThan 9001
|
||||
expect(cam.z2y).toBeCloseTo 0
|
||||
|
||||
it 'works at 0 degrees', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
|
||||
expect(cam.x2z).toBeGreaterThan 9001
|
||||
expect(cam.x2y).toBeCloseTo 1
|
||||
expect(cam.z2y).toBeCloseTo 0
|
||||
cam = new Camera {attr: (attr) -> 100}, 0
|
||||
expect(cam.x2y).toBeGreaterThan 9001
|
||||
expect(cam.x2z).toBeCloseTo 1
|
||||
expect(cam.z2y).toBeGreaterThan 9001
|
||||
|
||||
it 'works at 45 degrees', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
|
||||
expect(cam.x2y).toBeCloseTo 1
|
||||
expect(cam.x2z).toBeGreaterThan 9001
|
||||
expect(cam.z2y).toBeCloseTo 0
|
||||
cam = new Camera {attr: (attr) -> 100}, Math.PI / 4
|
||||
expect(cam.x2y).toBeCloseTo Math.sqrt(2)
|
||||
expect(cam.x2z).toBeCloseTo Math.sqrt(2)
|
||||
expect(cam.z2y).toBeCloseTo 1
|
||||
|
||||
xit 'works at default angle of asin(0.75) ~= 48.9 degrees', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
|
||||
angle = 1 / Math.cos angle
|
||||
it 'works at default angle of asin(0.75) ~= 48.9 degrees', ->
|
||||
cam = new Camera {attr: (attr) -> 100}, null
|
||||
angle = Math.asin(3 / 4)
|
||||
expect(cam.angle).toBeCloseTo angle
|
||||
expect(cam.x2y).toBeCloseTo 1
|
||||
expect(cam.x2z).toBeGreaterThan 9001
|
||||
expect(cam.z2y).toBeCloseTo 0
|
||||
expect(cam.x2y).toBeCloseTo 4 / 3
|
||||
expect(cam.x2z).toBeCloseTo 1 / Math.cos angle
|
||||
expect(cam.z2y).toBeCloseTo (4 / 3) * Math.cos angle
|
||||
|
||||
xit 'works at 2x zoom, 90 degrees', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
|
||||
cam = new Camera {attr: (attr) -> 100}, Math.PI / 2
|
||||
cam.zoomTo null, 2, 0
|
||||
checkCameraPos cam
|
||||
wop = x: 5, y: 2.5, z: 7
|
||||
cap = cam.worldToCanvas wop
|
||||
|
@ -143,7 +144,8 @@ describe 'Camera (Surface point of view)', ->
|
|||
expectPositionsEqual cap, {x: 0, y: 50}
|
||||
|
||||
xit 'works at 2x zoom, 30 degrees', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 2 * 100 * Camera.MPP
|
||||
cam = new Camera {attr: (attr) -> 100}, Math.PI / 6
|
||||
cam.zoomTo null, 2, 0
|
||||
expect(cam.x2y).toBeCloseTo 1
|
||||
expect(cam.x2z).toBeGreaterThan 9001
|
||||
checkCameraPos cam
|
||||
|
@ -164,15 +166,18 @@ describe 'Camera (Surface point of view)', ->
|
|||
expectPositionsEqual cap, {x: 50, y: -100}
|
||||
|
||||
it 'works at 2x zoom, 60 degree hFOV', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 100 * Camera.MPP, 100 * Camera.MPP
|
||||
cam = new Camera {attr: (attr) -> 100}, null, Math.PI / 3
|
||||
cam.zoomTo null, 2, 0
|
||||
checkCameraPos cam
|
||||
|
||||
xit 'works at 2x zoom, 60 degree hFOV, 40 degree hFOV', ->
|
||||
cam = new Camera {attr: (x) -> x is 'height' ? 63.041494 : 100}, 100 * Camera.MPP, 63.041494 * Camera.MPP
|
||||
it 'works at 2x zoom, 60 degree hFOV, 40 degree vFOV', ->
|
||||
cam = new Camera {attr: (attr) -> if attr is 'height' then 63.041494 else 100}, null, Math.PI / 3
|
||||
cam.zoomTo null, 2, 0
|
||||
checkCameraPos cam
|
||||
|
||||
xit 'works on a surface wider than it is tall, 30 degrees, default viewing upper left corner', ->
|
||||
cam = new Camera {attr: (x) -> 100}, 200 * Camera.MPP, 2 * 50 * Camera.MPP
|
||||
xit 'works at 2x zoom on a surface wider than it is tall, 30 degrees, default viewing upper left corner', ->
|
||||
cam = new Camera {attr: (attr) -> 100}, Math.PI / 6 # 200 * Camera.MPP, 2 * 50 * Camera.MPP
|
||||
cam.zoomTo null, 2, 0
|
||||
checkCameraPos cam
|
||||
expect(cam.zoom).toBeCloseTo 2
|
||||
wop = x: 5, y: 4, z: 6 * cam.y2z # like x: 5, y: 10 out of world width: 20, height: 10
|
||||
|
|
99
test/app/lib/world/ellipse.spec.coffee
Normal file
99
test/app/lib/world/ellipse.spec.coffee
Normal file
|
@ -0,0 +1,99 @@
|
|||
describe 'Ellipse', ->
|
||||
Ellipse = require 'lib/world/ellipse'
|
||||
Rectangle = require 'lib/world/rectangle'
|
||||
Vector = require 'lib/world/vector'
|
||||
|
||||
#it 'contains its own center', ->
|
||||
# ellipse = new Ellipse 0, 0, 10, 10
|
||||
# expect(ellipse.containsPoint(new Vector 0, 0)).toBe true
|
||||
#
|
||||
#it 'contains a point when rotated', ->
|
||||
# ellipse = new Ellipse 0, -20, 40, 40, 3 * Math.PI / 4
|
||||
# p = new Vector 0, 2
|
||||
# expect(ellipse.containsPoint(p, true)).toBe true
|
||||
#
|
||||
#it 'contains more points properly', ->
|
||||
# # ellipse with y major axis, off-origin center, and 45 degree rotation
|
||||
# ellipse = new Ellipse 1, 2, 4, 6, Math.PI / 4
|
||||
# expect(ellipse.contains new Vector(1, 2)).toBe true
|
||||
# expect(ellipse.contains new Vector(-1, 3)).toBe true
|
||||
# expect(ellipse.contains new Vector(0, 4)).toBe true
|
||||
# expect(ellipse.contains new Vector(1, 4)).toBe true
|
||||
# expect(ellipse.contains new Vector(3, 0)).toBe true
|
||||
# expect(ellipse.contains new Vector(1, 0)).toBe true
|
||||
# expect(ellipse.contains new Vector(0, 1)).toBe true
|
||||
# expect(ellipse.contains new Vector(-1, 2)).toBe true
|
||||
# expect(ellipse.contains new Vector(2, 2)).toBe true
|
||||
# expect(ellipse.contains new Vector(0, 0)).toBe false
|
||||
# expect(ellipse.contains new Vector(0, 5)).toBe false
|
||||
# expect(ellipse.contains new Vector(3, 4)).toBe false
|
||||
# expect(ellipse.contains new Vector(4, 0)).toBe false
|
||||
# expect(ellipse.contains new Vector(2, -1)).toBe false
|
||||
# expect(ellipse.contains new Vector(0, -3)).toBe false
|
||||
# expect(ellipse.contains new Vector(-2, -2)).toBe false
|
||||
# expect(ellipse.contains new Vector(-2, 0)).toBe false
|
||||
# expect(ellipse.contains new Vector(-2, 4)).toBe false
|
||||
#
|
||||
#it 'correctly calculates distance to a faraway point', ->
|
||||
# ellipse = new Ellipse 100, 50, 20, 40
|
||||
# p = new Vector 200, 300
|
||||
# d = 10 * Math.sqrt(610)
|
||||
# expect(ellipse.distanceToPoint(p)).toBeCloseTo d
|
||||
# ellipse.rotation = Math.PI / 2
|
||||
# d = 80 * Math.sqrt(10)
|
||||
# expect(ellipse.distanceToPoint(p)).toBeCloseTo d
|
||||
#
|
||||
#it 'does not modify itself or target Vector when calculating distance', ->
|
||||
# ellipse = new Ellipse -100, -200, 1, 100
|
||||
# ellipse2 = ellipse.copy()
|
||||
# p = new Vector -100.25, -101
|
||||
# p2 = p.copy()
|
||||
# ellipse.distanceToPoint(p)
|
||||
# expect(p.x).toEqual p2.x
|
||||
# expect(p.y).toEqual p2.y
|
||||
# expect(ellipse.x).toEqual ellipse2.x
|
||||
# expect(ellipse.y).toEqual ellipse2.y
|
||||
# expect(ellipse.width).toEqual ellipse2.width
|
||||
# expect(ellipse.height).toEqual ellipse2.height
|
||||
# expect(ellipse.rotation).toEqual ellipse2.rotation
|
||||
#
|
||||
#it 'correctly calculates distance to contained point', ->
|
||||
# ellipse = new Ellipse -100, -200, 1, 100
|
||||
# ellipse2 = ellipse.copy()
|
||||
# p = new Vector -100.25, -160
|
||||
# p2 = p.copy()
|
||||
# expect(ellipse.distanceToPoint(p)).toBe 0
|
||||
# ellipse.rotation = 0.00000001 * Math.PI
|
||||
# expect(ellipse.distanceToPoint(p)).toBe 0
|
||||
#
|
||||
#it 'AABB works when not rotated', ->
|
||||
# ellipse = new Ellipse 10, 20, 30, 40
|
||||
# rect = new Rectangle 10, 20, 30, 40
|
||||
# aabb1 = ellipse.axisAlignedBoundingBox()
|
||||
# aabb2 = ellipse.axisAlignedBoundingBox()
|
||||
# for prop in ['x', 'y', 'width', 'height']
|
||||
# expect(aabb1[prop]).toBe aabb2[prop]
|
||||
#
|
||||
#it 'AABB works when rotated', ->
|
||||
# ellipse = new Ellipse 10, 20, 30, 40, Math.PI / 3
|
||||
# rect = new Rectangle 10, 20, 30, 40, Math.PI / 3
|
||||
# aabb1 = ellipse.axisAlignedBoundingBox()
|
||||
# aabb2 = ellipse.axisAlignedBoundingBox()
|
||||
# for prop in ['x', 'y', 'width', 'height']
|
||||
# expect(aabb1[prop]).toBe aabb2[prop]
|
||||
#
|
||||
#it 'calculates ellipse intersections properly', ->
|
||||
# # ellipse with y major axis, off-origin center, and 45 degree rotation
|
||||
# ellipse = new Ellipse 1, 2, 4, 6, Math.PI / 4
|
||||
# expect(ellipse.intersectsShape new Rectangle(0, 0, 2, 2, 0)).toBe true
|
||||
# expect(ellipse.intersectsShape new Rectangle(0, -1, 2, 3, 0)).toBe true
|
||||
# expect(ellipse.intersectsShape new Rectangle(-1, -0.5, 2 * Math.SQRT2, 2 * Math.SQRT2, Math.PI / 4)).toBe true
|
||||
# expect(ellipse.intersectsShape new Rectangle(-1, -0.5, 2 * Math.SQRT2, 2 * Math.SQRT2, 0)).toBe true
|
||||
# expect(ellipse.intersectsShape new Rectangle(-1, -1, 2 * Math.SQRT2, 2 * Math.SQRT2, 0)).toBe true
|
||||
# expect(ellipse.intersectsShape new Rectangle(-1, -1, 2 * Math.SQRT2, 2 * Math.SQRT2, Math.PI / 4)).toBe false
|
||||
# expect(ellipse.intersectsShape new Rectangle(-2, -2, 2, 2, 0)).toBe false
|
||||
# expect(ellipse.intersectsShape new Rectangle(-Math.SQRT2 / 2, -Math.SQRT2 / 2, Math.SQRT2, Math.SQRT2, 0)).toBe false
|
||||
# expect(ellipse.intersectsShape new Rectangle(-Math.SQRT2 / 2, -Math.SQRT2 / 2, Math.SQRT2, Math.SQRT2, Math.PI / 4)).toBe false
|
||||
# expect(ellipse.intersectsShape new Rectangle(-2, 0, 2, 2, 0)).toBe false
|
||||
# expect(ellipse.intersectsShape new Rectangle(0, -2, 2, 2, 0)).toBe false
|
||||
# expect(ellipse.intersectsShape new Rectangle(1, 2, 1, 1, 0)).toBe true
|
51
test/app/lib/world/line_segment.spec.coffee
Normal file
51
test/app/lib/world/line_segment.spec.coffee
Normal file
|
@ -0,0 +1,51 @@
|
|||
describe 'LineSegment', ->
|
||||
LineSegment = require 'lib/world/line_segment'
|
||||
Vector = require 'lib/world/vector'
|
||||
|
||||
v00 = new Vector(0, 0)
|
||||
v11 = new Vector(1, 1)
|
||||
v22 = new Vector(2, 2)
|
||||
v34 = new Vector(3, 4)
|
||||
v04 = new Vector(0, 4)
|
||||
v30 = new Vector(3, 0)
|
||||
vneg = new Vector(-1, -1)
|
||||
|
||||
it 'intersects itself', ->
|
||||
lineSegment = new LineSegment v00, v34
|
||||
expect(lineSegment.intersectsLineSegment lineSegment).toBe true
|
||||
|
||||
it 'intersects other segments properly', ->
|
||||
l1 = new LineSegment v00, v34
|
||||
l2 = new LineSegment v04, v30
|
||||
l3 = new LineSegment v00, v11
|
||||
expect(l1.intersectsLineSegment l2).toBe true
|
||||
expect(l2.intersectsLineSegment l1).toBe true
|
||||
expect(l1.intersectsLineSegment l3).toBe true
|
||||
expect(l3.intersectsLineSegment l1).toBe true
|
||||
expect(l2.intersectsLineSegment l3).toBe false
|
||||
expect(l3.intersectsLineSegment l2).toBe false
|
||||
|
||||
it 'can tell when a point is on a line or segment', ->
|
||||
lineSegment = new LineSegment v00, v11
|
||||
expect(lineSegment.pointOnLine v22, false).toBe true
|
||||
#expect(lineSegment.pointOnLine v22, true).toBe false
|
||||
#expect(lineSegment.pointOnLine v00, false).toBe true
|
||||
#expect(lineSegment.pointOnLine v00, true).toBe true
|
||||
#expect(lineSegment.pointOnLine v11, true).toBe true
|
||||
#expect(lineSegment.pointOnLine v11, false).toBe true
|
||||
#expect(lineSegment.pointOnLine v34, false).toBe false
|
||||
#expect(lineSegment.pointOnLine v34, true).toBe false
|
||||
|
||||
it 'correctly calculates distance to points', ->
|
||||
lineSegment = new LineSegment v00, v11
|
||||
expect(lineSegment.distanceToPoint v00).toBe 0
|
||||
expect(lineSegment.distanceToPoint v11).toBe 0
|
||||
expect(lineSegment.distanceToPoint v22).toBeCloseTo Math.SQRT2
|
||||
expect(lineSegment.distanceToPoint v34).toBeCloseTo Math.sqrt(2 * 2 + 3 * 3)
|
||||
expect(lineSegment.distanceToPoint v04).toBeCloseTo Math.sqrt(1 * 1 + 3 * 3)
|
||||
expect(lineSegment.distanceToPoint v30).toBeCloseTo Math.sqrt(2 * 2 + 1 * 1)
|
||||
expect(lineSegment.distanceToPoint vneg).toBeCloseTo Math.SQRT2
|
||||
|
||||
nullSegment = new LineSegment v11, v11
|
||||
expect(lineSegment.distanceToPoint v11).toBe 0
|
||||
expect(lineSegment.distanceToPoint v22).toBeCloseTo Math.SQRT2
|
|
@ -1,6 +1,7 @@
|
|||
describe 'Rectangle', ->
|
||||
Rectangle = require 'lib/world/rectangle'
|
||||
Vector = require 'lib/world/vector'
|
||||
Ellipse = require 'lib/world/ellipse'
|
||||
|
||||
it 'contains its own center', ->
|
||||
rect = new Rectangle 0, 0, 10, 10
|
||||
|
@ -43,6 +44,13 @@ describe 'Rectangle', ->
|
|||
rect.rotation = 0.00000001 * Math.PI
|
||||
expect(rect.distanceToPoint(p)).toBe 0
|
||||
|
||||
it 'correctly calculates distance to other rectangles', ->
|
||||
expect(new Rectangle(0, 0, 4, 4, Math.PI / 4).distanceToRectangle(new Rectangle(4, -4, 2, 2, 0))).toBeCloseTo 2.2426
|
||||
expect(new Rectangle(0, 0, 3, 3, 0).distanceToRectangle(new Rectangle(0, 0, 2, 2, 0))).toBe 0
|
||||
expect(new Rectangle(0, 0, 3, 3, 0).distanceToRectangle(new Rectangle(0, 0, 2.5, 2.5, Math.PI / 4))).toBe 0
|
||||
expect(new Rectangle(0, 0, 4, 4, 0).distanceToRectangle(new Rectangle(4, 2, 2, 2, 0))).toBe 1
|
||||
expect(new Rectangle(0, 0, 4, 4, 0).distanceToRectangle(new Rectangle(4, 2, 2, 2, Math.PI / 4))).toBeCloseTo 2 - Math.SQRT2
|
||||
|
||||
it 'has predictable vertices', ->
|
||||
rect = new Rectangle 50, 50, 100, 100
|
||||
v = rect.vertices()
|
||||
|
@ -79,3 +87,22 @@ describe 'Rectangle', ->
|
|||
aabb = rect.axisAlignedBoundingBox()
|
||||
for prop in ['x', 'y', 'width', 'height']
|
||||
expect(rect[prop]).toBe aabb[prop]
|
||||
|
||||
it 'calculates rectangle intersections properly', ->
|
||||
rect = new Rectangle 1, 1, 2, 2, 0
|
||||
expect(rect.intersectsShape new Rectangle(3, 1, 2, 2, 0)).toBe true
|
||||
expect(rect.intersectsShape new Rectangle(3, 3, 2, 2, 0)).toBe true
|
||||
expect(rect.intersectsShape new Rectangle(1, 1, 2, 2, 0)).toBe true
|
||||
expect(rect.intersectsShape new Rectangle(1, 1, Math.SQRT1_2, Math.SQRT1_2, Math.PI / 4)).toBe true
|
||||
expect(rect.intersectsShape new Rectangle(4, 1, 2, 2, 0)).toBe false
|
||||
expect(rect.intersectsShape new Rectangle(3, 4, 2, 2, 0)).toBe false
|
||||
expect(rect.intersectsShape new Rectangle(1, 4, 2 * Math.SQRT1_2, 2 * Math.SQRT1_2, Math.PI / 4)).toBe false
|
||||
expect(rect.intersectsShape new Rectangle(3, 1, 2, 2, Math.PI / 4)).toBe true
|
||||
expect(rect.intersectsShape new Rectangle(1, 2, 2 * Math.SQRT2, 2 * Math.SQRT2, Math.PI / 4)).toBe true
|
||||
|
||||
it 'calculates ellipse intersections properly', ->
|
||||
rect = new Rectangle 1, 1, 2, 2, 0
|
||||
expect(rect.intersectsShape new Ellipse(1, 1, Math.SQRT1_2, Math.SQRT1_2, Math.PI / 4)).toBe true
|
||||
expect(rect.intersectsShape new Ellipse(4, 1, 2, 2, 0)).toBe false
|
||||
expect(rect.intersectsShape new Ellipse(3, 4, 2, 2, 0)).toBe false
|
||||
expect(rect.intersectsShape new Ellipse(1, 4, 2 * Math.SQRT1_2, 2 * Math.SQRT1_2, Math.PI / 4)).toBe false
|
||||
|
|
2
vendor/styles/jasmine.css
vendored
2
vendor/styles/jasmine.css
vendored
|
@ -1,5 +1,3 @@
|
|||
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
|
||||
|
||||
.html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
|
||||
.html-reporter a { text-decoration: none; }
|
||||
.html-reporter a:hover { text-decoration: underline; }
|
||||
|
|
Loading…
Reference in a new issue