Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放(三十九)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示

 

本节完后,同时会更新Silverlight+WCF 新手实例 象棋 专题索引,并顺路提供第八阶段源码

 

Silverlight+WCF 新手实例 象棋 主界面-棋谱-布局写谱(三十六)节中,我们完成了下棋双方的棋谱传递

Silverlight+WCF 新手实例 象棋 主界面-棋谱-获取列表(三十八)节中,我们完成了观棋者获取棋谱列表

在本节中,我们要进行最一步了,棋谱回放:

首先,当用户进入列表后,获取完棋谱信息之后,第一个动作,就是要把棋谱按顺序播放一下,这样,用户看到棋局就是双方正在下的棋局了,之后,就跟下棋一样,一步步接收棋步,然后一步步的自动移动就行了。

我们播放哪里的棋谱呢的?

界面上显示的ListBox显然是不能用来循环读取的,毕竟那显示的是格式化后的字符串,从字符串解析回棋步是不现实的;

一开始获取的列表不是可以循环?那也只有一部分,之后棋手双方下的呢?

所以,说了这么多,其实不就是想找多个变量来存棋谱列表么,于是,我们在App.xaml.cs全局又添加一个全局变量了:


public partial class App : Application
    {
     //...省略N行代码...
        public static List<GameService.MoveStep> stepList = new List<GameService.MoveStep>();//棋谱
        public static bool chessManualPlaying = false;//棋谱正回放中
        //...省略N行代码...
        public App()
        {
         //...省略N行代码...
        }
        //...省略N行代码...

}

 

这里又顺路添加了一个全局属性,用于设置棋谱是不是正在回放中,后面我们会用到[很后哦]。

OK,全局棋谱存贮变量有了,我们就得为它增加棋谱数据了,我们会在两个地方添加棋谱,

1:一个是用户下棋时传递时的棋谱:

我们进入Chess.xaml.cs,找到收到棋谱通知的代码,只需要添加一行,第一行,把棋步添加一下就行了:


void client_NotifyMoveStepReceived(object sender, NotifyMoveStepReceivedEventArgs e)
        {
            App.stepList.Add(e.player.Step);//只需要一行
            if (App.player.ID != e.player.ID)//非自己
            {
               //...省略N行...
            }
            HelpSetChessManualEvent(e.player.Step);
        }

 

 

2:进入页面时获取的棋谱列表读取到棋谱区时:

我们进入ChessManual.xaml.cs,找到获取棋谱列表的代码,同样只需要一行:


 void client_GetMoveStepListCompleted(object sender, GameService.GetMoveStepListCompletedEventArgs e)
        {
            //获取完棋谱后,这里循环调用添加就可以了
            if (e.Result != null && e.Result.Count > 0)
            {
                App.stepList = e.Result;//这里只需要一行代码
                foreach (GameService.MoveStep step in e.Result)
                {
                    lbChessManual.Items.Add(step.ID + ":" + step.Name);
                }
            }
        }

 

 

OK,我们对全局棋谱的传值,两行代码就搞定了,于是在播放棋谱时,理论上我们循环全局的stepList就行了:

我们先产生一个方法,用于播放一个棋步,就是传进一个棋步,然后自动播放:


void AutoMove(GameService.MoveStep step)
        {
            Point from = new Point(step.FromX, step.FromY);
            Point to = new Point(step.ToX, step.ToY);
            if (App.player.ColorValue + step.ColorValue == 3 || (step.ColorValue == 2 && App.player.ColorValue == 3))//旁观者 黑色棋子
            {
                from = App.chess.ReverseArray(from);
                to = App.chess.ReverseArray(to);
            }
            App.chess.Action.AutoMoveTo(from, to);
        }

 

这个方法其实有点简单,只要调用AotoMoveTo就搞完了,唯一的复杂点,就是判断要不要反转坐标了。

[两种情况:如果是下棋者,棋步是对手的,要反转坐标;观众默认是红色的,收到黑色棋步,也要反转坐标]

 

好了,有了单步的方法,我们for一下step里,然后循环传值就OK了?No,如果这样循环,棋步刷的一下就没了,还看啥回放?

因此,我们需要定间隔播放了,所以,我们需要先产生间隔的秒数,我们通过滑动块来设置文本框的数字:

我们设置一下滑动块的属性[默认值为0,最大值为9,最小滑动为0.5,最大滑动为1]:

我们同时添加滑动事件:

而我们滑动时只需要一行代码,为文本框赋值就行了:

private void slPlayerInternal_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            txtValue.Text = e.NewValue.ToString();
        }

 

我们增加一个方法,叫PlayStep,用于循环播放棋步:

private void PlayStep()
{     
   //待实现
}

 

好了,接着我们双击一下“回放”按钮,里面调用一下这个PlayStep就行了:

private void btnPlay_Click(object sender, RoutedEventArgs e)
{
  PlayStep();
}

 

默认我们加载完棋步列表后,也要定位棋步,所以也调用一下PlayStep:


void client_GetMoveStepListCompleted(object sender, GameService.GetMoveStepListCompletedEventArgs e)
        {
            //获取完棋谱后,这里循环调用添加就可以了
            if (e.Result != null && e.Result.Count > 0)
            {
                App.stepList = e.Result;//这里只需要一行代码
                foreach (GameService.MoveStep step in e.Result)
                {
                    lbChessManual.Items.Add(step.ID + ":" + step.Name);
                }
                PlayStep();//加完后马上调用播放棋步,默认0秒,所以刷一下就播放完了
            }
        }

 

于是,所有的重点只剩下怎么实现这个PlayStep了。

我们每一步棋步都需要间隔N秒走一步,一开始我竟然用线程的Sleep来操作,结果是,程序卡住了,直接播放完了才能动,那个汗-_-!

于是,N久之后,非线程阻塞的timer出来了,让它定时每N秒走一步就行了:

全局定义一下timer先,顺路加上移动的索引:

public partial class ChessManual : UserControl
    {
        System.Windows.Threading.DispatcherTimer timer;//定义timer
        int moveStepIndex = 0;//移动到第几步了
         
         //...下面省略N行...
}

 

接着初始化timer及事件:


 public partial class ChessManual : UserControl
    {
        System.Windows.Threading.DispatcherTimer timer;//定义timer
        int moveStepIndex = 0;//移动到第几步了
        public ChessManual()
        {
            //...省略N行...
            timer = new System.Windows.Threading.DispatcherTimer();
            timer.Tick += new EventHandler(timer_Tick);
        }

        void timer_Tick(object sender, EventArgs e)
        {
            //待实现
        }

            //...省略N行...
     }

 

我们这里没有初始化timer的间隔时间,是因为把间隔时间设置放到PlayStep函数里了,说到PlayStep,我们可以实现它了:


private void PlayStep()
        {
            if (App.stepList.Count > 0)
            {
                //播放前复位棋子
                  App.chess.Reset();
                timer.Interval = TimeSpan.FromSeconds(slPlayerInternal.Value);
                timer.Start();
            }
        }

 

我们只用了小小几行代码,其实就是设置一下时间,然后让timer它Start起来就完事了,于是重心又一步转移到timer的tick事件里了:


 void timer_Tick(object sender, EventArgs e)
        {
            //待实现
            GameService.MoveStep step = App.stepList[moveStepIndex];//获取棋步
            lbChessManual.SelectedIndex = moveStepIndex;//定位棋步索引
            lbChessManual.UpdateLayout();//需要更新下布局
            lbChessManual.ScrollIntoView(lbChessManual.SelectedItem);//滚动到先中的项
            AutoMove(step);//移动棋步
            moveStepIndex++;//索引加1
            if (moveStepIndex == App.stepList.Count)//判断棋步结束没有
            {
                moveStepIndex = 0;//重置索引
                timer.Stop();//停止timer
            }
        }

 

这里每一步都有注释,相信不会看不懂的了。OK,至此,我们是可以F5看效果了:

1:目前正在下棋,下到一半中:

 

2:观众进来了,获取完棋步,并播放了一次,定位到最后一步:

 

3:设置为2秒,点“回放”,自动播放了第一步:

 

4:回放走到第二步:

 

5:回放走到最后一步了:

 

 

OK,到此,我们的棋谱回放功能基本完成了,只是有一些细节,我们是需要另外处理了:

1:下棋者在下棋过程,要不要开放“回放”功能,如果开放,需要注意什么?

2:观众在回放过程中,突然又传来一个棋步,需要注意什么?

这两个小细节,下节处理,本系列到这里,所有基础区的功能都基本完成了差不多了,那本系列是不是也接近尾声了?

 

OK,本节点到为止了,提供第八阶段源码:点击下载

版权声明:本文原创发表于博客园,作者为路过秋天,原文链接:

http://www.cnblogs.com/cyq1162/archive/2010/08/09/1795873.html

时间: 2024-12-23 02:10:18

Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放(三十九)的相关文章

Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放-结局(四十)

查看本系列其他相关文章请点击:Silverlight+WCF 新手实例象棋专题索引 在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示 在Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放(三十九)中,我们实现了用户的棋谱回放,在文章的下面,我们曾留下了两个问题: 下棋者在下棋过程,要不要开放"回放"功能,如果开放,需要注意什么? 观众在回放过程中,突然又传来一个棋步,需要注意什么? 在解答这两个问题之前,我们先来解答上一篇的截图中发现的问题: 不知

一起谈.NET技术,Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放-结局(四十)

查看本系列其他相关文章请点击:Silverlight+WCF 新手实例象棋专题索引 在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示 在Silverlight+WCF 新手实例 象棋 主界面-棋谱-回放(三十九)中,我们实现了用户的棋谱回放,在文章的下面,我们曾留下了两个问题: 下棋者在下棋过程,要不要开放"回放"功能,如果开放,需要注意什么? 观众在回放过程中,突然又传来一个棋步,需要注意什么? 在解答这两个问题之前,我们先来解答上一篇的截图中发现的问题: 不知

Silverlight+WCF 新手实例 象棋 主界面-状态重置(三十四)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示   正如我们在:Silverlight+WCF 新手实例 象棋 主界面-事件区-求和认输(三十二)里面提到的一样: "游戏结束了,要干点什么呢?当然就是棋盘复位了,按钮重置了,如果还有棋谱之类的,全都得重置.这些,我们留下到另一节优化处理吧."   所以,本节就做这些手尾工作了. 由于游戏结束,我们复位的工作很多,至少有N个控件需要复位,因此,Silverlight+WCF 新手实例 象棋 主界面-控件消息传递(二

Silverlight+WCF 新手实例 象棋 主界面-棋谱-获取列表(三十八)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示   在Silverlight+WCF 新手实例 象棋 主界面-棋谱-布局写谱(三十六)中,我们完成下棋双方的棋谱显示,这节,我们为观众增加棋子列表: 观众进入房间后,第一时间当然也要获取棋步列表了,不然进来干麻呢?你当这是聊天室啊,光聊天不看棋.   首先,当然是要在服务端添加一个获取棋步列表的接口方法了: WCF服务端,IService.cs:  /// <summary>     /// 服务端方法接口 by 路过秋天

Silverlight+WCF 新手实例 象棋 主界面-棋谱-布局写谱(三十六)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示   这节,我们要实现棋谱列界面布局和棋谱的获取,先上一张久远的图片: 看清楚了,到本节为止,除了第三区棋谱区,其它的区域我们都已完成了,所以,我们抓紧时间,赶紧吧:   好了,先布局,和以往一样:   1:界面拖一个Border到Index.xaml,到第三区的位置,设置好宽和高[212*602]: <UserControl ...省略...   d:DesignHeight="620" d:DesignWi

Silverlight+WCF 新手实例 象棋 主界面-棋盘区(二十二)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示   这节我们要布局Index.xaml界面. 首先,我们定义一下全局的宽和高:1000*620[数字差不多就行了] 一堆代码,都是自动生成的,只是改了两个数字,不说大伙也知道改啥数字了. <UserControl x:Class="NewChessProject.Index"     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presen

Silverlight+WCF 新手实例 象棋 主界面-在线用户区(二十四)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示 演示已更新到此节介绍:Silverlight+WCF 新手实例 象棋 介绍III(二十三)   这节我们来实现在线用户区的显示,把上两节介绍那张图再弄来,看在线用户区是哪块:   一眼扫过看到了,是第四区,现在开始了,还是上次下棋区域一样的逻辑,往Index.xaml里拉一个Board控件,然后后台写两行代码代码一下. 当然了,得新建一个用户控件:就叫:OnlineUser.xaml,好,空白的在线用户建完了,下面还是两步实

Silverlight+WCF 新手实例 象棋 主界面-事件区-游戏开始(二十七)

本专题出产简单原由: 一开始的初衷,只是想写个简单的单机BS人机对战版的,开始还下了点AI算法看看的: 但是写到最后,都写成了通讯版本的对战了,只因中间不小心看到了WCF的相关内容,顺便加了进来; 最后就定局了,反正新手实例,能加多点内容就加多点了. 关于原始初衷,后期再补上了.       好了,先上几个附加索引: 1:Silverlight+WCF 新手实例 象棋 在线演示 2:Silverlight+WCF 简单部署问题集 3:Silverlight4 ListBox bug 4:Silv

Silverlight+WCF 新手实例 象棋 主界面-实时聊天区(二十五)

在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示 演示已更新到此节介绍:Silverlight+WCF 新手实例 象棋 介绍III(二十三)   本节连着Silverlight+WCF 新手实例 象棋 主界面-在线用户区(二十四) 发,主界面就不截图了,这节我们实现"实时聊天区": 这节内容几乎和上节一个样的逻辑 1:新建一个用户控件:就叫:Chat.xaml,用来在线聊天 2: 界面拖一个Border到Index.xaml,现在界面上有三个Border了,第三个