Hi I have a visual trail. A vertex from history vector positions.
I want this trail to be transitioning from full alpha at the beginning and 0 alpha at its end.
When I do this with individual ellipses for the history array it works but vertex seems to only allow 1 alpha value.
The ellipse version does not look like a trail.
How can I achieve a vertex with a smooth alpha transition?
Here is my code. The important part is in the show function. When I comment out the vertex and enable the ellipse part (currently commented out) The opacity does what it should but it looks to rough with the ellipses:
let vehicle;
let maxSpeed = 20;
let maxForce = 20;
let slowRadius = 80;
let sliders = [];
let target;
let targetRadius;
let waveSpeedSlider;
let waveCheckbox;
let minHeight = 8;
let maxHeight = 40;
let alpha = 255;
function setup() {
createCanvas(windowWidth, windowHeight);
vehicle = new Vehicle(
createVector(width / 2, height / 2, 0),
maxSpeed,
maxForce,
slowRadius
);
target = {
pos: createVector(width / 2, height / 2.5, 0),
isBeingDragged: false,
};
sliders.push(createSlider(0, 40, maxSpeed, 1));
sliders.push(createSlider(1, 40, maxForce, 1));
sliders.push(createSlider(1, 500, slowRadius, 10));
sliders.push(createSlider(0, height, height / 2, 1));
for (let i = 0; i < sliders.length; i++) {
sliders[i].position(50, 50 + i * 50);
sliders[i].style("width", "200px");
sliders[i].addClass("mySliders");
sliders[i].input(updateValues);
}
let sliderLabels = ["Max Speed", "Max Force", "Slow Down Radius", "Target Z"];
for (let i = 0; i < sliders.length; i++) {
let label = createP(sliderLabels[i]);
label.position(50, 50 + i * 50);
label.style("color", "white");
}
waveSpeedSlider = createSlider(0, 0.1, 0.01, 0.001);
waveSpeedSlider.position(50, 50 + sliders.length * 50);
waveSpeedSlider.style("width", "200px");
waveCheckbox = createCheckbox(
"Use square mod = abrupt height change target",
false
);
waveCheckbox.position(50, 70 + sliders.length * 50);
waveCheckbox.style("color", "white");
let targetLabel = createP("target = Red");
targetLabel.position(50, 100 + sliders.length * 50);
targetLabel.style("color", "rgb(248,63,82)");
let vehicleLabel = createP("vehicle/follower = Blue");
vehicleLabel.position(50, 130 + sliders.length * 50);
vehicleLabel.style("color", "rgb(2,158,211)");
let listenerLabel = createP("Listener");
listenerLabel.position(width / 2 - 25, height / 2 + 5);
listenerLabel.style("color", "white");
}
function draw() {
background(50);
let waveSpeed = waveSpeedSlider.value();
let waveValue;
if (waveCheckbox.checked()) {
waveValue = (floor(frameCount * waveSpeed) % 2) * 2 - 1;
} else {
waveValue = sin(frameCount * waveSpeed);
}
let mappedWaveValue = map(waveValue, -1, 1, 0, height);
sliders[3].value(mappedWaveValue);
target.pos.z = mappedWaveValue;
targetRadius = map(target.pos.z, 0, height, minHeight, maxHeight);
fill(248, 63, 82);
ellipse(target.pos.x, target.pos.y, targetRadius);
noStroke();
fill(255, 30);
ellipse(target.pos.x, target.pos.y, slowRadius * 2);
let d = dist(mouseX, mouseY, target.pos.x, target.pos.y);
if (d < targetRadius) {
cursor(HAND);
} else {
cursor(ARROW);
}
let steering = vehicle.arrive(target);
vehicle.applyForce(steering);
vehicle.update();
vehicle.show();
fill(255);
ellipse(width / 2, height / 2, 20);
textAlign(RIGHT, TOP);
fill(2, 158, 211);
text(
`Vehicle Position - X: ${vehicle.pos.x.toFixed(
2
)}, Y: ${vehicle.pos.y.toFixed(2)}, Z: ${vehicle.pos.z.toFixed(2)}`,
width - 20,
20
);
fill(248, 63, 82);
text(
`Target Position - X: ${target.pos.x.toFixed(2)}, Y: ${target.pos.y.toFixed(
2
)}, Z: ${target.pos.z.toFixed(2)}`,
width - 20,
40
);
}
function mousePressed() {
let d = dist(mouseX, mouseY, target.pos.x, target.pos.y);
if (d < targetRadius) {
target.isBeingDragged = true;
}
}
function mouseDragged() {
if (target.isBeingDragged) {
target.pos.x = mouseX;
target.pos.y = mouseY;
target.pos.z = sliders[3].value();
}
}
function mouseReleased() {
target.isBeingDragged = false;
}
function updateValues() {
maxSpeed = sliders[0].value();
maxForce = sliders[1].value();
slowRadius = sliders[2].value();
target.pos.z = sliders[3].value();
vehicle.maxSpeed = maxSpeed;
vehicle.maxForce = maxForce;
vehicle.slowRadius = slowRadius;
}
class Vehicle {
constructor(pos, maxSpeed, maxForce, slowRadius) {
this.pos = pos;
this.vel = createVector(0, 0, 0);
this.acc = createVector(0, 0, 0);
this.maxSpeed = maxSpeed;
this.maxForce = maxForce;
this.slowRadius = slowRadius;
this.history = [];
this.alpha = alpha;
}
arrive(target) {
let desired = p5.Vector.sub(target.pos, this.pos);
let d = desired.mag();
desired.normalize();
if (d < this.slowRadius) {
let m = map(d, 0, this.slowRadius, 0, this.maxSpeed);
desired.mult(m);
} else {
desired.mult(this.maxSpeed);
}
let steer = p5.Vector.sub(desired, this.vel);
steer.limit(this.maxForce);
return steer;
}
applyForce(force) {
this.acc.add(force);
}
update() {
this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.mult(0);
var v = createVector(this.pos.x, this.pos.y);
this.history.push(v);
if (this.history.length > 20) {
this.history.splice(0, 1);
// this.alpha -= 10;
}
}
show() {
// Draw the vehicle
push();
translate(this.pos.x, this.pos.y);
let radius = map(this.pos.z, 0, height, minHeight, maxHeight);
fill(2, 158, 211);
ellipse(0, 0, radius);
pop();
// Draw the trail
push();
beginShape();
let numOfSegments = this.history.length;
for (let i = 0; i < numOfSegments; i++) {
let pos = this.history[i];
let segmentAlpha = map(i, 0, numOfSegments - 1, 0, 200); // Decreases from 255 to 50
noFill();
strokeWeight(radius);
stroke(2, 158, 211, segmentAlpha);
vertex(pos.x, pos.y);
// fill(2, 158, 211,segmentAlpha);
// ellipse(pos.x, pos.y, radius);
}
endShape();
pop();
}
}