您的位置:首页 > 编程语言 > C#

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

2009-02-16 08:38 471 查看
[源码下载]

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

作者: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 });


}


}


}


}

未完待续>>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息