게임 렌더링
마우스를 사용하여 드래그하여 캔버스에 벽을 추가하고 화살표 키를 사용하여 다각형을 위, 아래, 왼쪽, 오른쪽으로 이동할 수 있습니다. 벽이 있으면 앞으로 나아갈 수 없습니다.
해결해야 할 문제
마우스 누르기, 마우스 끌기, 마우스 떼기 이벤트 감지
다각형 그리기
벽 그리기
충돌 다각형과 벽 사이의 감지 (본질적으로 원과 선분의 교차 판단)
MYCode:
코드는 다음과 같습니다.
<html> <head> <title>迷宫</title> <script> var canvas_width = 900; var canvas_height = 350; var ctx; var canvas; var everything = []; var cur_wall; var wall_width; var wall_style = "rgb(200,0,200)"; var walls = []; var in_motion = false; var unit = 10; function Token(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边形 { 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)); for (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(); } function move_token(dx, dy) { this.sx += dx; this.sy += dy; var i; var wall; for (i = 0; i < walls.length; i++) { wall = walls[i]; if (intersect(wall.sx, wall.sy, wall.fx, wall.fy, this.sx, this.sy, this.rad)) { this.sx -= dx; this.sy -= dy; break; } } } function Wall(sx, sy, fx, fy, width, styleString) { this.sx = sx; this.sy = sy; this.fx = fx; this.fy = fy; this.width = width; this.draw = draw_line; this.strokeStyle = styleString; } function 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(); } //note var mypent = new Token(100, 100, 20, "rgb(0,0,250)", 5); everything.push(mypent); function init() { canvas = document.getElementById("canvas"); ctx = canvas.getContext('2d'); //note canvas.addEventListener('mousedown', start_wall, false); canvas.addEventListener('mousemove', stretch_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 = new Wall(mx, my, mx + 1, my + 1, wall_width, wall_style); in_motion = true; everything.push(cur_wall); draw_all(); } function stretch_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); } function draw_all() { ctx.clearRect(0, 0, canvas_width, canvas_height); var i; for (i = 0; i < everything.length; i++) { everything[i].draw(); } } function getkey_and_move(event) { var keyCode; if (event == null) { keyCode = window.event.keyCode; window.event.preventDefault(); } else { keyCode = event.keyCode; event.preventDefault(); } switch (keyCode) { case 37://left arrow mypent.move(-unit, 0); break; case 38://up arrow mypent.move(0, -unit); break; case 39://right arrow mypent.move(unit, 0); break; case 40: mypent.move(0, unit); break; default: //window.removeEventListener('keydown', getkey_and_move, false); } draw_all(); } function intersect(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; } else 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) return true; else return false; } </script> <body onLoad="init();"> <canvas id="canvas" width="900" height="350"></canvas> </body> </html>
어려움
다각형과 선분 사이의 충돌 감지 방법
intersect() 함수는 다각형과 선분의 교차 여부를 감지하는 역할을 담당합니다.
점 p(x) 기억 ,y) 선분
선분 두 끝점은 (sx, sy) 및 (fx, fy)입니다.
기억하세요
dx=fx-sx
dy=fy-sy
x와 y는 다음과 같이 표현할 수 있습니다.
x=sx t*dx
y=sy t*dy
선분 여부를 확인하려면 그리고 다각형이 교차하면 선분과 다각형의 외접원이 교차하는지 여부로 변환됩니다
이를 위해서는 원의 중심 o에 가장 가까운 선분에서 점 p를 찾아야 합니다. .
|op|그렇지 않으면 교차하지 않습니다.
원의 중심에 가장 가까운 선분에서 점을 찾는 방법은 무엇입니까?
p 지점에서 o 지점까지의 거리는
distance=sqrt((x-cx)*(x-cx) (y-cy)*(y-cy)로 표현할 수 있습니다. );
대체
x=sx t*dx 및 y=sy t*dy
거리는 t에 대한 함수임을 알 수 있습니다
이 함수의 경우 미분
을 유도하고 함수 값이 0일 때 해당 t 값을 구하면 원의 중심에 가장 가까운 점을 얻을 수 있습니다