溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何用Silverlight開發(fā)貪吃蛇游戲

發(fā)布時間:2021-10-29 16:15:49 來源:億速云 閱讀:94 作者:柒染 欄目:編程語言

今天就跟大家聊聊有關(guān)如何用Silverlight開發(fā)貪吃蛇游戲,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

介紹

使用 Silverlight 3.0(c#) 開發(fā)一個貪吃蛇游戲

玩法

W/S/A/D 或 ↑/↓/←/→ 控制蛇的移動

截圖

如何用Silverlight開發(fā)貪吃蛇游戲

思路

1、貪吃蛇的每一段為 16×16 像素,場景為 640×480 像素,也就說網(wǎng)格為 40×30 個,每個網(wǎng)格的邊長為 16

2、食物的出現(xiàn)位置以及貪吃蛇的運(yùn)動方向的改變都要在相關(guān)的網(wǎng)格內(nèi)進(jìn)行

3、貪吃蛇的運(yùn)動用即時運(yùn)算的方法計(jì)算,當(dāng)貪吃蛇運(yùn)動到網(wǎng)格內(nèi)(蛇某一段的像素位置%網(wǎng)格的邊長<蛇在某時間單位下的移動偏移量)時做如下工作:修正蛇的位置使其正好在網(wǎng)格內(nèi),更新蛇的每一段的運(yùn)動方向,判斷是否吃到了食物、是否發(fā)生了碰撞等

4、貪吃蛇的每一段的運(yùn)動方向的修改:蛇頭的運(yùn)動方向根據(jù)用戶的操作改變,蛇的每一段的運(yùn)動方向設(shè)置為此段的前一段的運(yùn)動方向(計(jì)算時要從尾部向頭部逐段計(jì)算)(注:運(yùn)動方向的改變要在蛇移動到網(wǎng)格內(nèi)時進(jìn)行。其中如果蛇的某一段移動到了網(wǎng)格內(nèi),則表明其它各段都在網(wǎng)格內(nèi))

下面我們看看他的關(guān)鍵代碼都有哪些。

關(guān)鍵代碼

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; // 網(wǎng)格列數(shù)          private int _rows; // 網(wǎng)格行數(shù)          private Dictionary<Body, CellPoint> _bodies = new Dictionary<Body, CellPoint>(); // 貪吃蛇每一段的集合          private Dictionary<Bean, CellPoint> _beans = new Dictionary<Bean, CellPoint>(); // 豆的集合          private Dictionary<Skin, CellPoint> _skins = new Dictionary<Skin, CellPoint>(); // 蛻下來的皮的集合          private List<CellPoint> _emptyCells = new List<CellPoint>(); // 空網(wǎng)格的集合          private bool _enabled = false; // 游戲是否運(yùn)行          private double _dt = 0.01; // 多少毫秒計(jì)算一次          private int _decimals = 1; // 計(jì)算小數(shù)時所保留的小數(shù)位          private double _speed = 80; // 蛇的運(yùn)行速度          private Direction _moveDirection = Direction.Up; // 蛇的運(yùn)行方向          private int _selfLength = 5; // 蛇的最小長度          private int _beansCount = 5; // 豆的***出現(xiàn)數(shù)量          private int _ateCapacity = 10; // 食量(超過則蛻皮)          private bool _needRaiseAteEvent = false; // 在“蛇頭所處位置進(jìn)入了網(wǎng)格點(diǎn)區(qū)域內(nèi)”時是否需要觸發(fā)吃豆事件          private int _needBeansCount = 0; // 還需要增加的豆的數(shù)量          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);          }          /// <summary>          /// 初始化          /// </summary>          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();          }           /// <summary>          /// 蛇的初始化          /// </summary>          private void InitSnake()          {              InitHead();               for (int i = 0; i < _selfLength - 1; i++)                  AddTail();               for (int i = 0; i < _beansCount; i++)                  AddBean();          }          /// <summary>          /// 蛇頭的初始化          /// </summary>          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);          }          /// <summary>          /// 增加一個尾巴          /// </summary>          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);          }          /// <summary>          /// 增加一個豆          /// </summary>          private void AddBean()          {              if (_needBeansCount < _beansCount)                  _needBeansCount++;          }          private DateTime _prevAddBeanDateTime = DateTime.Now;          /// <summary>          /// 生成豆          /// </summary>          void UpdateBean()          {              if (_needBeansCount > 0 && (DateTime.Now - _prevAddBeanDateTime).TotalSeconds > 3)              {                  List<CellPoint> 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;          }          /// <summary>          /// 即時計(jì)算          /// </summary>          private void Update()          {              if (!_enabled)                  return;              double offset = Math.Round(_speed * _dt, _decimals);              // 蛇頭所處位置進(jìn)入了網(wǎng)格點(diǎn)區(qū)域內(nèi)              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();          }          /// <summary>          /// 蛻皮          /// </summary>          private void CheckSkin()          {              if (_bodies.Count >= _ateCapacity + _selfLength)                  AddSkin(_ateCapacity);          }          /// <summary>          /// 碰撞檢測          /// </summary>          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);              }          }          /// <summary>          /// 吃豆          /// </summary>          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;              }          }          /// <summary>          /// 更新蛇的每一段的運(yùn)動方向          /// </summary>          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;              }          }          /// <summary>          /// 更新蛇的每一段的位置          /// </summary>          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));              }          }          /// <summary>          /// 蛻指定數(shù)量的皮          /// </summary>          private void AddSkin(int count)          {              player.PlaySkin();              while (count > 0)              {                  KeyValuePair<Body, CellPoint> 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 輔助方法          /// <summary>          /// 修正指定的位置信息為整數(shù)          /// </summary>          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;          }          /// <summary>          /// 修正蛇的每一段的位置為整數(shù)          /// </summary>          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);              }          }          /// <summary>          /// 更新蛇的每一段的網(wǎng)格位置信息          /// </summary>          private void UpdateBodyCell()          {              for (int i = 0; i < _bodies.Count; i++)              {                  UpdateBodyCell(_bodies.ElementAt(i).Key);              }          }          /// <summary>          /// 更新指定的 Body 的網(wǎng)格位置信息          /// </summary>          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;          }          /// <summary>          /// 修正網(wǎng)格位置          /// </summary>          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;          }          /// <summary>          /// 獲取空網(wǎng)格集合          /// </summary>          private List<CellPoint> GetEmptyCells()          {              List<CellPoint> emptyCells = new List<CellPoint>();              List<CellPoint> aroundHeadCells = new List<CellPoint>();              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 的占位情況因?yàn)榇_定了就不變了,所以在 AddSkin() 處計(jì)算              // 為了以下 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      }  }

看完上述內(nèi)容,你們對如何用Silverlight開發(fā)貪吃蛇游戲有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI