canvas带方向指示的元素碰撞效果
代码语言:html
所属分类:动画
代码描述:canvas带方向指示的元素碰撞效果,点击鼠标左键增加元素
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> *{ margin: 0; padding: 0; } </style> </head> <body> <canvas id="canvas" width="640" height="480" /> <script> var canvas = document.getElementById("canvas"); var context = canvas.getContext('2d'); const log = document.getElementById('log'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; function distance(x1, y1, x2, y2) { return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); } class Vector2d { constructor(x, y) { this.x = x; this.y = y; } getRotateRad(cx, cy, x, y, radian) { const cos = Math.cos(radian); const sin = Math.sin(radian); const nx = cos * (x - cx) + sin * (y - cy); const ny = cos * (y - cy) - sin * (x - cx); return { x: nx, y: ny }; } rotateRad(cx, cy, x, y, radian) { const cos = Math.cos(radian); const sin = Math.sin(radian); this.x = cos * (x - cx) + sin * (y - cy); this.y = cos * (y - cy) - sin * (x - cx); } add(x, y) { this.x += x; this.y += y; } sub(x, y) { this.x -= x; this.y -= y; } mul(x, y) { this.x *= x; this.y *= y; }} class Ball { constructor(x, y, vecX, vecY, speed, scale) { this.x = x; this.y = y; this.defX = x; this.defY = y; this.vec = new Vector2d(vecX, vecY); this.forceVec = new Vector2d(0, 0); this.speed = speed; this.scale = scale; this.life = Math.random() * 500 + 500; this.mass = scale; this.color = `rgb(${Math.random() * 100 + 155}, ${Math.random() * 150 + 40}, ${Math.random() * 150 + 40})`; this.eye = new Eye(this); } setHit(val, hitObj, distance) { this.isHit = true; this.isHitObj = hitObj; this.hitdistance = distance; } draw(context) { context.beginPath(); //パス作成 //描写cmd start context.arc(this.x, this.y, this.scale, 0, 2 * Math.PI, true); context.fillStyle = this.color; //線の色指定 context.fill(); //線を描写 // vector表示 context.beginPath(); context.moveTo(this.x, this.y); context.lineTo(this.x + this.vec.x * 5, this.y + this.vec.y * 5); context.strokeStyle = "black"; context.lineWidth = 1; context.stroke(); context.closePath(); this.eye.draw(context); } update() { this.beforeX = this.x; this.beforeY = this.y; if (this.isHit && this.isHitObj) { let rad = Math.atan2(this.isHitObj.y - this.y, this.isHitObj.x - this.x); const cos = Math.cos(rad); const sin = Math.sin(rad); // 衝突の重なり部分解消 this.x += this.hitdistance / 2 * cos; this.y += this.hitdistance / 2 * sin; this.isHitObj.x -= this.hitdistance / 2 * cos; this.isHitObj.y -= this.hitdistance / 2 * sin; // 反射角出し参考 // https://thinkit.co.jp/article/8466 // 円同士の接点 const cx = cos * this.scale + this.x; const cy = sin * this.scale + this.y; // 180度回転後の座標 const rx = Math.cos(rad + Math.PI) * this.scale + this.x; const ry = Math.sin(rad + Math.PI) * this.scale + this.y; // 次の移動地点 反射後の地点 const gx = rx + this.vec.x; const gy = ry + this.vec.y; this.vec.x = (gx - cx) / this.scale; this.vec.y = (gy - cy) / this.scale; this.setHit(false, null); } this.x += this.speed * (this.vec.x + this.forceVec.x); this.y += this.speed * (this.vec.y + this.forceVec.y); // 上にめり込んだら if (this.y - this.scale <= 0) { this.y = this.scale; this.vec.y *= -1; this.forceVec.y *= -1; } //.........完整代码请登录后点击上方下载按钮下载查看
网友评论0