8

デスクトップやウィンドウに雪の結晶を重ねることができる楽しいプログラムを見つけました。プログラミングの課題として、これを自分で行う方法を理解しようとすることに興味があります。言うまでもなく、このプログラムはメモリを大量に消費します (メモリ リークがなければ)。以下は私が持っているスタートです。1 つのイメージで基本を理解しようとしています。

私が本当に助けてほしいのは、画像をよりスムーズかつ自然に動かすことです.


編集:

下の回答セクションに解決策を投稿しましたが、必要以上に 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">
    <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 コード:

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

フレーククラス:

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
4

2 に答える 2

2

現在提案されている解決策は次のとおりです。最終的に最大の修正要因となったのは、キャンバスを使用したことです。これにより、整数以外の増分で移動でき、cos関数をより効果的に使用できました。私が望むよりもCPUを集中的に使用します(25-30%)。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メインウィンドウ:

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フレーククラス:

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
于 2012-12-05T00:20:37.630 に答える
1

アニメーションを使用するのではなく、なぜ自分で動かすのですか?

WPF のアニメーション (Expression Blend で非常に簡単に実行できます) を使用すると、求める滑らかさを得られ、動きに多少の変化が得られ、よりリアルになると思います。

WPF Expression Blend ビデオ

基本的なアニメーション

于 2012-12-04T03:35:29.577 に答える