Pergunta

Estou trabalhando em algum código onde tenho um Time objeto com um membro time. Time.time Me dá tempo desde que meu aplicativo começou em segundos (valor float). Agora, quero criar um valor pulsante entre 0 e 1 e depois de 1 a 0 novamente, o que continua fazendo Thins até que o aplicativo pare.

Eu estava pensando em usar o sin (), mas não sei o que passar como parâmetros para criar esse valor pulsante.

Como eu criaria esse valor pulsante?

Atenciosamente, Pollux

Foi útil?

Solução

Você menciona usar o sin (), então eu acho que você quer que ele pulse continuamente entre 0 e 1.

Algo assim fará:

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 é o período, que é o tempo entre 1's.

Outras dicas

Que tal x = 1 - x? Ou se você quiser que seja baseado no tempo, use o timer % 2

Oh, você também queria os valores entre 0 e 1. Que tal math.abs (100 - (timer % 200)) / 100 onde o timer é algo como DateTime.now.TimeOfday.TotalmillisEconds

Editar:Meus testes indicam que isso é mais que duas vezes mais rápido que o método do pecado. Para 1 milhão de iterações, o método SIN leva 0,048 segundos, enquanto o método ABS leva cerca de 0,023 segundos. Além disso, você obtém formas de onda diferentes das duas, é claro. O pecado produz uma onda senoidal, enquanto o ABS produz uma onda triangular.

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));
}

Acho que uma função seno seria ideal, mas você precisa ajustar o período e a escala.

A função seno (sin(x)+1)/2.

A função senoidal começa em zero, vai para 1 em Pi/2, zero novamente em Pi, -1 a 3*pi/2 e volta a zero a 2*pi. Escalado, o primeiro zero acontecerá em 3*pi/2 e o primeiro máximo depois disso será de 5/2*pi. Então x na fórmula anterior é (2*time + 3) * pi/2.

Juntando tudo: (sin((2*time.time + 3) * pi/2) + 1) / 2

Com que frequência você quer que ele pulse?

Digamos que você queira ir de 0 a 1 por mais de 10 segundos.

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
}

Olhe para as funções de facilidade. Eles fazem esse tipo de coisa em todos os tipos de maneiras - linear, poli, exp, pecado, etc.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top