如何用Silverlight开发贪吃蛇游戏
发表于:2025-11-12 作者:千家信息网编辑
千家信息网最后更新 2025年11月12日,今天就跟大家聊聊有关如何用Silverlight开发贪吃蛇游戏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。介绍使用 Silverlight
千家信息网最后更新 2025年11月12日如何用Silverlight开发贪吃蛇游戏
今天就跟大家聊聊有关如何用Silverlight开发贪吃蛇游戏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。
介绍
使用 Silverlight 3.0(c#) 开发一个贪吃蛇游戏
玩法
W/S/A/D 或 ↑/↓/←/→ 控制蛇的移动
截图
思路
1、贪吃蛇的每一段为 16×16 像素,场景为 640×480 像素,也就说网格为 40×30 个,每个网格的边长为 16
2、食物的出现位置以及贪吃蛇的运动方向的改变都要在相关的网格内进行
3、贪吃蛇的运动用即时运算的方法计算,当贪吃蛇运动到网格内(蛇某一段的像素位置%网格的边长<蛇在某时间单位下的移动偏移量)时做如下工作:修正蛇的位置使其正好在网格内,更新蛇的每一段的运动方向,判断是否吃到了食物、是否发生了碰撞等
4、贪吃蛇的每一段的运动方向的修改:蛇头的运动方向根据用户的操作改变,蛇的每一段的运动方向设置为此段的前一段的运动方向(计算时要从尾部向头部逐段计算)(注:运动方向的改变要在蛇移动到网格内时进行。其中如果蛇的某一段移动到了网格内,则表明其它各段都在网格内)
下面我们看看他的关键代码都有哪些。
关键代码
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; using System.Windows.Media.Imaging; using System.Threading; namespace YYSnake.Core { public partial class Main : UserControl { private int _columns; // 网格列数 private int _rows; // 网格行数 private Dictionary _bodies = new Dictionary(); // 贪吃蛇每一段的集合 private Dictionary _beans = new Dictionary(); // 豆的集合 private Dictionary _skins = new Dictionary(); // 蜕下来的皮的集合 private List _emptyCells = new List(); // 空网格的集合 private bool _enabled = false; // 游戏是否运行 private double _dt = 0.01; // 多少毫秒计算一次 private int _decimals = 1; // 计算小数时所保留的小数位 private double _speed = 80; // 蛇的运行速度 private Direction _moveDirection = Direction.Up; // 蛇的运行方向 private int _selfLength = 5; // 蛇的最小长度 private int _beansCount = 5; // 豆的***出现数量 private int _ateCapacity = 10; // 食量(超过则蜕皮) private bool _needRaiseAteEvent = false; // 在"蛇头所处位置进入了网格点区域内"时是否需要触发吃豆事件 private int _needBeansCount = 0; // 还需要增加的豆的数量 Random _random = new Random(); public Main() { InitializeComponent(); this.Loaded += new RoutedEventHandler(Main_Loaded); } void Main_Loaded(object sender, RoutedEventArgs e) { this.Width = App.Width; // 640 this.Height = App.Height; // 480 _columns = (int)(Width / App.CellSize); // 40 _rows = (int)(Height / App.CellSize); // 30 // 防止动画飞出去 RectangleGeometry rg = new RectangleGeometry(); rg.Rect = new Rect(0, 0, App.Width, App.Height); LayoutRoot.Clip = rg; bg.Width = App.Width; bg.Height = App.Height; ripple.RippleBackground = bg; CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering); } /// /// 初始化 /// public void Init() { _enabled = false; canvasBean.Children.Clear(); canvasSnake.Children.Clear(); canvasSkin.Children.Clear(); _beans.Clear(); _bodies.Clear(); _skins.Clear(); _emptyCells.Clear(); for (int i = 0; i < _columns; i++) { for (int j = 0; j < _rows; j++) { _emptyCells.Add(new CellPoint(i, j)); } } _moveDirection = Direction.Up; InitSnake(); } /// /// 蛇的初始化 /// private void InitSnake() { InitHead(); for (int i = 0; i < _selfLength - 1; i++) AddTail(); for (int i = 0; i < _beansCount; i++) AddBean(); } /// /// 蛇头的初始化 /// private void InitHead() { Body head = new Body(BodyType.Head); head.MoveDirection = _moveDirection; CellPoint point = new CellPoint((int)(_columns / 2), (int)(_rows / 2)); head.SetValue(Canvas.LeftProperty, point.X * App.CellSize); head.SetValue(Canvas.TopProperty, point.Y * App.CellSize); _bodies.Add(head, point); canvasSnake.Children.Add(head); } /// /// 增加一个尾巴 /// private void AddTail() { var prevBody = _bodies.Last().Key; var prevBodyPoint = _bodies.Last().Value; Body tail = new Body(BodyType.Tail); tail.MoveDirection = prevBody.MoveDirection; CellPoint tailPoint = new CellPoint(prevBodyPoint.X, prevBodyPoint.Y); switch (prevBody.MoveDirection) { case Direction.Up: tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty)); tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty) + App.CellSize); tailPoint.Y++; break; case Direction.Down: tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty)); tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty) - App.CellSize); tailPoint.Y--; break; case Direction.Left: tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty) + App.CellSize); tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty)); tailPoint.X++; break; case Direction.Right: tail.SetValue(Canvas.LeftProperty, (double)prevBody.GetValue(Canvas.LeftProperty) - App.CellSize); tail.SetValue(Canvas.TopProperty, (double)prevBody.GetValue(Canvas.TopProperty)); tailPoint.X--; break; } tailPoint = CorrectCellPoint(tailPoint); _bodies.Add(tail, tailPoint); canvasSnake.Children.Add(tail); } /// /// 增加一个豆 /// private void AddBean() { if (_needBeansCount < _beansCount) _needBeansCount++; } private DateTime _prevAddBeanDateTime = DateTime.Now; /// /// 生成豆 /// void UpdateBean() { if (_needBeansCount > 0 && (DateTime.Now - _prevAddBeanDateTime).TotalSeconds > 3) { List emptyCells = GetEmptyCells(); if (emptyCells.Count == 0) { GameOver(this, EventArgs.Empty); return; } CellPoint point = emptyCells[_random.Next(0, emptyCells.Count)]; Bean bean = new Bean(); bean.SetValue(Canvas.LeftProperty, point.X * App.CellSize); bean.SetValue(Canvas.TopProperty, point.Y * App.CellSize); _beans.Add(bean, point); canvasBean.Children.Add(bean); bean.ani.Completed += delegate { ripple.ShowRipple(new Point(point.X * App.CellSize + App.CellSize / 2, point.Y * App.CellSize + App.CellSize / 2)); player.PlayDrop(); }; _needBeansCount--; _prevAddBeanDateTime = DateTime.Now; } } private DateTime _prevDateTime = DateTime.Now; private double _leftoverLength = 0d; void CompositionTarget_Rendering(object sender, EventArgs e) { double length = (DateTime.Now - _prevDateTime).TotalSeconds + _leftoverLength; while (length > _dt) { Update(); length -= _dt; } _leftoverLength = length; _prevDateTime = DateTime.Now; } /// /// 即时计算 /// private void Update() { if (!_enabled) return; double offset = Math.Round(_speed * _dt, _decimals); // 蛇头所处位置进入了网格点区域内 if (Math.Abs(Math.Round((double)_bodies.First().Key.GetValue(Canvas.TopProperty) % App.CellSize, _decimals)) < offset && Math.Abs(Math.Round((double)_bodies.First().Key.GetValue(Canvas.LeftProperty) % App.CellSize, _decimals)) < offset) { UpdateDirection(); CorrectPosition(); UpdateBodyCell(); CheckEat(); CheckSkin(); CheckCollision(); UpdateBean(); if (_needRaiseAteEvent) { Ate(this.Ate, EventArgs.Empty); _needRaiseAteEvent = false; } } UpdatePosition(); } /// /// 蜕皮 /// private void CheckSkin() { if (_bodies.Count >= _ateCapacity + _selfLength) AddSkin(_ateCapacity); } /// /// 碰撞检测 /// private void CheckCollision() { if (_skins.Any(p => p.Value == _bodies.First().Value) || _bodies.Where(p => p.Key.BodyType == BodyType.Tail).Any(p => p.Value == _bodies.First().Value)) { _enabled = false; player.PlayOver(); GameOver(this, EventArgs.Empty); } } /// /// 吃豆 /// private void CheckEat() { // 是否有被吃的豆 var bean = _beans.FirstOrDefault(p => p.Value == _bodies.First().Value).Key; if (bean != null) { _beans.Remove(bean); canvasBean.Children.Remove(bean); player.PlayEat(); AddTail(); AddBean(); _needRaiseAteEvent = true; } } /// /// 更新蛇的每一段的运动方向 /// private void UpdateDirection() { for (int i = _bodies.Count - 1; i > -1; i--) { if (i == 0) _bodies.ElementAt(i).Key.MoveDirection = _moveDirection; else _bodies.ElementAt(i).Key.MoveDirection = _bodies.ElementAt(i - 1).Key.MoveDirection; } } /// /// 更新蛇的每一段的位置 /// private void UpdatePosition() { double offset = Math.Round(_speed * _dt, _decimals); foreach (var body in _bodies.Keys) { if (body.MoveDirection == Direction.Up) body.SetValue(Canvas.TopProperty, Math.Round((double)body.GetValue(Canvas.TopProperty) - offset, _decimals)); else if (body.MoveDirection == Direction.Down) body.SetValue(Canvas.TopProperty, Math.Round((double)body.GetValue(Canvas.TopProperty) + offset, _decimals)); else if (body.MoveDirection == Direction.Left) body.SetValue(Canvas.LeftProperty, Math.Round((double)body.GetValue(Canvas.LeftProperty) - offset, _decimals)); else if (body.MoveDirection == Direction.Right) body.SetValue(Canvas.LeftProperty, Math.Round((double)body.GetValue(Canvas.LeftProperty) + offset, _decimals)); } } /// /// 蜕指定数量的皮 /// private void AddSkin(int count) { player.PlaySkin(); while (count > 0) { KeyValuePair body = _bodies.ElementAt(_bodies.Count - 1); CellPoint skinPoint = body.Value; Skin skin = new Skin(); skin.SetValue(Canvas.LeftProperty, skinPoint.X * App.CellSize); skin.SetValue(Canvas.TopProperty, skinPoint.Y * App.CellSize); _skins.Add(skin, skinPoint); canvasSkin.Children.Add(skin); _emptyCells.Remove(skinPoint); canvasSnake.Children.Remove(body.Key); _bodies.Remove(body.Key); count--; } } #region 辅助方法 /// /// 修正指定的位置信息为整数 /// private int CorrectPosition(double position) { double result; double offset = Math.Round(_speed * _dt, _decimals); double temp = Math.Round(position % App.CellSize, _decimals); if (Math.Abs(temp) < offset) result = Math.Round(position - temp); else result = Math.Round(position - temp) + Math.Sign(temp) * App.CellSize; return (int)result; } /// /// 修正蛇的每一段的位置为整数 /// private void CorrectPosition() { foreach (Body body in _bodies.Keys) { double x = CorrectPosition((double)body.GetValue(Canvas.LeftProperty)); double y = CorrectPosition((double)body.GetValue(Canvas.TopProperty)); if (x == App.Width) x = 0d; else if (x == -App.CellSize) x = App.Width - App.CellSize; else if (y == App.Height) y = 0d; else if (y == -App.CellSize) y = App.Height - App.CellSize; body.SetValue(Canvas.LeftProperty, x); body.SetValue(Canvas.TopProperty, y); } } /// /// 更新蛇的每一段的网格位置信息 /// private void UpdateBodyCell() { for (int i = 0; i < _bodies.Count; i++) { UpdateBodyCell(_bodies.ElementAt(i).Key); } } /// /// 更新指定的 Body 的网格位置信息 /// private void UpdateBodyCell(Body body) { CellPoint point = new CellPoint((int)((double)body.GetValue(Canvas.LeftProperty) / App.CellSize), (int)((double)body.GetValue(Canvas.TopProperty) / App.CellSize)); if (body.MoveDirection == Direction.Up) point.Y--; else if (body.MoveDirection == Direction.Down) point.Y++; else if (body.MoveDirection == Direction.Left) point.X--; else if (body.MoveDirection == Direction.Right) point.X++; point = CorrectCellPoint(point); _bodies[body] = point; } /// /// 修正网格位置 /// private CellPoint CorrectCellPoint(CellPoint point) { if (point.X > _columns - 1) point.X = _columns - point.X; else if (point.X < 0) point.X = point.X + _columns; if (point.Y > _rows - 1) point.Y = _rows - point.Y; else if (point.Y < 0) point.Y = point.Y + _rows; return point; } /// /// 获取空网格集合 /// private List GetEmptyCells() { List emptyCells = new List(); List aroundHeadCells = new List(); CellPoint headPoint = _bodies.First().Value; for (int i = -5; i < 5; i++) { for (int j = -5; j < 5; j++) { CellPoint point = new CellPoint(headPoint.X + i, headPoint.Y + j); point = CorrectCellPoint(point); aroundHeadCells.Add(point); } } // skin 的占位情况因为确定了就不变了,所以在 AddSkin() 处计算 // 为了以下 LINQ 的可用,需要重写 CellPoint 的 public override bool Equals(object obj) emptyCells = _emptyCells.Where(p => !_bodies.Select(x => x.Value).Contains(p)).ToList(); emptyCells = emptyCells.Where(p => !_beans.Select(x => x.Value).Contains(p)).ToList(); emptyCells = emptyCells.Where(p => !aroundHeadCells.Contains(p)).ToList(); return emptyCells; } #endregion #region 属性 public Direction MoveDirection { set { Body head = _bodies.First().Key; if (head.MoveDirection == Direction.Up && value == Direction.Down) return; if (head.MoveDirection == Direction.Down && value == Direction.Up) return; if (head.MoveDirection == Direction.Left && value == Direction.Right) return; if (head.MoveDirection == Direction.Right && value == Direction.Left) return; _moveDirection = value; } } public bool Enabled { get { return _enabled; } set { _enabled = value; } } public double Speed { get { return _speed; } set { _speed = value; } } public int AteCapacity { get { return _ateCapacity; } set { _ateCapacity = value; } } #endregion #region 事件 GameOver 和 Ate public event EventHandler GameOver; public event EventHandler Ate; #endregion } } 看完上述内容,你们对如何用Silverlight开发贪吃蛇游戏有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注行业资讯频道,感谢大家的支持。
网格
位置
运动
方向
更新
蛇头
移动
开发
信息
像素
内容
数量
运行
事件
代码
关键
区域
小数
整数
方法
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
医院网络安全简报
数据库代码外键
在线支付 网络安全
七年级网络安全教育平台
众安保险 软件开发
数据库中字节怎么表示
hpe服务器如何做riad
安装数据库时外部组件出现异常
olacle电脑服务器价格
电子资源数据库培训心得体会
手机软件开发票
dell服务器如何做硬盘引导盘
安徽智慧团建软件开发电话
邮件接收软件开发
常州物料备件管理软件开发
远程软件开发岗位
宝山区咨询软件开发质量
中国移动集客网络技术支撑
山东时代网络技术创新服务
无线传感器网络技术概论题库
网络安全和信息化名单
众安保险 软件开发
数据更新最快的数据库
集群服务器同步
关系型数据库简介
网络安全方向的就业前景怎样
手机自制我的世界服务器
2维关系表格 采用数据库
计算机网络技术网站设计是什么
霆智服务器的优势