2012-12-03 10 views
8

Znalazłem a fun program, który pozwala na overlay snowflakes over your desktop and windows. Jako wyzwanie programistyczne jestem zainteresowany próbą samodzielnego rozwiązania tego problemu. Nie wspominając o tym, że ten program jest trochę pamięciowy (jeśli nie ma wycieku pamięci). Poniżej jest początek, który mam. Próbuję zepsuć podstawy jednym obrazem, a następnie rozwinąć.Przenieś element, taki jak spadający płatek śniegu.

To, co naprawdę chciałbym uzyskać, sprawi, że obraz będzie płynniej i bardziej naturalnie.


Edit:

napisałem rozwiązanie w dół poniżej w sekcji odpowiedzi, ale to jest bardziej intensywna niż CPU Chciałbym, wszelkie myśli? Kod


WPF XAML:

<Window x:Class="MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    AllowsTransparency="True" 
     WindowStyle="None" 
    Title="MainWindow" Height="350" Width="525" Background="Transparent" Topmost="True" WindowState="Maximized" ResizeMode="NoResize"> 
    <Grid Name="grid1"> 
     <Image Height="26" HorizontalAlignment="Left" Margin="{Binding flakeMargin}" Name="Image1" Stretch="Fill" VerticalAlignment="Top" Width="28" Source="/snowTest;component/Images/blue-pin-md.png" /> 
    </Grid> 
</Window> 

kod VB:

Imports System.ComponentModel 

    Class MainWindow 
     Dim bw As BackgroundWorker = New BackgroundWorker 
     Dim flake0 As New flake 

     Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded 
      grid1.DataContext = flake0 
      AddHandler bw.DoWork, AddressOf backgroundMover 
      bw.RunWorkerAsync() 
     End Sub 

     Private Sub backgroundMover(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) 
      While (True) 
       flake0.move() 
       System.Threading.Thread.Sleep(100) 
      End While 
     End Sub 
    End Class 

Flake Klasa:

Imports System.ComponentModel 

Public Class flake 
    Implements INotifyPropertyChanged 

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged 

    Private Sub NotifyPropertyChanged(ByVal info As String) 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info)) 
    End Sub 

    Private Property startLeft As Integer = 300 
    Private Property left As Integer = left 
    Private Property top As Integer = 100 
    Private Property speed As Integer = 1 

    Public ReadOnly Property flakeMargin As Thickness 
     Get 
      Return New Thickness(left, top, 0, 0) 
     End Get 
    End Property 

    Public Sub move() 
     top += speed 
     left = (Math.Cos(top - 100)) * 6 + startLeft 
     NotifyPropertyChanged("flakeMargin") 
    End Sub 
End Class 
+6

Nie wiem, dlaczego ten został zamknięty, wydaje się, prawdziwe pytanie do mnie. Mój byłby: Ponieważ próbujesz zrobić animację na klatkę w WPF, powinieneś używać zdarzenia CompositionTarget.Redering zamiast własnego zegara. W zdarzeniu renderowania możesz wywołać swój kod "rysuj", który będzie przesuwał obraz. Prawdopodobnie chcesz użyć płótna zamiast siatki jako elementu hosta. –

Odpowiedz

1

Czemu przesuwając go samodzielnie w przeciwieństwie do korzystania z animacji ?

Jeśli korzystasz z Animacji WPF (która jest naprawdę łatwa do wykonania w Wyrażeniowej Mieszance), myślę, że uzyskasz gładkość, której szukasz i możesz uzyskać pewne zmiany w ruchu, czyniąc ją bardziej realistyczną.

WPF Expression Blend Videos

Basic Animation

+0

Dziękuję za to zalecenie. Dzięki temu ćwiczeniu odkryłem istnienie mieszanki ekspresji. Choć wygląda schludnie, nie jestem szczególnie zainteresowany zakupem oprogramowania w tej chwili. Zrobię kilka badań, jak zrobić animację WPF bez Expression Blend, ale oczywiście byłbym wdzięczny za wszelkie sugestie. – volderArt

+0

Wszystko, co możesz zrobić w Blendzie, możesz zrobić w czystym XAML, więc nie musisz kupować Blend, to tylko GUI do manipulowania XAML wizualnie ... –

+0

Tak, musisz albo kupić Expression Blend, albo jeśli masz szczęście, otrzymasz Visual Studio Premium z MSDN (lub Ultimate) poprzez swoją pracę. Na razie możesz skorzystać z wersji próbnej. Całkowicie warto skorzystać z wersji próbnej, aby śledzić filmy i nauczyć się XAML. – Rhyous

2

Oto moja obecnie proponowane rozwiązanie: Co skończyło się największe czynniki korygujące były że użyłem płótna, co pozwoliło mi poruszać się w odstępach nie jest liczbą całkowitą, a ja również cos działają bardziej efektywnie. Jest bardziej intensywny procesor, niż bym chciał (25-30%). Czy ktoś ma jakieś pomysły na zmniejszenie wpływu na procesor?

WPF/XAML:

<Window x:Class="MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    AllowsTransparency="True" 
     WindowStyle="None" 
    Title="MainWindow" Height="350" Width="525" Background="Transparent" Topmost="True" WindowState="Maximized" ResizeMode="NoResize"> 
    <Canvas Name="canvas1"> 

    </Canvas> 
</Window> 

VB.NET Okno główne:

Imports System.ComponentModel 

Class MainWindow 

    Dim bw As New BackgroundWorker 
    Dim flakes(17) As flake 

    Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded 
     For i = 0 To flakes.Count - 1 
      flakes(i) = New flake 
      flakes(i).image.DataContext = flakes(i) 
      flakes(i).image.SetBinding(Canvas.LeftProperty, "left") 
      flakes(i).image.SetBinding(Canvas.TopProperty, "top") 
      canvas1.Children.Add(flakes(i).image) 
     Next 

     AddHandler bw.DoWork, AddressOf backgroundMover 
     bw.RunWorkerAsync() 
    End Sub 


    Private Sub backgroundMover() 
     While (True) 
      For Each f In flakes 
       f.move() 
      Next 
      System.Threading.Thread.Sleep(50) 
     End While 
    End Sub 
End Class 

VB.Net płatek klasa:

Imports System.ComponentModel 

Public Class flake 
    Implements INotifyPropertyChanged 

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged 

    Private Sub NotifyPropertyChanged(ByVal info As String) 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info)) 
    End Sub 

    Private Property startLeft As Double 
    Private Property _left As Double 
    Private Property _top As Double 
    Private Property speed As Double 
    Private Property amplitude As Double 
    Private Property period As Double 
    Public Property image As New Image 
    Private Shared Property r As New Random 

    Public Sub New() 
     _image.Width = 28 
     _image.Height = 26 
     _image.Source = New System.Windows.Media.Imaging.BitmapImage(New Uri("/snowTest;component/Images/blue-pin-md.png", UriKind.Relative)) 
     startFresh() 
    End Sub 

    Public ReadOnly Property left As Double 
     Get 
      Return _left 
     End Get 
    End Property 

    Public ReadOnly Property top As Double 
     Get 
      Return _top 
     End Get 
    End Property 

    Public Sub startFresh() 
     _top = -30 
     amplitude = r.Next(5, 35) 
     period = 1/r.Next(20, 60) 
     speed = r.Next(15, 25)/10 
     startLeft = r.Next(0, System.Windows.SystemParameters.PrimaryScreenWidth) 
    End Sub 

    Public Sub move() 
     If _top > System.Windows.SystemParameters.PrimaryScreenHeight Then 
      startFresh() 
     Else 
      _top += speed 
      _left = amplitude * Math.Cos(period * _top) + startLeft 
     End If 

     NotifyPropertyChanged("top") 
     NotifyPropertyChanged("left") 
    End Sub 
End Class 
Powiązane problemy