const vec = p5.Vector; class Leg { constructor() { this.base = new vec(0, 0); this.end = new vec(0, 0); this.interPos = new vec(0, 0); this.ikJoint = new IKJoint(8, 8); this.repositionDist = 50; this.moveSpeed = 0.4; } moveTo(startX, startY, endX, endY) { // mover final de pierna cuando quede esta fuera del rango } getPoints() { return this.ikJoint.points; } } class IKJoint { constructor(numSegments, pointDist) { this.origin = new vec(0, 0); this.points = []; for (let i = 0; i < numSegments + 1; i++) { this.points.push(new ConstraintPoint(0, 0, pointDist, 0.5)); } this.pointDist = pointDist; this.iterations = 20; } moveStart(targetX, targetY) { // empezar a mover desde el punto 0 } moveEnd(targetX, targetY) { // empezar a mover desde el punto final } moveTo(origX, origY, targetX, targetY) { // alternar movimientos for (let i = 0; i < this.iterations; i++) { this.moveEnd(targetX, targetY); this.moveStart(origX, origY); } } } class ConstraintPoint { constructor(x, y, size, angleConstraint = 0.2) { this.size = size; this.pos = new vec(x, y); this.forward = new vec(0, 0); this.angleConstraint = angleConstraint; } getRel(angleOffset, dist) { // devolver vector relativo al punto con un angulo y distancia, completar return this.pos; } follow(targetX, targetY, parentForward = null) { // mover punto dentro de los constraints, completar let target = new vec(targetX, targetY); if (parentForward) { // si tenemos punto anterior, limitar angulos, completar } // asignar sigiente forward, completar this.forward = null; this.pos = target; } } function drawPoints(points, sizes, turnSegments = 10) { beginShape(); // dibujar vertice, completar let numPoints = points.length; let head = points[0]; let tail = points[numPoints - 1]; // debug push() noFill(); for (let i = 0; i < numPoints;i++) { circle(head.pos.x, head.pos.y, sizes[i] * 2); } pop() endShape(CLOSE); } function drawGills(basePoint, sign) { push(); // dibujar forma de branquias, completar pop(); } let numPoints = 0; const bodySizes = [60, 55, 50, 40, 45, 47, 50, 47, 45, 42, 39, 35, 30, 25, 22, 17, 13]; const legSizes = Array.from({ length: 20 }, () => 15); const bodyPoints = []; const leg1 = new Leg(); const leg2 = new Leg(); const leg3 = new Leg(); const leg4 = new Leg(); let mouseInter = new vec(0, 0); let baseColor; let gillColor; let lastBlinkTime = 0; let nextBlinkDelay = 3000; let blinkDuration = 150; function setup() { createCanvas(displayWidth, displayHeight); numPoints = bodySizes.length; for (let i = 0; i < numPoints; i++) { let pt = new ConstraintPoint(400, 400, 20); bodyPoints.push(pt); } baseColor = color(249, 182, 249) gillColor = color(243, 158, 189) } function draw() { background(150); mouseInter.lerp(new vec(mouseX, mouseY), 0.01); let time = millis(); // fisica bodyPoints[0].follow(mouseInter.x, mouseInter.y); for (let i = 1; i < numPoints; i++) { let prevPoint = bodyPoints[i - 1]; bodyPoints[i].follow(prevPoint.pos.x, prevPoint.pos.y, prevPoint.forward); let tailStart = Math.floor(numPoints / 2); } let legEndDist = 70; let baseJointL1 = bodyPoints[2]; let baseL1 = baseJointL1.getRel(-HALF_PI, 30); let endL1 = baseJointL1.getRel(-HALF_PI, legEndDist); let baseR1 = baseJointL1.getRel(HALF_PI, 30); let endR1 = baseJointL1.getRel(HALF_PI, legEndDist); let baseJointL2 = bodyPoints[6]; let baseL2 = baseJointL2.getRel(-HALF_PI, 30); let endL2 = baseJointL2.getRel(-HALF_PI, legEndDist); let baseR2 = baseJointL2.getRel(HALF_PI, 30); let endR2 = baseJointL2.getRel(HALF_PI, legEndDist); leg1.moveTo(baseL1.x, baseL1.y, endL1.x, endL1.y); leg2.moveTo(baseR1.x, baseR1.y, endR1.x, endR1.y); leg3.moveTo(baseL2.x, baseL2.y, endL2.x, endL2.y); leg4.moveTo(baseR2.x, baseR2.y, endR2.x, endR2.y); // dibujar fill(baseColor); stroke(0); strokeWeight(2); drawPoints(leg1.getPoints(), legSizes); drawPoints(leg2.getPoints(), legSizes); drawPoints(leg3.getPoints(), legSizes); drawPoints(leg4.getPoints(), legSizes); let currentBodySizes = [...bodySizes]; // animacion de respirar, completar drawPoints(bodyPoints, currentBodySizes); // dibujar aleta, completar let p1 = bodyPoints[4].pos; let p2 = bodyPoints[6].pos; let p3 = bodyPoints[8].pos; let p4 = bodyPoints[10].pos; drawGills(bodyPoints[2], 1); drawGills(bodyPoints[2], -1); let eye1 = bodyPoints[0].getRel(HALF_PI / 2, 45); let eye2 = bodyPoints[0].getRel(-HALF_PI / 2, 45); push(); fill(0); noStroke(); circle(eye1.x, eye1.y, 12); circle(eye2.x, eye2.y, 12); pop(); }