2017-01-03 222 views
0

我想在我的網格中創建一個動畫。我有一個5x5的網格,每個網格顯示一個按鈕。在網格加載之後,其中一個按鈕應隨機地將其顏色更改爲綠色。 1秒後該按鈕應該變回,另一個應該將其顏色改變爲綠色。網格動畫(按鈕顏色變化)

如果用戶能夠將此1秒鐘他的鼠標(鼠標懸停)按鈕應他的顏色變爲紅色,並保持紅色內達到這個按鈕。將他的顏色改爲綠色的下一個按鈕不應該是這個。

這應該是一個小遊戲。我的問題是,實現這個遊戲最簡單的方法是什麼?

請幫幫我!

<Page x:Class="LeapTest.Layout" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:local="clr-namespace:LeapTest" 
    mc:Ignorable="d" 
    d:DesignHeight="1050" d:DesignWidth="1000" 
    Title="Layout"> 

<Page.Resources> 
    <Style x:Key="pageTitle" TargetType="TextBlock"> 
     <Setter Property="Background" Value="DimGray"/> 
     <Setter Property="FontSize" Value="40"/> 
     <Setter Property="FontFamily" Value="Arial"/> 
     <Setter Property="TextAlignment" Value="Center"/> 
     <Setter Property="Padding" Value="0,5,0,5"/> 
    </Style> 

    <Style x:Key="Grid" TargetType="Grid"> 
     <Setter Property="Background" Value="White"/> 
    </Style> 

    <Style x:Key="Button" TargetType="Button"> 
     <Setter Property="Background" Value="White"/> 
     <Setter Property="BorderBrush" Value="Green"/> 
     <Setter Property="BorderThickness" Value="2"/> 
    </Style> 

</Page.Resources> 

<Grid Style="{StaticResource Grid}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="50" /> 
     <RowDefinition Height="200" /> 
     <RowDefinition Height="200" /> 
     <RowDefinition Height="200" /> 
     <RowDefinition Height="200" /> 
     <RowDefinition Height="200" /> 
    </Grid.RowDefinitions> 

    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="200" /> 
     <ColumnDefinition Width="200" /> 
     <ColumnDefinition Width="200" /> 
     <ColumnDefinition Width="200" /> 
     <ColumnDefinition Width="200" /> 
    </Grid.ColumnDefinitions> 

    <TextBlock Grid.Column="0" Grid.ColumnSpan="5" Style="{StaticResource pageTitle}"> LEAP Motion </TextBlock> 

    <Button Name ="BTN_0_0" Grid.Column="0" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_0_1" Grid.Column="1" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_0_2" Grid.Column="2" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_0_3" Grid.Column="3" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_0_4" Grid.Column="4" Grid.Row="1" Click="BTN_Click" Style="{StaticResource Button}"/> 

    <Button Name ="BTN_1_0" Grid.Column="0" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_1_1" Grid.Column="1" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_1_2" Grid.Column="2" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_1_3" Grid.Column="3" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_1_4" Grid.Column="4" Grid.Row="2" Click="BTN_Click" Style="{StaticResource Button}"/> 

    <Button Name ="BTN_2_0" Grid.Column="0" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_2_1" Grid.Column="1" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_2_2" Grid.Column="2" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_2_3" Grid.Column="3" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_2_4" Grid.Column="4" Grid.Row="3" Click="BTN_Click" Style="{StaticResource Button}"/> 

    <Button Name ="BTN_3_0" Grid.Column="0" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_3_1" Grid.Column="1" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_3_2" Grid.Column="2" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_3_3" Grid.Column="3" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_3_4" Grid.Column="4" Grid.Row="4" Click="BTN_Click" Style="{StaticResource Button}"/> 

    <Button Name ="BTN_4_0" Grid.Column="0" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_4_1" Grid.Column="1" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_4_2" Grid.Column="2" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_4_3" Grid.Column="3" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/> 
    <Button Name ="BTN_4_4" Grid.Column="4" Grid.Row="5" Click="BTN_Click" Style="{StaticResource Button}"/> 

</Grid> 

//BackEnd Code 
     private void BTN_Click(object sender, RoutedEventArgs e) 
    { 
     //BTN1.Background = Brushes.Green; 

     Button btnTest = (Button)sender; 
     if (btnTest.Background == Brushes.Green) 
     { 
      btnTest.Background = Brushes.White; 
     } 
     else 
     { 
      btnTest.Background = Brushes.Green; 
     } 
    } 
+0

什麼你的代碼是後端嗎?你試過了什麼? –

+0

後端代碼確實很有趣,你也可以用模板創建你的網格/按鈕(綁定到值或簡單模型的支持列表),它應該清理你的代碼 – Staeff

+0

我使用Visual Studio進行編程,我已經嘗試使用故事板......但由於不同的原因而失敗。其中之一是我不知道如何在沒有鼠標事件的情況下開始動畫 –

回答

0

你應該遍歷一個特殊的名稱或標記的形式上的所有按鈕控件。將其保存在數組中,隨機選擇一個並更改其顏色。如果鼠標懸停找到具有正確顏色的那個,則可以調用隨機查找控件的方法等等。

這應該是相當直截了當。因爲這看起來像功課。我不會爲你解決它,因爲你不會學到任何東西。想想需要做些什麼,並分別在各個部分中進行谷歌搜索。嘗試瞭解它,然後繼續!祝你好運!

0

編輯:關於在嚴格的方式你的問題,你不需要動畫acheive你想做的事,除非你需要的是動畫顏色變化是什麼。

這裏是一個完整的工作示例不使用MVVM但使用代表按鈕的模型集合。

主窗口/頁代碼處理所有的邏輯(隨機,模型的變化,等):

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    private const int BTN_NUMBERS = 25; 
    private ObservableCollection<ButtonModel> _buttonsCollection; 
    private ButtonModel _currentTarget; 

    public ObservableCollection<int> ExcludedItems 
    { 
     get { return _excludedItems; } 
     private set { _excludedItems = value; OnPropertyChanged(); } 
    } 

    private Random _rnd; 
    private Timer _timer; 
    private ObservableCollection<int> _excludedItems = new ObservableCollection<int>(); 

    public MainWindow() 
    { 
     DataContext = this; 

     InitializeComponent(); 
     ButtonsCollection = new ObservableCollection<ButtonModel>(); 
     for (int i = 0; i < BTN_NUMBERS; i++) 
     { 
      ButtonsCollection.Add(new ButtonModel() { ButtonNumber = i }); 
     } 

     Start(); 
    } 

    private void Start() 
    { 
     _currentTarget = null; 
     foreach (var bm in ButtonsCollection) 
     { 
      bm.IsCurrentTarget = bm.IsReached = false; 
     } 
     ExcludedItems.Clear(); 
     _rnd = new Random(DateTime.Now.Second); 
     _timer = new Timer(OnTargetChanged, null, 0, 1000); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public ObservableCollection<ButtonModel> ButtonsCollection 
    { 
     get { return _buttonsCollection; } 
     set { _buttonsCollection = value; OnPropertyChanged(); } 
    } 

    void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    private void Btn_candidate_OnMouseEnter(object sender, MouseEventArgs e) 
    { 
     ButtonModel model = ((Button)sender).DataContext as ButtonModel; 
     if (model != null && model.IsCurrentTarget && !ExcludedItems.Contains(model.ButtonNumber)) 
     { 
      model.IsReached = true; 
      ExcludedItems.Add(model.ButtonNumber); 
     } 
    } 

    private void ChangeTarget() 
    { 
     var target = GetNextTarget(); 
     if (target == -1) 
     { 

      if (_timer != null) 
      { 
       _timer.Dispose(); 
       _timer = null; 
      } 
      MessageBox.Show("All items have been reached ! Congratulations"); 
     } 
     if (_currentTarget != null) _currentTarget.IsCurrentTarget = false; 
     _currentTarget = ButtonsCollection[target]; 
     _currentTarget.IsCurrentTarget = true; 
    } 

    private int GetNextTarget() 
    { 
     if (ExcludedItems.Count == BTN_NUMBERS) 
     { 
      return -1; 
     } 
     var target = _rnd.Next(0, BTN_NUMBERS); 
     if (ExcludedItems.Contains(target)) 
     { 
      return GetNextTarget(); 
     } 
     return target; 
    } 

    private void OnTargetChanged(object state) 
    { 
     this.Dispatcher.InvokeAsync(ChangeTarget); 
    } 

    private void Btn_startover_OnClick(object sender, RoutedEventArgs e) 
    { 
     Start(); 
    } 
} 

表示的按鈕的模式,即包含觸發XAML變化的代碼:

public class ButtonModel : INotifyPropertyChanged 
{ 
    private bool _isCurrentTarget; 
    private bool _isReached; 

    public event PropertyChangedEventHandler PropertyChanged; 

    public int ButtonNumber { get; set; } 

    public bool IsCurrentTarget 
    { 
     get { return _isCurrentTarget; } 
     set { _isCurrentTarget = value; OnPropertyChanged(); } 
    } 

    public bool IsReached 
    { 
     get { return _isReached; } 
     set { _isReached = value; OnPropertyChanged(); } 
    } 

    private void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

最後,也是最重要的,簡化的XAML代碼:

<Window x:Class="GridAnimame.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:GridAnimame" 
    mc:Ignorable="d" 
    d:DataContext="{d:DesignInstance {x:Type local:MainWindow}}" 
    Title="MainWindow" Height="500" Width="500"> 
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="400"/> 
     <ColumnDefinition/> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="400"/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 
    <ItemsControl ItemsSource="{Binding ButtonsCollection}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <UniformGrid /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Button Name="btn_candidate" MouseEnter="Btn_candidate_OnMouseEnter" Margin="1"> 
        <Button.Template> 
         <ControlTemplate TargetType="Button"> 
          <Border x:Name="brd_btn_layout" Background="LightGray" BorderBrush="Black" BorderThickness="1"> 
           <TextBlock Text="{Binding ButtonNumber}" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="Black"></TextBlock> 
          </Border> 
          <ControlTemplate.Triggers> 
           <DataTrigger Binding="{Binding IsCurrentTarget}" Value="true"> 
            <Setter TargetName="brd_btn_layout" Property="Background" Value="Green"></Setter> 
           </DataTrigger> 
           <DataTrigger Binding="{Binding IsReached}" Value="true"> 
            <Setter TargetName="brd_btn_layout" Property="Background" Value="Red"></Setter> 
           </DataTrigger> 
          </ControlTemplate.Triggers> 
         </ControlTemplate> 
        </Button.Template> 
       </Button> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

    <ListBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding ExcludedItems}"></ListBox> 

    <Button x:Name="btn_startover" Grid.Row="1" Grid.Column="1" Content="Start Over !" Margin="2" Click="Btn_startover_OnClick"></Button> 
</Grid> 

Althought邏輯可以改進,下面是這個樣的關鍵點:

  • 不聲明在XAML中靜態的方式,所有的按鈕。相反,你的主模型認爲代表在按鈕和包含所有將觸發XAML(視覺)變化的數據模型的集合。因此,在XAML表示網格中的控制被綁定到該集合

  • 邏輯由throught代碼和這個loggic的視覺效果使用XAML

  • 只有2東西聲明觸發器被反射還是要做有一個乾淨的方法:1)主窗口的邏輯,現在可以很容易地被封裝到一個真正的視圖模型將作爲窗口數據上下文和2)事件應該由DelegateCommands更換