I'm trying to set up a feather-looking particle system in processing. I am trying to base it off of some code I found on OpenProcessing. When I copy and paste the code into processing (using Java) I get an error saying "expecting SEMI, found 'points'.
I figured this was maybe because the code uses var and not int indicating that this would be Javascript code instead. So I switched the processing mode to p5.js, and it runs but the browser that opens is just a blank white screen.
Any help on getting this to run would be appreciated! Thanks!
The code is below:
var points = [];
var painting = false;
var strokeNumber = 0;
var scl = 6;
var cols, rows;
var inc = 0.1;
var zOff = 0;
var particles = [];
var flowField = [];
var saturation = [];
function setup() {
createCanvas(windowWidth, windowHeight);
// createCanvas(400, 400);
background(0);
pixelDensity(5);
cols = floor(width / scl);
rows = floor(height / scl);
flowField = Array(cols * rows);
saturation = Array(width * height).fill(0);
greateForceField();
}
function mousePressed() {
painting = true;
strokeNumber++;
}
function mouseReleased() {
painting = false;
}
function updateForceField(){
var v = createVector(mouseX, mouseY);
var vPrev = createVector(pmouseX, pmouseY);
v.sub(vPrev);
v.setMag(1);
var i = floor(mouseX / scl);
var j = floor(mouseY / scl);
var index = i * rows + j;
flowField[index] = v;
}
function showForceField(){
for(var i = 0; i < cols; i++){
for(var j = 0; j < rows; j++){
var index = i * rows + j;
var v = flowField[index];
stroke(0,50);
strokeWeight(1);
push();
translate(i * scl, j * scl);
rotate(v.heading());
line(0,0,scl,0);
pop();
}
}
}
function greateForceField(){
var xOff = 0;
for(var i = 0; i < cols; i++){
var yOff = 0;
for(var j = 0; j < rows; j++){
yOff += inc;
var angle = noise(xOff, yOff, zOff) * TWO_PI;
var v = p5.Vector.fromAngle(angle);
v.setMag(.1);
var index = i * rows + j;
flowField[index] = v;
}
xOff += inc;
}
// zOff += inc * 0.1;
}
function draw() {
// background(255);
// showForceField();
if(painting){
updateForceField();
var idx = mouseY * width + mouseX;
if(saturation[idx] < 10){
var r = 1+sqrt(sq(mouseX-pmouseX)+sq(mouseY-pmouseY));
for(var a = 0; a < 100; a++){
var particle = new Particle(mouseX+random()*r*cos(random(TWO_PI)), mouseY+random()*r*sin(random(TWO_PI)));
particles.push(particle);
}
saturation[idx] ++;
}
}
particles.filter(particle => particle.spread > 0).map(particle => {
particle.update();
particle.show();
// particle.edges();
particle.follow();
})
particles.map((particle, idx) => {
if(particle.spread <= 0){
particles.splice(idx,1);
}
});
}
function Particle(x,y){
this.pos = createVector(x,y);
// this.color = color(245, 225, 50);
// this.color = color(145, 225, 192);
this.color = color(255);
this.spread = 127;
this.spreadInc = this.spread/100;
this.prevPos = this.pos.copy();
this.vel = p5.Vector.random2D();
this.acc = createVector(0,0);
this.maxSpeed = 2;
this.update = function(){
this.spread -= this.spreadInc;
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
this.applyForce = function(force){
this.acc.add(force);
}
this.follow = function(){
var i = floor(this.pos.x / scl);
var j = floor(this.pos.y / scl);
var index = i * rows + j;
var force = flowField[index];
this.applyForce(force);
}
this.show = function(){
stroke(red(this.color),green(this.color),blue(this.color),this.spread);
strokeWeight(.3*this.spread/127);
// point(this.pos.x, this.pos.y);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.updatePrev = function(){
this.prevPos = this.pos.copy();
}
this.edges = function(){
if(this.pos.x > width) {
this.pos.x = 0;
this.updatePrev();
}
if(this.pos.x < 0){
this.pos.x = width;
this.updatePrev();
}
if(this.pos.y > height){
this.pos.y = 0;
this.updatePrev();
}
if(this.pos.y < 0) {
this.pos.y = height;
this.updatePrev();
}
}
}
This looks like javascript waaay more than java. I'm not exactly a buff in these matters, but... are you trying to run javascript as java?
If you are using the Processing IDE, look in the upper right corner. Do you see the word "Java" ?
Like this:
If this is the case, you might want to consider installing p5.js :
Click here and choose "Add mode":
Now search for p5.js and install it:
Now your code will compile. I'm not saying it'll work, though, but your current problem will be behind you. Have fun!
Related
//Editable Vars
let cols = 35;
let rows = 35;
let fps = 5;
//Declarations
let canvas;
let ctx;
let background;
let grid = new Array(cols);
let w;
let h;
let pathfinder;
let target;
let timer;
let renderQueue = [];
let canPathfind = true;
//Space Class
class Space{
constructor(x,y,c='lightgrey'){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.c = c;
}
draw(){
ctx.fillStyle = this.c;
ctx.strokeStyle = 'black';
ctx.fillRect(this.x * w, this.y * h, this.w, this.h);
ctx.rect(this.x * w, this.y * h, this.w, this.h);
ctx.stroke();
}
move(x,y){
if(x < 0 || x > cols-1 || y < 0|| y > rows-1){
return;
}
grid[this.x][this.y] = new Space(this.x,this.y);
renderQueue.push(grid[this.x][this.y]);
this.x = x;
this.y = y;
grid[this.x][this.y] = this;
renderQueue.push(grid[this.x][this.y]);
}
}
//Game-Run code
function gameStart(){
canvas = document.getElementById('gameCanvas');
ctx = canvas.getContext('2d');
w = canvas.width / cols;
h = canvas.height / rows;
createGrid();
pathfinder = new Space(randomInt(cols-1),randomInt(rows-1),'green');
grid[pathfinder.x][pathfinder.y] = pathfinder;
target = new Space(randomInt(cols-1),randomInt(rows-1),'red');
grid[target.x][target.y] = target;
drawGrid();
timer = setInterval(updateScreen, 1000/fps);
}
function restartGame(){
clearInterval(timer);
gameStart();
}
//Starts loading process on windows load
window.onload = gameStart();
//Checks all 8 possible move directions and calls pathfinder.move for best move
function pathfind(pathfinder, target){
if(!canPathfind) return;
let p = {x: pathfinder.x, y: pathfinder.y};
let t = {x: target.x, y: target.y};
let move = {x : 0, y : 0};
// 0,0 9,9
//if(p.x == t.x && p.y == t.y){
//restartGame();
//}
if(t.x - p.x >= 1){
move.x = 1;
}else if(t.x - p.x <= -1){
move.x = -1;
}else{
move.x = 0;
}
if(t.y - p.y >= 1){
move.y = 1;
}else if(t.y - p.y <= -1){
move.y = -1;
}else{
move.y = 0;
}
pathfinder.move(pathfinder.x + move.x, pathfinder.y + move.y);
}
function updateScreen(){
pathfind(pathfinder,target);
drawUpdatedSpaces();
}
function drawUpdatedSpaces(){
for(let i = 0; i < renderQueue.length; i++){
renderQueue[i].draw();
}
renderQueue = [];
}
function drawGrid(){
for(let i = 0; i < grid.length; i++){
for(let j = 0; j < grid[i].length; j++){
grid[i][j].draw();
}
}
}
//Creates grid and instantiates Space in every cell
function createGrid(){
for(let i = 0; i < grid.length; i++){
grid[i] = new Array(rows);
}
for(let i = 0; i < grid.length; i++){
for(let j = 0; j < grid[i].length; j++){
grid[i][j] = new Space(i,j);
}
}
}
// Returns distance to target from specified coords
function distanceFromTarget(x, y) {
return (Math.sqrt(Math.pow(Math.abs(x - target.x), 2) + (Math.pow(Math.abs(y - target.y), 2))));
}
// Returns random Integer between 0 and Max
function randomInt(max) {
return Math.floor(Math.random() * max);
}
It runs as expected which is great, but performance is super slow. That may be because I'm using jsfiddle to work on this while away from my personal PC setup, but is there a way to make this perform better? As of right now I can't move the grid size to >50 without it running extremely slow. I would love to eventually move to a 4k x 4k grid and create an auto-generating maze for the 'pathfinder' to pathfind through.
Thoughts/things I'm considering for performance:
Using HTML grid and updating via CSS instead of HTML5 Canvas
Only re-drawing cells that have changed (Implemented in the Space.move() function with array renderQueue)
literally re-doing everything in python :D
I've written this quick script for random moving lines for the background for my portfolio. It works smoothly alone but when I start working with other CSS animations and stuff, there's a frame drop at the beginning (later it runs smooth). At least on my PC, struggles on low-end PC.
Some tips to optimize it would be helpful.
Here's my code:
/*Random Line Render Script aka Mini Browser Crasher */
/*XD Can't Revise This Script. Rofl Drains Memory. May crash low-end pc :V */
var c = document.getElementById("graph");
var dimension = [document.documentElement.clientWidth, document.documentElement.clientHeight];
c.width = dimension[0];
var ctx = c.getContext("2d");
var ctx2 = c.getContext("2d");
var posx = [100, 200, 150, 100, 0];
var posy = [100, 200, 300, 100, -100];
var posx2 = [600, 400, 200, 600];
var posy2 = [500, 200, 100, 150, 500, 500];
var posx3 = [];
var posy3 = [];
/*Generate random values for array( random starting point ) */
for (var i = 0; i < 2; i++) {
posx2.push(500 + Math.round(Math.random() * 700));
posy2.push(Math.round(Math.random() * 900));
}
for (var i = 0; i < 5; i++) {
posx3.push(1000 + Math.round(Math.random() * 300));
posy3.push(0 + Math.round(Math.random() * 1000));
}
var posx_len = posx.length;
var posx2_len = posx2.length;
var posx3_len = posx3.length;
var xa, ya;
var opa = 1;
var amount = 0.01;
var sinang = 0;
var distance1 = 0;
var distance2 = 0;
document.body.addEventListener('mousemove', (function(event) {
xa = event.clientX;
ya = event.clientY;
}));
/*Render Lines */
function draw() {
ctx.clearRect(0, 0, 10000, 10000);
ctx.beginPath();
ctx.moveTo(posx[0], posy[0]);
for (var i = 0; i < posx_len; i++) {
ctx.lineTo(posx[i], posy[i]);
ctx.strokeStyle = 'rgba(255,255,255,' + opa + ')';
ctx.stroke();
ctx.arc(posx[i], posy[i], 5, 0, 2 * Math.PI, false);
}
if (opa > 1) {
amount = -0.01 * Math.random();
}
if (opa < 0) {
amount = 0.01 * Math.random();
}
opa = opa + amount;
ctx.moveTo(posx2[0], posy2[0]);
for (var i = 0; i < posx2_len; i++) {
ctx.lineTo(posx2[i], posy2[i]);
ctx.strokeStyle = 'rgba(255,255,255,' + opa + ')';
ctx.stroke();
ctx.arc(posx2[i], posy2[i], 5, 0, 2 * Math.PI, false);
}
ctx.moveTo(posx3[0], posy3[0]);
for (var i = 0; i < posx3_len; i++) {
ctx.lineTo(posx3[i], posy3[i]);
ctx.strokeStyle = 'rgba(255,255,255,' + opa + ')';
ctx.stroke();
ctx.arc(posx3[i], posy3[i], 5, 0, 2 * Math.PI, false);
}
sinang = sinang + 0.01;
/*Frame Render Ends here*/
/*Calculation for next frame*/
for (var i = 0; i < posx_len; i++) {
posx[i] = posx[i] + (Math.cos(sinang) * i) / 2; /* Sin curve for smooth value transition. Smooth assss Butter */
posy[i] = posy[i] + (Math.cos(sinang) * i) / 2;
/* Can't believe Distance Formula is useful ahaha */
distance1 = Math.sqrt(Math.pow((posx[i] - xa), 2) + Math.pow((posy[i] - ya), 2));
if (distance1 <= 500) {
ctx.moveTo(posx[i], posy[i]);
ctx.lineTo(xa, ya);
}
for (var j = 0; j < posx2_len; j++) {
distance12 = Math.sqrt(Math.pow((posx[i] - posx2[j]), 2) + Math.pow((posy[i] - posy2[j]), 2));
if (distance12 <= 500) {
ctx.moveTo(posx[i], posy[i]);
ctx.lineTo(posx2[j], posy2[j]);
}
}
for (var j = 0; j < posx3_len; j++) {
distance13 = Math.sqrt(Math.pow((posx[i] - posx3[j]), 2) + Math.pow((posy[i] - posy3[j]), 2));
if (distance13 <= 500) {
ctx.moveTo(posx[i], posy[i]);
ctx.lineTo(posx3[j], posy3[j]);
}
}
}
posx[posx.length - 1] = posx[0];
posy[posy.length - 1] = posy[0];
/*Repeat Above Steps. Should have done this in Multi-dimensional array. Ugh I feel sad now*/
for (var i = 0; i < posx2_len; i++) {
posx2[i] = posx2[i] + (Math.sin(sinang) * i) / 2;
posy2[i] = posy2[i] - (Math.sin(sinang) * i) / 2;
distance2 = Math.sqrt(Math.pow((posx2[i] - xa), 2) + Math.pow((posy2[i] - ya), 2));
if (distance2 <= 500) {
ctx.moveTo(posx2[i], posy2[i]);
ctx.lineTo(xa, ya);
}
for (var j = 0; j < posx3_len; j++) {
distance22 = Math.sqrt(Math.pow((posx2[i] - posx3[j]), 2) + Math.pow((posy2[i] - posy3[j]), 2));
if (distance22 <= 500) {
ctx.moveTo(posx2[i], posy2[i]);
ctx.lineTo(posx3[j], posy3[j]);
}
}
}
posx2[posx2.length - 1] = posx2[0];
posy2[posy2.length - 1] = posy2[0];
for (var i = 0; i < posx3_len; i++) {
posx3[i] = posx3[i] - (Math.sin(sinang) * i) / 1.2;
posy3[i] = posy3[i] - (Math.sin(sinang) * i) / 1.2;
distance2 = Math.sqrt(Math.pow((posx3[i] - xa), 2) + Math.pow((posy3[i] - ya), 2));
if (distance2 <= 500) {
ctx.moveTo(posx3[i], posy3[i]);
ctx.lineTo(xa, ya);
}
}
posx3[posx3.length - 1] = posx3[0];
posy3[posy3.length - 1] = posy3[0];
ctx.restore();
ctx.stroke();
window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);
body {
background: #1f1f1f;
}
<canvas height="1080px" width="1100px" id="graph">
</canvas>
So, what I've done is used square colliders instead of circular(distance formula) and it has faster runtime now. (not much but still)
<html>
<head>
</head>
<style>
body{
background: #1f1f1f;
}
canvas{
}
</style>
<body >
<canvas height="1080px" width="1100px" id="graph">
</canvas>
</body>
<script>
/*Random Line Render Script aka Mini Browser Crasher */
/*XD Can't Revise This Script. Rofl Drains Memory. May crash low-end pc :V */
var c = document.getElementById("graph");
var dimension = [document.documentElement.clientWidth, document.documentElement.clientHeight];
c.width = dimension[0];
var ctx = c.getContext("2d");
var posx = [100,200,150,100,0];
var posy = [100,200,300,100,-100];
var posx2 = [600,400,200,600];
var posy2 = [500,200,100,150,500,500];
var posx3 = [];
var posy3 = [];
/*Generate random values for array( random starting point ) */
for(var i=0; i<2;i++){
posx2.push(500+Math.round(Math.random()*700));
posy2.push(Math.round(Math.random()*900));
}
for(var i=0; i<5;i++){
posx3.push(1000+Math.round(Math.random()*300));
posy3.push(0+Math.round(Math.random()*1000));
}
var posx_len = posx.length;
var posx2_len = posx2.length;
var posx3_len = posx3.length;
var xa,ya;
var opa =1;
var amount = 0.01;
var sinang = 0;
var distance1 = 0;
var distance2 = 0;
var t1, t2;
document.body.addEventListener('mousemove', (function (event) {
xa = event.clientX;
ya = event.clientY;
}));
/*Render Lines */
function draw(){
t1 =performance.now();
ctx.clearRect(0, 0, 1920,1080);
ctx.beginPath();
ctx.moveTo(posx[0], posy[0]);
for(var i= 0; i<posx_len;i++){
ctx.lineTo(posx[i], posy[i]);
ctx.arc(posx[i],posy[i], 5, 0, 2 * Math.PI, false);
}
if(opa>1){
amount = -0.01*Math.random();
}
if(opa<0){
amount =0.01*Math.random();
}
opa =opa +amount;
ctx.moveTo(posx2[0], posy2[0]);
for(var i = 0; i<posx2_len;i++){
ctx.lineTo(posx2[i], posy2[i]);
ctx.arc(posx2[i],posy2[i], 5, 0, 2 * Math.PI, false);
}
ctx.moveTo(posx3[0], posy3[0]);
for(var i = 0; i<posx3_len;i++){
ctx.lineTo(posx3[i], posy3[i]);
ctx.arc(posx3[i],posy3[i], 5, 0, 2 * Math.PI, false);
}
sinang = sinang+0.01;
/*Frame Render Ends here*/
/*Calculation for next frame*/
for(var i = 0;i<posx_len;i++){
posx[i] = posx[i]+ (Math.cos(sinang)*i)/2;/* Sin curve for smooth value transition. Smooth assss Butter */
posy[i] = posy[i]+ (Math.cos(sinang)*i)/2;
/* Can't believe Distance Formula is useful ahaha */
if(Math.abs(posx[i]-xa)<500 && Math.abs(posy[i]-ya)<500){
ctx.moveTo(posx[i],posy[i]);
ctx.lineTo(xa, ya);
}
for(var j = 0;j<posx2_len;j++){
if(Math.abs(posx[i]-posx2[j])<500 && Math.abs(posy[i]-posy2[j])<500){
ctx.moveTo(posx[i],posy[i]);
ctx.lineTo(posx2[j], posy2[j]);
}
}
for(var j = 0;j<posx3_len;j++){
if(Math.abs(posx[i]-posx3[j])<500 && Math.abs(posy[i]-posy3[j])<500){
ctx.moveTo(posx[i],posy[i]);
ctx.lineTo(posx3[j], posy3[j]);
}
}
}
posx[posx.length-1]=posx[0];
posy[posy.length-1] = posy[0];
/*Repeat Above Steps. Should have done this in Multi-dimensional array. Ugh I feel sad now*/
for(var i = 0;i<posx2_len;i++){
posx2[i] = posx2[i]+ (Math.sin(sinang)*i)/2;
posy2[i] = posy2[i]-(Math.sin(sinang)*i)/2;
if(Math.abs(posx2[i]-xa)<500 && Math.abs(posy2[i]-ya)<500){
ctx.moveTo(posx2[i],posy2[i]);
ctx.lineTo(xa, ya);
}
for(var j = 0;j<posx3_len;j++){
if(Math.abs(posx2[i]-posx3[j])<500 && Math.abs(posy2[i]-posy3[j])<500){
ctx.moveTo(posx2[i],posy2[i]);
ctx.lineTo(posx3[j], posy3[j]);
}
}
}
posx2[posx2.length-1]=posx2[0];
posy2[posy2.length-1] = posy2[0];
for(var i = 0;i<posx3_len;i++){
posx3[i] = posx3[i]- (Math.sin(sinang)*i)/1.2;
posy3[i] = posy3[i]-(Math.sin(sinang)*i)/1.2;
if(Math.abs(posx3[i]-xa)<500 && Math.abs(posy3[i]-ya)<500){
ctx.moveTo(posx3[i],posy3[i]);
ctx.lineTo(xa, ya);
}
}
posx3[posx3.length-1]=posx3[0];
posy3[posy3.length-1] = posy3[0];
ctx.restore();
ctx.strokeStyle = 'rgba(255,255,255,'+opa+')';
ctx.stroke();
window.requestAnimationFrame(draw);
t2=performance.now();
console.log(t2-t1);
}
window.requestAnimationFrame(draw);
</script>
</html>
I have a large piece of code that draws feather-looking designs controlled by the mouse. This is using mouse pressed and mouseX, mouseY.
I would like the code to run and draw the feathers without the mouse being involved (ie. opening the canvas and having feathers automatically draw on the screen).
The full code is below:
var points = [];
var painting = false;
var strokeNumber = 0;
var scl = 6;
var cols, rows;
var inc = 0.1;
var zOff = 0;
var particles = [];
var flowField = [];
var saturation = [];
function setup() {
createCanvas(windowWidth, windowHeight);
// createCanvas(400, 400);
pixelDensity(5);
background(0);
cols = floor(width / scl);
rows = floor(height / scl);
flowField = Array(cols * rows);
saturation = Array(width * height).fill(0);
greateForceField();
}
function mousePressed() {
painting = true;
strokeNumber++;
}
function mouseReleased() {
painting = false;
}
function updateForceField(){
var v = createVector(mouseX, mouseY);
var vPrev = createVector(pmouseX, pmouseY);
v.sub(vPrev);
v.setMag(1);
var i = floor(mouseX / scl);
var j = floor(mouseY / scl);
var index = i * rows + j;
flowField[index] = v;
}
function showForceField(){
for(var i = 0; i < cols; i++){
for(var j = 0; j < rows; j++){
var index = i * rows + j;
var v = flowField[index];
stroke(0,50);
strokeWeight(1);
push();
translate(i * scl, j * scl);
rotate(v.heading());
line(0,0,scl,0);
pop();
}
}
}
function greateForceField(){
var xOff = 0;
for(var i = 0; i < cols; i++){
var yOff = 0;
for(var j = 0; j < rows; j++){
yOff += inc;
var angle = noise(xOff, yOff, zOff) * TWO_PI;
var v = p5.Vector.fromAngle(angle);
v.setMag(.1);
var index = i * rows + j;
flowField[index] = v;
}
xOff += inc;
}
// zOff += inc * 0.1;
}
function draw() {
// background(255);
// showForceField();
if(painting){
updateForceField();
var idx = mouseY * width + mouseX;
if(saturation[idx] < 10){
var r = 1+sqrt(sq(mouseX-pmouseX)+sq(mouseY-pmouseY));
for(var a = 0; a < 100; a++){
var particle = new Particle(mouseX+random()*r*cos(random(TWO_PI)), mouseY+random()*r*sin(random(TWO_PI)));
particles.push(particle);
}
saturation[idx] ++;
}
}
particles.filter(particle => particle.spread > 0).map(particle => {
particle.update();
particle.show();
// particle.edges();
particle.follow();
})
particles.map((particle, idx) => {
if(particle.spread <= 0){
particles.splice(idx,1);
}
});
}
function Particle(x,y){
this.pos = createVector(x,y);
// this.color = color(245, 225, 50);
// this.color = color(145, 225, 192);
this.color = color(255);
this.spread = 127;
this.spreadInc = this.spread/100;
this.prevPos = this.pos.copy();
this.vel = p5.Vector.random2D();
this.acc = createVector(0,0);
this.maxSpeed = 2;
this.update = function(){
this.spread -= this.spreadInc;
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
this.applyForce = function(force){
this.acc.add(force);
}
this.follow = function(){
var i = floor(this.pos.x / scl);
var j = floor(this.pos.y / scl);
var index = i * rows + j;
var force = flowField[index];
this.applyForce(force);
}
this.show = function(){
stroke(red(this.color),green(this.color),blue(this.color),this.spread);
strokeWeight(.3*this.spread/127);
// point(this.pos.x, this.pos.y);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.updatePrev = function(){
this.prevPos = this.pos.copy();
}
this.edges = function(){
if(this.pos.x > width) {
this.pos.x = 0;
this.updatePrev();
}
if(this.pos.x < 0){
this.pos.x = width;
this.updatePrev();
}
if(this.pos.y > height){
this.pos.y = 0;
this.updatePrev();
}
if(this.pos.y < 0) {
this.pos.y = height;
this.updatePrev();
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
Use 4 variables current_x, current_y, prev_x and prev_y instead of mosueX, mouseY, pmouseX and pmouseY.
var current_x=0, current_y=0, prev_x=0, prev_y=0;
function updateForceField(){
var v = createVector(current_x, current_y);
var vPrev = createVector(prev_x, prev_y);
v.sub(vPrev);
v.setMag(1);
var i = floor(current_x / scl);
var j = floor(current_y / scl);
var index = i * rows + j;
flowField[index] = v;
}
Instead of the state painting use a time interval. The time between 2 frames can be get from the built-in variable deltaTime (in milliseconds). Set the x and y positions by random values. e.g.:
var interval = 200; // 200 milliseconds
var sum_time = 0;
function draw() {
sum_time += deltaTime;
if(sum_time > interval){
sum_time = 0;
current_x = Math.floor(random(width));
current_y = Math.floor(random(height));
updateForceField();
prev_x = current_x;
prev_y = current_y;
var idx = current_y * width + current_x;
if(saturation[idx] < 10){
var r = 1+sqrt(sq(current_x-prev_x)+sq(current_y-prev_y));
for(var a = 0; a < 100; a++){
var particle = new Particle(current_x+random()*r*cos(random(TWO_PI)), current_y+random()*r*sin(random(TWO_PI)));
particles.push(particle);
}
saturation[idx] ++;
}
}
// [...]
}
See the example:
var points = [];
var painting = false;
var strokeNumber = 0;
var scl = 6;
var cols, rows;
var inc = 0.1;
var zOff = 0;
var particles = [];
var flowField = [];
var saturation = [];
function setup() {
//createCanvas(windowWidth, windowHeight);
createCanvas(500, 200);
pixelDensity(5);
background(0);
cols = floor(width / scl);
rows = floor(height / scl);
flowField = Array(cols * rows);
saturation = Array(width * height).fill(0);
greateForceField();
}
function mousePressed() {
painting = true;
strokeNumber++;
}
function mouseReleased() {
painting = false;
}
var current_x=0, current_y=0, prev_x=0, prev_y=0;
function updateForceField(){
var v = createVector(current_x, current_y);
var vPrev = createVector(prev_x, prev_y);
v.sub(vPrev);
v.setMag(1);
var i = floor(current_x / scl);
var j = floor(current_y / scl);
var index = i * rows + j;
flowField[index] = v;
}
function showForceField(){
for(var i = 0; i < cols; i++){
for(var j = 0; j < rows; j++){
var index = i * rows + j;
var v = flowField[index];
stroke(0,50);
strokeWeight(1);
push();
translate(i * scl, j * scl);
rotate(v.heading());
line(0,0,scl,0);
pop();
}
}
}
function greateForceField(){
var xOff = 0;
for(var i = 0; i < cols; i++){
var yOff = 0;
for(var j = 0; j < rows; j++){
yOff += inc;
var angle = noise(xOff, yOff, zOff) * TWO_PI;
var v = p5.Vector.fromAngle(angle);
v.setMag(.1);
var index = i * rows + j;
flowField[index] = v;
}
xOff += inc;
}
// zOff += inc * 0.1;
}
var interval = 200; // 200 milliseconds
var sum_time = 0;
function draw() {
// background(255);
// showForceField();
sum_time += deltaTime;
if(sum_time > interval){
sum_time = 0;
current_x = Math.floor(random(width));
current_y = Math.floor(random(height));
updateForceField();
prev_x = current_x;
prev_y = current_y;
var idx = current_y * width + current_x;
if(saturation[idx] < 10){
var r = 1+sqrt(sq(current_x-prev_x)+sq(current_y-prev_y));
for(var a = 0; a < 100; a++){
var particle = new Particle(current_x+random()*r*cos(random(TWO_PI)), current_y+random()*r*sin(random(TWO_PI)));
particles.push(particle);
}
saturation[idx] ++;
}
}
particles.filter(particle => particle.spread > 0).map(particle => {
particle.update();
particle.show();
// particle.edges();
particle.follow();
})
particles.map((particle, idx) => {
if(particle.spread <= 0){
particles.splice(idx,1);
}
});
}
function Particle(x,y){
this.pos = createVector(x,y);
// this.color = color(245, 225, 50);
// this.color = color(145, 225, 192);
this.color = color(255);
this.spread = 127;
this.spreadInc = this.spread/100;
this.prevPos = this.pos.copy();
this.vel = p5.Vector.random2D();
this.acc = createVector(0,0);
this.maxSpeed = 2;
this.update = function(){
this.spread -= this.spreadInc;
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
this.applyForce = function(force){
this.acc.add(force);
}
this.follow = function(){
var i = floor(this.pos.x / scl);
var j = floor(this.pos.y / scl);
var index = i * rows + j;
var force = flowField[index];
this.applyForce(force);
}
this.show = function(){
stroke(red(this.color),green(this.color),blue(this.color),this.spread);
strokeWeight(.3*this.spread/127);
// point(this.pos.x, this.pos.y);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.updatePrev = function(){
this.prevPos = this.pos.copy();
}
this.edges = function(){
if(this.pos.x > width) {
this.pos.x = 0;
this.updatePrev();
}
if(this.pos.x < 0){
this.pos.x = width;
this.updatePrev();
}
if(this.pos.y > height){
this.pos.y = 0;
this.updatePrev();
}
if(this.pos.y < 0) {
this.pos.y = height;
this.updatePrev();
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>
I'm practicing with JavaScript and p5, but when I tried to run this example on my browser locally, all I get is a black screen and the GUI. What I'm supposed to see is text being displayed via lines and some particle motion both on the screen and when I click my mouse. I double checked to make sure that the correct libraries have been included, and I re-downloaded the code from the tutorial multiple times. Right now, the only thing showing up on my screen is the GUI (and it also seems that the "message" control in the GUI doesn't work either). And just a fyi, I'm using Chrome.
HTML CODE:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style> body {padding: 0; margin: 0;} </style>
<script src="./libraries/p5.js"></script>
<script src="./libraries/dat.gui.min.js"></script>
<script src="./libraries/rune.js"></script>
<script src="./libraries/rune.font.js"></script>
<script src="./libraries/rune.font.js"></script>
<script src="sketch.js"></script>
</head>
<body>
</body>
</html>
JAVASCRIPT CODE:
// update particles position on/off
var f;
var path;
var polys;
var drawing = false;
var gui, params;
var anchorX, anchorY;
var particles = [];
// this function loads a font, and create an array of polygons
// a polygon being itself an array of vectors with x/y coordinates
// in this example we want to create a new 'tentacle' on each point on the outline
// of the font path
function getPoints(){
drawing = false;
// create new font : we use rune
console.log(params.font);
f = new Rune.Font(params.font)
particles = [];
// load the font
f.load(function(err){
path = f.toPath(params.message, 0, 0, params.size)
polys = path.toPolygons({ spacing:params.spacing })
for (var j=0; j < polys.length ; j++){ // get each polygon
var poly = polys[j];
for(var k = 0; k < poly.state.vectors.length; k++) { // get each point of each polygon
var vec = poly.state.vectors[k];
particles.push(new Particle(random(0,windowWidth), random(0,windowHeight), vec.x,vec.y));
}
}
drawing= true;
});
}
function setup(){
createCanvas(windowWidth,windowHeight)
background(0)
// init all parameters
params = new Parameters();
// create dat.gui drawer
gui = new dat.GUI();
// gui setup
var f2 = gui.addFolder('configuration / path generation');
var f1 = gui.addFolder('real-time parameters');
// Configuration parameters
// font selector
f2.add(params, 'font', {Avenir : "../fonts/AvenirNextLTW01-Medium.woff", BlackOpsOne : "../fonts/Black_Ops_One/BlackOpsOne-Regular.ttf",
Comfortaa : "../fonts/Comfortaa/Comfortaa-Bold.ttf",
NovaMono : "../fonts/Nova_Mono/NovaMono.ttf", ShadowsIntoLight : "../fonts/Shadows_Into_Light/ShadowsIntoLight.ttf",
Sniglet: "../fonts/Sniglet/Sniglet-ExtraBold.ttf",Tangerine : "../fonts/Tangerine/Tangerine_Bold.ttf",
UnicaOne : "../fonts/Unica_One/UnicaOne-Regular.ttf"});
f2.add(params, 'message').listen();
f2.add(params, 'spacing', 1, 40).listen();
f2.add(params, 'size', 100, 1000).listen();
f2.add(params, 'regenerate');
f1.addColor(params, 'background').listen();
f1.addColor(params, 'color').listen();
f1.add(params, 'strokeWeight',0.1,2).listen();
f1.add(params, 'threshold',10,150 ).listen();
f1.add(params, 'show_particles').listen();
f1.add(params, 'xoffset',0,windowWidth-300).listen();
f1.add(params, 'yoffset',0,windowHeight).listen();
gui.add(params, 'preset0')
gui.add(params, 'preset1')
gui.add(params, 'preset2')
gui.add(params, 'preset3')
gui.add(params, 'save')
getPoints();
}
function draw(){
noStroke();
fill(params.background)
rect(0,0,windowWidth,windowHeight)
if (drawing){
for (var i = 0 ; i < particles.length ; i++){
particles[i].update();
particles[i].check_bounds();
if (params.show_particles)particles[i].draw();
}
push()
translate(params.xoffset, params.yoffset)
strokeWeight(params.strokeWeight )
stroke(params.color);
for (var j=0; j < polys.length ; j++){ // get each polygon
var poly = polys[j];
for(var k = 0; k < poly.state.vectors.length; k++) { // get each point of each polygon
var vec = poly.state.vectors[k];
for (var i = 0 ; i < particles.length ; i++){
if (dist(particles[i].x-params.xoffset, particles[i].y-params.yoffset, vec.x, vec.y) < params.threshold){
line(particles[i].x-params.xoffset, particles[i].y-params.yoffset, vec.x, vec.y)
}
}
}
}
pop()
}
if(mouseIsPressed && mouseX < windowWidth-300) particles.push(new Particle(mouseX,mouseY,mouseX,mouseY));
}
function Particle(x,y,tx,ty){
this.x =x ;
this.y =y;
this.size = 5;
var r = random(1)
var signe = 1
if(r < 0.5){
signe = -1
}
this.xspeed = signe * random(0.15,1.5)
r = random(1)
signe = 1
if(r < 0.5){
signe = -1
}
this.yspeed = signe * random(0.15,1.5)
//this.xspeed = 0;
//this.yspeed = 0;
this.xacc= 0;
this.yacc =0;
this.targetX = tx;
this.targetY = ty;
this.draw = function(){
fill(params.color);
noStroke();
ellipse(this.x, this.y, this.size, this.size);
}
this.update = function(){
this.xspeed += this.xacc
this.yspeed += this.yacc
this.x = this.x + this.xspeed
this.y = this.y + this.yspeed
this.xacc = 0;
this.yacc = 0;
}
this.check_bounds = function(){
if (this.x < 0 || this.x> windowWidth){
this.xspeed = - this.xspeed;
}
else if (this.y<0 || this.y>windowHeight){
this.yspeed = - this.yspeed;
}
}
}
var Parameters = function(){
this.font = "../fonts/AvenirNextLTW01-Medium.woff"
this.message = 'p5*js';
this.spacing = 20;
this.size = 600;
this.background = [0,0,0,150];
this.color = [237,34,93];
this.strokeWeight = 0.51;
this.threshold = 50;
this.xoffset = windowWidth/3 - this.size
this.yoffset = windowHeight*2/3
this.show_particles = true;
this.regenerate = function(){
background(0);
getPoints();
}
this.save = function(){
saveCanvas()
}
this.clear = function(){
background(0);
}
this.preset0 = function(){
this.spacing = 20;
this.size = 600;
this.background = [0,0,0,150];
this.color = [237,34,93];
this.strokeWeight = 0.51;
this.threshold = 50;
this.show_particles =true;
getPoints();
}
this.preset1 = function(){
this.spacing = 40;
this.size = 600;
this.background = [0,0,0,5];
this.color = [237,34,93];
this.strokeWeight = 0.25;
this.threshold = 75;
this.show_particles =false;
getPoints();
}
this.preset2 = function(){
this.spacing = 8;
this.size = 600;
this.background = [0,0,0];
this.color = [237,34,93];
this.strokeWeight = 0.41;
this.threshold = 85;
this.show_particles =false;
getPoints();
}
this.preset3 = function(){
this.spacing = 4;
this.size = 600;
this.background = [0,0,0,50];
this.color = [237,34,93];
this.strokeWeight = 0.41;
this.threshold = 25;
this.show_particles = false;
getPoints();
}
}
I'm new to html5 and trying to display an array of code in a graph. It works for a line graph but for some reason unknown to me not for an exponential one. this my code.
My question is, is there a fault in the code that would break the graph?(i'm sure there's a metric ton of mistakes in the code).
I also got a lot of my code here.
thanks in advance for any help I receive.
<canvas id="graph5" width="400" height="300"></canvas>
function generateTestData5() // generates the array
{
var data = [];
for(var i=0; i<300; i++){
var sensfi = ((document.getElementById("f5").value)*(document.getElementById("xPos5").value)*(document.getElementById("f5").value))/((i*i*document.getElementById("sDI5").value)/(document.getElementById("rI5").value));
data[i] = sensfi;
}
return data;
}
var graph;
var xPadding = 40;
var yPadding = 40;
function getMaxY5() {
var data = generateTestData5();
var max = 0;
for(var i = 0; i < data.length; i ++) {
if(data[i] > max) {
max = data[i];
}
}
max += 10 - max % 10;
return max;
}
function getXPixel5(val) {
var data = generateTestData5();
return ((graph.width() - 20) / data.length) * val + (20 * 1.5);
}
function getYPixel5(val) {
var data = generateTestData5();
return graph.height() - (((graph.height() - 20) / getMaxY5()) * val) - 20;
}
function draw5(){
var data = generateTestData5();
graph = $('#graph5');
var c = graph[0].getContext('2d');
c.lineWidth = 2;
c.strokeStyle = '#333';
c.font = 'italic 8pt sans-serif';
c.textAlign = "center";
c.beginPath();
c.moveTo(xPadding, 0);
c.lineTo(xPadding, graph.height() - yPadding);
c.lineTo(graph.width(), graph.height() - yPadding);
c.stroke();
var x = 0;
for(var i = 0; i < data.length + 1; i ++) {
if(x==30) {
c.fillText(i, getXPixel5(i), graph.height() - yPadding + 20);
x=0;}
else {
x++;
}
}
c.textAlign = "right";
c.textBaseline = "middle";
for(var i = 0; i < getMaxY5(); i += getMaxY5()/10) {
c.fillText(i, xPadding-10, getYPixel5(i));
}
c.strokeStyle = '#f00';
c.beginPath();
c.moveTo(getXPixel5(0)+10, getYPixel5(data[0])-20);
for(var i = 1; i < data.length + 1; i ++) {
c.lineTo(getXPixel5(i)+10, getYPixel5(data[i])-20);
}
c.stroke();
//c.clearRect(0,0,graph.width(),graph.height());
}
I had to change width() and height() to width and height a few times (they are simple properties), start the test data at 1 because otherwise the first value is always +infinity", and store data and max instead of generating them multiple times, but now it seems to work.
var data; /* KEEP DATA AS A GLOBAL VARIABLE INSTEAD OF GENERATING IT AGAIN EACH TIME */
var graph;
var xPadding = 40;
var yPadding = 40;
function generateTestData5() // generates the array
{
var data = [];
for(var i=1; i<=300; i++){
var sensfi = ((document.getElementById("f5").value)*(document.getElementById("xPos5").value)*(document.getElementById("f5").value))/((i*i*document.getElementById("sDI5").value)/(document.getElementById("rI5").value));
data[i-1] = sensfi;
}
return data;
}
function getMaxY5() {
var max = 0;
for(var i = 0; i < data.length; i ++) {
if(data[i] > max) {
max = data[i];
}
}
max += 10 - max % 10;
return max;
}
function getXPixel5(val) {
return ((graph.width - 20) / data.length) * val + (20 * 1.5);
}
function getYPixel5(val) {
return graph.height - (((graph.height - 20) / getMaxY5()) * val) - 20;
}
function draw5(){
data = generateTestData5(); /* USE THE GLOBAL VARIABLE */
var max = getMaxY5(); /* STORE MAX INSTEAD OF CHECKING IT MULTIPLE TIMES */
graph = document.getElementById("graph5");
var c = graph.getContext('2d');
c.lineWidth = 2;
c.strokeStyle = '#333';
c.font = 'italic 8pt sans-serif';
c.textAlign = "center";
c.beginPath();
c.moveTo(xPadding, 0);
c.lineTo(xPadding, graph.height - yPadding);
c.lineTo(graph.width, graph.height - yPadding);
c.stroke();
var x = 0;
for(var i = 0; i < data.length + 1; i ++) {
if(x==30) {
c.fillText(i, getXPixel5(i), graph.height - yPadding + 20);
x=0;}
else {
x++;
}
}
c.textAlign = "right";
c.textBaseline = "middle";
for(var i = 0; i < max; i += max/10) {
c.fillText(i, xPadding-10, getYPixel5(i));
}
c.strokeStyle = '#f00';
c.beginPath();
c.moveTo(getXPixel5(0)+10, getYPixel5(data[0])-20);
for(var i = 1; i < data.length + 1; i ++) {
c.lineTo(getXPixel5(i)+10, getYPixel5(data[i])-20);
}
c.stroke();
//c.clearRect(0,0,graph.width,graph.height);
}
draw5();
<form>
<input name="f5" id="f5" value=8>
<input name="xpos5" id="xPos5" value=100>
<input name="sDI5" id="sDI5" value=6.4>
<input name="rI5" id="rI5" value=1280>
</form>
<canvas id="graph5" width="400" height="300"></canvas>