游戏人生Silverlight(2) - 趣味钢琴[Silverlight 2.0(c#)]

[源码下载]


游戏人生Silverlight(2) - 趣味钢琴[Silverlight 2.0(c#)]


作者:webabcd


介绍
使用 Silverlight 2.0(c#) 开发一个趣味钢琴


玩法
打开音箱,从左侧列表选择要挑战的乐谱,右侧会出现对应的乐谱提示动画,等按键提示移动到目标区后敲击键盘上对应的按键


在线DEMO



思路
1、添加多个MediaElement控件,循环使用,以达到同时播放多个音阶的效果
2、提示按键模块分3组动画,分别为提示部分、目标部分和离开部分,进入目标区和离开目标区都要触发对应的事件,以使外部判断用户是否按照提示正确地敲击了按键


关键代码
1、钢琴音阶播放器
ScalePlayer.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace YYPiano.Controls.Parts
{
         public partial class ScalePlayer : UserControl
        {
                 // MediaElement 控件总数
                 private int _count = 32;

                 // MediaElement 控件集合的索引
                 private int _index = 0;

                 public ScalePlayer()
                {
                        InitializeComponent();

                         this.Loaded += new RoutedEventHandler(Player_Loaded);
                }

                 void Player_Loaded( object sender, RoutedEventArgs e)
                {
                         // 在 Canvas 上添加指定数量的 MediaElement 控件
                         for ( int i = 0; i < _count; i++)
                        {
                                var element = new MediaElement();
                                element.Volume = 1d;

                                root.Children.Add(element);
                        }
                }

                 /// <summary>
                 /// 播放音阶
                 /// A 键对应 Scale 文件夹内的 A.mp3,以此类推
                 /// A 键对应 C 大调的低音 dou,以此类推
                 /// </summary>
                 /// <param name="key">键值</param>
                 public void Play(Key key)
                {
                         if (key >= Key.A && key <= Key.Z)
                        {
                                 // 循环使用 MediaElement 控件集合中的控件
                                 if (_index > _count - 1)
                                        _index = 0;

                                 // 设置 MediaElement 的 Source 并播放
                                var element = root.Children[_index] as MediaElement;
                                element.Source = new Uri( "/YYPiano;component/Scale/" + key.ToString() + ".mp3", UriKind.Relative);
                                element.Stop();
                                element.Play();

                                _index++;
                        }
                }
        }
}
 
2、按键提示动画
AnimationKey.xaml
<UserControl x:Class="YYPiano.Controls.Parts.AnimationKey"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
        <Canvas>
                <!--3个椭圆,目标区,按键动画进入该区域后敲击则为有效敲击-->
                <Ellipse x:Name="target" Width="80" Height="80" Stroke="#F80" Fill="Transparent" StrokeThickness="1" Canvas.Left="0" Canvas.Top="250" />
                <Ellipse x:Name="target2" Width="80" Height="80" Stroke="#F80" Fill="Transparent" StrokeThickness="1" Canvas.Left="120" Canvas.Top="250" />
                <Ellipse x:Name="target3" Width="80" Height="80" Stroke="#F80" Fill="Transparent" StrokeThickness="1" Canvas.Left="240" Canvas.Top="250" />

                <!--提示按键-->
                <Border x:Name="container" BorderBrush="Gray" BorderThickness="1" Width="50" Height="50" CornerRadius="50" Canvas.Left="135" RenderTransformOrigin="0.5, 0.5">
                        <TextBlock x:Name="key" TextAlignment="Center" VerticalAlignment="Center" FontSize="40" FontWeight="Bold">
                        </TextBlock>
                        <Border.RenderTransform>
                                <TransformGroup>
                                        <RotateTransform x:Name="rt" />
                                        <TranslateTransform x:Name="tt" />
                                        <ScaleTransform x:Name="st" ScaleX="0.3" ScaleY="0.3" />
                                </TransformGroup>
                        </Border.RenderTransform>
                </Border>

                <Canvas.Resources>
                        <!--主动画(缓冲提示)-->
                        <Storyboard x:Name="mainAni" Completed="mainAni_Completed">
                                <!--坐标-->
                                <DoubleAnimation x:Name="targetX" From="0" To="0" Duration="0:0:4" Storyboard.TargetName="tt" Storyboard.TargetProperty="X" />
                                <DoubleAnimation From="0" To="250" Duration="0:0:4" Storyboard.TargetName="tt" Storyboard.TargetProperty="Y" />

                                <!--旋转-->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="rt" Storyboard.TargetProperty="Angle" RepeatBehavior="1x" >
                                        <SplineDoubleKeyFrame Value="366" KeySpline="0.1,0 0.2,0.95" KeyTime="0:0:4" />
                                </DoubleAnimationUsingKeyFrames>

                                <!--缩放-->
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleX">
                                        <SplineDoubleKeyFrame Value="1" KeySpline="0.1,0 0.3,0.8" KeyTime="0:0:4" />
                                </DoubleAnimationUsingKeyFrames>
                                <DoubleAnimationUsingKeyFrames Storyboard.TargetName="st" Storyboard.TargetProperty="ScaleY">
                                        <SplineDoubleKeyFrame Value="1" KeySpline="0.1,0 0.3,0.8" KeyTime="0:0:4" />
                                </DoubleAnimationUsingKeyFrames>
                        </Storyboard>

                        <!--进入目标区后的动画-->
                        <Storyboard x:Name="insideAni" Completed="insideAni_Completed" Duration="0:0:0.4">
                                <DoubleAnimation To="310" Storyboard.TargetName="tt" Storyboard.TargetProperty="Y" />
                        </Storyboard>

                        <!--离开目标区后的动画-->
                        <Storyboard x:Name="outsideAni">
                                <DoubleAnimation To="400" Storyboard.TargetName="tt" Storyboard.TargetProperty="Y" />
                                <DoubleAnimation To="0" Storyboard.TargetName="container" Storyboard.TargetProperty="Opacity" />
                        </Storyboard>
                </Canvas.Resources>
        </Canvas>
</UserControl>
 
AnimationKey.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace YYPiano.Controls.Parts
{
         public partial class AnimationKey : UserControl
        {
                 public AnimationKey()
                {
                        InitializeComponent();
                }

                 /// <summary>
                 /// 键值 A - Z,动画显示,用于提示用户应该敲什么键
                 /// </summary>
                 public Key Key
                {
                        get { return Convert.ToChar(key.Text).ToKey(); }
                        set { key.Text = value.ToChar().ToString(); }
                }

                 /// <summary>
                 /// 开始动画
                 /// </summary>
                 public void Start()
                {
                        mainAni.Begin();
                }

                 /// <summary>
                 /// 停止动画
                 /// </summary>
                 public void Stop()
                {
                        mainAni.Stop();
                        insideAni.Stop();
                        outsideAni.Stop();
                }

                 /// <summary>
                 /// 动画开始时间
                 /// </summary>
                 public TimeSpan BeginTime
                {
                        set { mainAni.BeginTime = value; }
                }

                 private int _targetIndex;
                 /// <summary>
                 /// UI 上设置了 3 个目标区,设置键的动画最终要落到哪个区上
                 /// </summary>
                 public int TargetIndex
                {
                        set
                        {
                                 if (value == 0)
                                        targetX.To = -120;
                                 else if (value == 1)
                                        targetX.To = 0;
                                 else if (value == 2)
                                        targetX.To = 120;
                                 else
                                        targetX.To = 0;

                                _targetIndex = value;
                        }
                }

                 /// <summary>
                 /// 主动画完成后
                 /// </summary>
                 /// <param name="sender"></param>
                 /// <param name="e"></param>
                 private void mainAni_Completed( object sender, EventArgs e)
                {
                         if (_targetIndex == 0)
                                target.Fill = new SolidColorBrush(Colors.Orange);
                         else if (_targetIndex == 1)
                                target2.Fill = new SolidColorBrush(Colors.Orange);
                         else if (_targetIndex == 2)
                                target3.Fill = new SolidColorBrush(Colors.Orange);

                        insideAni.Begin();

                        OnInside();
                }

                 /// <summary>
                 /// 目标区动画完成后
                 /// </summary>
                 /// <param name="sender"></param>
                 /// <param name="e"></param>
                 private void insideAni_Completed( object sender, EventArgs e)
                {
                         if (_targetIndex == 0)
                                target.Fill = new SolidColorBrush(Colors.Transparent);
                         else if (_targetIndex == 1)
                                target2.Fill = new SolidColorBrush(Colors.Transparent);
                         else if (_targetIndex == 2)
                                target3.Fill = new SolidColorBrush(Colors.Transparent);

                        outsideAni.Begin();

                        OnOutside();
                }

                 /// <summary>
                 /// 动画进入目标区后的事件
                 /// </summary>
                 public event EventHandler<PianoKeyEventArgs> Inside;
                 public void OnInside()
                {
                         if (Inside != null)
                        {
                                Inside( this, new PianoKeyEventArgs() { Key = this.Key });
                        }
                }

                 /// <summary>
                 /// 动画离开目标区后的事件
                 /// </summary>
                 public event EventHandler<PianoKeyEventArgs> Outside;
                 public void OnOutside()
                {
                         if (Outside != null)
                        {
                                Outside( this, new PianoKeyEventArgs() { Key = this.Key });
                        }
                }
        }
}
 
 
未完待续>>

你可能感兴趣的:(游戏,人生,silverlight,趣味,钢琴)