一. 总体设计
篮球计分器的实现主要包括客户端和服务器两部分,按照客户/服务器的模式进行工作,提供交互式的访问,在INTERNET使用广泛。通信协议主要采用TCP协议。主要实现了篮球计分器的几个关键功能:服务器段与客户端的通信、七段码、断电保存、广告、动画、声音。这是07年5月份课余时间完成的微机实践项目,其主要技术还是在于Socket编程。
二、开发环境及主要技术说明
VS2005,主要利用Socket编程,其中还涉及到线程方面的内容
Socket套接字的工作原理:通过局域网互联网进行通信,至少采用一对套接字,其中一个运行于客户端,另一个运行于服务器端。根据连接启动的方式以及本地套接字要连接的对象连接过程分为三个步骤:服务端接听、客户端接听和连接请求
三、具体实现过程
实现的具体过程:
(1)声音的实现:
主要设计思想:根据服务器端传过来的控制信息,调用API的接口来实现声音的播放
实现过程:
声音的实现
1 public enum PlaySoundFlags : int
2
3 {
4
5 SND_SYNC = 0x0000, /**//* play synchronously (default) */ //同步
6
7 SND_ASYNC = 0x0001, /**//* play asynchronously */ //异步
8
9 SND_NODEFAULT = 0x0002, /**//* silence (!default) if sound not found */
10
11 SND_MEMORY = 0x0004, /**//* pszSound points to a memory file */
12
13 SND_LOOP = 0x0008, /**//* loop the sound until next sndPlaySound */
14
15 SND_NOSTOP = 0x0010, /**//* don't stop any currently playing sound */
16
17 SND_NOWAIT = 0x00002000, /**//* don't wait if the driver is busy */
18
19 SND_ALIAS = 0x00010000, /**//* name is a registry alias */
20
21 SND_ALIAS_ID = 0x00110000, /**//* alias is a predefined ID */
22
23 SND_FILENAME = 0x00020000, /**//* name is file name */
24
25 SND_RESOURCE = 0x00040004 /**//* name is resource name or atom */
26
27 }
28
29 [DllImport("winmm")]
30
31 public static extern bool PlaySound(string szSound, IntPtr hMod, PlaySoundFlags flags);
32
33 public static void playSound(string path)
34
35 {
36
37 PlaySound(path, IntPtr.Zero, PlaySoundFlags.SND_ASYNC);
38
39 }
40
41
参数Path为声音存放的路径。
具体应用: playSound("sound""欢呼.WAV");存在缺陷只支持WAV的音乐格式。
(二)广告的实现
主要设计思想:首先在客户端设置广告的内容,然后把把它传回给客户端,客户端在经过处理,使其能过“飘”起来。主要用一个Timer控件让广告的内容一定时间内向左移动。
实现过程:
广告动态显示
private void timer1_Tick(object sender, EventArgs e)
{
pos = new Point(lbl_word.Location.X, lbl_word.Location.Y);
if (pos.X > -lbl_word.Width)
{
lbl_word.Location = new Point(lbl_word.Location.X - 2, lbl_word.Location.Y);
}
else
{
lbl_word.Location = new Point(panel1.Width+lbl_word.Width, 30);
}
lbl_NowTime.Text = "北京时间: " + DateTime.Now.ToLongTimeString(); //显示当前时间
}
(3) 动画的实现
主要设计思想:将每个动作(2分,3分,1分,犯规等)动画分割成100张图片,根据服务器传过来的信息,100毫秒显示一张,整个看起来就形成了动画。
实现过程:
动画实现
动画显示效果#region 动画显示效果
public int i = 0;
private void timer2_Tick(object sender, EventArgs e)
{
if (label4.Text != "") / /记录传过来的信号
{
if (i < 100)
{
string path = @""" + label4.Text.Trim() + @""" + i.ToString() + ".JPG";
pictureBox1.ImageLocation = Environment.CurrentDirectory + path;
}
else
{
pictureBox1.ImageLocation = "";
}
i++;
}
}
#endregion
(4)LED七段码设计:
1、 主要设计思想:
使用GDI+ 绘图,显示数字时填充特定区域。
2、 详细设计:
(1)、采用双缓冲,以减少或避免显示时的闪烁
this.DoubleBuffered = true;
(2)、属性:
Color 显示颜色
Length 显示数字位数
Num 显示值
(3)、主要方法:
DrawHBar() 画横向显示码
DrawVBar() 画竖向显示码
showNum() 按照输入num值七段码显示
OnPaint() 重写onpaint事件
3、 显示实例:
显示一位数字(length=1)
显示两位数字(length=2)
显示三位数字(length=3)
4、 部分代码:
public NumBar() //
{
this.DoubleBuffered = true;
}
//color属性
private Color _color=Color.Red;
[
Category("my"),
Description("color")
]
public Color color
{
get { return _color; }
set
{
_color = value;
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e) //重载onpaint函数
{
base.OnPaint(e);
Graphics g = e.Graphics;
int xStart = 0;
int width = 0;
int numValue = 0;
if (this.length < 1 || this.length > 3)
{
return;
}
switch (this.length)
{
case 1:
/*…*/
case 2:
/*…*/
case 3:
/*…*/
default:
break;
}
}
private void showNum(Graphics g, int xStart, int width, int numValue)
{
this.DrawHBar(g, pStart[0], h[0], w[0], Color.DimGray);
this.DrawVBar(g, pStart[1], h[1], w[1], Color.DimGray);
this.DrawVBar(g, pStart[2], h[2], w[2], Color.DimGray);
this.DrawHBar(g, pStart[3], h[3], w[3], Color.DimGray);
this.DrawVBar(g, pStart[4], h[4], w[4], Color.DimGray);
this.DrawVBar(g, pStart[5], h[5], w[5], Color.DimGray);
this.DrawHBar(g, pStart[6], h[6], w[6], Color.DimGray);
#region
switch (numValue)
{
/*…*/
}
#endregion
}
// 画横向的显示条
private void DrawHBar(Graphics g, Point start, int length, int width, Color color)
{
int h = length;
int w = width;
int x = start.X;
int y = start.Y;
h = h - 4;
w = w - 4;
Point[] ps = new Point[6];
ps[0] = new Point(x + 2, h / 2 + 2 + y);
ps[1] = new Point(x + 2 + (h / 2), 2 + y);
ps[2] = new Point(x + w + 2 - (h / 2), 2 + y);
ps[3] = new Point(x + w + 2, h / 2 + 2 + y);
ps[4] = new Point(x + w + 2 - (h / 2), 2 + h + y);
ps[5] = new Point(x + 2 + h / 2, h + 2 + y);
Pen pen = new Pen(Color.Gray, 1);
SolidBrush br = new SolidBrush(color);
g.FillPolygon(br, ps);
g.DrawPolygon(pen, ps);
br.Dispose();
pen.Dispose();
}
四、程序运行结果
客户端:
服务器端:
(五)总结
《篮球计分器》主要涉及Socket编程、GDI+自定义控件、XML序列化以及二进制序列化与反序列化、还有一些多媒体的简单的声音与图片的播放。