Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
css
html,body { width:100%; height:100%; margin:0; overflow:hidden; background:#000; }
JavaScript
var canvas, ctx, m1 = {x: 0, y: 0}, m2 = {x: 0, y: 0}, dx = 0, dy = 0, radius = 50, trail = 400; var ground = []; const sqrDist = (x1, y1, x2, y2) => { var dx = x2 - x1, dy = y2 - y1; return dx * dx + dy * dy; }; function dist(x1, y1, x2, y2) { var dx = x2 - x1, dy = y2 - y1; return Math.sqrt(dx * dx + dy * dy); } function distToLine(p, l1, l2) { var dx = l2.x - l1.x, dy = l2.y - l1.y; var len = dx * dx + dy * dy; if(len === 0) return dist(p.x, p.y, l1.x, l1.y); var t = ((p.x - l1.x) * dx + (p.y - l1.y) * dy) / len; t = Math.max(0, Math.min(1, t)); return dist(p.x, p.y, l1.x + t * dx, l1.y + t * dy); } function closestPointOnLine(p, l1, l2) { var dx = l2.x - l1.x, dy = l2.y - l1.y; var sqrLen = dx * dx + dy * dy; //if(len === 0) return dist(p.x, p.y, l1.x, l1.y); if(sqrLen === 0) return l1; var t = ((p.x - l1.x) * dx + (p.y - l1.y) * dy) / sqrLen; t = Math.max(0, Math.min(1, t)); return {x: l1.x + t * dx, y: l1.y + t * dy}; } function line_intersect(p1, p2, p3, p4) { var x1 = p1.x, y1 = p1.y, x2 = p2.x, y2 = p2.y, x3 = p3.x, y3 = p3.y, x4 = p4.x, y4 = p4.y; if( // Check AABB collission Math.min(x1, x2) > Math.max(x3, x4) || Math.max(x1, x2) < Math.min(x3, x4) || Math.min(y1, y1) > Math.max(y3, y4) || Math.max(y1, y2) < Math.min(y3, y4) ) return undefined; var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1); if (denom == 0) return undefined; var ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom; if(!(ua >= 0 && ua <= 1)) return undefined; var ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom; if(!(ub >= 0 && ub <= 1)) return undefined; return { x: Math.round(x1 + ua * (x2 - x1)), y: Math.round(y1 + ua * (y2 - y1)) }; } const getHitBox = (p1, p2, radius = 0) => { return { left: Math.min(p1.x, p2.x) - radius, right: Math.max(p1.x, p2.x) + radius, top: Math.min(p1.y, p2.y) - radius, bottom: Math.max(p1.y, p2.y) + radius, width: Math.abs(p2.x - p1.x) + 2 * radius, height: Math.abs(p2.y - p1.y) + 2 * radius, }; }; const hitAABB = (b1, b2) => b1.right >= b2.left && b1.left <= b2.right && b1.bottom >= b2.top && b1.top <= b2.bottom; function inteceptCircleLineSeg(c, r, p1, p2){ var a, b, c, d, u1, u2, ret, retP1, retP2, v1, v2; v1 = {}; v2 = {}; v1.x = p2.x - p1.x; v1.y = p2.y - p1.y; v2.x = p1.x - c.x; v2.y = p1.y - c.y; b = (v1.x * v2.x + v1.y * v2.y); c = 2 * (v1.x * v1.x + v1.y * v1.y); b *= -2; d = Math.sqrt(b * b - 2 * c * (v2.x * v2.x + v2.y * v2.y - r * r)); if(isNaN(d)){ // no intercept return []; } u1 = (b - d) / c; // these represent the unit distance of point one and two on the line u2 = (b + d) / c; retP1 = {}; // return points retP2 = {} ret = []; // return array if(u1 <= 1 && u1 >= 0){ // add point if on the line segment retP1.x = p1.x + v1.x * u1; retP1.y = p1.y + v1.y * u1; ret[0] = retP1; } if(u2 <= 1 && u2 >= 0){ // second add point if on the line segment retP2.x = p1.x + v1.x * u2; retP2.y = p1.y + v1.y * u2; ret[ret.length] = retP2; } return ret; } const drawLine = (p1, p2) => { ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.stroke(); }; const drawCircle = (x, y, r) => { ctx.beginPath(); ctx.arc(x, y, r, 0, Math.PI * 2); ctx.stroke(); }; const drawCollission = (x, y) => { ctx.beginPath(); ctx.moveTo(x - 20, y - 20); ctx.lineTo(x + 20, y + 20); ctx.moveTo(x + 20, y - 20); ctx.lineTo(x - 20, y + 20); ctx.strokeStyle = 'red'; ctx.stroke(); }; const drawBall = (x, y, radius = 10) => { ctx.beginPath(); ctx.moveTo(x, y); ctx.arc(x, y, radius, 0, Math.PI * 2); ctx.fill(); }; const drawCollider = (p1, p2, radius = 0) => { var hb = getHitBox(p1, p2, radius); ctx.beginPath(); ctx.rect(hb.left, hb.top, hb.width, hb.height); ctx.lineWidth = 1; ctx.stroke(); }; const drawColliders = (radius = 0) => { for(var i = 0; i < ground.length - 1; i++) drawCollider(ground[i], ground[i + 1], radius); }; const drawSegment = (p1, p2) => { ctx.beginPath(); ctx.moveTo(p1.x, p1.y); ctx.lineTo(p2.x, p2.y); ctx.strokeStyle = 'orange'; ctx.lineWidth = 3; ctx.stroke(); ctx.beginPath(); ctx.arc(p1.x, p1.y, 5, 0, Math.PI * 2); ctx.arc(p2.x, p2.y, 5, 0, Math.PI * 2); ctx.fillStyle = 'red'; ctx.fill(); }; const drawGroundSegments = () => { for(var i = 0; i < ground.length - 1; i++) drawSegment(ground[i], ground[i + 1]); }; const rayMarch = (p1, p2, l1, l2, radius = 0) => { ctx.strokeStyle = 'rgba(0, 255, 255, 0.4)'; drawLine(p1, p2); var dx = p2.x - p1.x, dy = p2.y - p1.y, len = dist(p1.x, p1.y, p2.x, p2.y); var vx = dx / len, vy = dy / len; var sumDist = 0, lastHitD = Number.PositiveInfinity; const testPoint = (p) => { var hitP = closestPointOnLine(p, l1, l2); var hitD = dist(p.x, p.y, hitP.x, hitP.y) - radius; if(hitD > lastHitD) return false; sumDist += hitD; if(sumDist > len) return false; if(hitD <= 0) { return { point: p, hit: hitP, dist: dist(p1.x, p1.y, p.x, p.y) }; } drawCircle(p.x, p.y, hitD); var stepSize = Math.max(1, hitD); lastHitD = hitD; return testPoint({ x: p.x + vx * stepSize, y: p.y + vy * stepSize }); }; return testPoint(p1); }; const draw = () => { ctx.save(); ctx.fillStyle = '#111'; ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); drawGroundSegments(); ctx.strokeStyle = 'white'; drawColliders(0); ctx.fillStyle = 'blue'; drawBall(m1.x, m1.y, radius); ctx.fillStyle = 'rgba(0, 0, 255, 0.5)'; drawBall(m2.x, m2.y, radius); ctx.strokeStyle = 'white'; drawCollider(m1, m2, radius); var hits = [], closestHit; for(var i = 0; i < ground.length - 1; i++) { var l1 = ground[i], l2 = ground[i + 1] var b1 = getHitBox(l1, l2); var b2 = getHitBox(m1, m2, radius); var hit = hitAABB(b1, b2); if(hit) { var hit = rayMarch(m2, m1, l1, l2, radius); if(hit !== false) { hits.push(hit); if(closestHit === undefined || hit.dist < closestHit.dist) closestHit = hit; } } } ctx.fillStyle = 'rgba(255, 255, 0, 0.1)'; hits.forEach(hit => drawBall(hit.point.x, hit.point.y, radius)) ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; if(closestHit) { drawBall(closestHit.point.x, closestHit.point.y, radius); ctx.strokeStyle = '#fff'; drawLine(closestHit.point, closestHit.hit); } ctx.restore(); }; const initGround = () => { ground = [{"x":0.1,"y":0.25},{"x":0.18,"y":0.55},{"x":0.25,"y":0.45},{"x":0.35,"y":0.55},{"x":0.43,"y":0.71},{"x":0.49,"y":0.59},{"x":0.54,"y":0.55},{"x":0.59,"y":0.45},{"x":0.64,"y":0.55},{"x":0.72,"y":0.6},{"x":0.81,"y":0.37},{"x":0.87,"y":0.43},{"x":0.9,"y":0.43}]; ground = ground.map(p => ({x: p.x * canvas.width, y: p.y * canvas.height})); return; ground = []; var step = 0.1, randFact = 0.7, x = step, y = 0.5; while(x < (1 - step)) { y = 0.5 + (Math.floor(Math.random() * 2) ? -1 : 1) * (0.05 + 0.2 * Math.pow(Math.random(), 3)); ground.push({x, y}); x += ((1 - randFact) + randFact * Math.random()) * step; } x = 1 - step; ground.push({x, y}); ground = ground.map(p => ({x: Math.round(p.x * 100) / 100, y: Math.round(p.y * 100) / 100})); console.log(JSON.stringify(ground)); ground.forEach(p => { p.x *= canvas.width; p.y *= canvas.height; }); }; const handleRAF = time => { requestAnimationFrame(handleRAF); draw(); }; const init = () => { console.clear(); canvas = document.body.appendChild(document.createElement('canvas')); ctx = canvas.getContext('2d'); window.addEventListener('resize', handleResize); window.addEventListener('mousemove', handleMouseMove); requestAnimationFrame(handleRAF); handleResize(); initGround(); }; const handleMouseMove = event => { var x = event.clientX, y = event.clientY; //var len = dist(; //dx = x - mx; //dy = y - my; m1.x = x; m1.y = y; var d = dist(m1.x, m1.y, m2.x, m2.y); if(d > trail) { m2.x = Math.round(m1.x + (m2.x - m1.x) * trail / d); m2.y = Math.round(m1.y + (m2.y - m1.y) * trail / d); } }; const handleResize = event => { canvas.width = document.body.clientWidth; canvas.height = document.body.clientHeight; initGround(); draw(); }; window.addEventListener('DOMContentLoaded', init);
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>碰撞检测-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号