كيفية إنشاء قيمة نابضة من 0..1..0..1..0 وما إلى ذلك لمدة معينة؟

StackOverflow https://stackoverflow.com/questions/3018550

سؤال

أنا أعمل على بعض الكود حيث لدي Time اعتراض مع عضو time. Time.time يعطيني الوقت منذ أن بدأ طلبي في ثوان (قيمة التعويم). الآن أريد إنشاء قيمة نابضة بين 0 و 1 ثم من 1 إلى 0 مرة أخرى ، والتي تستمر في القيام بالتوقف حتى يتوقف التطبيق.

كنت أفكر في استخدام SIN () ولكن لا أعرف ما الذي يجب أن ننقل إليه كمعلمات لإنشاء هذه القيمة النابضة.

كيف يمكنني إنشاء هذه القيمة النابضة؟

التحيات الكريمة ، بولوكس

هل كانت مفيدة؟

المحلول

أذكر استخدام SIN () ، لذلك أعتقد أنك تريد أن تنبض بشكل مستمر بين 0 و 1.

شيء من هذا القبيل سوف يفعل:

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 هي الفترة ، وهي الوقت بين 1.

نصائح أخرى

ماذا عن x = 1 - x؟ أو إذا كنت تريد أن يكون الوقت مستندًا إلى الوقت ، فاستخدم Timer ٪ 2

أوه ، أردت القيم بين 0 و 1 كذلك. ماذا عن Math.ABS (100 - (Timer ٪ 200)) / 100 حيث يكون المؤقت مثل DateTime.Now.timeofday.totalmilliseconds

تعديل:تشير اختباراتي إلى أن هذا يزيد عن ضعف طريقة SIN. لمليون تكرار ، تستغرق طريقة SIN 0.04 ثانية بينما تستغرق طريقة ABS حوالي 0.023 ثانية. أيضا ، يمكنك الحصول على أشكال موجية مختلفة من الاثنين ، بالطبع. تنتج Sin موجة جيبية ، بينما تنتج ABS موجة ثلاثية.

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

أعتقد أن وظيفة الجيب مثالية ، لكنك تحتاج إلى ضبط الفترة والمقياس.

تنتج وظيفة الجيب نتائج بين -1 و 1 ، لكنك تريد أن تذهب بين 0 و 1. لتوسيع نطاقها بشكل صحيح تريد (sin(x)+1)/2.

تبدأ وظيفة الجيب من الصفر ، وتنتقل إلى 1 في PI/2 ، صفر مرة أخرى في PI ، -1 في 3*PI/2 ، والعودة إلى الصفر عند 2*PI. Scaled ، سيحدث الصفر الأول في 3*PI/2 والأول الحد الأقصى بعد ذلك سيكون عند 5/2*PI. لذا x في الصيغة السابقة (2*time + 3) * pi/2.

ضع كل شيء معا: (sin((2*time.time + 3) * pi/2) + 1) / 2

كم مرة تريد أن تنبض؟

دعنا نقول أنك تريد الانتقال من 0 إلى 1 أكثر من 10 ثوان.

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
}

ابحث في وظائف سهولة. يفعلون هذا النوع من الأشياء في جميع أنواع الأخلاق - الخطية ، بولي ، إكسب ، الخطيئة ، إلخ.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top