Быстрый фон частицы WPF

Вот оно:

Идея состоит в том, чтобы найти все элементы Stat, в которых Type является предпочитаемым_фотом

import xml.etree.ElementTree as ET

xml = '''<?xml version="1.0" encoding="UTF-8"?>
<SoccerFeed>
  <SoccerDocument>
    <Team>
      <Founded>1919</Founded>
      <Name>Angers</Name>
      <Player uID="p40511">
        <Name>Denis Petric</Name>
        <Position>Goalkeeper</Position>
        <Stat Type="first_name">Denis</Stat>
        <Stat Type="last_name">Petric</Stat>
        <Stat Type="preferred_foot">Left</Stat>
      </Player>
      <Player uID="p119744">
        <Name>Mathieu Michel</Name>
        <Position>Goalkeeper</Position>
        <Stat Type="first_name">Mathieu</Stat>
        <Stat Type="preferred_foot">Right</Stat>
      </Player>
    </Team>
  </SoccerDocument>
</SoccerFeed>'''

root = ET.fromstring(xml)
prefered_foots = root.findall(".//Stat[@Type='preferred_foot']")
for foot in prefered_foots:
    print(foot.text)

.

8
задан ZogStriP 18 January 2012 в 14:07
поделиться

9 ответов

Эрих Мирабал >> Я попробовал HLSL, и мне было довольно интересно узнать что-то новое, но, как я, в целом Новичок Мне не удалось сделать размытие по Боксу / Гауссу ...

Во всяком случае, я нашел способ, который вообще не использует процессор.

Вместо того, чтобы перемещать Ellipse, я перемещаю их изображение.

Я генерирую PNG в памяти с классами RenderTargetBitmap и PngBitmapEncoder и перемещаю тезисы уже размытые и прозрачные изображения!

Большое спасибо всем за ответы!

2
ответ дан 5 December 2019 в 17:41
поделиться

На вашем месте я бы изучите использование встроенной в WPF системы анимации, а не обновляйте позиции вручную, используя обратный вызов, как вы это делаете. Например, возможно, стоит обратить внимание на класс Point3DAnimation в пространстве имен System.Windows.Media.Animation . С другой стороны, не похоже, что использование 3D-точек на самом деле вам что-то дает (насколько я могу судить, вы игнорируете значения Z при рендеринге эллипсов), поэтому вы можете захотеть перейти на простое использование Точка s

Встроенная система анимации вместо обновления позиций вручную с помощью обратного вызова, как вы делаете. Например, возможно, стоит обратить внимание на класс Point3DAnimation в пространстве имен System.Windows.Media.Animation . С другой стороны, не похоже, что использование 3D-точек на самом деле вам что-то дает (насколько я могу судить, вы игнорируете значения Z при рендеринге эллипсов), поэтому вы можете захотеть перейти на простое использование Точка s

Встроенная система анимации вместо обновления позиций вручную с помощью обратного вызова, как вы делаете. Например, возможно, стоит обратить внимание на класс Point3DAnimation в пространстве имен System.Windows.Media.Animation . С другой стороны, не похоже, что использование 3D-точек на самом деле вам что-то дает (насколько я могу судить, вы игнорируете значения Z при рендеринге эллипсов), поэтому вы можете захотеть перейти на простое использование Точка s

1
ответ дан 5 December 2019 в 17:41
поделиться

Не думаю, что проблема в производительности. Приложение почти не привязывается к моему процессору, но частота кадров все еще не выглядит плавной.

Я бы посмотрел на две вещи. Как вы рассчитываете обновление вашей позиции и как часто вы запускаете событие для этого.

timer.Interval = TimeSpan.FromMilliseconds(10);

Это 100 кадров в секунду. Вместо этого выберите 30 кадров в секунду (каждое другое обновление на вашем мониторе) или 60 и т. Д. Вы должны попытаться синхронизировать обновления с монитором, как в видеоигре.

timer.Interval = TimeSpan.FromMilliseconds(33.33); // 30 fps

Одно это, вероятно, не решит проблему плавности. Вы также не должны предполагать, что время между событиями является фиксированным:

double elapsed = 0.1;

Когда вы запускаете таймер для обновления каждые 0,01 секунды, это не означает, что он фактически выполняется за единицу времени. Сборка мусора, планирование ОС, все, что может повлиять на количество времени, которое на самом деле требуется. Измерьте время, прошедшее с момента последнего обновления, и выполните расчеты на основе этого числа.

Удачи!

4
ответ дан 5 December 2019 в 17:41
поделиться

MSDN WPF имеет отличную демонстрацию Particle Effects. Кроме того, книга О'Рейли «Изучение XNA» посвящена тому, как использовать эффекты частиц с использованием XNA.

1
ответ дан 5 December 2019 в 17:41
поделиться

Thanks everyone for answering me.

I've taken into account each of your answers:

  • Lucas Aardvark >> I've done that and it increased a little bit the speed of the application and used less CPU/Memory.
  • Rob Walker >> I followed the link, but I stopped when I saw : "The emulator is pretty CPU intensive due to zero optimization and lots of array copies".
  • kvb >> I've tried to use Animations but it was way more complex and did not improve the smoothness of the application... Maybe I did it wrong! I've also removed the use of Point3D as there was effectively no need to use them
  • Jogn Noonan >> Really instructing answer, but I'm not sure that will help. If I measure the time between 2 updates, then the longer it is the bigger the ratio will be. So particles will be like "teleported", right?

I've updated my source code :

The Particle class now only have the following properties:

public class Particle
{
    public Point Velocity { get; set; } // Speed of move

    public BlurEffect Blur { get; set; } // Blur effect
    public Brush Brush { get; set; } // Brush (opacity)
}

The Window1.xaml did not change, but I changed his behind code:

public partial class Window1 : Window
{
    DispatcherTimer timer = new DispatcherTimer();
    Random random = new Random(DateTime.Now.Millisecond);

    // Some general values
    double MaxSize = 150;
    double NumberOfParticles = 25;
    double VerticalVelocity = 0.4;
    double HorizontalVelocity = -2.2;

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        for (int i = 0; i < NumberOfParticles; i++)
        {
            CreateParticle();
        }

        timer.Interval = TimeSpan.FromMilliseconds(33.33);
        timer.Tick += new EventHandler(timer_Tick);
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        // I control "particle" from their ellipse representation
        foreach (Ellipse ellipse in ParticleHost.Children)
        {
            var p = ellipse.Tag as Particle;
            var t = ellipse.RenderTransform as TranslateTransform;

            // Update location
            t.X += p.Velocity.X;
            t.Y -= p.Velocity.Y;

            // Check if the particle is too high
            if (t.Y < -MaxSize)
            {
                t.Y = Height + MaxSize;
            }

            // Check if the particle has gone outside
            if (t.X < -MaxSize || t.X > Width + MaxSize)
            {
                t.X = random.NextDouble() * Width;
                t.Y = Height + MaxSize;
            }

            // Brush & Effect
            ellipse.Fill = p.Brush;
            // Comment this line to deactivate the Blur Effect
            ellipse.Effect = p.Blur;
        }
    }

    private void CreateParticle()
    {
        // Brush (White)
        var brush = Brushes.White.Clone();
        // Opacity (0.2 <= 1)
        brush.Opacity = 0.2 + random.NextDouble() * 0.8;
        // Blur effect
        var blur = new BlurEffect();
        blur.RenderingBias = RenderingBias.Performance;
        // Radius (1 <= 40)
        blur.Radius = 1 + random.NextDouble() * 39;
        // Ellipse
        var ellipse = new Ellipse();
        // Size (from 15% to 95% of MaxSize)
        ellipse.Width = ellipse.Height = MaxSize * 0.15 + random.NextDouble() * MaxSize * 0.8;
        // Starting location of the ellipse (anywhere in the screen)
        ellipse.RenderTransform = new TranslateTransform(random.NextDouble() * Width, random.NextDouble() * Height);
        ellipse.Tag = new Particle
        {
            Blur = blur,
            Brush = brush,
            Velocity = new Point
            {
                X = HorizontalVelocity + random.NextDouble() * 4,
                Y = VerticalVelocity + random.NextDouble() * 2
            }
        };
        // Add the ellipse to the Canvas
        ParticleHost.Children.Add(ellipse);
    }
}

If you try this new version, you'll see that it's still not smooth.

But if you comment the line that affect the Blur effect, you'll see it going very smooth!

Any thoughts?

1
ответ дан 5 December 2019 в 17:41
поделиться

Я читал чей-то блог, который пытался сделать то же самое, но я не могу его найти ( Я буду продолжать искать это). Способ, которым он смог ускорить его применение, был путем повторного использования частиц. Каждый раз, когда вы создаете новую частицу, вы видите, как вы забираете память. Вы не можете позволить себе эту память, если у вас нет безумно хорошей системы, потому что .NET использует много памяти.

Решение: Повторно используйте частицы, как только частица больше не появляется на экране, или освободите ее память ( вероятно, не будет работать из-за GC) или переместить эту частицу внизу и использовать ее повторно.

0
ответ дан 5 December 2019 в 17:41
поделиться

Вы смотрели на выполнение ShaderEffect с использованием HLSL для рендеринга на GPU? Вы можете написать PixelShader . Вот некоторые другие примеры из одного анонса , и он также имеет несколько хороших ссылок. Это должно определенно быть гладким при рендеринге.

0
ответ дан 5 December 2019 в 17:41
поделиться

Не уверен, что это будет работать лучше, но кто-то собрал эмулятор Silverlight C64 , и техника, которую они используют, заключается в том, чтобы в основном отображать фильм с пользовательским источником (вашим кодом), который обеспечивает кадры.

Преимущество состоит в том, что вы получаете обратные вызовы, когда кадры отображаются, поэтому они могут адаптироваться к фактической скорости воспроизведения. Я не уверен, насколько хорошо это будет работать для более высоких разрешений, хотя пример C64 имеет только экран с низким разрешением для эмуляции.

0
ответ дан 5 December 2019 в 17:41
поделиться

Я решил вашу проблему, удалив строку ellipse.Effect и вместо этого добавил следующее в Window1.xaml

  <Canvas x:Name="ParticleHost">
        <Canvas.Effect>
            <BlurEffect />
        </Canvas.Effect>
    </Canvas>

Конечно, у нее нет тот же вид, у каждого из них свой радиус размытия.

1
ответ дан 5 December 2019 в 17:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: