1
votes

Ok, so I am learning HTML5 and I wanted to update my portfolio to have a moving black hole instead of a static picture of one. I could have just taken the picture and rotated it in the canvas, but I thought it would be better if I did it all without an image. The major issue I am having is I can't seem to understand how to calculate (and therefor update) the path of each particle along a circular path.

I have read the equation to convert from polar coordinates to cartesian, but there is obviously something I am doing wrong.

Here are the most relevant snippets of code:

particle class

 function particle(rad, vel, dist, angle, x, y){

   this.rad = rad;
   this.vel = vel;
   this.dist = dist;
   this.x = x;
   this.y = y;
   this.angle = angle;
} 

Function to initialize the particles being used

function initParticles(parts, innerCircleRad, nbr_circles, w, h){
   var rad, vel, dist;

   for (var i = 1; i <= nbr_circles; ++i) {
      if(i < 10){
          rad = (Math.random()*2.5)+1;
          vel = (Math.random()*.5)+3;
          dist = (Math.random()*1.5) + innerCircleRad;
          angle = Math.floor(Math.random()*(360))
      }else if( i < 15){
          rad = (Math.random()*2.7)+1;
          vel = (Math.random()*.4)+2;
          dist = (Math.random()*1.5) + innerCircleRad+1;
          angle = Math.floor(Math.random()*(360))
      }else if( i < 18){
          rad = (Math.random()*2.8)+1;
          vel = (Math.random()*.3)+1;
          dist = (Math.random()*1.5) + innerCircleRad+2.5;
          angle = Math.floor(Math.random()*(360))
      }else {
          rad = (Math.random()*2.9)+1;
          vel = (Math.random()*.2)+1;
          dist = (Math.random()*1.5) + innerCircleRad+4;
          angle = Math.floor(Math.random()*(360))
      }

    var x = w/2 + Math.cos(angle) * dist;
    var y = h/2 + Math.sin(angle) * dist;
    parts[i] = new particle(rad, vel, dist, angle, x, y);       
  }
}

Function that gets continually called to update the canvas and draws the points

function refresh(dc,width,height,frame_number, particles, nbr_circles) {
  dc.clearRect(0,0,width,height);  
  dc.fillStyle='#000';

  for (var i = 1; i <= nbr_circles; ++i) {
    // set up increment for new angle based on particles velocity
    var angle_incr = ((frame_number)/12.0) * Math.PI/180;
    // updated new angle, make sure it is in correct range of circle
    particles[i].angle = (angle_incr+particles[i].angle)%Math.PI/180
    // set new x and y points based on the angle change
    particles[i].x = particles[i].x + Math.cos(particles[i].angle) * particles[i].dist;
    particles[i].y = particles[i].y + Math.sin(particles[i].angle) * particles[i].dist;

    // draw tiny circle at x,y
    dc.beginPath();
    dc.arc(particles[i].x, particles[i].y, particles[i].rad, 0, 2*Math.PI, false);
    dc.fill();
  }
}

I have the code set up so I can pause and play, which turns on and off the updating method. For some reason while play is on (it is updating) I can't seen anything in the canvas, but when I pause all the dots show up. So that is the first issue, I thought it might have something to do with the velocity being too high so I dropped it down, but I couldn't see the particles any time while the updating was happening. Every time I play then pause the dots show up, and they have not rotated but shifted to the right along the x axis... I output the x and y coordinates of the particles and it seems like only the x value is being updated and only going up. Which explains their motion.

So the 2 questions I have are:

  1. How do I get each particle to follow its own circular path based on its distance from the center of the circle, its velocity and current x y coordinates.

  2. How do I get the particles to display while following the path described above (since for some reason they aren't displaying at all, possible because of their velocity?)

My end goal is to have an inner circle that is empty then lots of particles close to the radius of the inner circle moving fast. Then less particles as you move out to the outer radius of the black hole, where the particles are moving slower. I have looked around for tutorials all day, and I haven't found much that was relevant besides the equations for a circular path. But I can't seem to get that working.

Any insight or reference where a similar problem is broken down I would really appreciate it. Thanks for taking the time to read this.

-Alan

2
Can you show us how you are calling your refresh method? I have a feeling this be why you're not seeing anything until you hit pause... Also have you looked at using a framework to help you along? There's some excellent options out there including mrdoob.github.com/three.jstimothyclifford
@timothyclifford while three.js is nice, it seems like overkill to recommend a 3d library for someone just trying to make a 2d particle engine.Loktar
That's funny you should bring that up, because I actually looked into three.js dled it and found a tutorial on building something a little more interesting. But I still would like to try to figure out how to get this to work as well. I am pretty positive where the refresh is happening is working correctly because I used a skeleton script and am adding in my own code to display within the refresh method. I had the skeleton working with the basic script code. I know there is something wrong with my equation for finding the next x y coordinate because they only shift in the positive x direction.Alan DeLonga
@Alan This sounds like a really neat problem. Did you ever find a working solution?rarrarrarrr

2 Answers

2
votes

1) you must either have a centerX, centerY within each particule, or have them shared (set them on particle.prototype for the latter). Then the formula for x,y is :

particles[i].x = particles[i].centerX + Math.cos(particles[i].angle) * particles[i].dist;
particles[i].y = particles[i].centerY + Math.sin(particles[i].angle) * particles[i].dist;

2) your angular velocity should depend on the dist of the particle. Either store the angular velocity as a particle property or have angle_incr = somefunction ( particles[i].dist ); might be k*dist, or k*sqrt(dist), ...

3) for the color, you draw in black after a clearRect, -> red '#F00' for instance.

4) cache particles[i] in the for loop. ( var thisPart = particles[i]; )

You might make use of my particle engine if you like, it is fast and convenient, the article is here :

http://gamealchemist.wordpress.com/2013/06/16/introducing-jsparkle-a-versatile-and-fast-javascript-particle-engine/

0
votes

you can use the proton html5 particle engine http://a-jie.github.io/Proton/ It is very easy!