Deep Sea Prawn
Pelagic prawn anatomy showing articulated catenary abdomen somites, undulating wave sensory antennae, and metachronal pleopod swimming strokes.
60 FPS • Canvas 2D
Click + Drag to interact with field
</>
Full Executable Algorithm Code
204 lines
7634 chars
// 028 - Deep Sea Prawn (creatures)
// 1:1 Original algorithm engine source
function createDeepSeaPrawn() {
return {
setup() {
},
render(context, timeState, params) {
const { ctx, width, height } = context;
const speed = Number(params.swimSpeed || 1.3);
const antennaLength = Number(params.antennaLength || 200);
const t = timeState.time * speed;
ctx.fillStyle = "#04060b";
ctx.fillRect(0, 0, width, height);
const cx = width * 0.48 + Math.cos(t * 0.7) * (width * 0.06);
const cy = height * 0.48 + Math.sin(t * 1.2) * (height * 0.05);
const prawnScale = Math.min(width, height) / 500;
for (let side = -1; side <= 1; side += 2) {
ctx.beginPath();
const antRootX = cx - 35 * prawnScale;
const antRootY = cy - 25 * prawnScale + side * 4;
ctx.moveTo(antRootX, antRootY);
const antSteps = 36;
for (let i = 1; i <= antSteps; i++) {
const normI = i / antSteps;
const antX = antRootX - normI * antennaLength * prawnScale;
const antWave = Math.sin(t * 3 - normI * 5 + side) * (20 * normI * prawnScale);
const antY = antRootY - Math.pow(normI, 1.4) * (75 * prawnScale) + side * (normI * 38 * prawnScale) + antWave;
ctx.lineTo(antX, antY);
}
ctx.strokeStyle = hsla(14, 95, 72, 0.85);
ctx.lineWidth = 1.3;
ctx.stroke();
ctx.beginPath();
ctx.moveTo(antRootX, antRootY);
ctx.lineTo(antRootX - 35 * prawnScale, antRootY - 14 * prawnScale);
ctx.strokeStyle = "rgba(251, 146, 60, 0.6)";
ctx.lineWidth = 2 * prawnScale;
ctx.stroke();
}
const SEGMENTS = 6;
let prevSegX = cx;
let prevSegY = cy;
for (let s = 0; s < SEGMENTS; s++) {
const segmentArchAngle = 0.35 + Math.sin(t * 2) * 0.15;
const segDist = 24 * prawnScale;
const segX = prevSegX + Math.cos(segmentArchAngle * s * 0.4) * segDist;
const segY = prevSegY + Math.sin(segmentArchAngle * s * 0.4) * segDist * 0.9;
ctx.save();
ctx.translate((prevSegX + segX) / 2, (prevSegY + segY) / 2);
ctx.rotate(segmentArchAngle * s * 0.35);
const segW = (28 - s * 2.8) * prawnScale;
const segH = (34 - s * 3.5) * prawnScale;
ctx.beginPath();
ctx.ellipse(0, 0, segW, segH, 0.2, 0, Math.PI * 2);
const somiteGrad = ctx.createRadialGradient(0, -segH * 0.3, 2, 0, 0, segW);
somiteGrad.addColorStop(0, hsla(12 + s * 4, 92, 55, 0.9));
somiteGrad.addColorStop(1, hsla(6 + s * 4, 90, 42, 0.9));
ctx.fillStyle = somiteGrad;
ctx.fill();
ctx.strokeStyle = hsla(24 + s * 4, 95, 75, 0.9);
ctx.lineWidth = 1.8;
ctx.stroke();
const paddlePhase = t * 6 - s * 0.8;
const paddleAngle = Math.sin(paddlePhase) * 0.6 + 0.45;
const padLen = 22 * prawnScale;
const pad1X = Math.cos(paddleAngle) * padLen;
const pad1Y = Math.sin(paddleAngle) * padLen;
ctx.beginPath();
ctx.moveTo(0, segH * 0.45);
ctx.lineTo(pad1X, segH * 0.45 + pad1Y);
ctx.strokeStyle = hsla(16, 95, 75, 0.85);
ctx.lineWidth = 2.2 * prawnScale;
ctx.stroke();
const pad2X = Math.cos(paddleAngle + 0.25) * (padLen * 0.85);
const pad2Y = Math.sin(paddleAngle + 0.25) * (padLen * 0.85);
ctx.beginPath();
ctx.moveTo(0, segH * 0.45);
ctx.lineTo(pad2X, segH * 0.45 + pad2Y);
ctx.strokeStyle = hsla(22, 95, 70, 0.7);
ctx.lineWidth = 1.6 * prawnScale;
ctx.stroke();
ctx.restore();
prevSegX = segX;
prevSegY = segY;
}
ctx.save();
ctx.translate(prevSegX, prevSegY);
ctx.rotate(0.6 + Math.sin(t * 2) * 0.15);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(38 * prawnScale, 0);
ctx.strokeStyle = hsla(12, 100, 75, 0.95);
ctx.lineWidth = 2.4 * prawnScale;
ctx.stroke();
for (let f = -2; f <= 2; f++) {
if (f === 0) continue;
ctx.beginPath();
ctx.moveTo(0, 0);
const fanAngle = f * 0.28;
const fanLen = 34 * prawnScale;
ctx.lineTo(Math.cos(fanAngle) * fanLen, Math.sin(fanAngle) * fanLen);
ctx.strokeStyle = hsla(18 + Math.abs(f) * 6, 95, 70, 0.9);
ctx.lineWidth = 2.8 * prawnScale;
ctx.stroke();
}
ctx.restore();
ctx.save();
ctx.translate(cx, cy);
ctx.beginPath();
ctx.ellipse(-15 * prawnScale, -5 * prawnScale, 40 * prawnScale, 30 * prawnScale, -0.15, 0, Math.PI * 2);
ctx.fillStyle = hsla(8, 92, 48, 0.95);
ctx.fill();
ctx.strokeStyle = hsla(25, 95, 72, 0.95);
ctx.lineWidth = 2.4;
ctx.stroke();
ctx.beginPath();
ctx.moveTo(-45 * prawnScale, -14 * prawnScale);
ctx.lineTo(-105 * prawnScale, -32 * prawnScale);
ctx.lineTo(-45 * prawnScale, -2 * prawnScale);
ctx.fillStyle = hsla(10, 95, 55, 0.95);
ctx.fill();
ctx.strokeStyle = hsla(28, 100, 78, 0.95);
ctx.lineWidth = 2;
ctx.stroke();
for (let tooth = 1; tooth <= 6; tooth++) {
const normT = tooth / 7;
const tx = (-48 - normT * 50) * prawnScale;
const ty = (-15 - normT * 15) * prawnScale;
ctx.beginPath();
ctx.moveTo(tx, ty);
ctx.lineTo(tx + 2, ty - 6 * prawnScale);
ctx.strokeStyle = "#fef08a";
ctx.lineWidth = 1.6;
ctx.stroke();
}
ctx.fillStyle = "#05070d";
ctx.beginPath();
ctx.arc(-38 * prawnScale, -18 * prawnScale, 5.5 * prawnScale, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = "#38bdf8";
ctx.lineWidth = 1.6;
ctx.stroke();
for (let p = 0; p < 5; p++) {
const legAngle = -0.4 + p * 0.22 + Math.sin(t * 3 + p) * 0.15;
const legBaseX = (-28 + p * 9) * prawnScale;
const legBaseY = 20 * prawnScale;
const legKneeX = legBaseX + Math.cos(legAngle) * (22 * prawnScale);
const legKneeY = legBaseY + Math.sin(legAngle) * (26 * prawnScale);
const legTipX = legKneeX + 14 * prawnScale;
const legTipY = legKneeY + 22 * prawnScale;
ctx.beginPath();
ctx.moveTo(legBaseX, legBaseY);
ctx.lineTo(legKneeX, legKneeY);
ctx.lineTo(legTipX, legTipY);
ctx.strokeStyle = hsla(18, 92, 65, 0.85);
ctx.lineWidth = 2 * prawnScale;
ctx.stroke();
}
ctx.restore();
}
};
}
// Default parameters from content metadata
const defaultParams = [
{
"key": "swimSpeed",
"label": "Swimming Frequency",
"type": "range",
"min": 0.5,
"max": 2.5,
"step": 0.1,
"defaultValue": 1.3,
"description": "Pleopod metachronal beat speed"
},
{
"key": "antennaLength",
"label": "Antenna Span",
"type": "range",
"min": 100,
"max": 320,
"step": 20,
"defaultValue": 200,
"description": "Sensory whip extension length"
}
];
if (!window.__art_instances) window.__art_instances = {};
if (!window.__art_instances['deep-sea-prawn']) {
const inst = typeof createDeepSeaPrawn === 'function' ? createDeepSeaPrawn() : null;
if (inst && inst.setup) {
inst.setup({ ctx, width, height, dpr: 1, aspectRatio: width / height }, defaultParams);
}
window.__art_instances['deep-sea-prawn'] = inst;
}
const instance = window.__art_instances['deep-sea-prawn'];
if (instance && instance.render) {
instance.render(
{ ctx, width, height, dpr: 1, aspectRatio: width / height },
{ time, deltaTime: dt, frameCount: Math.floor(time * 60), fps: 60 },
defaultParams
);
} Edit in Interactive Playground
Zero Dependencies • Standalone Canvas 2D
ƒ
Mathematical Formulation
high
Analytical Equation
ps=p0+i=1∑sLi[cos(i⋅Δθ(t))sin(i⋅Δθ(t))],θpleopod(t)=Apsin(ωt−s⋅ϕ)
Click to expand
∑
Deep Sea Prawn
Full Mathematical System • creatures
100%
Complete System of Equations
[Governing Law][Discrete Progression][Domain & Space][Parameter State]ps=p0+i=1∑sLi[cos(i⋅Δθ(t))sin(i⋅Δθ(t))],θpleopod(t)=Apsin(ωt−s⋅ϕ)antenna=−s⋅L−s1.4⋅70+sin(3t−5s)⋅18s,pleopod=sin(6t−0.8s)⋅0.6x∈R2,t∈R+,ω∈[0,2π]λswimSpeed=1.3(Swimming Frequency),λantennaLength=200(Antenna Span)
ps=p0+i=1∑sLi[cos(i⋅Δθ(t))sin(i⋅Δθ(t))],θpleopod(t)=Apsin(ωt−s⋅ϕ)
Computational Implementation (JavaScript Engine Equivalent)
antenna = -s*L - s^1.4*70 + sin(3t - 5s)*18s, pleopod = sin(6t - 0.8s)*0.6 Compact Formula
antenna = -s*L - s^1.4*70 + sin(3t - 5s)*18s, pleopod = sin(6t - 0.8s)*0.6 Mathematical Tags
#prawn
#shrimp
#creatures
#segmented
#biomechanics
#marine
Author: Math Art Core Target: 60 FPS
Press ESC or F to exit