I found a fun program that allows you to overlay snowflakes over your desktop and windows. As a programming challenge I am interested in trying to figure out how to do this myself. Not to mention that this program is a bit of a memory hog (if it doesn't have a memory leak). Below is the start I have. I am trying to get the basics down with one image and then will expand.
What I would really like help on is making the image move more smoothly and naturally.
Edit:
I posted a solution down below in the answers section but it is more CPU intensive than I would like, any thoughts?
WPF XAML code:
<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
To find these snowflakes, use PowerPoint's Online Pictures option on the Insert tab in the Images group. In the search control, enter snowflake and press Enter. Make sure to check the Creative Commons only option and start inserting snowflake images.
Go to Giphy.com and search for “snow transparent”, choose the GIF you like the most and select it. Go to copy link and get it, once you have it copied to your clipboard, go to your Google Slide and select Insert > Image > By URL and paste the link.
Here is my currently proposed solution: What ended up being the biggest correcting factors were that I used the canvas, which allowed me to move in non-integer increments and I also used the cos function more effectively. It is more CPU intensive than I would like (25-30%). Does any one have any ideas on reducing the impact on the 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 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 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
Why are you moving it yourself as opposed to using an animation?
If you use WPF's Animation (which is really easy to do in Expression Blend), I think you will get the smoothness you are looking for and you can get some variation in movement, making it more real.
WPF Expression Blend Videos
Basic Animation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With