Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
Large
Small
Antigravity
css
html { overflow: hidden; } body { position: absolute; margin: 0; padding: 0; width: 100%; height: 100%; background: #222; } canvas { position: absolute; width: 100vw; height: 50vw; max-height: 100vh; max-width: 200vh; margin: auto; top: 0; bottom: 0; left: 0; right: 0; background: #000; } .radio { position: absolute; left: 50%; width: 260px; margin: 10px; margin-left: -130px; z-index: 1000; } .radio label { cursor: pointer; font-size: 13px; font-family: verdana; color: #666; }
JavaScript
"use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Contact = function () { function Contact(world) { _classCallCheck(this, Contact); this.bA = null; this.bB = null; this.px = 0.0; this.py = 0.0; this.nx = 0.0; this.ny = 0.0; this.Pn = 0.0; // accumulated normal impulse this.Pt = 0.0; // accumulated tangent impulse this.r1x = 0.0; this.r1y = 0.0; this.r2x = 0.0; this.r2y = 0.0; this.rvx = 0.0; this.rvy = 0.0; this.separation = 0.0; this.massNormal = 0.0; this.massTangent = 0.0; this.bias = 0.0; this.friction = 0.0; this.allowedPenetration = world.allowedPenetration; this.biasFactor = -world.biasFactor * world.invDT; this.min = Math.min; this.max = Math.max; this.abs = Math.abs; this.ctx = ctx; } Contact.prototype.update = function update(bA, bB, separation, nx, ny, friction, px, py) { this.bA = bA; this.bB = bB; this.separation = separation; this.nx = nx; this.ny = ny; this.Pn = 0.0; this.Pt = 0.0; this.friction = friction; // slide contact point onto reference face (easy to cull) this.px = px; this.py = py; this.r1x = this.px - this.bA.px; this.r1y = this.py - this.bA.py; this.r2x = this.px - this.bB.px; this.r2y = this.py - this.bB.py; // Precompute normal mass, tangent mass, and bias. var rn1 = this.r1x * this.nx + this.r1y * this.ny; var rn2 = this.r2x * this.nx + this.r2y * this.ny; this.massNormal = 1.0 / (this.bA.iM + this.bB.iM + this.bA.iI * (this.r1x * this.r1x + this.r1y * this.r1y - rn1 * rn1) + this.bB.iI * (this.r2x * this.r2x + this.r2y * this.r2y - rn2 * rn2)); var rt1 = this.r1x * this.ny - this.r1y * this.nx; var rt2 = this.r2x * this.ny - this.r2y * this.nx; this.massTangent = 1.0 / (this.bA.iM + this.bB.iM + this.bA.iI * (this.r1x * this.r1x + this.r1y * this.r1y - rt1 * rt1) + this.bB.iI * (this.r2x * this.r2x + this.r2y * this.r2y - rt2 * rt2)); this.bias = this.biasFactor * this.min(0.0, this.separation + this.allowedPenetration); }; Contact.prototype.relativeVelocity = function relativeVelocity() { this.rvx = this.bB.vx + -this.bB.va * this.r2y - this.bA.vx - -this.bA.va * this.r1y; this.rvy = this.bB.vy + this.bB.va * this.r2x - this.bA.vy - this.bA.va * this.r1x; }; Contact.prototype.impulse = function impulse(px, py) { this.bA.vx -= this.bA.iM * px; this.bA.vy -= this.bA.iM * py; this.bA.va -= this.bA.iI * (this.r1x * py - this.r1y * px); this.bB.vx += this.bB.iM * px; this.bB.vy += this.bB.iM * py; this.bB.va += this.bB.iI * (this.r2x * py - this.r2y * px); }; Contact.prototype.applyImpulse = function applyImpulse() { var dPn = undefined, Pn0 = undefined, maxPt = undefined; // Relative velocity at contact this.relativeVelocity(); // Compute normal impulse dPn = this.massNormal * (-(this.rvx * this.nx + this.rvy * this.ny) + this.bias); // Clamp the accumulated impulse Pn0 = this.Pn; this.Pn = this.max(Pn0 + dPn, 0.0); dPn = this.Pn - Pn0; // Apply contact impulse this.impulse(this.nx * dPn, this.ny * dPn); // Relative velocity at contact this.relativeVelocity(); dPn = -this.massTangent * (this.rvx * this.ny - this.rvy * this.nx); // Compute friction impulse maxPt = this.friction * this.Pn; // Clamp friction Pn0 = this.Pt; this.Pt = this.max(-maxPt, this.min(Pn0 + dPn, maxPt)); dPn = this.Pt - Pn0; // Apply contact impulse this.impulse(this.ny * dPn, -this.nx * dPn); }; Contact.prototype.draw = function draw() { this.ctx.beginPath(); this.ctx.arc(this.px, this.py, 1.5, 0, 2 * Math.PI); this.ctx.fillStyle = "#F00"; this.ctx.fill(); }; return Contact; }(); var Body = function () { function Body(world, setup) { _classCallCheck(this, Body); var w = setup.w || 1.0; var h = setup.h || 1.0; this.px = setup.x || 0.0; this.py = setup.y || 0.0; this.vx = setup.vx || 0.0; this.vy = setup.vy || 0.0; this.hw = w * 0.5; this.hh = h * 0.5; this.rd = Math.sqrt(this.hw * this.hw + this.hh * this.hh); this.va = setup.angularVelocity || 0.0; this.ra = setup.rotation || 0.0; this.cos = Math.cos(this.ra); this.sin = Math.sin(this.ra); this.friction = setup.friction === undefined ? world.friction : setup.friction; var mass = setup.mass || Infinity; this.color = setup.color || "#FFF"; this.visible = setup.visible === undefined ? true : setup.visible; if (mass < Infinity) { this.iM = 1.0 / mass; this.iI = 1.0 / (mass * (w * w + h * h) / 12); } else { this.iM = 0.0; this.iI = 0.0; } this.dt = world.timeStep; this.gravity = setup.gravity || world.gravity; this.ctx = ctx; } Body.prototype.integrate = function integrate() { if (this.iM) { this.px += this.vx * this.dt; this.py += this.vy * this.dt; this.ra += this.va * this.dt; this.vy += this.gravity * this.dt; this.cos = Math.cos(this.ra); this.sin = Math.sin(this.ra); } }; Body.prototype.draw = function draw() { if (this.visible) { var chw = this.cos * this.hw; var shw = this.sin * this.hw; var chh = this.cos * this.hh; var shh = this.sin * this.hh; this.ctx.beginPath(); this.ctx.moveTo(this.px - chw + shh, this.py - shw - chh); this.ctx.lineTo(this.px + chw + shh, this.py + shw - chh); this.ctx.lineTo(this.px + chw - shh, this.py + shw + chh); this.ctx.lineTo(this.px - chw - shh, this.py - shw + chh); this.ctx.closePath(); this.ctx.strokeStyle = this.color; this.ctx.stroke(); } }; return Body; }(); var Joint = function () { function Joint(world, setup) { _classCallCheck(this, Joint); this.bA = setup.b1; this.bB = setup.b2; var c = undefined, s = undefined, x = undefined, y = undefined; c = this.bA.cos; s = this.bA.sin; x = setup.ax - this.bA.px; y = setup.ay - this.bA.py; this.a1x = c * x + s * y; this.a1y = -s * x + c * y; c = this.bB.cos; s = this.bB.sin; x = setup.ax - this.bB.px; y = setup.ay - this.bB.py; this.a2x = c * x + s * y; this.a2y = -s * x + c * y; this.m00 = 0.0; this.m01 = 0.0; this.m11 = 0.0; this.r1x = 0.0; this.r1y = 0.0; this.r2x = 0.0; this.r2y = 0.0; this.bsx = 0.0; this.bsy = 0.0; this.aix = 0.0; // accumulated impulse this.aiy = 0.0; var bias = setup.biasFactor ? setup.biasFactor : world.biasFactor; this.biasFactor = -bias * world.invDT; this.softness = setup.softness || 0.0; this.iM = this.bA.iM + this.bB.iM + this.softness; this.color = setup.color || "#888"; this.ctx = ctx; } Joint.prototype.preStep = function preStep() { // Pre-compute anchors, mass matrix, and bias. this.r1x = this.bA.cos * this.a1x - this.bA.sin * this.a1y; this.r1y = this.bA.sin * this.a1x + this.bA.cos * this.a1y; this.r2x = this.bB.cos * this.a2x - this.bB.sin * this.a2y; this.r2y = this.bB.sin * this.a2x + this.bB.cos * this.a2y; var Km00 = this.iM + this.bA.iI * this.r1y * this.r1y + this.bB.iI * this.r2y * this.r2y; var Km01 = -this.bA.iI * this.r1x * this.r1y + -this.bB.iI * this.r2x * this.r2y; var Km11 = this.iM + this.bA.iI * this.r1x * this.r1x + this.bB.iI * this.r2x * this.r2x; var det = 1.0 / (Km00 * Km11 - Km01 * Km01); this.m00 = det * Km11; this.m01 = -det * Km01; this.m11 = det * Km00; this.bsx = (this.bB.px + this.r2x - (this.bA.px + this.r1x)) * this.biasFactor; this.bsy = (this.bB.py + this.r2y - (this.bA.py + this.r1y)) * this.biasFactor; // Apply accumulated impulse. this.bA.vx -= this.aix * this.bA.iM; this.bA.vy -= this.aiy * this.bA.iM; this.bA.va -= this.bA.iI * (this.r1x * this.aiy - this.r1y * this.aix); this.bB.vx += this.aix * this.bB.iM; this.bB.vy += this.aiy * this.bB.iM; this.bB.va += this.bB.iI * (this.r2x * this.aiy - this.r2y * this.aix); }; Joint.prototype.applyImpulse = function applyImpulse() { var bx = this.bsx - (this.bB.vx + -this.bB.va * this.r2y - this.bA.vx - -this.bA.va * this.r1y) - this.aix * this.softness; var by = this.bsy - (this.bB.vy + this.bB.va * this.r2x - this.bA.vy - this.bA.va * this.r1x) - this.aiy * this.softness; var ix = this.m00 * bx + this.m01 * by; var iy = this.m01 * bx + this.m11 * by; this.bA.vx -= ix * this.bA.iM; this.bA.vy -= iy * this.bA.iM; this.bA.va -= this.bA.iI * (this.r1x * iy - this.r1y * ix); this.bB.vx += ix * this.bB.iM; this.bB.vy += iy * this.bB.iM; this.bB.va += this.bB.iI * (this.r2x * iy - this.r2y * ix); this.aix += ix; this.aiy += iy; }; Joint.prototype.draw = function draw() { this.ctx.beginPath(); this.ctx.strokeStyle = this.color; this.ctx.setLineDash([2, 2]); this.ctx.moveTo(this.bA.px, this.bA.py); this.ctx.lineTo(this.bA.px + this.r1x, this.bA.py + this.r1y); this.ctx.stroke(); this.ctx.setLineDash([]); }; return Joint; }(); var World = function () { function World(setup) { _classCallCheck(this, World); this.gravity = setup.gravity || 50; this.iterations = setup.iterations || 10; this.timeStep = setup.timeStep || 1 / 30; this.invDT = 1 / this.timeStep; this.friction = setup.friction || 0.2; this.allowedPenetration = setup.allowedPenetration || 0.01; this.biasFactor = setup.biasFactor || 0.2; this.relativeTol = setup.relativeTol || 0.95; this.absoluteTol = setup.absoluteTol || 0.01; this.bodies = []; this.joints = []; this.contacts = []; this.numContacts = 0; this.maxContacts = 0; this.ie = [0.0, 0.0, 0.0, 0.0]; this.c1 = [0.0, 0.0, 0.0, 0.0]; this.c2 = [0.0, 0.0, 0.0, 0.0]; this.bodyCount = 0; this.jointsCount = 0; this.abs = Math.abs; } World.prototype.addBody = function addBody(setup) { var body = new Body(this, setup); this.bodies.push(body); this.bodyCount = this.bodies.length; return body; }; World.prototype.addJoint = function addJoint(setup) { var joint = new Joint(this, setup); this.joints.push(joint); this.jointsCount = this.joints.length; return joint; }; World.prototype.step = function step() { var i = undefined, j = undefined, bi = undefined, bj = undefined, dx = undefined, dy = undefined, d = undefined, ct = undefined; // O(n^2) broad-phase this.numContacts = 0; for (i = 0; i < this.bodyCount; ++i) { bi = this.bodies[i]; for (j = i + 1; j < this.bodyCount; ++j) { bj = this.bodies[j]; if (bi.iM || bj.iM) { // circle vs circle collision dx = bj.px - bi.px; dy = bj.py - bi.py; d = bi.rd + bj.rd; if (dx * dx + dy * dy < d * d) { // OBB collision and update contact points this.collide(bi, bj, dx, dy); } } } } // Perform joints pre-steps for (i = 0; i < this.jointsCount; ++i) { this.joints[i].preStep(); } // Perform iterations for (j = 0; j < this.iterations; ++j) { for (i = 0; i < this.numContacts; ++i) { this.contacts[i].applyImpulse(); } for (i = 0; i < this.jointsCount; ++i) { this.joints[i].applyImpulse(); } } // integrate velocities for (i = 0; i < this.bodyCount; ++i) { this.bodies[i].integrate(); } // draw joints for (i = 0; i < this.jointsCount; ++i) { this.joints[i].draw(); } // draw bodies for (i = 0; i < this.bodyCount; ++i) { this.bodies[i].draw(); } }; // Box vertex and edge numbering: // // ^ y // | // e1 // v2 ------ v1 // | | // e2 | | e4 --> x // | | // v3 ------ v4 // e3 // The normal points from A to B World.prototype.collide = function collide(bA, bB, dpx, dpy) { // Setup var dax = bA.cos * dpx + bA.sin * dpy; var day = -bA.sin * dpx + bA.cos * dpy; var dbx = bB.cos * dpx + bB.sin * dpy; var dby = -bB.sin * dpx + bB.cos * dpy; var m00 = this.abs(bA.cos * bB.cos + bA.sin * bB.sin); var m01 = this.abs(-bA.sin * bB.cos + bA.cos * bB.sin); var m10 = this.abs(-bA.cos * bB.sin + bA.sin * bB.cos); var m11 = this.abs(bA.sin * bB.sin + bA.cos * bB.cos); // Box A faces var fAx = this.abs(dax) - bA.hw - (m00 * bB.hw + m10 * bB.hh); var fAy = this.abs(day) - bA.hh - (m01 * bB.hw + m11 * bB.hh); if (fAx > 0.0 || fAy > 0.0) return; // Box B faces var fBx = this.abs(dbx) - bB.hw - (m00 * bA.hw + m01 * bA.hh); var fBy = this.abs(dby) - bB.hh - (m10 * bA.hw + m11 * bA.hh); if (fBx > 0.0 || fBy > 0.0) return; // Find best axis var nx = undefined, ny = undefined; // Box A faces var axis = 0; var separation = fAx; if (dax > 0.0) { nx = bA.cos; ny = bA.sin; } else { nx = -bA.cos; ny = -bA.sin; } if (fAy > this.relativeTol * separation + this.absoluteTol * bA.hh) { axis = 1; separation = fAy; if (day > 0.0) { nx = -bA.sin; ny = bA.cos; } else { nx = bA.sin; ny = -bA.cos; } } // Box B faces if (fBx > this.relativeTol * separation + this.absoluteTol * bB.hw) { axis = 2; separation = fBx; if (dbx > 0.0) { nx = bB.cos; ny = bB.sin; } else { nx = -bB.cos; ny = -bB.sin; } } if (fBy > this.relativeTol * separation + this.absoluteTol * bB.hh) { axis = 3; separation = fBy; if (dby > 0.0) { nx = -bB.sin; ny = bB.cos; } else { nx = bB.sin; ny = -bB.cos; } } // Setup clipping plane data based on the separating axis var fnx = undefined, fny = undefined, snx = undefined, sny = undefined; var front = undefined, negSide = undefined, posSide = undefined, side = undefined; switch (axis) { case 0: fnx = nx; fny = ny; front = bA.px * fnx + bA.py * fny + bA.hw; snx = -bA.sin; sny = bA.cos; side = bA.px * snx + bA.py * sny; negSide = -side + bA.hh; posSide = side + bA.hh; this.computeIncidentEdge(this.ie, bB, fnx, fny); break; case 1: fnx = nx; fny = ny; front = bA.px * fnx + bA.py * fny + bA.hh; snx = bA.cos; sny = bA.sin; side = bA.px * snx + bA.py * sny; negSide = -side + bA.hw; posSide = side + bA.hw; this.computeIncidentEdge(this.ie, bB, fnx, fny); break; case 2: fnx = -nx; fny = -ny; front = bB.px * fnx + bB.py * fny + bB.hw; snx = -bB.sin; sny = bB.cos; side = bB.px * snx + bB.py * sny; negSide = -side + bB.hh; posSide = side + bB.hh; this.computeIncidentEdge(this.ie, bA, fnx, fny); break; case 3: fnx = -nx; fny = -ny; front = bB.px * fnx + bB.py * fny + bB.hh; snx = bB.cos; sny = bB.sin; side = bB.px * snx + bB.py * sny; negSide = -side + bB.hw; posSide = side + bB.hw; this.computeIncidentEdge(this.ie, bA, fnx, fny); break; } // clip other face with 5 box planes (1 face plane, 4 edge planes) // Clip to box side 1 if (this.clipSegmentToLine(this.c1, this.ie, -snx, -sny, negSide) < 2) return; // Clip to negative box side 1 if (this.clipSegmentToLine(this.c2, this.c1, snx, sny, posSide) < 2) return; // Now clipPoints2 contains the clipping points. // Due to roundoff, it is possible that clipping removes all points. var i = undefined, cpx = undefined, cpy = undefined, ct = undefined; var friction = Math.sqrt(bA.friction * bB.friction); for (i = 0; i < 2; ++i) { cpx = this.c2[i * 2]; cpy = this.c2[i * 2 + 1]; separation = fnx * cpx + fny * cpy - front; if (separation < 0) { if (this.numContacts < this.maxContacts) { // reuse existing contact ct = this.contacts[this.numContacts]; } else { // create new contact ct = new Contact(this); this.contacts.push(ct); this.maxContacts++; } // update contact and pre-step ct.update(bA, bB, separation, nx, ny, friction, cpx - fnx * separation, cpy - fny * separation); this.numContacts++; } } }; World.prototype.clipSegmentToLine = function clipSegmentToLine(vO, vI, nx, ny, offset) { // Start with no output points var numOut = 0; // Calculate the distance of end points to the line var distance0 = nx * vI[0] + ny * vI[1] - offset; var distance1 = nx * vI[2] + ny * vI[3] - offset; // If the points are behind the plane if (distance0 <= 0.0) { vO[numOut * 2] = vI[0]; vO[numOut * 2 + 1] = vI[1]; numOut++; } if (distance1 <= 0.0) { vO[numOut * 2] = vI[2]; vO[numOut * 2 + 1] = vI[3]; numOut++; } // If the points are on different sides of the plane if (distance0 * distance1 < 0.0) { // Find intersection point of edge and plane var interp = distance0 / (distance0 - distance1); vO[numOut * 2] = vI[0] + interp * (vI[2] - vI[0]); vO[numOut * 2 + 1] = vI[1] + interp * (vI[3] - vI[1]); ++numOut; } return numOut; }; World.prototype.computeIncidentEdge = function computeIncidentEdge(ie, b, nx, ny) { // The normal is from the reference box. Convert it // to the incident boxe's frame and flip sign. var nrx = -(b.cos * nx + b.sin * ny); var nry = -(-b.sin * nx + b.cos * ny); if (this.abs(nrx) > this.abs(nry)) { if (nrx > 0.0) { ie[0] = b.hw; ie[1] = -b.hh; ie[2] = b.hw; ie[3] = b.hh; } else { ie[0] = -b.hw; ie[1] = b.hh; ie[2] = -b.hw; ie[3] = -b.hh; } } else { if (nry > 0.0) { ie[0] = b.hw; ie[1] = b.hh; ie[2] = -b.hw; ie[3] = b.hh; } else { ie[0] = -b.hw; ie[1] = -b.hh; ie[2] = b.hw; ie[3] = -b.hh; } } var x = undefined, y = undefined; x = ie[0]; y = ie[1]; ie[0] = b.px + b.cos * x - b.sin * y; ie[1] = b.py + b.sin * x + b.cos * y; x = ie[2]; y = ie[3]; ie[2] = b.px + b.cos * x - b.sin * y; ie[3] = b.py + b.sin * x + b.cos * y; }; return World; }(); var Canvas = function () { function Canvas(resx, resy) { var _this = this; _classCallCheck(this, Canvas); this.elem = document.createElement('canvas'); this.resx = resx; this.resy = resy; this.left = 0; this.top = 0; this.ctx = this.elem.getContext('2d'); document.body.appendChild(this.elem); this.resize(); window.addEventListener('resize', function () { return _this.resize(); }, false); if (!this.ctx.setLineDash) { this.ctx.setLineDash = function () {}; } } Canvas.prototype.resize = function resize() { var o = this.elem; this.width = this.elem.width = this.resx; this.height = this.elem.height = this.resy; for (this.left = 0, this.top = 0; o != null; o = o.offsetParent) { this.left += o.offsetLeft; this.top += o.offsetTop; } }; return Canvas; }(); var Pointer = function () { function Pointer(canvas) { var _this2 = this; _classCallCheck(this, Pointer); this.x = 0; this.y = 0; this.canvas = canvas; window.addEventListener('mousemove', function (e) { return _this2.move(e); }, false); canvas.elem.addEventListener('touchmove', function (e) { return _this2.move(e); }, false); } Pointer.prototype.move = function move(e) { var touchMode = e.targetTouches, pointer = undefined; if (touchMode) { e.preventDefault(); pointer = touchMode[0]; } else pointer = e; this.x = (-this.canvas.left + pointer.clientX) * this.canvas.resx / this.canvas.elem.offsetWidth; this.y = (-this.canvas.top + pointer.clientY) * this.canvas.resy / this.canvas.elem.offsetHeight; }; return Pointer; }(); var canvas = new Canvas(1200, 600); var ctx = canvas.ctx; var pointer = new Pointer(canvas); function run() { requestAnimationFrame(run); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.lineWidth = 1.5; world.step(); } // init the world function init() { var timeStep = 1 / 30; world = new World({ gravity: 40, iterations: 20, timeStep: timeStep, friction: 0.3, allowedPenetration: 0.05, biasFactor: 0.2, relativeTol: 0.95, absoluteTol: 0.01 }); // ground var ground = world.addBody({ x: 600, y: 649, w: 1200, h: 100, mass: Infinity, friction: 3.8, visible: false }); // side walls world.addBody({ x: -50, y: 0, w: 100, h: 1200, mass: Infinity, friction: 3.8, visible: false }); world.addBody({ x: 1250, y: 0, w: 100, h: 1200, mass: Infinity, friction: 3.8, visible: false }); // lot of small boxes for (var i = 0; i < 40; i++) { for (var j = 0; j < 10; j++) { world.addBody({ x: 300 + i * 16, y: -200 + j * 16, w: 12, h: 12, mass: 5, vy: -150 + j * 5, color: "#f80" }); } } // A suspension bridge var numPlanks = 15; var mass = 50.0; var frequencyHz = 0.8; var dampingRatio = 0.7; // frequency in radians var omega = 2.0 * Math.PI * frequencyHz; // damping coefficient var d = 2.0 * mass * dampingRatio * omega; // spring stifness var k = mass * omega * omega; // magic formulas var softness = 1.0 / (d + timeStep * k); var biasFactor = timeStep * k / (d + timeStep * k); var p = ground, b = undefined; for (var i = 0; i < numPlanks; ++i) { b = world.addBody({ x: 250 + 50 * i, y: 200, w: 45, h: 12, mass: mass, friction: 1, color: "#888" }); if (p) { world.addJoint({ b1: b, b2: p, ax: -50 + 250 + 50 * i, ay: 200, softness: softness, biasFactor: biasFactor }); } p = b; } world.addJoint({ b1: b, b2: ground, ax: 250 + 50 * numPlanks, ay: 200, softness: softness, biasFactor: biasFactor }); // 2 Pendulum for (var i = 200; i <= 1000; i += 800) { var bb = world.addBody({ x: i, y: 300, w: 50, h: 50, mass: 40 }); var bc = world.addBody({ x: i, y: 400, w: 50, h: 50, mass: 40 }); world.addJoint({ b1: bb, b2: ground, ax: i, ay: 200 }); world.addJoint({ b1: bc, b2: bb, ax: i, ay: 300 }); bc.vx = 100 * Math.random() - 50; } world.addBody({ x: 400, y: 0, w: 50, h: 50, mass: 100 }); world.addBody({ x: 600, y: 0, w: 50, h: 50, mass: 100 }); world.addBody({ x: 800, y: 0, w: 50, h: 50, mass: 100 }); } // let's start var world = undefined; init(); run(); // add more box on click / touch window.addEventListener('mousedown', function (e) { return down(e); }, false); window.addEventListener('touchstart', function (e) { return down(e); }, false); function down(e) { pointer.move(e); e.preventDefault(); var bc = world.addBody({ x: pointer.x, y: pointer.y, w: boxSize, h: boxSize, mass: mass, gravity: grav, color: color }); } // some options var boxSize = undefined, color = undefined, grav = undefined, mass = undefined; radio(document.getElementById("large")); function radio(b) { switch (b.value) { case "large": boxSize = 50; color = "#FFF"; grav = 50; mass = 100; break; case "small": boxSize = 12; color = "#f80"; grav = 50; mass = 40; break; case "antigravity": boxSize = 12; color = "#08f"; grav = -50; mass = 20; break; } return false; }
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>Box2d Lite in JavaScript-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号