*,html,body{margin:0px;padding:0px;overflow:hidden;}
let msec = 0, prevInitMsec = 0, prevNow = 0;
let plotLabels = ["Posição (y)", "Velocidade (y)", "Aceleração (y)"];
let plotStartMsec = 0, plotData = [[], [], []];
const gravity = 9.81;
const plotScale = 25;
const timeScale = 3;
let apple;
// Cores do tema Dracula
const colors = {
background: "#282a36",
currentLine: "#44475a",
foreground: "#f8f8f2",
comment: "#6272a4",
cyan: "#8be9fd",
green: "#50fa7b",
orange: "#ffb86c",
pink: "#ff79c6",
purple: "#bd93f9",
red: "#ff5555",
yellow: "#f1fa8c"
};
function setup() {
createCanvas(windowWidth, windowHeight);
apple = new Body(1);
prevNow = window.performance.now();
}
function draw() {
clear();
background(colors.background);
ellapseTime();
let minWH = min(width, height);
// Renderiza a posição atual da maçã
push();
translate(min((width - minWH) / 2 + 32, width / 4), 32);
fill(colors.cyan);
ellipse(0, apple.position.y * plotScale, 24, 24);
pop();
// Plota o gráfico mostrando posição, velocidade e aceleração
let graphW = minWH - 64;
plotGraph(plotData, (width - graphW) / 2 + 32, 32, graphW, height - 64, 0, 8000, -(height - 64), 0, "Tempo", "Valores");
}
function ellapseTime() {
let ellapsedMsec = (window.performance.now() - prevNow) * timeScale;
prevNow = window.performance.now();
updateSimulation(ellapsedMsec / 2000);
msec += ellapsedMsec;
if (msec > prevInitMsec + 5000) {
apple = new Body(1);
plotData = [[], [], []];
prevInitMsec += 5000;
}
if (plotData[0].length == 0) {
plotStartMsec = msec;
}
let protMsec = msec - plotStartMsec;
plotData[0].push({x: protMsec * 2.5, y: -apple.position.y * plotScale});
plotData[1].push({x: protMsec * 2.5, y: -apple.velocity.y * plotScale});
plotData[2].push({x: protMsec * 2.5, y: -gravity * plotScale});
}
function updateSimulation(t) {
apple.applyForce(getForce(apple), t);
apple.update(t);
}
function getForce(o) {
return createVector(0, gravity).mult(o.mass);
}
function plotGraph(data, ox, oy, w, h, minX, maxX, minY, maxY, xLabel, yLabel) {
let left = ox - minX / (maxX - minX) * w;
let top = oy - maxY / (maxY - minY) * h;
let labelLeft = abs(left - ox) > abs(left + w - ox);
let labelTop = abs(top - oy) > abs(top + h - oy);
drawGrid(ox, oy, w, h, 10);
push();
noFill();
stroke(colors.comment);
line(left, oy, left + w, oy);
line(ox, top, ox, top + h);
const lineColors = [colors.yellow, colors.pink, colors.green];
for (let j = 0; j < data.length; j++) {
stroke(lineColors[j]);
beginShape();
for (let i = 0; i < data[j].length; i++) {
let x = ox + data[j][i].x / (maxX - minX) * w;
let y = oy - data[j][i].y / (maxY - minY) * h;
vertex(x, y);
}
endShape();
}
fill(colors.foreground);
drawLabel(labelLeft ? left : left + w, oy + (labelTop ? 16 : -8), xLabel, labelLeft ? LEFT : RIGHT);
drawLabel(ox, labelTop ? top : top + h, yLabel, labelLeft ? RIGHT : LEFT);
// Adiciona legenda
for (let i = 0; i < plotLabels.length; i++) {
fill(lineColors[i]);
stroke(lineColors[i]);
rect(ox + 10, oy + 20 + i * 20, 10, 10);
fill(colors.foreground);
drawLabel(ox + 25, oy + 30 + i * 20, plotLabels[i], LEFT);
}
pop();
}
class Body {
constructor(m) {
this.position = createVector(0, 0, 0);
this.velocity = createVector(0, 0, 0);
this.mass = m;
}
applyForce(f, t) {
this.velocity.add(f.copy().mult(t / this.mass));
}
update(t) {
this.position.add(this.velocity.copy().mult(t))
}
}
function drawGrid(ox, oy, w, h, steps) {
stroke(colors.currentLine);
let stepW = w / steps;
let stepH = h / steps;
for (let i = 1; i < steps; i++) {
line(ox + i * stepW, oy, ox + i * stepW, oy + h); // Vertical grid lines
line(ox, oy + i * stepH, ox + w, oy + i * stepH); // Horizontal grid lines
}
}
function drawLegend(x, y, colors) {
for (let i = 0; i < plotLabels.length; i++) {
fill(colors[i]);
stroke(colors[i]);
rect(x, y + 20 + i * 20, 10, 10);
fill(colors.foreground);
drawLabel(x + 20, y + 30 + i * 20, plotLabels[i], LEFT);
}
}
function drawLabel(x, y, label, align = CENTER) {
push();
strokeWeight(0);
textFont("monospace");
textSize(14);
textAlign(align);
if (align == LEFT) {x += 6;}
if (align == RIGHT) {x -= 6;}
text(label, x, y);
pop();
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
This Pen doesn't use any external CSS resources.