Заслуженный участник |
|
20/08/14 11867 Россия, Москва
|
Последний раз редактировалось Dmitriy40 08.02.2018, 23:41, всего редактировалось 2 раз(а).
Сделал и для квадратного, убил всё лишнее и получилось из предыдущей достаточно просто: https://codepen.io/anon/pen/yvgzmGПри k=4,7 утка на берег не выходит. Всё же слишком тривиальная стратегия утки, надо её допиливать. Выложу наверное здесь код, а то там кажется любой может случайно его изменить:
<html><head><meta charset="CP1251"><!-- Ozero3 -->
<center><canvas id="canvas">Ваш браузер не поддерживает canvas</canvas></center>
<script>
var k, xu, yu, l;
var xl, yl, ds = 1, rep, s3 = Math.sqrt(3), x0, y0, size, winx, winy;
var hu = [{x: xu, y: yu, l: l, wx: winx, wy: winy}];
var g = canvas.getContext("2d");
Init(6); // Относительная скорость лисы
function Init(t) {
k = t; xu = 0; yu = 0; l = 0; winx = 0; winy = 0; rep = 20;
hu = [{x: xu, y: yu, l: l, wx: winx, wy: winy}];
document.getElementById("stK").value = "k = " + t;
document.getElementById("stSpeed").value = "Скорость = " + rep + "x";
LisaCoords(); ReDraw();
}
function lineto(x, y) { g.lineTo(x0+x*size, y0-y*size); }
function moveto(x, y) { g.moveTo(x0+x*size, y0-y*size); }
function line(x, y, xx, yy) { moveto(x, y); lineto(xx, yy); }
function circle(x, y, r, w, c) {
g.beginPath(); g.strokeStyle = c; g.lineWidth = w;
g.arc(x0+x*size, y0-y*size, r, 0, 0.001, true);
g.stroke();
}
function ReDraw() {
size = Math.min(innerWidth / 4, innerHeight / 3 - 50);
canvas.width = size * 4; canvas.height = size * 3.2;
x0 = Math.round(size * 2), y0 = Math.round(size * 2.1);
g.beginPath(); g.strokeStyle = "black"; g.lineWidth = 1;
g.clearRect(0, 0, canvas.width, canvas.height)
g.moveTo(0, y0+0.5); g.lineTo(innerWidth, y0+0.5);
g.moveTo(x0+0.5, 0); g.lineTo(x0+0.5, y0+size);
line(-s3, -1, s3/2, 0.5); line(s3, -1, -s3/2, 0.5);
line(xl, yl, xl-(xl-xu)*99, yl-(yl-yu)*99);
g.stroke();
g.beginPath(); g.strokeStyle = "red"; g.lineWidth = 3;
line(0, 2, -s3, -1); lineto(+s3, -1); lineto(0, 2);
g.stroke();
circle(xl, yl, 5, 8, "red");
g.beginPath(); g.strokeStyle = "blue"; g.lineWidth = 3;
line(0, -2/k, -s3/k, 1/k); lineto(+s3/k, 1/k); lineto(0, -2/k);
g.stroke();
g.beginPath(); g.strokeStyle = "green"; g.lineWidth = 5; g.lineCap = "round";
moveto(xu, yu); hu.forEach(function(u, i) { lineto(u.x, u.y); });
g.stroke();
if ((winx != 0) || (winy != 0)) {
g.beginPath(); g.strokeStyle = "purple"; g.lineWidth = 3;
line(xu, yu, winx, winy);
g.stroke();
}
circle(xu, yu, 5, 7, "green");
}
function MoveUtka() {
var tor = (2 - xu * s3 + 3 * yu) / 4; // до правой стороны
var sur = (tor - yu) * 2, slr = 3*s3 - (2 - tor) * 2/s3; // пути утки и лисы
var tol = (2 + xu * s3 + 3 * yu) / 4; // до левой стороны
var sul = (tol - yu) * 2, sll = (2 - tol) * 2/s3 - 3*s3; // пути утки и лисы
if (1.01 + yu < Math.min(Math.abs(l - xu), Math.abs(l + 6*s3 - xu), Math.abs(l - 6*s3 - xu)) / k) { // А не пойти ли утке по прямой к нижней стороне?
yu -= ds / k; winy = -1; winx = xu;
} else if (sur + 0.01 < Math.min(Math.abs(l - slr), Math.abs(l + 6*s3 - slr), Math.abs(l - 6*s3 - slr)) / k) { // А не пойти ли утке по прямой к правой стороне?
xu += ds / k * s3 / 2; yu += ds / k / 2; winy = tor; winx = (2 - winy) / s3;
} else if (sul + 0.01 < Math.min(Math.abs(l - sll), Math.abs(l + 6*s3 - sll), Math.abs(l - 6*s3 - sll)) / k) { // А не пойти ли утке по прямой к левой стороне?
xu -= ds / k * s3 / 2; yu += ds / k / 2; winy = tol; winx = (winy - 2) / s3;
} else { // Ну тогда пойдём по диаметру
var dx = xu - xl, dy = yu - yl;
var s = ds / k / Math.sqrt(dx*dx + dy*dy);
xu += dx * s; yu += dy * s;
winx = 0; winy = 0; // Пока утка к берегу не попадает
}
AddStep();
}
function MoveLisa(dl) {
ds = Math.min(Math.sqrt((xu-xl)*(xu-xl) + (yu-yl)*(yu-yl)) / 30, 0.03); // Уменьшение шага при сближении лисы и утки
l += dl * ds; // Шаг лисы
LisaCoords();
}
function LisaCoords() { // Преобразование линейной координаты лисы в двухмерные
xl = l; yl = -1;
if (l > +3*s3) l -= 6*s3;
if (l < -3*s3) l += 6*s3;
if (l > +s3) {
xl = (3*s3 - l) / 2; yl = 2 - (3*s3 - l) * s3/2;
}
if (l < -s3) {
xl = - (3*s3 + l) / 2; yl = 2 - (3*s3 + l) * s3/2;
}
}
function AddStep() {
hu.unshift({x: xu, y: yu, l: l, wx: winx, wy: winy})
}
function UndoStep() {
for (var i = 0; i < rep && hu.length > 1; i++) {
hu.shift();
xu = hu[0].x; yu = hu[0].y; l = hu[0].l; winx = hu[0].wx; winy = hu[0].wy;
MoveLisa(0);
}
ReDraw();
}
function Left() {
for (var i = 0; i < rep; i++) { MoveLisa(-1); MoveUtka(); }
ReDraw();
}
function Wait() {
for (var i = 0; i < rep; i++) { MoveLisa(0); MoveUtka(); }
ReDraw();
}
function Right() {
for (var i = 0; i < rep; i++) { MoveLisa(+1); MoveUtka(); }
ReDraw();
}
function NewK() {
var t = prompt("Введите новое значение k в диапазоне от 2 до 10:", k);
if (t >= 2 && t <= 10) Init(t); else ReDraw();
}
function ChangeSpeed() {
if (rep > 1) rep = 1; else rep = 20;
document.getElementById("stSpeed").value = "Скорость = " + rep + "x";
ReDraw();
}
</script>
</head><body onload="Init(6)">
<center>
<input type=button value=" По часовой " id=left onclick="Left()">
<input type=button value=" | Стоять | " id=wait onclick="Wait()">
<input type=button value=" Против часовой " id=right onclick="Right()">
<p>
<input type=button value=" k=? " id=stK onclick="NewK()">
<input type=button id="Undo" onclick="UndoStep()" value="ААА! Спасите! Срочно отменить шаг!">
<input type=button id="stSpeed" onclick="ChangeSpeed()" value=" Скорость ? ">
<center>
<body></html>
<html><head><meta charset="CP1251"><!-- Ozero4 -->
<center><canvas id="canvas">Ваш браузер не поддерживает canvas</canvas></center>
<script>
var k, xu, yu, l;
var xl, yl, ds = 1, rep, x0, y0, size, winx, winy;
var hu = [{x: xu, y: yu, l: l, wx: winx, wy: winy}];
var g = canvas.getContext("2d");
Init(5); // Относительная скорость лисы
function Init(t) {
k = t; xu = 0; yu = 0; l = 0; winx = 0; winy = 0; rep = 20;
hu = [{x: xu, y: yu, l: l, wx: winx, wy: winy}];
document.getElementById("stK").value = "k = " + t;
document.getElementById("stSpeed").value = "Скорость = " + rep + "x";
LisaCoords(); ReDraw();
}
function lineto(x, y) { g.lineTo(x0+x*size, y0-y*size); }
function moveto(x, y) { g.moveTo(x0+x*size, y0-y*size); }
function line(x, y, xx, yy) { moveto(x, y); lineto(xx, yy); }
function circle(x, y, r, w, c) {
g.beginPath(); g.strokeStyle = c; g.lineWidth = w;
g.arc(x0+x*size, y0-y*size, r, 0, 0.001, true);
g.stroke();
}
function ReDraw() {
size = Math.min(innerWidth / 2.1, innerHeight / 2.1 - 50);
canvas.width = size * 2.1; canvas.height = size * 2.1;
x0 = Math.round(size * 1.05), y0 = Math.round(size * 1.05);
g.beginPath(); g.strokeStyle = "black"; g.lineWidth = 1;
g.clearRect(0, 0, canvas.width, canvas.height)
g.moveTo(0, y0+0.5); g.lineTo(innerWidth, y0+0.5);
g.moveTo(x0+0.5, 0); g.lineTo(x0+0.5, innerHeight);
line(-1, -1, 1, 1); line(1, -1, -1, 1);
line(xl, yl, xl-(xl-xu)*99, yl-(yl-yu)*99);
g.stroke();
g.beginPath(); g.strokeStyle = "red"; g.lineWidth = 3;
line(-1, -1, -1, 1); lineto(1, 1); lineto(1, -1); lineto(-1, -1);
g.stroke();
circle(xl, yl, 5, 8, "red");
g.beginPath(); g.strokeStyle = "blue"; g.lineWidth = 3;
line(-1/k, -1/k, -1/k, 1/k); lineto(1/k, 1/k); lineto(1/k, -1/k); lineto(-1/k, -1/k);
g.stroke();
g.beginPath(); g.strokeStyle = "green"; g.lineWidth = 5; g.lineCap = "round";
moveto(xu, yu); hu.forEach(function(u, i) { lineto(u.x, u.y); });
g.stroke();
if ((winx != 0) || (winy != 0)) {
g.beginPath(); g.strokeStyle = "purple"; g.lineWidth = 3;
line(xu, yu, winx, winy);
g.stroke();
}
circle(xu, yu, 5, 7, "green");
}
function MoveUtka() {
if (1.001 + yu < Math.min(Math.abs(l - xu), Math.abs(l + 8 - xu)) / k) { // А не пойти ли утке по прямой к нижней стороне?
yu -= ds / k; winy = -1; winx = xu;
} else if (1.001 - xu < Math.min(Math.abs(l - 2 - yu), Math.abs(l + 6 - yu)) / k) { // А не пойти ли утке по прямой к правой стороне?
xu += ds / k; winy = yu; winx = +1;
} else if (1.001 + xu < Math.min(Math.abs(l + 2 - yu), Math.abs(l - 6 - yu)) / k) { // А не пойти ли утке по прямой к левой стороне?
xu -= ds / k; winy = yu; winx = -1;
} else if (1.001 - yu < Math.min(Math.abs(l - 4 - xu), Math.abs(l + 4 - xu)) / k) { // А не пойти ли утке по прямой к верхней стороне?
yu += ds / k; winy = 1; winx = xu;
} else { // Ну тогда пойдём по диаметру
var dx = xu - xl, dy = yu - yl;
var s = ds / k / Math.sqrt(dx*dx + dy*dy);
xu += dx * s; yu += dy * s;
winx = 0; winy = 0; // Пока утка к берегу не попадает
}
AddStep();
}
function MoveLisa(dl) {
ds = Math.min(Math.sqrt((xu-xl)*(xu-xl) + (yu-yl)*(yu-yl)) / 50, 0.015); // Уменьшение шага при сближении лисы и утки
l += dl * ds; // Шаг лисы
LisaCoords();
}
function LisaCoords() { // Преобразование линейной координаты лисы в двухмерные
xl = l; yl = -1;
if (l > +4) l -= 8;
if (l < -4) l += 8;
if (l > +1) { xl = +1; yl = l - 2; }
if (l > +3) { xl = 4 - l; yl = +1; }
if (l < -1) { xl = -1; yl = -l - 2; }
if (l < -3) { xl = - l - 4; yl = +1; }
}
function AddStep() {
hu.unshift({x: xu, y: yu, l: l, wx: winx, wy: winy})
}
function UndoStep() {
for (var i = 0; i < rep && hu.length > 1; i++) {
hu.shift();
xu = hu[0].x; yu = hu[0].y; l = hu[0].l; winx = hu[0].wx; winy = hu[0].wy;
MoveLisa(0);
}
ReDraw();
}
function Left() {
for (var i = 0; i < rep; i++) { MoveLisa(-1); MoveUtka(); }
ReDraw();
}
function Wait() {
for (var i = 0; i < rep; i++) { MoveLisa(0); MoveUtka(); }
ReDraw();
}
function Right() {
for (var i = 0; i < rep; i++) { MoveLisa(+1); MoveUtka(); }
ReDraw();
}
function NewK() {
var t = prompt("Введите новое значение k в диапазоне от 2 до 10:", k);
if (t >= 2 && t <= 10) Init(t); else ReDraw();
}
function ChangeSpeed() {
if (rep > 1) rep = 1; else rep = 20;
document.getElementById("stSpeed").value = "Скорость = " + rep + "x";
ReDraw();
}
</script>
</head><body onload="Init(5)">
<center>
<input type=button value=" По часовой " id=left onclick="Left()">
<input type=button value=" | Стоять | " id=wait onclick="Wait()">
<input type=button value=" Против часовой " id=right onclick="Right()">
<p>
<input type=button value=" k=? " id=stK onclick="NewK()">
<input type=button id="Undo" onclick="UndoStep()" value="ААА! Спасите! Срочно отменить шаг!">
<input type=button id="stSpeed" onclick="ChangeSpeed()" value=" Скорость ? ">
<center>
<body></html>
|
|