27 votes

Toile Champ d'étoiles en rotation

J'adopte l'approche suivante pour animer un champ d'étoiles à travers l'écran, mais je suis bloqué pour la partie suivante.

JS

var c = document.getElementById('stars'),
    ctx = c.getContext("2d"),
    t = 0; // time

c.width = 300;
c.height = 300;

var w = c.width,
    h = c.height,
    z = c.height,
    v = Math.PI; // angle of vision

(function animate() {

    Math.seedrandom('bg');
    ctx.globalAlpha = 1;

    for (var i = 0; i <= 100; i++) {

        var x = Math.floor(Math.random() * w), // pos x
            y = Math.floor(Math.random() * h), // pos y
            r = Math.random()*2 + 1, // radius
            a = Math.random()*0.5 + 0.5, // alpha

            // linear
            d = (r*a),       // depth
            p = t*d;         // pixels per t

        x = x - p;       // movement
        x = x - w * Math.floor(x / w); // go around when x < 0

        (function draw(x,y) {
            var gradient = ctx.createRadialGradient(x, y, 0, x + r, y + r, r * 2);
            gradient.addColorStop(0, 'rgba(255, 255, 255, ' + a + ')');
            gradient.addColorStop(1, 'rgba(0, 0, 0, 0)');

            ctx.beginPath();
            ctx.arc(x, y, r, 0, 2*Math.PI);
            ctx.fillStyle = gradient;
            ctx.fill();

            return draw;

        })(x, y);

    }

    ctx.restore();
    t += 1;

    requestAnimationFrame(function() {
        ctx.clearRect(0, 0, c.width, c.height);
        animate();
    });
})();

HTML

<canvas id="stars"></canvas>

CSS

canvas {
    background: black;
}

JSFiddle

Pour l'instant, il anime chaque étoile avec un delta X qui prend en compte l'opacité et la taille de l'étoile, de sorte que les plus petites semblent se déplacer plus lentement.

Utilice p = t; pour que toutes les étoiles se déplacent à la même vitesse.

QUESTION

Je cherche un modèle clairement défini où les vitesses donnent l'illusion des étoiles. tournant autour de l'expectative définie en fonction du centre de rotation. cX, cY et l'angle de vision v ce qui correspond à la fraction de 2π que l'on peut voir (si le centre du cercle n'est pas le centre de l'écran, le rayon devrait être au moins la plus grande partie). J'ai du mal à trouver un moyen qui applique ce cosinus à la vitesse de déplacement des étoiles, même pour un cercle centré avec une rotation de π.

Ces diagrammes pourraient expliquer davantage ce que je recherche :

Cercle centré :

center of vision in x,y

Non centré :

shifted center

Un angle de vision différent :

different angle of vision

Je suis vraiment perdue quant à la façon d'avancer. Je me suis déjà un peu fatigué pour en arriver là. Pouvez-vous m'aider à faire les premiers pas ?

Merci


UPDATE

J'ai fait quelques progrès avec ce code :

        // linear
        d = (r*a)*z,   // depth
        v = (2*Math.PI)/w,
        p = Math.floor( d * Math.cos( t * v ) );     // pixels per t

    x = x + p;       // movement
    x = x - w * Math.floor(x / w); // go around when x < 0

JSFiddle

Dónde p est la coordonnée x d'une particule en mouvement circulaire uniforme et v est la vitesse angulaire, mais cela génère un effet de pendule. Je ne sais pas comment modifier ces équations pour créer l'illusion que l'observateur tourne au contraire.


UPDATE 2 :

On y est presque. Un utilisateur du canal ##Math freenode a eu la gentillesse de proposer le calcul suivant :

        // linear
        d = (r*a),       // depth
        p = t*d;         // pixels per t

    x = x - p;       // movement
    x = x - w * Math.floor(x / w); // go around when x < 0

    x = (x / w) - 0.5;
    y = (y / h) - 0.5;

    y /= Math.cos(x);

    x = (x + 0.5) * w;
    y = (y + 0.5) * h;

JSFiddle

L'effet est obtenu visuellement, mais il ne suit pas un modèle clairement défini en termes de variables (il ne fait que "bidouiller" l'effet). Je ne vois donc pas de moyen direct de réaliser différentes implémentations (changer le centre, l'angle de vision). Le modèle réel pourrait être très similaire à celui-ci.


MISE À JOUR 3

Suite à la réponse d'Iftah, j'ai pu utiliser Sylvester pour appliquer une matrice de rotation aux étoiles, qui doivent d'abord être enregistrées dans un tableau. De plus, les données de chaque étoile z est maintenant déterminée et le rayon r et l'opacité a en sont dérivés à la place. Le code est substantiellement différent et plus long donc je ne le posterai pas, mais il pourrait être un pas dans la bonne direction. Je n'arrive pas encore à obtenir une rotation continue. L'utilisation d'opérations matricielles sur chaque image semble coûteuse en termes de performances.

JSFiddle

2voto

Iftah Points 1892

Vous réinitialisez la position des étoiles 2d à chaque image, puis vous déplacez les étoiles (en fonction du temps et de la vitesse de chaque étoile) - c'est une mauvaise façon d'atteindre votre objectif. Comme vous l'avez découvert, cela devient très complexe lorsque vous essayez d'étendre cette solution à d'autres scénarios.

Une meilleure solution serait de définir la position 3D des étoiles une seule fois (à l'initialisation) puis de déplacer une "caméra" à chaque image (en fonction du temps). Lorsque vous voulez rendre l'image 2d, vous calculez alors la position des étoiles à l'écran. La position à l'écran dépend de la position 3D des étoiles et de la position actuelle de la caméra. Cela vous permettra de déplacer la caméra (dans n'importe quelle direction), de la faire tourner (dans n'importe quel angle) et d'obtenir la position correcte des étoiles tout en gardant la raison.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X