如何用Silverlight开发贪吃蛇游戏
发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,今天就跟大家聊聊有关如何用Silverlight开发贪吃蛇游戏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。介绍使用 Silverlight
千家信息网最后更新 2025年01月19日如何用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) { ListemptyCells = 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 ListGetEmptyCells() { 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安全错误
数据库的锁怎样保障安全
叮叮出行互联网科技
在家上网用什么网络安全
观看未成年人网络安全专题课
杭州百世网络技术有限公司存续
信息网络安全的三个时段
火山软件开发平台找图
段攻网络技术
杜比服务器怎么整合
网络安全易购
显示mysql数据库的命令是
军队网络安全教育讨论
智慧仓储管理使用哪种服务器
软件开发可以自己做软件吗
mir3数据库
中国网络安全管理双语文本
cf端游幻神搭配什么服务器
lol国服服务器是谁家的
网络安全股估值
私服服务器波动
国家网络安全局局长王
非关系型数据库管理技术
一流的软件开发
河南软件开发资格
苏州c语言软件开发服务
数据库a表怎么同步b表
魔兽找不到的服务器角色
计算机网络技术好学
杭州呈美网络技术有限公司
潮州自主可控软件开发供应商
包头市网络安全等级备案