html5 迷宮游戲(碰撞檢測)實例一
來源:易賢網 閱讀:1117 次 日期:2016-07-13 13:58:39
溫馨提示:易賢網小編為您整理了“html5 迷宮游戲(碰撞檢測)實例一”,方便廣大網友查閱!

通過鼠標拖拽在畫布上添加墻壁,通過方向鍵控制多邊形上下左右移動,遇到墻壁則無法前進,下面為大家介紹下需要解決的問題及具體的實現代碼,感興趣的朋友可以學習下

需要解決的問題

鼠標按下,鼠標拖動,鼠標釋放事件的檢測

多邊形的繪制

墻壁的繪制

多邊形和墻壁的碰撞檢測(實質上是圓和線段的相交判斷)

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)

線段2個端點是(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

可以得到distance是一個關于t的函數

對此函數求導

求出函數值為0時對應的t值就可以得到距離圓心最近的點

更多信息請查看網頁制作
易賢網手機網站地址:html5 迷宮游戲(碰撞檢測)實例一

2025國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 加入群交流 | 手機站點 | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
聯系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
咨詢QQ:526150442(9:00—18:00)版權所有:易賢網