Silverlight实现的纸牌(完成)

0. 前言

    上次急切的想看看自己写的Silverlight程序放在日志上是什么样子的,所以放了一个半成品上去。但是突然发现自己好像不知道怎么把Silverlight插入到日志中,只是见到别人这么干过。自己又对Html,JS这类东西不怎么了解,还好找到了博客园的一位高人“菩提树下的杨过”的方法,照搬上来,果然好用。先谢过。

    本人不才,做的这个东西没有用什么NB的技术和高深的思想,只是完全本着面向对象的基本思想然后很认真很认真的一点点写出来的。所以高手请直接无视,新人可以选择性的看看,只是不要被我误导了就好。这算是我在博客园的第一个帖子,谢大家捧场。

    对上次的半成品添加了一些加强和修正。现放出一个较完整的版本,有源码可下载。下面介绍一些我觉得可以说一说的东西。

1. 增加图片效果

    首先是看看扑克牌的图片,我从网上总算是搜寻出了一个一套54张的图片。但是质量不行,每张牌都是四四方方的,切割也很粗糙,看上去就很死板。只能是这样的图片效果的话,我可就没兴趣做下去了,但是又找不到其他更好的图片了,只能在显示的时候用一些小手段了。主要是两个手段:圆角+阴影。

代码如下

代码
_ForeImage = new Image()
{
// 设定Source(其实就是那些很粗糙的图片了)
Source = CardGameLib.CardImageLib.GetCardBitmap(cv),
Width
= 80,
Height
= 123,
// 切割成圆角矩形
Clip = new RectangleGeometry() { RadiusX = 4, RadiusY = 4, Rect = new Rect(0, 0, 80, 123) },
// 阴影效果(ShadowDepth=0是为了让四周的阴影一样,看个人喜好了)
Effect = new DropShadowEffect() { Opacity = 0.6, BlurRadius = 3, ShadowDepth = 0 }
};

 

看看对比效果

原图效果

使用手段后

image_thumb[1] image3_thumb[1]

恩,帅多了。

2. 拖动

     拖动本来就是一个很简单的东西,无非就是处理MouseLeftbuttonDown, MouseMove, MouseLeftButtonUp,这三个事件就行了。

     但是在这里面我的设计是桌面上的牌堆是放在Grid容器中的,为了方便自动布局。但是拖动的时候,我是将要拖动的扑克牌移到了Grid上面覆盖的一个Canvas容器中的,方便随时定位。但是这样就有一个问题了:我在把牌从Grid中移到Canvas中的时候(即MouseLeftButtonDown的时候),怎么保证他们的位置是一致的呢(即看上去位置没有变化)?毕竟他们的定位方式不同,而且可能两个容器的相对位置是不一定的。

     幸运的是鼠标事件参数e很强大,可以直接e.GetPosition(**)来获得鼠标相对与某个控件的位置。这样的话,在把牌移到Canvas里面之前,我们可以先得到鼠标相对与牌的位置pos1,然后在得到鼠标相对于Canvas的位置pos2,这样,用鼠标做参考,pos2-pos1就可以得到牌相对与Canvas的位置了。然后将牌从Grid中remove掉,add进Canvas,再Canvas.SetLeft, Canvas.SetTop,问题解决。

代码如下:

代码
// 获取鼠标相对与牌的位置
Point tmpP1 = e.GetPosition(theCard);

// 获取鼠标相对与Canvas的位置
Point tmpP2 = e.GetPosition(this.DragCanvas);
// 想减,得到牌相对与Canvas的位置
Point tmpP3 = new Point(tmpP2.X - tmpP1.X, tmpP2.Y - tmpP1.Y);
// 把牌从Grid中移到Canvas中(这里注意,如果有Margin值的需要清掉)
ContentGrid.Children.Remove(theCard);
DragCanvas.Children.Add(theCard);
// 设定初始位置
Canvas.SetLeft(MoveStack, tmpP3.X);
Canvas.SetTop(MoveStack, tmpP3.Y);

 

3. 对象

    纸牌这个游戏很简单,如果只是想写出来这个程序,可能并不需要那么严格的面向对象,封装的思想。但是学习不是完成任务,而且为了代码思路更加清晰,为了使程序有更大的扩展性,我就尽量的“面向对象”了(也不知道我理解的面向对象对不对)。下面说一下该程序中的类,和代码结构。

image6_thumb

    第一个工程是一个SilverlightClassLibrary。里面定义了这些类

Card 扑克牌(继承UserControl)
CardImageLib 扑克牌图片管理类
可以从中取出各张牌的Bitmapimage
CardStackBase 牌堆的基类,定义的一些基本操作和属性
Contact 这不是类名,里面定义了一个牌面值的枚举类型CardValue
EnumHelper 枚举类型功能扩展(Silverlight比Wpf少了好多东西)

    第二个工程就是Silverlight程序了。先说一下牌堆的概念,游戏中会有多个地方可以放置扑克牌,统称为牌堆,这些地方规则和功能都不相同,但是有一些共同的性质和操作。于是就有了牌堆基类CardstackBase,和他的几个子类了。

image14 

    第二个工程里面定义的这些类如上图所示,其中CardMoveStack是拖动中的牌堆的意思。他们都继承CardStackBase并自己定义了一些特殊的功能。

    对于CardImageLib存在的意义,一是便于管理图片(废话)。二是,游戏里面可能会用到同一张图片很多次,如果每次都去new一个BitmapImage,必然会浪费资源。多个Image公用一个BitmapImage是可以的,所以CardImageLib里面就在程序一开始就new了54张牌的BitmapImage,然后就不在new了,以后外面有需要,就直接传引用出去。这样应该会比较好。

 

好了,就这样,上示例和源码。


在线演示

源代码

posted @ 2010-08-02 20:53  carlWolf  阅读(854)  评论(5编辑  收藏  举报