p2模拟真实的物理转盘转动动画效果代码
代码语言:html
所属分类:动画
代码描述:p2模拟真实的物理转盘转动动画效果代码
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> body { background-color: #fff; margin: 0; } .centered { position: absolute; margin: auto; top: 0; bottom: 0; left: 0; right: 0; } #container { width: 768px; height: 768px; } #status_label { position: absolute; top: 768px; width: 768px; color: black; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 1.5em; text-align: center; pointer-events: none; } #drawing_canvas { position: absolute; } </style> </head> <body> <div id="container" class="centered"> <canvas id="drawing_canvas"></canvas> <div id="status_label"> loading... </div> </div> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/p2.min.js"></script> <script> const TWO_PI = Math.PI * 2; const HALF_PI = Math.PI * 0.5; // canvas settings var viewWidth = 768, viewHeight = 768, viewCenterX = viewWidth * 0.5, viewCenterY = viewHeight * 0.5, drawingCanvas = document.getElementById("drawing_canvas"), ctx, timeStep = (1/60), time = 0; var ppm = 24, // pixels per meter physicsWidth = viewWidth / ppm, physicsHeight = viewHeight / ppm, physicsCenterX = physicsWidth * 0.5, physicsCenterY = physicsHeight * 0.5; var world; var wheel, arrow, mouseBody, mouseConstraint; var arrowMaterial, pinMaterial, contactMaterial; var wheelSpinning = false, wheelStopped = true; var particles = []; var statusLabel = document.getElementById('status_label'); window.onload = function() { initDrawingCanvas(); initPhysics(); requestAnimationFrame(loop); statusLabel.innerHTML = 'Give it a good spin!'; }; function initDrawingCanvas() { drawingCanvas.width = viewWidth; drawingCanvas.height = viewHeight; ctx = drawingCanvas.getContext('2d'); drawingCanvas.addEventListener('mousemove', updateMouseBodyPosition); drawingCanvas.addEventListener('mousedown', checkStartDrag); drawingCanvas.addEventListener('mouseup', checkEndDrag); drawingCanvas.addEventListener('mouseout', checkEndDrag); } function updateMouseBodyPosition(e) { var p = getPhysicsCoord(e); mouseBody.position[0] = p.x; mouseBody.position[1] = p.y; } function checkStartDrag(e) { if (world.hitTest(mouseBody.position, [wheel.body])[0]) { mouseConstraint = new p2.RevoluteConstraint(mouseBody, wheel.body, { worldPivot: mouseBody.position, collideConnected: false }); world.addConstraint(mouseConstraint); } if (wheelSpinning === true) { wheelSpinning = false; wheelStopped = true; statusLabel.innerHTML = "Impatience will not be rewarded."; } } function checkEndDrag(e) { if (mouseConstraint) { world.removeConstraint(mouseConstraint); mouseConstraint = null; if (wheelSpinning === false && wheelStopped === true) { if (Math.abs(wheel.body.angularVelocity) > 7.5) { wheelSpinning = true; wheelStopped = false; console.log('good spin'); statusLabel.innerHTML = '...clack clack clack clack clack clack...' } else { console.log('sissy'); statusLabel.innerHTML = 'Come on, you can spin harder than that.' } } } } function getPhysicsCoord(e) { var rect = drawingCanvas.getBoundingClientRect(), x = (e.clientX - rect.left) / ppm, y = physicsHeight - (e.clientY - rect.top) / ppm; return { x: x, y: y }; } function initPhysics() { world = new p2.World(); world.solver.iterations = 100; world.solver.tolerance = 0; arrowMaterial = new p2.Material(); pinMaterial = new p2.Material(); contactMaterial = new p2.ContactMaterial(arrowMaterial, pinMaterial, { friction: 0.0, restitution: 0.1 }); world.addContactMaterial(contactMaterial); var wheelRadius = 8, wheelX = physicsCenterX, wheelY = wheelRadius + 4, arrowX = wheelX, arrowY = wheelY + wheelRadius + 0.625; wheel = new Wheel(wheelX, wheelY, wheelRadius, 32, 0.25, 7.5); wheel.body.angle = (Math.PI / 32.5); wheel.body.angularVelocity = 5; arrow = new Arrow(arrowX, arrowY, 0.5, 1.5); mouseBody = new p2.Body(); world.addBody(mouseBody); } function spawnPartices() { for (var i = 0; i < 200; i++) { var p0 = new Point(viewCenterX, viewCenterY - 64); var p1 = new Point(viewCenterX, 0); var p2 = new Point(Math.random() * viewWidth, Math.random() * viewCenterY); var p3 = new Point(Math.random() * viewWidth, viewHeight + 64); particles.push(new Particle(p0, p1, p2, p3)); } } function update() { particles.forEach(function(p) { p.update(); if (p.complete) { particles.splice(particles.indexOf(p), 1); } }); // p2 does not support continuous collision detection :( // but stepping twice seems to help // considering there are only a few bodies, this is ok for now. world.step(timeStep * 0.5); world.step(timeStep * 0.5); if (wheelSpinning === true && wheelStopped === false && wheel.body.angularVelocity < 1 && arrow.hasStopped()) { var win = wheel.gotLucky(); wheelStopped = true; wheelSpinning = false; wheel.body.angularVelocity = 0; if (win) { spawnPartices(); statusLabel.innerHTML = 'Woop woop!' } else { statusLabel.innerHTML = 'Too bad! Invite a Facebook friend to try again!'; } } } function draw() { // ctx.fillStyle = '#fff'; ctx.clearRect(0, 0, viewWidth, viewHeight); wheel.draw(); arrow.draw(); particles.forEach(function(p) { p.draw(); }); } function loop() { update(); draw(); requestAnimationFrame(loop); } ///////////////////////////// // wheel of fortune ///////////////////////////// function Wheel(x, y, radius, segments, pinRadius, pinDistance) { this.x = x; this.y = y; this.radius = radius; this.segments = segments; this.pinRadius = pinRadius; this.pinDistance = pinDistance; this.pX = this.x * ppm; this.pY = (physicsHeight - this.y) * ppm; this.pRadius = this.radius * ppm; this.pPinRadius = this.pinRadius * ppm; this.pPinPositions = []; this.deltaPI = TWO_PI / this.segments; this.createBody(); this.createPins(); } Wheel.prototype = { createBody: function() { this.body = new p2.Body({ mass: 1, position: [this.x, this.y]}); this.body.angularDamping = 0.0; this.body.addShape(new p2.Circle(this.radius)); this.body.shapes[0].sensor = true; //TODO use collision bits instead var axis = new p2.Body({ position: [this.x, this..........完整代码请登录后点击上方下载按钮下载查看
网友评论0