xxxxxxxxxx
279
let time = 0;
let helixSpeed = 30;
let segmentSize = 200;
let helixWidth = 100;
let helixCenter = 150;
let genesPerSegment = 3;
let geneArray = [];
let geneString = "";
let geneLoad = 0;
let rows = 50;
let Acol;
let Ccol;
let Tcol;
let Gcol;
let segments = Math.ceil((600 + segmentSize * 2) / segmentSize);
let animatedIndex = -1;
function initGeneArray() {
geneString = "";
geneLoad = 0;
if (geneArray.length < segments) {
for (let i = 0; i < segments * genesPerSegment * rows; i++) {
let gene;
let rand = Math.random();
if (rand < 0.25) gene = "AC";
if (rand >= 0.25 && rand < 0.5) gene = "CA";
if (rand >= 0.5 && rand < 0.75) gene = "TG";
if (rand >= 0.75) gene = "GT";
geneArray[i] = gene;
}
}
}
function setup() {
createCanvas(600, 600);
Acol = color(255, 30, 0);
Ccol = color(0, 255, 80);
Tcol = color(230, 145, 0);
Gcol = color(0, 100, 230);
initGeneArray();
}
let selectorPos = 0
let prevSelectorPos = 0
let selectorTransitionTime = 2
let selectorCooldown = 5
let selectorAnim = 0
let selectorAnimated = false
let selectorCooldownTime = 3
function draw() {
background(0, 0, 20);
time += round(deltaTime / 1000, 3);
push();
translate(-helixCenter, -300);
rotate(PI / 12);
translate(helixCenter, 300);
translate(150, 0);
translate(0, (-time * helixSpeed) % segmentSize);
let geneOffset = floor((time * helixSpeed) / segmentSize) * genesPerSegment;
// move selector
if((time - selectorCooldownTime > selectorCooldown || selectorPos < geneOffset + genesPerSegment) && !selectorAnimated){
prevSelectorPos = selectorPos
selectorPos = geneOffset + round(random(genesPerSegment,genesPerSegment*segments - 2*genesPerSegment))
selectorCooldownTime = time
}
noStroke()
fill(0,255,255)
let Sspace = segmentSize * 0.75;
let Sslot = (Sspace / genesPerSegment) * (selectorPos % genesPerSegment) + Sspace / (genesPerSegment * 2);
let Spos = floor((selectorPos - geneOffset) / 3) * segmentSize + segmentSize / 8 + Sslot;
if(time - selectorCooldownTime < selectorTransitionTime){
let PSspace = segmentSize * 0.75;
let PSslot = (Sspace / genesPerSegment) * (prevSelectorPos % genesPerSegment) + Sspace / (genesPerSegment * 2);
let PSpos = floor((prevSelectorPos - geneOffset) / 3) * segmentSize + segmentSize / 8 + Sslot;
let tSPos = PSpos + max(sin( ( (time - selectorCooldownTime) / selectorTransitionTime ) * (PI/2) ) * (Spos - PSpos), 0)
rect(helixCenter - (helixWidth/2) - 10, tSPos - 10 , helixWidth + 20, 20)
} else {
rect(helixCenter - (helixWidth/2) - 10, Spos - 10 , helixWidth + 20, 20)
}
// helix and genes
for (let i = 0; i < ceil((600 + segmentSize * 2) / segmentSize); i++) {
stroke(0, 255, 255); // helix color
line(
helixCenter,
(i - 1) * segmentSize,
helixCenter + helixWidth / 2,
(i - 1) * segmentSize + segmentSize / 8
);
line(
helixCenter,
(i - 1) * segmentSize,
helixCenter - helixWidth / 2,
(i - 1) * segmentSize + segmentSize / 8
);
line(
helixCenter + helixWidth / 2,
(i - 1) * segmentSize + segmentSize / 8,
helixCenter + helixWidth / 2,
(i - 1) * segmentSize + (segmentSize / 8) * 7
);
line(
helixCenter - helixWidth / 2,
(i - 1) * segmentSize + segmentSize / 8,
helixCenter - helixWidth / 2,
(i - 1) * segmentSize + (segmentSize / 8) * 7
);
line(
helixCenter + helixWidth / 2,
(i - 1) * segmentSize + (segmentSize / 8) * 7,
helixCenter,
i * segmentSize
);
line(
helixCenter - helixWidth / 2,
(i - 1) * segmentSize + (segmentSize / 8) * 7,
helixCenter,
i * segmentSize
);
// genes
let space = segmentSize * 0.75;
let slot;
let pos;
for (let g = 0; g < genesPerSegment; g++) {
switch (geneArray[geneOffset + i * genesPerSegment + g]) {
case "AC":
slot = (space / genesPerSegment) * g + space / (genesPerSegment * 2);
pos = (i - 1) * segmentSize + segmentSize / 8 + slot;
noStroke();
fill(Acol);
rect(
helixCenter - helixWidth / 2 + 5,
pos - 5,
helixWidth / 2 - 7.5,
10
);
fill(Ccol);
rect(helixCenter + 2.5, pos - 5, helixWidth / 2 - 7.5, 10);
break;
case "CA":
slot = (space / genesPerSegment) * g + space / (genesPerSegment * 2);
pos = (i - 1) * segmentSize + segmentSize / 8 + slot;
noStroke();
fill(Ccol);
rect(
helixCenter - helixWidth / 2 + 5,
pos - 5,
helixWidth / 2 - 7.5,
10
);
fill(Acol);
rect(helixCenter + 2.5, pos - 5, helixWidth / 2 - 7.5, 10);
break;
case "TG":
slot = (space / genesPerSegment) * g + space / (genesPerSegment * 2);
pos = (i - 1) * segmentSize + segmentSize / 8 + slot;
noStroke();
fill(Tcol);
rect(
helixCenter - helixWidth / 2 + 5,
pos - 5,
helixWidth / 2 - 7.5,
10
);
fill(Gcol);
rect(helixCenter + 2.5, pos - 5, helixWidth / 2 - 7.5, 10);
break;
case "GT":
slot = (space / genesPerSegment) * g + space / (genesPerSegment * 2);
pos = (i - 1) * segmentSize + segmentSize / 8 + slot;
noStroke();
fill(Gcol);
rect(
helixCenter - helixWidth / 2 + 5,
pos - 5,
helixWidth / 2 - 7.5,
10
);
fill(Tcol);
rect(helixCenter + 2.5, pos - 5, helixWidth / 2 - 7.5, 10);
break;
}
}
}
pop();
noStroke();
fill(220);
textSize(8);
text(geneString, 350, 100);
if (geneLoad < geneArray.length) {
if ((geneLoad + 1) % (segments * genesPerSegment) == 0) {
geneString += geneArray[geneLoad] + " \n";
} else {
geneString += geneArray[geneLoad] + " ";
}
geneLoad++;
}
textSize(15)
text(time - selectorCooldownTime, 20, 20)
}