Комментарий: Добавьте стену на холст, перетаскивая мышь, и управляйте многоугольником, чтобы перемещаться вверх, вниз, влево и вправо через клавиши направления. Если вы столкнетесь с стеной, вы не можете двигаться вперед. Ниже приводится введение в проблемы, которые необходимо решить, и конкретный код реализации. Заинтересованные друзья могут узнать это.
Игровые визуализацииДобавьте стену на холсте, перетаскивая мышь, и используйте клавиши стрелки, чтобы управлять полигоном, чтобы перемещаться вверх, вниз, влево и вправо. Если вы столкнетесь с стеной, вы не можете двигаться вперед.
Проблемы, которые необходимо решить
Обнаружение мышиной прессы, перетаскивание мыши, событие выпуска мыши
Рисунок многоугольников
Живопись стен
Обнаружение столкновений между многоугольниками и стенами (по сути, это суждение о пересечении между кругами и сегментами линий)
Mycode:
<html>
<голова>
<Title> Maze </title>
<Скрипт>
var canvas_width = 900;
var canvas_height = 350;
var ctx;
вар холст;
var все = [];
var cur_wall;
var Wall_width;
var Wall_style = "rgb (200,0,200)";
var стены = [];
var in_motion = false;
var Unit = 10;
Функциональный токен (sx, sy, rad, style_string, n)
{
this.sx = sx;
this.sy = sy;
this.rad = rad;
this.draw = draw_token;
this.n = n;
this.Angle = (2 * math.pi) / n;
this.move = move_token;
this.fill_style = style_string;
}
function draw_token () // Нарисуйте обычную n-side
{
ctx.fill_style = this.fill_style;
ctx.beginpath ();
var i;
var rad = this.rad;
ctx.moveto (this.sx + rad * math.cos (-0,5 * this.Angle), this.Sy + rad * math.sin (-0,5 * this.Angle));
для (i = 1; i <this.n; i ++)
ctx.lineTo (this.sx + rad * math.cos ((i - 0.5) * this.Angle), this.sy + rad * math.sin ((i - 0,5) * this.Angle));
ctx.fill ();
}
Функция move_token (dx, dy)
{
this.sx += dx;
this.sy += dy;
var i;
var стена;
для (i = 0; i <Walls.length; i ++)
{
стена = стены [i];
if (пересечь (wall.sx, wall.sy, wall.fx, wall.fy, this.sx, this.sy, this.rad)))
{
this.sx -= dx;
this.sy -= dy;
перерыв;
}
}
}
Функциональная стена (SX, SY, FX, FY, ширина, стильнирование)
{
this.sx = sx;
this.sy = sy;
this.fx = fx;
this.fy = fy;
this.width = ширина;
this.draw = draw_line;
this.strokestyle = stylestring;
}
функция draw_line ()
{
ctx.linewidth = this.width;
ctx.strokestye = this.strokestyle;
ctx.beginpath ();
ctx.moveto (this.sx, this.sy);
ctx.lineTo (this.fx, this.fy);
ctx.stroke ();
}
//примечание
var mypent = новый токен (100, 100, 20, "rgb (0,0,250)", 5);
Все. Push (mypent);
функция init ()
{
canvas = document.getElementbyId ("canvas");
ctx = canvas.getContext ('2d');
//примечание
canvas.addeventlistener ('mousedown', start_wall, false);
canvas.addeventlistener ('mousemove', strept_wall, false);
canvas.addeventlistener ('mouseup', finish_wall, false);
window.addeventlistener ('keydown', getkey_and_move, false);
draw_all ();
}
function start_wall (ev)
{
var mx;
var my;
if (ev.layerx || ev.layerx == 0)
{
mx = ev.layerx;
my = ev.layery;
}
else if (ev.offsetx || ev.offsetx == 0)
{
mx = ev.offsetx;
my = ev.offsety;
}
cur_wall = новая стена (MX, My, MX + 1, My + 1, Wall_Width, Wall_Style);
in_motion = true;
Все. Push (cur_wall);
draw_all ();
}
Функция strest_wall (EV)
{
if (in_motion)
{
var mx;
var my;
if (ev.layerx || ev.layerx == 0)
{
mx = ev.layerx;
my = ev.layery;
}
else if (ev.offsetx || ev.offsetx == 0)
{
mx = ev.offsetx;
my = ev.offsety;
}
cur_wall.fx = mx;
cur_wall.fy = my;
draw_all ();
}
}
function finish_wall (EV)
{
in_motion = false;
Walls.push (cur_wall);
}
функция draw_all ()
{
ctx.clearrect (0, 0, canvas_width, canvas_height);
var i;
для (i = 0; i <ill.length; i ++)
{
Все [i] .draw ();
}
}
функция getKey_and_move (событие)
{
var KeyCode;
if (событие == null)
{
KeyCode = window.event.keyCode;
window.event.preventdefault ();
}
еще
{
KeyCode = event.KeyCode;
Event.preventDefault ();
}
переключатель (KeyCode)
{
Случай 37: // Левая стрелка
mypent.move (-unit, 0);
перерыв;
Случай 38: // up стрелка
mypent.move (0, -unit);
перерыв;
Случай 39: // Стрелка правой
mypent.move (блок, 0);
перерыв;
Случай 40:
mypent.move (0, Unit);
перерыв;
по умолчанию:
//window.removeeventlistener('keydown ', getkey_and_move, false);
}
draw_all ();
}
Функция пересекается (SX, SY, FX, FY, CX, CY, RAD)
{
var dx;
var dy;
var t;
var rt;
dx = fx - sx;
dy = fy - sy;
t = 0,0 - (((sx - cx) * dx + (sy - cy) * dy) / (dx * dx + dy * dy));
if (t <0,0)
{
t = 0,0;
}
иначе if (t> 1,0)
t = 1,0;
var dx1 = (sx + t * dx) - cx;
var dy1 = (sy + t * dy) - cy;
var rt = dx1 * dx1 + dy1 * dy1;
if (rt <rad * rad)
вернуть истину;
еще
вернуть ложь;
}
</script>
<тело>
<Canvas> </canvas>
</body>
</html>
сложность
Методы обнаружения столкновений между полигонами и сегментами линий
Функция recesect () отвечает за обнаружение, пересекается ли полигон и линейный сегмент.
Обратите внимание на точку P (x, y) в сегменте линии
Две конечные точки сегмента линии: (SX, SY) и (FX, FY)
помнить
dx = fx-sx
dy = fy-sy
X и Y могут быть представлены следующим образом
x = sx+t*dx
y = sy+t*dy
Чтобы определить, пересекаются ли сегмент линии и многоугольник, он преобразуется в определение того, пересекаются ли сегмент линии и полигон.
Для этого вам нужно найти точку P, ближайшую к центру круга O на сегменте линии
Если | op | <радиус круга, вы можете судить о пересечении сегмента линии и круга.
В противном случае они не будут пересекаться.
Как найти точку ближайшей к центру круга на сегменте линии?
Расстояние от точки P до точки O может быть выражено как
Расстояние = SQRT ((x-cx)*(x-cx)+(y-cy)*(y-cy));
Заменять
x = sx+t*dx и y = sy+t*dy
Вы можете получить расстояние - это функция о t
Производство этой функции
Найдите соответствующее значение t, когда значение функции составляет 0, и вы можете получить ближайшую точку к центру круга