Просмотр полной версии : Области Вороного
В этой статье http://noregret.org/tutor/n/collision/#2.2 описаны Области Вороного , но как их реализовать не могу найти, может кто подскажет?
Нужно для того что бы определить к какой части многоугольника окружность находиться ближе или проще говоря в какую часть блока летит шарик.
schmetterling
05.12.2012, 10:24
Берём для примера прямоугольник. Дальше мы считаем его проекцию на Ох. Она делит эту ось координат на три части: от минус бесконечности до начала проекции, от начала проекции до конца проекции, от конца проекции до плюс бесконечности. Обозначим их, для примера, -1, 0, 1. После этого мы проверяем, какой из частей принадлежит координата X центра окружности. Тоже самое делаем с осью Oy. Итого у нас получается девять возможных комбинаций. В зависимости от каждой из этих комбинаций мы берём нужную точку прямоугольника.
schmetterling
05.12.2012, 10:55
Вот примерный код, хотя я не тестировал его.
function distance(x1, y1, x2, y2) { // считаем расстояние между двумя точками
return Math.sqrt(Math.power((x2-x1), 2) + Math.power((y2-y1), 2))
}
/*
Проверка на столкновение.
x1, y1 -- координаты левой верхней точки прямоугольника.
x2, y2 -- координаты правой нижней точки прямоугольника.
x, y -- координаты центра окружности
r -- радиус окружности.
*/
function isCollision(x1, y1, x2, y2, x, y, r) {
var compX, compY;
// выбираем точку X прямоугольника, которая ближе всего к центру окружности.
if (x <= x1) { // если X центра слева от проекции на Ox...
compX= x1;
} else if (x < x2) { // ...принадлежит проекции
compX= x;
} else { // ...справа от проекции
compX= x2;
}
// выбираем точку Y прямоугольника, которая ближе всего к центру окружности.
if (y <= y1) { // если y центра слева от проекции на Oy...
compY= y1;
} else if (y < y2) { // ...принадлежит проекции
compY= y;
} else { // ...справа от проекции
compY= y2;
}
return r <= distance(x, y, compX, compY);
}
schmetterling, спасибо, буду разбираться)
schmetterling
05.12.2012, 16:34
schmetterling, спасибо, буду разбираться)
Не за что, удачи)
schmetterling, сразу поверхностно глянул на код , а теперь сел дальше мучатся со своим арканоидом, и понял что ваш код в общем работает так же как и мой)
вот из тестового варианта
(y <= Bl_bottom && y >= block.y - ball.R) && (x >= block.x - ball.R && x <= Bl_right)
код ниже это просто черновик
<!DOCTYPE HTML>
<html>
<head> </head>
<body>
<canvas width="500" height="500"></canvas>
<script>
var canva = document.body.children[0];
var ctx = canva.getContext("2d");
var ball = {
x:20,
y:280,
R:20,
Draw: function (x, y) {
ctx.clearRect(this.x - this.R, this.y - this.R, this.R *2,this.R *2);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.arc(x,y, this.R,0, (Math.PI / 180)* 360, false);
ctx.fill();
this.y = y;
this.x = x;
}
};
var block = {
width:150,
height:30,
Draw: function (x, y) {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.fillRect(x,y,this.width, this.height);
this.y = y;
this.x = x;
}
};
block.Draw(150,100);
var valX = -10 , valY = -10;
var Bl_bottom = block.y + block.height + ball.R ;
var Bl_right = block.x + block.width + ball.R ;
var one = false;
function action(){
if(ball.x < 0 + ball.R || ball.x > canva.width - ball.R){
valX = -valX;
};
if(ball.y < 0 + ball.R || ball.y > canva.height - ball.R){
valY = -valY;
//y = canva.height - ball.R;
}
var x = ball.x;
var y = ball.y ;
if((y <= Bl_bottom && y >= block.y - ball.R) && (x >= block.x - ball.R && x <= Bl_right)){
if(!one) drawOs(x,y);
if(!one){// запускаем еще один мячик
ball.x = 200;
ball.y = 200;
action();
one = true;
}
return;
};
x += valX;
y += valY;
ball.Draw(x,y);
setTimeout(action,1000/60);
};
action();
function drawOs(x,y){
ctx.beginPath();
ctx.moveTo(block.x - ball.R ,Bl_bottom);
ctx.lineTo(x,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(Bl_right ,Bl_bottom);
ctx.lineTo(x,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x - ball.R,block.y - ball.R);
ctx.lineTo(x,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(Bl_right,block.y - ball.R );
ctx.lineTo(x,y);
ctx.stroke();
};
</script>
</body>
</html>
проблема в столкновение с углом, в примере выше видно что если сталкивается не с углом все работает.
schmetterling
06.12.2012, 20:02
Вот картинка, тут понятно, что идёт не так)
http://cs305100.userapi.com/v305100005/3770/wjm_5L1nhvU.jpg
schmetterling,я и так это понял;)
и вообще уже знаю как поправить, просто показал если кто то будет писать арканоид и будет читать эту тему и мучатся)
вот так должен выглядить блок
<!DOCTYPE HTML>
<html>
<head> </head>
<body>
<canvas width="500" height="500"></canvas>
<script>
var canva = document.body.children[0];
var ctx = canva.getContext("2d");
var block = {
width:150,
height:30,
Draw: function (x, y) {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.fillRect(x,y,this.width, this.height);
this.y = y;
this.x = x;
boundary();
}
};
block.Draw(150,100);
function boundary() {
var rad = 20;
ctx.beginPath();
ctx.moveTo(block.x,block.y - rad);
ctx.lineTo(block.x + block.width , block.y - rad);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x+ block.width + rad,block.y);
ctx.lineTo(block.x+ block.width + rad , block.y + block.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x, block.y + block.height + rad);
ctx.lineTo(block.x + block.width , block.y + block.height + rad);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x- rad,block.y);
ctx.lineTo(block.x - rad , block.y + block.height);
ctx.stroke();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x,block.y);
ctx.arc(block.x,block.y, rad,(Math.PI / 180)* -90, (Math.PI / 180)* -180, true);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x +block.width,block.y);
ctx.arc(block.x +block.width, block.y, rad,(Math.PI / 180)* -90, (Math.PI / 180)* 0, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x + block.width, block.y + block.height);
ctx.arc(block.x + block.width, block.y + block.height, rad,(Math.PI / 180)* 0, (Math.PI / 180)* 90, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x ,block.y + block.height);
ctx.arc(block.x ,block.y + block.height, rad,(Math.PI / 180)* 180, (Math.PI / 180)* 90, true);
ctx.fill();
}
</script>
</body>
</html>
но я так и не понял раз 15 перечитывал коммент http://javascript.ru/forum/events/33223-canvas-i-metod-arc-4.html#post216503 как правильно определить окружность ...
просто не пойму фишки кода не увеличиваю блок на радиус шарик вроде нормально входит в угол, но наверно просто так кажется ...
<!DOCTYPE HTML>
<html>
<head> </head>
<body>
<canvas width="500" height="500"></canvas>
<script>
var canva = document.body.children[0];
var ctx = canva.getContext("2d");
var ball = {
x:20,
y:280,
R:20,
Draw: function (x, y) {
ctx.clearRect(this.x - this.R, this.y - this.R, this.R *2,this.R *2);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.arc(x,y, this.R,0, (Math.PI / 180)* 360, false);
ctx.fill();
this.y = y;
this.x = x;
}
};
var block = {
width:150,
height:30,
Draw: function (x, y) {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.fillRect(x,y,this.width, this.height);
this.y = y;
this.x = x;
}
};
block.Draw(150,100);
var valX = -10 , valY = -10;
var Bl_bottom = block.y + block.height ;
var Bl_right = block.x + block.width ;
!function action(){
if(ball.x < 0 + ball.R || ball.x > canva.width - ball.R){
valX = -valX;
};
if(ball.y < 0 + ball.R || ball.y > canva.height - ball.R){
valY = -valY;
//y = canva.height - ball.R;
}
var x = ball.x ;
var y = ball.y ;
if((y <= Bl_bottom && y >= block.y ) && (x >= block.x && x <= Bl_right)){
//if(isCollision(block.x ,block.y , Bl_right, Bl_bottom ,x,y, ball.R)){
drawOs(x,y);
return;
};
x = ball.x + valX;
y = ball.y + valY;
ball.Draw(x,y);
setTimeout(action,1000/60);
}();
function drawOs(x,y){
ctx.beginPath();
ctx.moveTo(block.x ,Bl_bottom);
ctx.lineTo(x,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(Bl_right ,Bl_bottom);
ctx.lineTo(x,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x ,block.y );
ctx.lineTo(x,y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(Bl_right,block.y );
ctx.lineTo(x,y);
ctx.stroke();
};
function distance(x1,y1,x2,y2){
return Math.sqrt(Math.pow(x2-x1,2) + Math.pow(y2-y1,2));
};
</script>
</body>
</html>
кажеться понял, но разберусь уже завтра)
schmetterling
07.12.2012, 12:16
cyber, в случае, если у вас шарик будет соприкасаться с углом, вам нужно считать расстояние между центром и углом) И проверять, не меньше ли оно радиуса.
нет все таки не разобрался)
если брать углы за окружность
<!DOCTYPE HTML>
<html>
<head> </head>
<body>
<canvas width="500" height="500"></canvas>
<script>
var canva = document.body.children[0];
var ctx = canva.getContext("2d");
var block = {
width:150,
height:30,
Draw: function (x, y) {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.fillRect(x,y,this.width, this.height);
this.y = y;
this.x = x;
boundary();
}
};
block.Draw(150,100);
function boundary() {
var rad = 20;
ctx.beginPath();
ctx.moveTo(block.x,block.y - rad);
ctx.lineTo(block.x + block.width , block.y - rad);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x+ block.width + rad,block.y);
ctx.lineTo(block.x+ block.width + rad , block.y + block.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x, block.y + block.height + rad);
ctx.lineTo(block.x + block.width , block.y + block.height + rad);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(block.x- rad,block.y);
ctx.lineTo(block.x - rad , block.y + block.height);
ctx.stroke();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x,block.y);
ctx.arc(block.x,block.y, rad,(Math.PI / 180)* -90, (Math.PI / 180)* -180, true);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x +block.width,block.y);
ctx.arc(block.x +block.width, block.y, rad,(Math.PI / 180)* -90, (Math.PI / 180)* 0, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x + block.width, block.y + block.height);
ctx.arc(block.x + block.width, block.y + block.height, rad,(Math.PI / 180)* 0, (Math.PI / 180)* 90, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.moveTo(block.x ,block.y + block.height);
ctx.arc(block.x ,block.y + block.height, rad,(Math.PI / 180)* 180, (Math.PI / 180)* 90, true);
ctx.fill();
}
</script>
</body>
</html>
расчитывать пересечение двух окружностей , то возникает проблема когда шарик на шаге n не пересекается с окружностью , а на шаге n+1 он нужен дальше окружности..
проверял так
var d = (x - block.x)*(x - block.x) + (y - block.y + block.height) * (y - block.y + block.height);
if(d < (ball.R + ball.R ) * (ball.R + ball.R) && d > (ball.R - ball.R) * (ball.R - ball.R))
и блин не как не могу понять как автор этой (http://noregret.org/tutor/n/collision/#2.2) статьи так просто расчитывает пересечения с углами
cyber, в случае, если у вас шарик будет соприкасаться с углом, вам нужно считать расстояние между центром и углом) И проверять, не меньше ли оно радиуса.
если бы прочитал бы этот коммент на пол часа раньше, то не ломал бы голову пол часа, но в итоге сам дошел)
Кстати арканоид хороший способ подучить геометрию))
П.с сор что туплю, понимаю что достал уже)
schmetterling
08.12.2012, 00:19
П.с сор что туплю, понимаю что достал уже)
Да всё норм)
schmetterling,хм, запутался.
Так как расчитываю координаты следущие, то если шарик залетает на блок нужно уменьшать растояние до того на котором он только столкнется , а не пересечет и не могу найти как определить ту точку в которой он будет сталкиваться а не пересекать(проблема только с углами)?
schmetterling
10.12.2012, 23:06
cyber, ну вы же координаты последующие как-то вычисляете? Вот и проверяете каждый раз пересечение круга и блока для вычисленных координат. Если пересеклись -- значит, текущая точка и есть точка столкновения.
schmetterling,можно на ты ?
я делаю так:
что бы найти растояние до нужной точки я от радиуса отнимаю растояние между точками В и А и прибавляю его к А.
https://lh3.googleusercontent.com/-8p56xj9-2QI/UMYwi-mR1DI/AAAAAAAAAJk/frKG5rQWpxw/s300/2.jpg
но работает как то не так...
schmetterling
11.12.2012, 01:12
schmetterling,можно на ты ?
Да, конечно)
что бы найти растояние до нужной точки
Это можно, но сложно. Зачем? Просто проверяй вычисленные координаты на столкновение.
schmetterling, не совсем понял.
Если новые координаты внутри блока, а если отразить раньше то сильно заметно..
Дзен-трансгуманист
11.12.2012, 16:27
В общем набросал кое-что, но сюда код не помещается, поэтому кладу на дропбокс: Collisions (http://dl.dropbox.com/u/19390559/lab/Collisions.html).
Управление:
стрелочки - перемещение шарика
WSAD - поворот и изменение длины вектора движения
Иногда шарик проходит углы насквозь. Иногда даже зависает.
Писать красиво и модульно мне было некогда, поэтому говнокод.
В данный момент только статическая трассировка, может в другой раз заставлю картинку двигаться самостоятельно.
Дзен-трансгуманист, спасибо, буду разбираться
вот пока то что у меня есть http://learn.javascript.ru/play/8nu3s
<!DOCTYPE HTML>
<html>
<head> </head>
<body>
<canvas width="500" height="500"></canvas>
<script>
var canva = document.body.children[0];
var ctx = canva.getContext("2d");
var ball = {
// x:20,
// y:280,
x:50,
y:40,
R:20,
Draw: function (x, y) {
ctx.clearRect(this.x - this.R, this.y - this.R, this.R *2,this.R *2);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.arc(x,y, this.R,0, (Math.PI / 180)* 360, false);
ctx.fill();
this.y = y;
this.x = x;
}
};
var block = {
width:150,
height:30,
Draw: function (x, y) {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.fillRect(x,y,this.width, this.height);
this.y = y;
this.x = x;
}
};
block.Draw(150,100);
var valX = -10 , valY = -10;
var Bl_bottom = block.y + block.height + ball.R ;
var Bl_right = block.x + block.width + ball.R ;
var stop = false;
!function action(){
if(ball.x < 0 + ball.R || ball.x > canva.width - ball.R){
valX = -valX;
};
if(ball.y < 0 + ball.R || ball.y > canva.height - ball.R){
valY = -valY;
}
var x = ball.x + valX;
var y = ball.y + valY;
if((y <= Bl_bottom && y >= block.y - ball.R) && (x >= block.x - ball.R && x <= Bl_right)){
var pos = getPosit();
if(pos == "angle") {
// проверка на столкновение с одним из 4х углов
if(distance(x,y,block.x, block.y + block.height) <= ball.R ||
distance(x,y,block.x, block.y ) <= ball.R
|| distance(x,y,block.x + block.width, block.y + block.height) <= ball.R||
distance(x,y,block.x+ block.width, block.y) <= ball.R){
valY = - valY;
valX = - valX;
return;
}
}
if(pos == "x") {
valX = - valX;
}
if(pos == "y") {
valY = - valY;
}
// return;
};
ball.Draw(x,y);
setTimeout(action,1000/60);
}();
function getPosit() {
var x,y;
if(ball.x <= block.x){
x = "left";
}
else if(ball.x >= block.x + block.width){
x = "right";
}
else x = "on";
if(ball.y >= block.y + block.height){
y = "bottom";
}
else if(ball.y <= block.y){
y = "top";
}
else y = "on";
if((x == "right" || x == "left") && (y == "on")) {
return "x";
}
else if((y == "bottom" || y == "top") && x == "on"){
return "y";
}
else return "angle";
}
function distance(x1,y1,x2,y2){
return Math.sqrt(Math.pow(x2-x1,2) + Math.pow(y2-y1,2));
};
</script>
</body>
</html>
сделал остановку когда новые координаты шарика будут равны углу или внутри угла.
Дзен-трансгуманист, я понимаю что это уже наглость, но не могу разобраться в твоем коде, какой метод отвечает за рисование шариков которые рисуются на векторе?
Дзен-трансгуманист
11.12.2012, 21:48
cyber,
drawPath в области видимости TracerView, строчки 489-500 (потом рисуются линии). Это типа как приватная функция, только вместо контекста this я передаю экземпляр класса явно в аргументе object.
Дзен-трансгуманист
11.12.2012, 22:01
Я сейчас понял, что трейсер возвращает только путь в виде набора точек, но не возвращает новый вектор движения после всех столкновений. Без этого, конечно, шарик самостоятельно никуда не полетит.
И наверное я неправильно поступил, что мастер-объектом движения сделал вектор [x,y]. Так теряется некоторая точность преобразований, причем, чем больше столкновений за один ход - тем больше потери точности. Надо было хранить и обрабатывать его как [длина,азимут].
Не знаю, дойдут ли у меня руки править это, но, честно говоря, не очень-то хочется, поскольку не люблю поддерживать код, написанный второпях буквально за один день. Такие вещи надо продумывать и делать основательно, а не на коленке. ;)
Дзен-трансгуманист,хм, не совсем понял как ты расчитываешь расстояние от угла до центра шарика?
Дзен-трансгуманист,да вообщем я понимаю как все работает, но у меня проблемы с реализацией из за пробелов в школьной геометрии пофигизм выходит боком , если тот пример ты для меня лепил, то спасибо, но все таки не нужно, я в общем разобрался с колизиями и отражением, но только не могу правильно найти расстояние на которое нужно сместить шарик по вектору движения так что бы он не оказался внутри блока.
Допустим по формуле
Math.sqrt(Math.pow(x2-x1,2) + Math.pow(y2-y1,2));
я определил что на шаге n+1 шарик будет внутри блока, то нужно установить такие координаты при которых шарик не пересечет угол.
Вроде просто, а не фига не получается .
Дзен-трансгуманист
11.12.2012, 22:13
как ты расчитываешь расстояние от угла до центра шарика?
Функция vertexCollision. Я даже не уверен, что она полностью правильная. ;) Там решается квадратное уравнение чтобы найти точки пересечения прямой и окружности. А нормаль столкновения это не что иное как вектор, проложенный от угла к центру шарика в сам момент столкновения.
Дзен-трансгуманист
11.12.2012, 22:14
из за пробелов в школьной геометрии
Я вообще троечник был. Думаешь мне легко?
Я вообще троечник был. Думаешь мне легко?
Неа)
Значить не я один вместо повторение учу что то новое из школьной программы)))
П.с я тоже троечником был)
Дзен-трансгуманист, хм, а если найти угол падения, а через него угол отражения?
Дзен-трансгуманист
11.12.2012, 22:39
cyber,
Все равно нужна нормаль. На отрезках она во всех точках одинакова, а на углах зависит от направления удара.
Дзен-трансгуманист, как то так http://habrahabr.ru/post/105882/ там есть под раздел "Вычисление отражённого луча" ?
Дзен-трансгуманист
11.12.2012, 23:00
cyber,
Хороший пост. И?
Дзен-трансгуманист,мне он тоже показался хорошим:)
но я не совсем понял как получить новые координаты из градуса угла
http://habrastorage.org/storage/436a45df/f727f4f8/2f748788/54ace04f.png
Дзен-трансгуманист
11.12.2012, 23:18
cyber,
Где ты там видишь градус?) Это пост об алгебре, нет там никаких градусов.)
Точка в формуле - это скалярное произведение, если че.
Дзен-трансгуманист, wtf , ну меня и лагануло)
прочитал статью на хабре, потом начал читать эту http://www.ecto.ru/details/reflex_drop/ и получился бред в голове)
Дзен-трансгуманист
11.12.2012, 23:24
cyber,
Если смотреть на мой код с такой точки зрения, то у меня там действительно много избыточных вычислений. Это еще одна причина, почему я не хочу его править, ибо проще написать новый с нуля.
вроде тут все понятно http://www.ecto.ru/details/reflex_drop/, но как найти нормаль я так и не понял..
Дзен-трансгуманист, смысел писать целый скрипт, что бы только показать что делать с углами?
Дзен-трансгуманист
11.12.2012, 23:35
cyber,
Ты не понял, я говорю о том, что векторной алгеброй можно было бы многое сократить и ускорить в моем примере. А писать что-то или переписывать я уже не буду, надоело.
Дзен-трансгуманист
11.12.2012, 23:36
но как найти нормаль я так и не понял..
Кстати, я не рассказал, как её определить. Если прямая задана двумя точками (x1,y1) и (x2,y2), то вектор нормали (ненормированый) легко определяется вот так:
http://habrastorage.org/storage/19f690e2/c9bbb888/57ab0761/58072d9d.png
Отличие моего кода в том, что у меня нормали левосторонние, так как фигуры у меня определяются по часовой стрелке.
Дзен-трансгуманист, видел, но не понял.
мне нужно y1-y2 / (x2-x1)?
Дзен-трансгуманист
11.12.2012, 23:51
cyber,
Круглые скобки там - это просто описание компонент вектора. Так еще матрицы описываются.
x = y1-y2
y = x2-x1
Лучше пойди выспись и перечитай тот пост с утра на свежую голову, а то я всю ночь тут тебе объяснять буду... Всё, умаялся я уже.
Дзен-трансгуманист, да, чет по вечерам у меня включается режим тормоз))
Зная х и у , можно получить угол нормали через теорему косинусов...
Дзен-трансгуманист
12.12.2012, 15:33
cyber,
Если угол все-таки нужен, то Math.atan2 (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math/atan2).
Дзен-трансгуманист, вот блин, как я мог пропустить такую полезную функцию....
ну вот как то так)
function reflect(dx,dy){
var power = Math.sqrt(dx*dx + dy*dy); // сила=корень из (dx*dx + dy*dy)
var sinDrop = dy/power; //sin(угла падения) = dy / сила
var cosDrop = dx/power; //cos(угла падения) = dx / сила
var normal = Math.atan2(wall.x - ball.x, ball.y - wall.y);
var sinL = Math.sin(normal) * cosDrop - Math.cos(normal) * sinDrop; //sin(L)=sin(Нормали)*cos(падения)-cos(Нормали)*sin(падения);
var cosL = Math.cos(normal) * cosDrop + Math.sin(normal) * sinDrop; //cos(L)=cos(Нормали)*cos(падения)+sin (Нормали)*sin(падения);
var reflSin = sinL * Math.cos(normal) + cosL * Math.sin(normal); //sin(отражения)=sin(L)*cos(Нормали) +cos(L)*sin(Нормали);
var reflCos = cosL * Math.cos(normal) - sinL * Math.sin(normal); //cos(отражения)=cos(L)*cos(Нормали)-sin(L)*sin(Нормали);
dx = Math.cos(reflCos) * power; //dx = cos(угол)*сила
dy = Math.sin(reflSin) * power; //dy = sin(угол)*сила
return {
dx:dx,
dy:dy
}
};
<!DOCTYPE HTML>
<html>
<head> </head>
<body>
<canvas width="500" height="500"></canvas>
<script>
var canv = document.body.children[0];
var ctx = canv.getContext("2d");
var ball = {
x:80,
y:170,
R:20,
Draw: function (x,y){
ctx.clearRect(this.x - this.R, this.y - this.R, this.R *2,this.R *2);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.arc(x,y,ball.R,0, (Math.PI/180)* 360, false);
ctx.fill();
}
};
var wall = {
x:100,
y:100,
width:100,
height:50,
Draw:function() {
ctx.beginPath();
ctx.fillStyle = "green";
ctx.fillRect(wall.x,wall.y,wall.width,wall.height) ;
}
};
ball.Draw(ball.x, ball.y, false);
wall.Draw();
var dx = 10, dy = 10;
var ref = reflect(dx,dy);
ball.Draw(ball.x + ref.dx,ball.y + ref.dy);
function distance(x1,y1,x2,y2){
return Math.sqrt(Math.pow(x2-x1,2) + Math.pow(y2-y1,2));
};
function reflect(dx,dy){
var power = Math.sqrt(dx*dx + dy*dy); // сила=корень из (dx*dx + dy*dy)
var sinDrop = dy/power; //sin(угла падения) = dy / сила
var cosDrop = dx/power; //cos(угла падения) = dx / сила
var nx = wall.x - ball.x;
var ny = ball.y - wall.y;
var normal = Math.atan2(nx,ny);
var sinL = Math.sin(normal) * cosDrop - Math.cos(normal) * sinDrop; //sin(L)=sin(Нормали)*cos(падения)-cos(Нормали)*sin(падения);
var cosL = Math.cos(normal) * cosDrop + Math.sin(normal) * sinDrop; //cos(L)=cos(Нормали)*cos(падения)+sin (Нормали)*sin(падения);
var reflSin = sinL * Math.cos(normal) + cosL * Math.sin(normal); //sin(отражения)=sin(L)*cos(Нормали) +cos(L)*sin(Нормали);
var reflCos = cosL * Math.cos(normal) - sinL * Math.sin(normal); //cos(отражения)=cos(L)*cos(Нормали)-sin(L)*sin(Нормали);
dx = Math.cos(reflCos) * power; //dx = cos(угол)*сила
dy = Math.sin(reflSin) * power; //dy = sin(угол)*сила
return {
dx:dx,
dy:dy
}
}
</script>
</body>
</html>
Дзен-трансгуманист
12.12.2012, 15:58
cyber,
Там в статье написано, что углы отсчитываются против часовой стрелки, но здесь имеется ввиду традиционное представление координат, как на обычных графиках, когда игрек направлен вверх. В экранных же координатах, как и на канвасе, игрек направлен вниз, поэтому угол тут возрастает по часовой стрелке.
Там в статье написано,
чет не могу найти такого , но не важно , я вроде понял к чему ты клонишь.
В экранных же координатах, как и на канвасе, игрек направлен вниз, поэтому тут угол возрастает по часовой стрелке.
т.е y нужно отнимать , а не прибавлять?
Дзен-трансгуманист
12.12.2012, 16:24
т.е y нужно отнимать , а не прибавлять?
Я просто прокомментировал то, о чем написано в статье про Math.atan2, уточнил на всякий случай.
Алгоритмов это никак не касается.
Ладно, как-нибудь сам разберешься... ;)
Дзен-трансгуманист, тьфу блин, запутал :)
Я думал ты про статью с алгоритмом , перечетал ее еще раз 5, после твоего коммента.
Прочитав описание Math.atan2 , понял к чему ты
This is the counterclockwise angle, measured in radians,
кстати нужно было сразу описание читать, так как результат возвращает в радианах, значить нужно перевести его в градусы ?!
var normal = (Math.atan2(nx,ny)) * 180/ Math.PI;
Дзен-трансгуманист
12.12.2012, 16:43
cyber,
Зачем тебе градусы? Градусы не нужны.
var normal = (Math.atan2(nx,ny)) * 180/ Math.PI;
ЩИТО? О_о
Зачем тебе градусы? Градусы не нужны.
да ты прав, там нужен угол, про градусы нечего не сказано
ЩИТО? О_о
var normal = Math.atan2(nx,ny) * 180/ Math.PI
Rad:=Grad*Pi/180;//перевод градусов (Grad) в радианы (Rad)
Grad:=Rad*180/Pi;//обратный перевод
Дзен-трансгуманист
12.12.2012, 16:48
cyber,
Нормаль - это вектор, а ты что думал? :lol: иди еще раз перечитывай статью на хабре.
Дзен-трансгуманист
12.12.2012, 16:51
Math.atan2(nx,ny)
Опять же твоя невнимательность. В этой функции сначала Y, потом X.
Ну всё, я снимаю подписку с этой темы, а то это будет бесконечно длиться, а у меня еще работы дохера. :)
Успехов!
Нормаль - это вектор, а ты что думал? иди еще раз перечитывай статью на хабре.
пора завязывать с травкой:lol:
Опять же твоя невнимательность. В этой функции сначала Y, потом X.
блин, ну вот нет что бы сделать по нормальному сначала х потом у,не нужно выпендрится )
Ну всё, я снимаю подписку с этой темы, а то это будет бесконечно длиться, а у меня еще работы дохера.
Успехов!
Огромное спасибо.:thanks:
Удачи!
vBulletin® v3.6.7, Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot