spring-rope-to-rope-gravity.js

total 0
used 0
limit 0
/* categories: springs files: ../point_src/core/head.js ../point_src/pointpen.js ../point_src/pointdraw.js ../point_src/math.js ../point_src/extras.js ../point_src/point-content.js ../point_src/pointlistpen.js ../point_src/pointlist.js ../point_src/events.js ../point_src/point.js ../point_src/distances.js ../point_src/dragging.js ../point_src/stage.js ../point_src/stagepen.js ../point_src/automouse.js ../point_src/functions/springs.js ../point_src/functions/clamp.js ../point_src/setunset.js ../point_src/stroke.js ../point_src/rope.js ../point_src/collisionbox.js ../point_src/gravity.js */ const stringLength = 200 const heavyStep = function(followPoint, mouse, gravity, damping=.9, dotDamping=.2, forceMultiplier=.1, forceValue=undefined) { // Apply gravity to the follow point's vertical velocity // Calculate the vector from the mouse to the follow point // let dx = followPoint.x - mouse.x ; // let dy = followPoint.y - mouse.y ; let dx = mouse.x - followPoint.x; let dy = mouse.y - followPoint.y; // Calculate the current distance between the follow point and the mouse let distance = Math.sqrt(dx * dx + dy * dy); // Set the follow point's position to be exactly on the circumference of the string length // const force = (distance - stringLength) * 0.01; // Tweak this factor as needed // If the distance exceeds the string length, we need to constrain the follow point if (distance > stringLength) { // Normalize the direction vector dx /= distance; dy /= distance; if(dotDamping!==false) { // Adjust the velocity so that it reflects the string tension let dotProduct = (followPoint.vx * dx + followPoint.vy * dy) * dotDamping; followPoint.vx -= dotProduct * dx; followPoint.vy -= dotProduct * dy; } if(forceMultiplier!==false){ const force = forceValue? forceValue: (distance - stringLength) * forceMultiplier; // Tweak this factor as needed followPoint.vx += force * dx; followPoint.vy += force * dy; } } // Apply gravity if(gravity){ followPoint.vy += gravity.y; followPoint.vx += gravity.x; } // Update the follow point's position based on its velocity followPoint.x += followPoint.vx; followPoint.y += followPoint.vy; if(damping) { // Apply damping continuously to smooth the motion followPoint.vx *= damping; followPoint.vy *= damping; } }; class Balloon { defaults = { // gravity: .2 gravity: {x:.01, y: -.03} , visibleRopeGravity: {x:0, y:0.02} , ropePointLength: 20 , segmentLength: 10 , invMass: .3 , color: '#990000' , knotColor: '#225555' , ropeColor: '#AAA' , radius: 10 // , position: [1,1] } constructor(settings={}){ Object.assign(this, this.defaults, settings) this.points = PointList.generate.random(10, [100, 200], [0, 0, 2, 0]) this.points.forEach((p)=>{ p.update({vx: 0, vy:0, radius: 2 }) }); if(this.position) { this.mounted() } } mounted(initPos=this.position) { // this.ropePointLength = 20; // this.segmentLength = 10; // this.gravity = -.31; // this.gravity2D = gravity2D // let initPos = this.center.copy() this.points = this.ropePoints(initPos, this.ropePointLength * .4) this.points2 = this.ropePoints(initPos, this.ropePointLength) this.points.each.radius = 2 // let penUlt = this.points[this.points.length - 3] // penUlt.invMass = 200 let lastPoint = this.points.last() lastPoint.invMass = this.invMass lastPoint.radius = this.radius this.ropeReactor = new RopeReactor() this.visibleRopeReactor = new RopeReactor() this.points[0].copy(initPos.add(10,100)) this.points2[0].copy(initPos.add(10,100)) // this.visibleRopeReactor.pin(0) this.ropeReactor.pin(0) this.visibleRopeReactor.pin( this.points2.length-1 , this.points[this.points.length - 1] ) // this.visibleRopeReactor.pin(5) } ropePoints(initPos, ropePointLength){ let points = Array.from({ length: ropePointLength }, () => ({ x: initPos.x, y: initPos.y, oldX: initPos.x, oldY: initPos.y, })); // points[9].invMass = .01 return new PointList(...points).cast() } get head() { return this.points.last() } get handle() { return this.points[0] } step(){ /* A viscous fluid, applied through 2d invMass*/ // this.applyPhysics2(this.points, this.gravity2D, [1, this.points.length-1]); let ropeReactor = this.ropeReactor let visibleRopeReactor = this.visibleRopeReactor /* Rope like mass physics.*/ ropeReactor.applyPhysics(this.points, this.gravity); visibleRopeReactor.applyPhysics(this.points2, this.visibleRopeGravity) // ropeReactor.applyPhysics2(this.points, this.gravity2D) /* Different solving methods */ // this.solveConstraints1(this.points, this.segmentLength); // this.solveConstraints2(this.points, this.segmentLength); ropeReactor.solveConstraints3(this.points, this.segmentLength * 2.5); visibleRopeReactor.solveConstraints3(this.points2, this.segmentLength); } draw(ctx) { // this.clear(ctx); // this.points2[0].xy = this.points[0].xy this.step() // ctx.fillStyle = '#999' // ctx.font = 'normal 30px lexend deca' // ctx.textAlign = 'center' // this.points.pen.indicator(ctx); // this.points.pen.line(ctx, {color:'#444'}); this.points2.pen.quadCurve(ctx, this.ropeColor); // this.points2.pen.line(ctx, {color:'#AAA'}); this.points[0].pen.indicator(ctx) // last.lookAt(penUlt)//, Math.PI *.5) // last.pen.indicator(ctx) // penUlt.pen.indicator(ctx) // last.pen.indicator(ctx, {color: '#770000'}) // let penUlt = this.points[this.points.length - 3] // penUlt.pen.fill(ctx, this.knotColor) this.points.pen.fill(ctx, this.knotColor) let last = this.points.last() last.pen.fill(ctx, {'color': this.color}) // last.text.label(ctx, 'Polypoint') } } class MainStage extends Stage { // canvas = document.getElementById('playspace'); canvas = 'playspace' mounted(){ this.pinPoint = new Point(200, 200) this.points = new PointList( new Point({ x: 150, y: 230 , radius: 4 , vx: .1, vy: 0 , mass: 5 }) , new Point({ x: 350, y: 200 , vx: 2, vy: 0 , radius: 4 , mass: 5 }) , new Point({ x: 250, y: 270 , vx: .4, vy: -1 , radius: 4 , mass: 5 }) , new Point({ x: 260, y: 290 , vx: .4, vy: -1 , radius: 4 , mass: 5 }) ) this.balloon = new Balloon() this.balloon.mounted(this.center.copy().add(50)) this.dragging.addPoints(...this.points, this.pinPoint, this.balloon.handle, this.balloon.head) this.dragging.onWheel = this.onWheel.bind(this) this.dragging.onDragStart = this.onDragStart.bind(this) this.dragging.onDragEnd = this.onDragEnd.bind(this) this.showBraces = false this.showPoints = true this.showOuter = true this.fillBall = false this.showBall = false this.blobColor = 'green' this.braceColor = 'red' this.restLength = 40 this.springConstant = .4 this.dampingFactor = 0.99 // Adjust this value between 0 and 1 let gp = new Point(0,3) this.collisionBox = new CollisionBox(this.points) this.gravityBox = new GravityReactor(gp, this.points) // this.gravityBox.points.push(this.pinpo) } onDragStart(ev, p) { this.dragPoint = p } onDragEnd(ev, p) { this.dragPoint = undefined } onWheel(ev, p) { p.mass = p.radius } draw(ctx){ this.clear(ctx) this.collisionBox.shuffle() let mouse = Point.mouse.position let ps = this.points; let sv = this.dragPoint != undefined? [this.dragPoint]: []; const lockedPoints = new Set(sv)//ps[0]]); // Lock pointA in place this.gravityBox.step(1, lockedPoints) heavyStep(ps[0],this.pinPoint, this.gravityBox.gravityPoint, .99) const rLen = this.restLength const springConstant = this.springConstant const damping = this.dampingFactor const deltaTime = .2 const extra = 2 this.balloon.draw(ctx) // cross brace springs this.points[0].spring.to(this.points[2] , rLen * 3 , springConstant * extra , .99 , lockedPoints , deltaTime ) this.points[1].spring.to(this.points[3] , rLen * 3 , springConstant * extra , .99 , lockedPoints , deltaTime ) ps.spring.loop(rLen, springConstant, damping, lockedPoints, deltaTime) if(this.fillBall) { this.points.draw.quadCurve(ctx, true) this.pen.fill(ctx, {color: this.blobColor}) } if(this.showBall) { this.points.pen.quadCurve(ctx, { loop: true, color: this.blobColor}) } // cross braces. if(this.showBraces) { this.points[0].pen.line(ctx, this.points[2], this.braceColor) this.points[1].pen.line(ctx, this.points[3], this.braceColor) } this.pinPoint.pen.fill(ctx, this.blobColor) this.showOuter && this.points.pen.line(ctx, {color: this.blobColor}) this.showPoints && this.points.pen.fill(ctx, this.blobColor) this.showOuter && this.points[0].pen.line(ctx, this.points[3], this.blobColor) } } stage = MainStage.go(/*{ loop: true }*/)
Run
Meta Data
imports ()
files ('../point_src/core/head.js', '../point_src/pointpen.js', '../point_src/pointdraw.js', '../point_src/math.js', '../point_src/extras.js', '../point_src/point-content.js', '../point_src/pointlistpen.js', '../point_src/pointlist.js', '../point_src/events.js', '../point_src/point.js', '../point_src/distances.js', '../point_src/dragging.js', '../point_src/stage.js', '../point_src/stagepen.js', '../point_src/automouse.js', '../point_src/functions/springs.js', '../point_src/functions/clamp.js', '../point_src/setunset.js', '../point_src/stroke.js', '../point_src/rope.js', '../point_src/collisionbox.js', '../point_src/gravity.js')
unused_keys ('title',)
unknown_keys ('categories',)
categories ['springs']
filepath_exists True
path spring-rope-to-rope-gravity.js
filepath spring-rope-to-rope-gravity.js
clean_files ('../point_src/core/head.js', '../point_src/pointpen.js', '../point_src/pointdraw.js', '../point_src/math.js', '../point_src/extras.js', '../point_src/compass.js', '../point_src/center.js', '../point_src/point-content.js', '../point_src/pointlistpen.js', '../point_src/pointlistdraw.js', '../point_src/pointlistgradient.js', '../point_src/pointlistshape.js', '../point_src/pointlistgenerator.js', '../point_src/unpack.js', '../point_src/pointlist.js', '../point_src/events.js', '../point_src/relative-xy.js', '../point_src/pointcast.js', '../point_src/point.js', '../point_src/distances.js', '../point_src/protractor.js', '../point_src/text/beta.js', '../point_src/dragging.js', '../point_src/stage-resize.js', '../point_src/functions/resolve.js', '../point_src/stage.js', '../point_src/stagepen.js', '../point_src/automouse.js', '../point_src/functions/springs.js', '../point_src/functions/clamp.js', '../point_src/setunset.js', '../point_src/stroke.js', '../point_src/rope.js', '../point_src/collisionbox.js', '../point_src/gravity.js')
markdown {'html': '', 'content': 'categories: springs\nfiles:\n ../point_src/core/head.js\n ../point_src/pointpen.js\n ../point_src/pointdraw.js\n ../point_src/math.js\n ../point_src/extras.js\n ../point_src/point-content.js\n ../point_src/pointlistpen.js\n ../point_src/pointlist.js\n ../point_src/events.js\n ../point_src/point.js\n ../point_src/distances.js\n ../point_src/dragging.js\n ../point_src/stage.js\n ../point_src/stagepen.js\n ../point_src/automouse.js\n ../point_src/functions/springs.js\n ../point_src/functions/clamp.js\n ../point_src/setunset.js\n ../point_src/stroke.js\n ../point_src/rope.js\n ../point_src/collisionbox.js\n ../point_src/gravity.js'}