>웹 프론트엔드 >H5 튜토리얼 >HTML5 미로 게임(충돌 감지) 예제 1_html5 튜토리얼 기술

HTML5 미로 게임(충돌 감지) 예제 1_html5 튜토리얼 기술

PHP中文网
PHP中文网원래의
2016-05-16 15:49:011863검색

게임 렌더링

마우스를 사용하여 드래그하여 캔버스에 벽을 추가하고 화살표 키를 사용하여 다각형을 위, 아래, 왼쪽, 오른쪽으로 이동할 수 있습니다. 벽이 있으면 앞으로 나아갈 수 없습니다.

해결해야 할 문제

마우스 누르기, 마우스 끌기, 마우스 떼기 이벤트 감지
다각형 그리기
벽 그리기
충돌 다각형과 벽 사이의 감지 (본질적으로 원과 선분의 교차 판단)

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(&#39;2d&#39;); 
//note 
canvas.addEventListener(&#39;mousedown&#39;, start_wall, false); 
canvas.addEventListener(&#39;mousemove&#39;, stretch_wall, false); 
canvas.addEventListener(&#39;mouseup&#39;, finish_wall, false); 
window.addEventListener(&#39;keydown&#39;, 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(&#39;keydown&#39;, 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 값을 구하면 원의 중심에 가장 가까운 점을 얻을 수 있습니다

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.