2012-12-03 30 views
8

Tôi đã tìm thấy a fun program cho phép bạn overlay snowflakes over your desktop and windows. Là một thách thức lập trình, tôi quan tâm đến việc cố gắng tìm ra cách tự làm điều này. Chưa kể rằng chương trình này là một chút của một bộ nhớ hog (nếu nó không có rò rỉ bộ nhớ). Dưới đây là sự khởi đầu tôi có. Tôi đang cố gắng để có được những điều cơ bản xuống với một hình ảnh và sau đó sẽ mở rộng.Di chuyển phần tử như vảy tuyết rơi

Điều tôi thực sự muốn trợ giúp là làm cho hình ảnh di chuyển trơn tru và tự nhiên hơn.


Edit:

tôi đăng một giải pháp xuống dưới trong phần câu trả lời nhưng nó là nhiều CPU chuyên sâu hơn tôi muốn, bất kỳ suy nghĩ? đang


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> 

VB Code:

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 Class:

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

Không chắc tại sao điều này đã đóng cửa, nó có vẻ như một câu hỏi thực sự với tôi. Anser của tôi sẽ là: Vì bạn đang cố gắng thực hiện một hoạt ảnh trên mỗi khung hình trong WPF, bạn nên sử dụng sự kiện CompositionTarget.Redering thay vì đồng hồ của riêng bạn. Trên sự kiện kết xuất, bạn có thể gọi mã "vẽ" của mình, để chuyển hình ảnh xung quanh. Bạn có thể muốn sử dụng canvas thay vì lưới làm phần tử máy chủ –

Trả lời

1

Tại sao các bạn di chuyển nó cho mình như trái ngược với cách sử dụng một hình ảnh động ?

Nếu bạn sử dụng hoạt ảnh của WPF (thực sự dễ làm trong Expression Blend), tôi nghĩ bạn sẽ có được độ mượt mà bạn đang tìm kiếm và bạn có thể nhận được một số thay đổi trong chuyển động, làm cho nó trở nên thật hơn.

WPF Expression Blend Videos

Basic Animation

+0

Cảm ơn bạn đã đề xuất này. Thông qua bài tập này, tôi đã khám phá ra sự tồn tại của sự pha trộn biểu thức. Trong khi nó trông gọn gàng, tôi không đặc biệt quan tâm đến việc mua phần mềm vào lúc này. Tôi sẽ làm một số nghiên cứu về làm thế nào để làm WPF hoạt hình mà không có Expression Blend nhưng tất nhiên sẽ được biết ơn đối với bất kỳ lời đề nghị. – volderArt

+0

Bất cứ điều gì bạn có thể làm trong Blend bạn có thể làm trong XAML tinh khiết cũng vì vậy không cần phải mua Blend, nó chỉ là một GUI để thao tác XAML trực quan ... –

+0

Vâng, bạn phải mua Expression Blend hoặc nếu bạn may mắn, bạn sẽ có được Visual Studio Premium với MSDN (hoặc Ultimate) thông qua công việc của bạn. Bây giờ, bạn có thể sử dụng bản dùng thử. Nó là hoàn toàn giá trị nó để sử dụng thử nghiệm để làm theo các video và tìm hiểu các xaml. – Rhyous

2

Đây là giải pháp hiện đề xuất của tôi: Điều gì đã kết thúc là những yếu tố điều chỉnh lớn nhất là rằng tôi đã sử dụng vải, cho phép tôi để di chuyển trong từng bước phi nguyên và tôi cũng sử dụng hàm cos hiệu quả hơn. Nó là CPU nhiều hơn tôi muốn (25-30%). Có ai có bất kỳ ý tưởng về việc giảm tác động trên CPU?

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 Main Window:

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 flake lớp:

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 
Các vấn đề liên quan