2010-06-10 7 views
2

Je travaille sur un code où j'ai un objet Time avec un membre time. Time.time donne moi depuis le démarrage de mon application en secondes (valeur flottante). Maintenant, je veux créer une pulsation entre 0 et 1, puis de nouveau de 1 à 0, ce qui continue jusqu'à ce que l'application s'arrête.Comment créer une valeur de pulsation à partir de 0..1..0..1..0 etc pour une durée donnée?

Je pensais utiliser sin() mais je ne sais pas quoi lui passer comme paramètres pour créer cette valeur de pulsation.

Comment créer cette valeur de pulsation?

Meilleures salutations, Pollux

+3

Etes-vous en programmation en C++, C#, ou ne savez-vous pas? –

+2

Pourquoi ne pas moduler votre temps en secondes par 2, et l'utiliser? –

+0

Très simple, vous ajoutez beaucoup d'ondes sinusoïdales l'une à l'autre jusqu'à obtenir une bonne approximation d'une onde carrée. Vous lui donnez la fréquence et l'amplitude adéquates et vous le décalez un peu le long de l'axe des y et vous voilà. :) – stakx

Répondre

11

Vous mentionnez en utilisant le péché(), donc je suppose que vous voulez qu'il continue d'impulsion entre 0 et 1.

Quelque chose comme cela va faire:

float pulse(float time) { 
    const float pi = 3.14; 
    const float frequency = 10; // Frequency in Hz 
    return 0.5*(1+sin(2 * pi * frequency * time)); 
} 

1/frequency = 0.1 second est la période, qui est le temps entre 1.

+0

Beaucoup plus propre que ma version - très bien! – corsiKa

+0

Kleist, donc la fréquence serait le framerate? – pollux

+0

Oh et serait-ce (1/fréquence) * Time.time * (TWO_PI) – pollux

4

Que diriez-vous x = 1 - x? Ou si vous voulez qu'il soit basé sur le temps, utilisez Minuterie% 2

Oh, vous vouliez aussi les valeurs entre 0 et 1. Que diriez-vous Math.abs (100 - (200 Temporisateur%))/100 Lorsque la minuterie est quelque chose comme DateTime.Now.TimeOfDay.TotalMilliseconds

Edit: Mes tests indiquent que cela est plus que deux fois plus vite comme la méthode du péché. Pour 1 million d'itérations, la méthode sin prend 0,048 secondes alors que la méthode Abs prend environ 0,023 secondes. En outre, vous obtenez des formes d'onde différentes sur les deux, bien sûr. Le péché produit une onde sinusoïdale, tandis que Abs produit une onde triangulaire.

static void Main(string[] args) 
{ 
    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); 
    sw.Start(); 
    const int count = 1000000; 
    float[] results = new float[count]; 
    for (int i = 0; i < count; i++) 
    { 
     results[i] = AbsPulse(i/1000000F); 
     //results[i] = SinPulse(i/1000000F); 
    } 
    sw.Stop(); 
    Console.WriteLine("Time Elapsed: {0} seconds", sw.Elapsed.TotalSeconds); 
    char[,] graph = new char[80, 20]; 
    for (int y = 0; y <= graph.GetUpperBound(1); y++) 
     for (int x = 0; x <= graph.GetUpperBound(0); x++) 
     graph[x, y] = ' '; 
    for (int x = 0; x < count; x++) 
    { 
     int col = x * 80/count; 
     graph[col, (int)(results[x] * graph.GetUpperBound(1))] = 'o'; 
    } 
    for (int y = 0; y <= graph.GetUpperBound(1); y++) 
    { 
     for (int x = 0; x < graph.GetUpperBound(0); x++) 
     Console.Write(graph[x, y]); 
     Console.WriteLine(); 
    } 
} 

static float AbsPulse(float time) 
{ 
    const int frequency = 10; // Frequency in Hz 
    const int resolution = 1000; // How many steps are there between 0 and 1 
    return Math.Abs(resolution - ((int)(time * frequency * 2 * resolution) % (resolution * 2)))/(float)resolution; 
} 

static float SinPulse(float time) 
{ 
    const float pi = 3.14F; 
    const float frequency = 10; // Frequency in Hz 
    return 0.5F * (1 + (float)Math.Sin(2 * pi * frequency * time)); 
} 
0

À quelle fréquence voulez-vous qu'il pulse?

Supposons que vous souhaitiez passer de 0 à 1 en 10 secondes.

float pulseValueForTime(int sec) { 
    int pulsePoint = sec % 10; 
    float pulsePercent = (float)pulsePoint/(float)10; 
    float pulseInTermsOfPI = (pulsePercent * 2 * PI) - PI; 
    float sinVal = MagicalSinFunction(pulseInTermsOfPI); // what framework you use to compute sin is up to you... I'm sure you can google that! 
    return (sinVal + 1)/2; // sin is between 1 and -1, translate to between 0 and 1 
} 
+0

glowcoder, merci, je fais quelque chose comme maintenant, même si cela ne fonctionne pas avec une durée fixe. Je veux être en mesure d'obtenir une impulsion toutes les X-secondes. Je pense que j'ai besoin de l'exemple de Kleist d'en haut. BTW, vous n'utilisez pas pulsePoint dans votre code. – pollux

+0

L'idée derrière cela était que vous feriez 'pulseValueForTime (getTimeInSec());' et 'pulsePoint' devrait être utilisé pour le premier flottant (vous remarquerez que pulse n'est jamais déclaré). Je corrigerai l'erreur, bien que la version de Kliest, comme vous l'avez déjà remarqué, soit beaucoup plus propre que celle-ci si elle est identique dans son concept. – corsiKa

+0

Vous pouvez faire 'pulsePoint/10F' au lieu de' (float) pulsePoint/(float) 10': int/float donne float, et 10f est float - voir http://msdn.microsoft.com/fr-fr/library /b1e65aza%28VS.71%29.aspx – ANeves

0

Une fonction sinusoïdale serait idéale je pense, mais vous devez ajuster la période et l'échelle.

La fonction sinus donne des résultats compris entre -1 et 1, mais vous voulez passer de 0 à 1. Pour la mettre à l'échelle correctement, vous voulez (sin(x)+1)/2.

La fonction sinus commence à zéro, passe à 1 à pi/2, zéro à nouveau à pi, -1 à 3 * pi/2 et revient à zéro à 2 * pi. Mis à l'échelle, le premier zéro arrivera à 3 * pi/2 et le premier maximum après sera à 5/2 * pi. Donc x dans la formule précédente est (2*time + 3) * pi/2.

Mettre le tout ensemble: (sin((2*time.time + 3) * pi/2) + 1)/2

0

Regardez dans les fonctions de facilité. Ils font ce genre de choses de toutes sortes de manières - linéaire, poly, exp, sin, etc.

Questions connexes