Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Бонус #2

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.idea/
.idea/
/*.bat
/node_modules
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "qunit"]
path = qunit
url = git://github.com/jquery/qunit.git
107 changes: 107 additions & 0 deletions Ball.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Created with JetBrains WebStorm.
* User: yunnii
* Date: 12/1/12
* Time: 3:35 AM
* To change this template use File | Settings | File Templates.
*/
/*global R: true*/
/*global Point: true*/
/*global Vector: true*/

(function (exports) {
"use strict";

var colour = "90-rgb(151, 193, 246)-rgb(89, 154, 219)",
speed = 5;

/**
* Конструктор, принимает координаты центра шара, радиус и объект на котором необходимо его разместить
*
* @param {object} paper
* @param {double}x
* @param {double}y
* @param {double}r
* @constructor
* @this {Ball}
*/
var Ball = function (paper, x, y, r) {
this.r = r;
this.circle = paper.circle(x, y, r).attr({fill: colour});
this.areaRadius = r + 30;
this.Speed = new Vector(0, 0);
};

exports.Ball = Ball;

Ball.prototype.X = function () { return this.circle.attrs.cx; };
Ball.prototype.Y = function () { return this.circle.attrs.cy; };
Ball.prototype.moveSpeed = function () { return speed; };
/**
* Пересчитать скорость для движения в указанном направлении
*
* @param {double}x - координата x, откуда по отношению к центру был толчок
* @param {double}y - координата y, откуда по отношению к центру был толчок
*/

Ball.prototype.moveBall = function (x, y) {

var center = new Point(this.X(), this.Y()),
hypot = Math.sqrt((center.Y - y) * (center.Y - y) + (center.X - x) * (center.X - x)),
sinus = (center.Y - y) / hypot,
cosinus = (center.X - x) / hypot;

this.Speed.set(cosinus * speed, sinus * speed);
};

/**
* Двигаться в указанном ранее направлении
*
*/
Ball.prototype.move = function (updateTime) {

var center = new Point(this.X(), this.Y()),
nextX = center.X + this.Speed.X(),
nextY = center.Y + this.Speed.Y();

this.circle.stop().animate({cx: nextX, cy: nextY, r: this.r}, updateTime);

};

/** Принадлежит ли точка, переданная в параметре, окрестности радиуса this.areaRadius шара
*
* @param {double}x - координата x
* @param {double}y - координата y
*/
Ball.prototype.isNearBall = function (x, y) {
return (Math.abs(this.X() - x) < this.areaRadius &&
Math.abs(this.Y() - y) < this.areaRadius);
};

/**
* Пересчет скорости при возникновении события "отражение от стенки"
*
* @param {Line}borderLine - уравнение прямой, описывающей стенку
*/

Ball.prototype.reflectDirection = function (borderLine) {

var center = new Point(this.X(), this.Y()),
normalToBorderLine = borderLine.getNormalLine(center),
previousLocation = new Point(center.X - 2 * this.Speed.X(), center.Y - 2 * this.Speed.Y()),
parallelToBorderLine = normalToBorderLine.getNormalLine(previousLocation),
reflectionPoint = parallelToBorderLine.getIntersectPoint(normalToBorderLine),
nextPoint = new Point(2 * reflectionPoint.X - previousLocation.X, 2 * reflectionPoint.Y - previousLocation.Y),
normalizeNext = Vector.getVectorFrom2Point(center, nextPoint).normalize();

this.Speed.set(speed * normalizeNext.X(), speed * normalizeNext.Y());
};

/**
* Изменить направление скорости на противоположное
*/

Ball.prototype.reflect = function () {
this.Speed.stretch(-speed);
};
}(window));
138 changes: 138 additions & 0 deletions Driver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* Created with JetBrains WebStorm.
* User: yunnii
* Date: 1/13/13
* Time: 3:09 AM
* To change this template use File | Settings | File Templates.
*/
/*global Point: true*/
/*global Line: true*/
/*global Vector: true*/
/*global Graphic: true*/

(function (exports) {
"use strict";
var colour = "90-rgb(151, 193, 246)-rgb(89, 154, 219)";
/**
*
* Водитель. Управляет перемещением некоего объекта с радиусом в рамках многоугольной границы
*
* @param element - ведомый объект, чьей логикой движения при столкновении будем управлять
* @param {Array of Line object} borderArray - массив границ
* @constructor
* @this {Driver}
*/
var Driver = function (element, borderArray) {
this.follower = element;
this.border = borderArray;
this.borderWidth = Graphic.borderWidth;
};

exports.Driver = Driver;

/**
* Находит расстояние до реальной точки пересечения (follower имеет радиус)
*
* @param lineNumber - номер линии в массиве borderArray, с которой произошло столкновение
* @param crossPoint - точка "мнимого" пересечения (пересечение материальной точки с линией)
* @param center - центр follower-a
* @return {Object} информация о будущем пересечении
*/
Driver.prototype.getDistanceToRealCross = function (lineNumber, crossPoint, center) {
var distance,
distanceToLine,
cathetus,
distanceToRealCross;

distance = crossPoint.getDistanceBetween(center);
distanceToLine = this.border[lineNumber].distanceBetween(center);
cathetus = (this.follower.r + this.borderWidth) * distance / distanceToLine;
distanceToRealCross = distance - cathetus;

return {
distance: distanceToRealCross,
line: this.border[lineNumber],
cathetus: cathetus
};
};

Driver.prototype.getImaginaryCross = function (anglePoint, speedLine, center) {
var distance,
distanceToLine,
cathetus,
distanceToRealCross;

distanceToLine = speedLine.distanceBetween(anglePoint);
cathetus = Math.sqrt((this.follower.r + this.borderWidth) * (this.follower.r + this.borderWidth) - distanceToLine * distanceToLine);
distance = speedLine.getNormalLine(anglePoint).getIntersectPoint(speedLine).getDistanceBetween(center);
distanceToRealCross = distance - cathetus;

return {
distance: distanceToRealCross
};
};

/**
* Находит пересечение границ с follower-ом
*
* @return {Object} информация о будущем пересечении
*/
Driver.prototype.findIntersection = function () {
var i,
center = new Point(this.follower.X(), this.follower.Y()),
line = Line.getLineFromVectorAndPoint(this.follower.Speed, center),
crossPoint = null,
crossBorder = [],
minimalCrossPoint = null,
result,
temp;

for (i = 0; i < this.border.length; i += 1) {
crossPoint = this.border[i].getIntersectSegmentPointWithLimits(line, center, this.follower.r);
if (crossPoint === null) continue;

if ((minimalCrossPoint === null) || (minimalCrossPoint && crossPoint.p.getDistanceBetween(center) < minimalCrossPoint.p.getDistanceBetween(center))) {
if (this.follower.Speed.isAlignment(new Vector(crossPoint.p.X - center.X, crossPoint.p.Y - center.Y))) {
minimalCrossPoint = crossPoint;
crossBorder = [];
crossBorder.push(i);
}
} else if (Math.abs(crossPoint.p.getDistanceBetween(center) - minimalCrossPoint.p.getDistanceBetween(center)) < 0.2) {
if (this.follower.Speed.isAlignment(new Vector(crossPoint.p.X - center.X, crossPoint.p.Y - center.Y))) {
crossBorder.push(i);
}
}
}

if (crossBorder.length === 1) {
if (minimalCrossPoint.imaginaryStart) {
temp = this.getImaginaryCross(this.border[crossBorder[0]].start, line, center);
temp.line = this.border[crossBorder[0]];
return temp;
}
if (minimalCrossPoint.imaginaryFinish) {
temp = this.getImaginaryCross(this.border[crossBorder[0]].finish, line, center);
temp.line = this.border[crossBorder[0]];
return temp;
}
return this.getDistanceToRealCross(crossBorder[0], minimalCrossPoint.p, center);
}
if (crossBorder.length > 1) {
result = [];
for (i = 0; i < 2; i += 1) {
result.push(this.getDistanceToRealCross(crossBorder[i], minimalCrossPoint.p, center));
}

if (Math.abs(result[0].distance - result[1].distance) < 1) {
result[0].changeOnOpposite = true;
return result[0];
}
}
return {
distance: 0,
line: 0,
changeOnOpposite: true
};
};

}(window));
78 changes: 78 additions & 0 deletions Graphic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* Created with JetBrains WebStorm.
* User: yunnii
* Date: 1/12/13
* Time: 6:26 PM
* To change this template use File | Settings | File Templates.
*/
/*global Point: true*/
/*global Line: true*/
/*global tmpl: true*/

(function (exports) {
"use strict";

var template = "M <%= previous.X %>,<%= previous.Y %> L <%= next.X %>, <%= next.Y %>",
arr = "M 154,477 L 237,381 L 237,381";

/**
* Создает экземпляр объекта, отвечающего за отрисовку объектов
*
* @param paper
* @constructor
* @this {Graphic}
*/
var Graphic = function (paper) {
this.canvas = paper;
};

exports.Graphic = Graphic;
Graphic.borderWidth = 9;

Graphic.prototype.paintArrow = function () {
return this.canvas.path(arr)
.attr({stroke: "rgb(206, 102, 95)", "stroke-width": 20, "arrow-end": "classic", "stroke-opacity": 1});
};

Graphic.prototype.paintBorder = function (pathArray, pth) {
this.canvas.path(pth)
.attr({fill: "#eee", "fill-opacity": 1, stroke: "#333", "stroke-width": 0, "stroke-linecap": "square"});

var that = this;
pathArray.forEach(function (path) {
that.canvas.path(path)
.attr({fill: "#ddd", "fill-opacity": 1, stroke: "#fff", "stroke-width": 22, "stroke-linecap": "square"});
that.canvas.path(path)
.attr({fill: "#ddd", "fill-opacity": 1, stroke: "#333", "stroke-width": Graphic.borderWidth * 2, "stroke-linecap": "square"});
});
};

Graphic.prototype.createBorder = function (result) {
var i,
current,
borderArray = [],
pathArray = [],
previous = new Point(result[0].x, result[0].y),
pth = "M".concat(previous.X, ",", previous.Y);

for (i = 1; i < result.length; i += 1) {
current = new Point(result[i].x, result[i].y);

pathArray.push(tmpl(template, { previous: previous, next: current}));
borderArray.push(Line.getLineFrom2Point(previous, current));
pth = pth.concat("L", current.X, ",", current.Y);

previous = current;
}

current = new Point(result[0].x, result[0].y);
pathArray.push(tmpl(template, { previous: previous, next : current}));
borderArray.push(Line.getLineFrom2Point(previous, current));
pth = pth.concat("L", current.X, ",", current.Y);

this.paintBorder(pathArray, pth);

return borderArray;
};

}(window));
Loading