point
class Point {
/**
*
* @param {number} x
* @param {number} y
* @param {number=} vx
* @param {number=} vy
* @param {number=} radius
*/
constructor(x, y, vx, vy, radius) {
this.pos = new Vector(x, y);
this.oldpos = new Vector(x + (vx || 0), y + (vy || 0));
this.bounce = 0.99;
this.friction = 0.97;
this.groundFriction = 0.7;
this.gravity = new Vector(0, 1);
this.pinned = false;
this.radius = radius || 5;
this.color = '#e62a4f';
this.mass = 1;
this.sticks = [];
// this.behaviors = [];
this.forceAcc = 1;
this.uid = ''
}
/**
*
* @param {Vector} g
*/
setGravity(g) {
this.gravity = g;
return this;
}
/**
*
* @param {number} f
*/
setFriction(f) {
this.friction = f;
return this;
}
/**
*
* @param {number} f
*/
setGroundFriction(f) {
this.groundFriction = f;
return this;
}
/**
*
* @param {number} b
*/
setBounce(b) {
this.bounce = b;
return this;
}
/**
*
* @param {number} f
* @returns {Point}
*/
setForceAcc(f) {
this.forceAcc = f;
return this;
}
/**
*
* @param {number} m
* @returns {Point}
*/
setMass(m) {
this.mass = m;
return this;
}
/**
*
* @param {number} radius
* @returns {Point}
*/
setRadius(radius) {
this.radius = radius;
return this;
}
/**
* @param {string} color
* @returns {Point}
*/
setColor(color) {
this.color = color;
return this;
}
/**
* @param {Vector} vel
* @returns {Point}
*/
setVelocity(vel) {
this.oldpos.setXY(vel.x, vel.y);
return this;
}
/**
* @returns {Point}
*/
pin() {
this.pinned = true;
return this;
}
/**
* @returns {Point}
*/
unpin() {
this.pinned = false;
return this;
}
resetVelocity() {
this.oldpos.setXY(this.pos.x, this.pos.y);
}
/**
*
* @param {number} angle
* @param {number} offset
*/
rotate(angle, offset) {
let x = offset.x + (this.pos.x - offset.x) * Math.cos(angle) - (this.pos.y - offset.y) * Math.sin(angle);
let y = offset.y + (this.pos.x - offset.x) * Math.sin(angle) + (this.pos.y - offset.y) * Math.cos(angle);
this.pos.setXY(x, y);
}
/**
*
* @param {Point} p
* @param {number} radius
* @param {number} strength
*/
resolveBehaviors(p, radius = this.radius, strength = this.forceAcc) {
var delta = Vector.sub(this.pos, p.pos);
var dist = delta.magSq();
let magR = radius * radius;
if (dist < magR) {
var f = delta.normalizeTo(1 - (dist / magR)).mult(strength);
this.applyForce(f);
}
}
/**
*
* @param {number|Vector} f
*/
applyForce(f) {
this.pos.add(f);
}
/**
*
* @param {number} x
* @param {number} y
* @param {number} time
* @param {number} radius
* @param {number} speed
*/
addMotor(x, y, time, radius, speed) {
this.pos.x = x + radius * Math.cos(time * speed);
this.pos.y = y + radius * Math.sin(time * speed);
}
/**
* @param {Verly} verlyInstance
*/
constrain(verlyInstance) {
// if (this.pos.y > HEIGHT - 1) {
// this.pos.y = HEIGHT - 1;
// }
// if (this.pos.x < 0) {
// this.pos.x = 0;
// }
// if (this.pos.x > WIDTH - 1) {
// this.pos.x = WIDTH - 1;
// }
// let vel = Vector.sub(this.pos, this.oldpos);
if (this.pos.x > verlyInstance.WIDTH - this.radius) {
this.pos.x = verlyInstance.WIDTH - this.radius;
// this.oldpos.x = (this.pos.x + vel.x) * this.bounce;
}
if (this.pos.x < this.radius) {
this.pos.x = this.radius;
// this.oldpos.x = (this.pos.x + vel.x) * this.bounce;
}
if (this.pos.y > verlyInstance.HEIGHT - this.radius) {
this.pos.y = verlyInstance.HEIGHT - this.radius;
// this.oldpos.y = (this.pos.y + vel.y) * this.bounce;
}
if (this.pos.y < this.radius) {
this.pos.y = this.radius;
// this.oldpos.y = (this.pos.y + vel.y) * this.bounce;
}
};
/**
* @param {Verly} verlyInstance
*/
update(verlyInstance) {
if (this.pinned) return;
let vel = Vector.sub(this.pos, this.oldpos);
vel.mult(this.friction);
// if the point touches the ground set groundFriction
if (this.pos.y >= verlyInstance.HEIGHT - this.radius && vel.magSq() > 0.000001) {
var m = vel.mag();
vel.x /= m;
vel.y /= m;
vel.mult(m * this.groundFriction);
}
this.oldpos.setXY(this.pos.x, this.pos.y);
this.pos.add(vel);
this.pos.add(this.gravity);
}
/**
* @param {CanvasRenderingContext2D} ctx
*/
render(ctx) {
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.pos.x, this.pos.y, this.radius, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
}
}
export default Point;
stick
class Stick {
/**
* creates a stick between two Point
* takes optional length and stiffness
* @param {Point} p1
* @param {Point} p2
* @param {number=} length
* @param {number=} stiffness
* @param {boolean=} hidden
*/
constructor(p1, p2, length, stiffness, hidden) {
this.startPoint = p1;
this.endPoint = p2;
this.stiffness = stiffness || 2;
this.color = '#f5476a';
this.hidden = hidden;
if (!length) {
this.length = this.startPoint.pos.dist(this.endPoint.pos);
} else {
this.length = length;
}
this.startPoint.sticks.push(this);
this.endPoint.sticks.push(this);
}
/**
*
* @param {number=} stepCoef
*/
update(stepCoef) {
// not gonna use vectors for performance optimization
// let dx = this.endPoint.pos.x - this.startPoint.pos.x;
// let dy = this.endPoint.pos.y - this.startPoint.pos.y;
// let dist = Math.sqrt(dx * dx + dy * dy);
// let diff = this.length - dist;
// let percent = diff / dist / 2;
// let offsetx = (dx * percent);
// let offsety = (dy * percent);
// if (!this.startPoint.pinned) {
// this.startPoint.pos.x -= offsetx;
// this.startPoint.pos.y -= offsety;
// }
// if (!this.endPoint.pinned) {
// this.endPoint.pos.x += offsetx;
// this.endPoint.pos.y += offsety;
// }
// ----- algo two
// algo three
let dx = this.endPoint.pos.x - this.startPoint.pos.x;
let dy = this.endPoint.pos.y - this.startPoint.pos.y;
let dist = Math.sqrt(dx * dx + dy * dy);
let diff = (this.length - dist) / dist * this.stiffness;
let offsetx = dx * diff * 0.5;
let offsety = dy * diff * 0.5;
// calculate mass
let m1 = this.startPoint.mass + this.endPoint.mass;
let m2 = this.startPoint.mass / m1;
m1 = this.endPoint.mass / m1;
if (!this.startPoint.pinned) {
this.startPoint.pos.x -= offsetx * m1;
this.startPoint.pos.y -= offsety * m1;
}
if (!this.endPoint.pinned) {
this.endPoint.pos.x += offsetx * m2;
this.endPoint.pos.y += offsety * m2;
}
// calculate mass
// var m1 = this.startPoint.mass + this.endPoint.mass;
// var m2 = this.startPoint.mass / m1;
// m1 = this.endPoint.mass / m1;
// var normal = Vector.sub(this.startPoint.pos, this.endPoint.pos);
// var m = normal.magSq();
// let diff = ((this.length * this.length) - m);
// normal.mult((diff / m) * this.stiffness * stepCoef);
// if (!this.startPoint.pinned) {
// this.startPoint.pos.add(normal);
// }
// if (!this.endPoint.pinned) {
// this.endPoint.pos.sub(normal);
// }
}
/**
* @param {string} color
* @returns {Stick}
*/
setColor(color) {
this.color = color;
return this;
}
/**
* @param {number} length
* @returns {Stick}
*/
setLength(length) {
this.length = length;
return this;
}
/**
* @param {number} value
* @returns {Stick}
*/
setStiffness(value) {
this.stiffness = value;
return this;
}
/**
* @param {boolean} value
* @returns {Stick}
*/
setHidden(value) {
this.hidden = value;
return this;
}
/**
*
* @param {CanvasRenderingContext2D} ctx
*/
render(ctx) {
if (this.hidden) return;
ctx.beginPath();
ctx.strokeStyle = this.color;
ctx.moveTo(this.startPoint.pos.x, this.startPoint.pos.y);
ctx.lineTo(this.endPoint.pos.x, this.endPoint.pos.y);
ctx.stroke();
ctx.closePath();
}
}
export default Stick;
Comentarios