html5 迷宫游戏(碰撞检测)实例一


Posted in HTML / CSS onJuly 25, 2013

游戏效果图
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值就可以得到距离圆心最近的点

HTML / CSS 相关文章推荐
浅析两列自适应布局的3种思路
May 03 HTML / CSS
CSS3 translate导致字体模糊的实例代码
Aug 30 HTML / CSS
纯CSS打造(无图像无js)的非常流行的讲话(语音)气泡效果
Dec 28 HTML / CSS
8款精美的CSS3表单设计(登录表单/下拉选择/按钮附演示及源码)
Feb 04 HTML / CSS
纯CSS3实现的8种Loading动画效果
Jul 05 HTML / CSS
CSS3实现多背景模拟动态边框的效果
Nov 08 HTML / CSS
纯CSS3大转盘抽奖示例代码(响应式、可配置)
Jan 13 HTML / CSS
css和css3弹性盒模型实现元素宽度(高度)自适应
May 15 HTML / CSS
css3实现蒙版弹幕功能
Jun 18 HTML / CSS
html5使用html2canvas实现浏览器截图的示例
Aug 31 HTML / CSS
HTML5中的音频和视频媒体播放元素小结
Jan 29 HTML / CSS
微信html5页面调用第三方位置导航的示例
Mar 14 HTML / CSS
html5弹跳球示例代码
Jul 23 #HTML / CSS
x-ua-compatible content=”IE=7, IE=9″意思理解
Jul 22 #HTML / CSS
canvas使用注意点总结
Jul 19 #HTML / CSS
有关HTML5 Video对象的ontimeupdate事件(Chrome上无效)的问题
Jul 19 #HTML / CSS
HTML5 的新的表单元素(datalist/keygen/output)使用介绍
Jul 19 #HTML / CSS
HTML5注册表单的自动聚焦与占位文本示例代码
Jul 19 #HTML / CSS
HTML5标签与HTML4标签的区别示例介绍
Jul 18 #HTML / CSS
You might like
php+mysql实现用户注册登陆的方法
2015/01/03 PHP
php分享朋友圈的实现代码
2019/02/18 PHP
JS 如果改变span标签的是否隐藏属性
2011/10/06 Javascript
40款非常有用的 jQuery 插件推荐(系列一)
2011/12/21 Javascript
在javaScript中关于submit和button的区别介绍
2013/10/20 Javascript
浅谈JavaScript function函数种类
2014/12/29 Javascript
jQuery插件开发的五种形态小结
2015/03/04 Javascript
微信小程序 开发MAP(地图)实例详解
2017/06/27 Javascript
详解React-Native解决键盘遮挡问题(Keyboard遮挡问题)
2017/07/13 Javascript
创建echart多个联动的示例代码
2018/11/23 Javascript
基于mpvue小程序使用echarts画折线图的方法示例
2019/04/24 Javascript
python和C语言混合编程实例
2014/06/04 Python
用Python程序抓取网页的HTML信息的一个小实例
2015/05/02 Python
Python的Django应用程序解决AJAX跨域访问问题的方法
2016/05/31 Python
Python编程实现生成特定范围内不重复多个随机数的2种方法
2017/04/14 Python
Python使用matplotlib绘图无法显示中文问题的解决方法
2018/03/14 Python
Python3 中把txt数据文件读入到矩阵中的方法
2018/04/27 Python
解决python升级引起的pip执行错误的问题
2018/06/12 Python
Django中的Model操作表的实现
2018/07/24 Python
python3+PyQt5 创建多线程网络应用-TCP客户端和TCP服务器实例
2019/06/17 Python
python实现ip代理池功能示例
2019/07/05 Python
浅析PEP570新语法: 只接受位置参数
2019/10/15 Python
python命令 -u参数用法解析
2019/10/24 Python
下载与当前Chrome对应的chromedriver.exe(用于python+selenium)
2020/01/14 Python
介绍CSS3使用技巧5个
2009/04/02 HTML / CSS
使用CSS3的font-face字体嵌入样式的方法讲解
2016/05/13 HTML / CSS
HTML5 在canvas中绘制矩形附效果图
2014/06/23 HTML / CSS
世界领先的26岁以下学生和青少年旅行预订网站:StudentUniverse
2018/07/01 全球购物
购买美国制造的相框和画框架:Picture Frames
2018/08/14 全球购物
澳大利亚先进的皮肤和激光诊所购物网站:Soho Skincare
2018/10/15 全球购物
DOUGLAS波兰:在线销售香水和化妆品
2020/07/05 全球购物
自考生毕业自我鉴定
2013/10/10 职场文书
工作检讨书500字
2014/10/19 职场文书
五年级学生期末评语
2014/12/26 职场文书
答谢词范文
2015/01/05 职场文书
家庭教育培训学习心得体会
2016/01/14 职场文书