永利电玩城首页 25

Silverlight+WCF 新手实例 象棋 棋子移动-吃子(五卡塔尔

上一节,我们给棋子赋于了鼠标点击事件,并通过故事板Storyboard
来移动棋子,同时实现了吃棋子。

上一节,我们的棋子就是一个Canvas,里面add进了一个Ellipse圆圈和TextBlock字

现在我们在实现鼠标在棋盘上点击,然后棋子就移动到那去。

想想我们是怎么下棋的,要先选中棋子吧,选中后,随便找个地方点,棋就会自动移过去。

好了,鼠标在棋盘上点击,这里要为点击的棋盘,其实就是最外面那个Panel容器啦,还是加上一个MouseLeftButtonDown事件。

所以,这里就产生了两件事,一是选中,二是移动。

我们回到Chess类,因为这里是第一手Canvas传进来的地方,我们在Chess的构造函数里,为Panel添加这一事件

要选中,其实就是选中棋子,选中棋子就是选中Canvas了。

 

于是,我们为Canvas增加一个鼠标点击事件。

永利电玩城首页 1永利电玩城首页 2

让我们回到棋子类Chessman的Draw方法里,为chessman添加一个MouseLeftButtonDown事件,于是代码变成了

 public Chess(Panel control)
        {
            control.MouseLeftButtonDown += new MouseButtonEventHandler(control_MouseLeftButtonDown);//新加的
            container = control;
            ChessmanList = new List<Chessman>(32);
            Action = new ChessAction(this);
        }

 

        void control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show(“我是棋盘,你点中我了,我的坐标是:” + e.GetPosition(null).X+”,” + e.GetPosition(null).Y);
        }

永利电玩城首页 3永利电玩城首页 4

 

 private void Draw()
        {
            //这里实现画啦
            Ellipse elp = new Ellipse()
            {
                Width = Radius * 2,
                Height = Radius * 2,
                Stroke = new SolidColorBrush(Color),
                Fill = new SolidColorBrush(Color),
                Opacity = 15
            };
            TextBlock text = new TextBlock()
            {
                TextAlignment = TextAlignment.Center,
                Foreground = new SolidColorBrush(Colors.White),
                Text = Name,
                FontFamily = new FontFamily(“宋体”),
                FontSize = Radius,
                FontWeight = FontWeights.Bold,
                Margin = new Thickness(Radius / 2 – 2, Radius / 2 – 2, 0, 0)
            };
            chessman = new Canvas();
            //—-这里新加一个事件啦—–
            chessman.MouseLeftButtonDown += new MouseButtonEventHandler(chessman_MouseLeftButtonDown);
            //—-这里新加一个事件啦—–
            Point pixel = Parent.SwitchPixelArray(InitPoint);
            chessman.Margin = new Thickness(pixel.X – Radius, pixel.Y – Radius, 0, 0);
            chessman.Children.Add(elp);
            chessman.Children.Add(text);
            container.Children.Add(chessman);
        }
        //新加的事件方法
        void chessman_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            MessageBox.Show(“你选中的是:” + Name);
        }

OK,按F5运行,效果就出来了,随便找个地方点击,效果图如下,为了突出点,这里给Canvas弄上了绿色背景:

 

永利电玩城首页 5

其实就一共新增加了三行代码,运行看看效果。

这里有几点注意:

永利电玩城首页 6

1。外部的Canvas必须有背景色,如果没有背景色,点击事件是无效的。

好了,选中是OK了,那我们怎么移动?

2。加上背景色后,我们发现,能点击的范围太大,我们只要像棋盘那么宽和高的范围就够了。于是我们回到棋盘Board类的DrawIn函数里,顺便把容器的宽高都给加上了。

Silverlight里有几种移动方法,这里挑了Storyboard故事板来移动棋子。

永利电玩城首页 7永利电玩城首页 8

按原始想法,棋子自己不会动,所以新建一个ChessAction类来实现棋子的移动。

public void DrawIn(Panel control)
        {
            Width = gap * 9 + marginLeft;
            Height = gap * 10 + marginTop;
            container = control;
            container.Width = Width;//设置宽
            container.Height = Height;//设置高
            Draw();
        }

啥也不说,对着类库右键-》添加类—》ChessAction.cs就新建了。

 

 

OK,再运行,看看效果,背景范围正好合适了。

 /// <summary>
    /// 棋子动作类 by 路过秋天
    /// </summary>
    public class ChessAction
    {

永利电玩城首页 9

    }

OK,有了点击事件我们并可以获取到点击的点所在的坐标,可是我们点击的坐标,不一定是精确在点上的,所以咋办呢?

 

如果是吃棋子好说,因为吃棋子可以通过被吃的棋子就可以获取到棋子的精准坐标。

想想棋子是怎么动的?其实就两个动作,一个是吃子,另一个没子吃直接移动。于是呢,就先产生两个方法:

那这里我们咋么能精准的定位到线交叉点上呢??

 

没的说咋办,加个函数进行修正了。

永利电玩城首页 10永利电玩城首页 11

于是一个在Chess类中的修正点坐标函数产生了:

 /// <summary>
    /// 棋子动作类 by 路过秋天
    /// </summary>
    public class ChessAction
    {
        /// <summary>
        /// 吃子
        /// </summary>
        /// <param name=”moveChessman”>移动的棋子</param>
        /// <param name=”eatChessman”>被吃的棋子</param>
        public void EatChessman(Chessman moveChessman, Chessman eatChessman)
        {

永利电玩城首页 12永利电玩城首页 13

        }
         /// <summary>
        /// 移动棋子
        /// </summary>
        /// <param name=”chessman”>棋子</param>
        /// <param name=”toX”>移动到X坐标</param>
        /// <param name=”toY”>移动到Y坐标</param>
        public bool MoveTo(Chessman chessman, Point moveTo)
        {
            return true;
        }
    }

/// <summary>
        /// 修正像素并转成坐标
        /// </summary>
        public Point FixPoint(Point point)
        {
            Point fixPoint = new Point();
            fixPoint.X = Math.Round((point.X – Board.marginLeft) / Board.gap);
            fixPoint.Y = Math.Round((point.Y – Board.marginTop) / Board.gap);
            return fixPoint;
        }

 

 

再想想,其实吃子,就是移动棋子,让后叫被吃的那个子离开自己的位置gotodead。

看,很简单吧,首先把点减去margin的,然后剩下的除以棋盘间隔,最后四舍五入就行了。

-_-..这里顺便为Chessman棋子类自己加个方法叫GoToDead好了。

OKOK,有了修正点坐标,我们回去修改下那个点击事件,让它调用ChessAction的MoveTo方法移动吧

永利电玩城首页 14永利电玩城首页 15

永利电玩城首页 16永利电玩城首页 17

/// <summary>
        /// 销亡
        /// </summary>
        public void GoToDead()
        {
            container.Children.Remove(chessman);//从控件中移除
            Parent.ChessmanList.Remove(this);//从棋子列表移除
            
        }

void control_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //MessageBox.Show(“我是棋盘,你点中我了,我的坐标是:” + e.GetPosition(null).X+”,” + e.GetPosition(null).Y);
            if (e.OriginalSource is Canvas || e.OriginalSource is Line)
            {
                Chessman chessman =ReadyMoveChessman;
                if (chessman != null)
                {
                    Point fixPoint = FixPoint(e.GetPosition(null));
                     Action.MoveTo(chessman, fixPoint);
                   
                }
永利电玩城首页,            }
        }

 

 

OK,我们可以为吃子方法写完它了。先移动棋子,然后叫被吃的自己GoToDead了。

OK,F5运行,移动棋子。。效果图上来:

永利电玩城首页 18永利电玩城首页 19

永利电玩城首页 20

public void EatChessman(Chessman moveChessman, Chessman eatChessman)
        {
            if (MoveTo(moveChessman, eatChessman.MovePoint))
            {
                eatChessman.GoToDead();
            }
        }

哇哇~~的叫,笨来是想移动到棋盘中的,谁知道自己跑到外面去了。

 

于是又小研究了一下,又是相对坐标惹的祸了,看,棋盘默认跑中间去了,不是靠左和靠顶对齐的。

说来说去,就剩下要完成MoveTo的时候,棋子要移动了。

我们回到Silverlight应用程序中,找到那个Canvas容器,把它的水平对齐设置为Left,垂直对齐设置为Top,

我们把移动的动作封成一个函数叫PlayMove,所以在MoveTo里轻松调用PlayMove就搞定了。

 

永利电玩城首页 21永利电玩城首页 22

<Canvas Height=”600″ Name=”canvas1″ Width=”800″ Background=”Green” Margin=”0,0,0,0″ HorizontalAlignment=”Left” VerticalAlignment=”Top” />

public bool MoveTo(Chessman chessman, Point moveTo)
        {
            PlayMove(chessman, moveTo);
            return true;
        }
        void PlayMove(Chessman chessman, Point moveTo)
        {
            //这里完成移动啦
        }

 

 

 

移动的代码的故事版,先上代码,再解说

当然啦,也可以通过代码设置属性值了。

永利电玩城首页 23永利电玩城首页 24

然后看看效果:

 void PlayMove(Chessman chessman, Point moveTo)
        {
            //这里完成移动啦
            moveTo = Parent.SwitchPixelArray(moveTo);
            Point initPixel = Parent.SwitchPixelArray(chessman.InitPoint);
            Point movePixel = Parent.SwitchPixelArray(chessman.MovePoint);

永利电玩城首页 25

            Storyboard sb = new Storyboard();//创建动画版
            //创建X方向的动画
            DoubleAnimation daX = new DoubleAnimation();
            daX.Duration = new Duration(TimeSpan.FromMilliseconds(200));
            daX.From = movePixel.X – initPixel.X;
            daX.To = moveTo.X – initPixel.X;
          
            //创建Y方向的动画
            DoubleAnimation daY = new DoubleAnimation();
            daY.Duration = new Duration(TimeSpan.FromMilliseconds(200));
            daY.From = movePixel.Y – initPixel.Y;
            daY.To = moveTo.Y – initPixel.Y;
         
            //设置动画版上的目标
            Storyboard.SetTarget(daX, chessman.chessman);
            Storyboard.SetTarget(daY, chessman.chessman);
            //设置动画版上的目标要变化的属性
            Storyboard.SetTargetProperty(daX, new PropertyPath(“(Canvas.Left)”));
            Storyboard.SetTargetProperty(daY, new PropertyPath(“(Canvas.Top)”));

 

            sb.Children.Add(daX);
            sb.Children.Add(daY);
            sb.Begin();

OKOK,这个是正常了,我们让棋子移到了指定的位置上去了。

            sb = null;
        }

下一节,我们为棋子增加规则,让它们不能随意移动,得按规则来办事。

 

作者博客:

其实Storyboard的类用法,比较死的,记住怎么用就行了,记不住就Copy多几次也就差不多了。

实在看不懂,多在博客园里多搜搜该类的用法,看来看去基本就是这么用,看的多了习惯了就也是这么一回事了。

这里说几个注意点:

1。Parent哪来的?我们的棋子类不是也有一个Parent么,其实就是Chess类对象了。

所以呢,我们要为ChessAction添加一个属性和构造函数,让Chess对象传进来啦。

永利电玩城首页 26永利电玩城首页 27

/// <summary>
        /// Chess对象
        /// </summary>
        public Chess Parent
        {
            get;
            set;
        }
        public ChessAction(Chess ownChess)
        {
            Parent = ownChess;
        }

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注