views:

140

answers:

1

So I'm just doing a basic orbit simulator using Raphael JS, where I draw one circle as the "star" and another circle as the "planet". It seems to be working just fine, with the one snag that as the simulation continues, its framerate progressively slows down until the orbital motion no longer appears fluid. Here's the code (note: uses jQuery only to initialize the page):

$(function() {
    var paper = Raphael(document.getElementById('canvas'), 640, 480);
    var star = paper.circle(320, 240, 10);
    var planet = paper.circle(320, 150, 5);
    var starVelocity = [0,0];
    var planetVelocity = [20.42,0];
    var starMass = 3.08e22;
    var planetMass = 3.303e26;
    var gravConstant = 1.034e-18;
    function calculateOrbit() {
        var accx = 0;
        var accy = 0;
        accx = (gravConstant * starMass * ((star.attr('cx') - planet.attr('cx')))) / (Math.pow(circleDistance(), 3));
        accy = (gravConstant * starMass * ((star.attr('cy') - planet.attr('cy')))) / (Math.pow(circleDistance(), 3));
        planetVelocity[0] += accx;
        planetVelocity[1] += accy;
        planet.animate({cx: planet.attr('cx') + planetVelocity[0], cy: planet.attr('cy') + planetVelocity[1]}, 150, calculateOrbit);
        paper.circle(planet.attr('cx'), planet.attr('cy'), 1); // added to 'trace' orbit
    }
    function circleDistance() {
        return (Math.sqrt(Math.pow(star.attr('cx') - planet.attr('cx'), 2) + Math.pow(star.attr('cy') - planet.attr('cy'), 2)));
    }
    calculateOrbit();
});

It doesn't appear, to me anyway, that any part of that code would cause the animation to gradually slow down to a crawl, so any help solving the problem will be appreciated!

A: 

The problem is with the call back to calculateOrbit in your planet.animate() call. Its not being handled by raphael correctly and is causing a memory leak or an execution slow down. if you remove it and replace the line

calculateOrbit()

with

setInterval(calculateOrbit, 150);

it should run smoothly.

full code:

$(function() {
var paper = Raphael(document.getElementById('canvas'), 640, 480);
var star = paper.circle(320, 240, 10);
var planet = paper.circle(320, 150, 5);
var starVelocity = [0,0];
var planetVelocity = [20.42,0];
var starMass = 3.08e22;
var planetMass = 3.303e26;
var gravConstant = 1.034e-18;
function calculateOrbit() {
    var accx = 0;
    var accy = 0;
    accx = (gravConstant * starMass * ((star.attr('cx') - planet.attr('cx')))) / (Math.pow(circleDistance(), 3));
    accy = (gravConstant * starMass * ((star.attr('cy') - planet.attr('cy')))) / (Math.pow(circleDistance(), 3));
    planetVelocity[0] += accx;
    planetVelocity[1] += accy;
    planet.animate({cx: planet.attr('cx') + planetVelocity[0], cy: planet.attr('cy') + planetVelocity[1]}, 150);
    paper.circle(planet.attr('cx'), planet.attr('cy'), 1); // added to 'trace' orbit
}
function circleDistance() {
    return (Math.sqrt(Math.pow(star.attr('cx') - planet.attr('cx'), 2) + Math.pow(star.attr('cy') - planet.attr('cy'), 2)));
}
setInterval(calculateOrbit, 150);
});
greg