/// <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>
/// 即时计算
/// </summary>
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();
}
/// <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>
/// 更新蛇的每一段的运动方向
/// </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>
/// 蜕指定数量的皮
/// </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>
/// 修正指定的位置信息为整数
/// </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>
/// 修正蛇的每一段的位置为整数
/// </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>
/// 更新蛇的每一段的网格位置信息
/// </summary>
private void UpdateBodyCell()
{
for ( int i = 0; i < _bodies.Count; i++)
{
UpdateBodyCell(_bodies.ElementAt(i).Key);
}
}
/// <summary>
/// 更新指定的 Body 的网格位置信息
/// </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>
/// 修正网格位置
/// </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>
/// 获取空网格集合
/// </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 的占位情况因为确定了就不变了,所以在 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
事件 GameOver 和 Ate #region 事件 GameOver 和 Ate
public event EventHandler GameOver;
public event EventHandler Ate;
#endregion
}
}
/// 生成豆
/// </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>
/// 即时计算
/// </summary>
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();
}
/// <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>
/// 更新蛇的每一段的运动方向
/// </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>
/// 蜕指定数量的皮
/// </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>
/// 修正指定的位置信息为整数
/// </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>
/// 修正蛇的每一段的位置为整数
/// </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>
/// 更新蛇的每一段的网格位置信息
/// </summary>
private void UpdateBodyCell()
{
for ( int i = 0; i < _bodies.Count; i++)
{
UpdateBodyCell(_bodies.ElementAt(i).Key);
}
}
/// <summary>
/// 更新指定的 Body 的网格位置信息
/// </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>
/// 修正网格位置
/// </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>
/// 获取空网格集合
/// </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 的占位情况因为确定了就不变了,所以在 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
事件 GameOver 和 Ate #region 事件 GameOver 和 Ate
public event EventHandler GameOver;
public event EventHandler Ate;
#endregion
}
}
OK
[源码下载]
本文转自webabcd 51CTO博客,原文链接:
http://blog.51cto.com/webabcd/345619
,如需转载请自行联系原作者