這一節分析下具體實體類的定義和實現,下面是這個遊戲的實體類結構:
遊戲物體的運動就是不斷創建畫面和銷燬畫面的過程,原理和播放錄象帶一樣。所以我定義了一個基類,裏面定義了子類共同的成員,由於方法具體實現都一樣,所以在基類裏的Draw和Crear方法並沒有定義爲抽象方法,反而具體實現了它們!子類繼承後就不需要具體實現了。
CommonMethod.cs
- /// <summary>
- /// 這裏定義了一些蛇類和食物類中共同用到的函數和基本屬性數據,供子類繼承
- /// </summary>
- public class CommonMethod
- {
- public Point Point { get; set; }
- public void Draw(Graphics g, Pen p, SolidBrush s,Point point)
- {
- g.DrawRectangle(p, (11 * point.X - 9), (11 * point.Y - 9), 10, 10);
- g.FillRectangle(s, (11 * point.X - 8), (11 * point.Y - 8), 10 - 1, 10 - 1);
- }
- public void Crear(Graphics g, SolidBrush s, Point point)
- {
- g.FillRectangle(s, (11 * point.X - 9), (11 * point.Y - 9), 10 + 1, 10 + 1);
- }
- }
(上面的"10",爲遊戲地圖小方格的大小,遊戲地圖就是由N*M個小方格組成的,根據愛好自己定義了)
蛇類,除了繼承基類之外,還有屬於自己的成員。比如,蛇可以爬行而食物是靜止的。
蛇由座標集組成List<Point>,故蛇的爬行就是改邊蛇的座標點,我考慮到兩種實現爬行的方法:
方法一:遍歷所有List<Point>,讓後一個座標點等於前一個座標點,蛇頭爲運動方向的一個新座標,這樣蛇就可以爬行了;
for
(int i = 蛇身.Count - 1; i >= 1; i--)
{
蛇身[i] = 蛇身[i - 1];
}
.......
蛇身[0]=new Point(新座標);
方法二:蛇的爬行就是畫頭和消尾的過程,所以只需要改變蛇頭座標和刪掉尾座標即可,如果喫到食物,不用去尾,這樣蛇自然就變長了。
void Move()
{
蛇身.Insert(0, 新座標);
if(喫到食物)
......
else
蛇身.Remove(尾座標);
}
對比兩種方法,方法二效率明顯高於方法一,方法一每次蛇爬行都要重新畫整個蛇身,有時會導致畫面很閃爍(沒雙緩衝);方法二隻需畫蛇頭和消蛇尾就可以了。
Snake.cs
- public enum SnakeDirection
- {
- Up, Down, Left, Right
- }
- public enum SnakeState
- {
- Normal = 50, Fast = 30, Low = 200
- }
- public class Snake:CommonMethod
- {
- public List<Point> SnakePoints{get;set;}
- public SnakeDirection SnakeDirection { get; set; }
- public SnakeState SnakeState { get; set; }
- //活動場地
- public int backWidth;
- public int backHeight;
- //構造函數
- public Snake(int snakeLengh, SnakeDirection direction,int w,int h)
- {
- SnakePoints = new List<Point>();
- //缺省蛇長度
- for (int i = snakeLengh; i > 0; i--)
- {
- SnakePoints.Add(new Point(i,5));
- }
- this.SnakeDirection = direction;
- this.backWidth = w;
- this.backHeight = h;
- }
- //是否可以爬行,如果爲真,則把新座標添加進蛇身並充當蛇頭
- public bool IsCanMove(ref Point point)
- {
- point.X = SnakePoints[0].X;
- point.Y = SnakePoints[0].Y;
- switch (SnakeDirection)
- {
- case SnakeDirection.Up:
- if (point.Y == 1)
- return false;
- else
- point.Y -= 1;
- break;
- case SnakeDirection.Down:
- if (point.Y ==backHeight/10-3)
- return false;
- else
- point.Y += 1;
- break;
- case SnakeDirection.Left:
- if (point.X == 1)
- return false;
- else
- point.X -= 1;
- break;
- case SnakeDirection.Right:
- if (point.X ==backWidth/10-2)
- return false;
- else
- point.X += 1;
- break;
- }
- SnakePoints.Insert(0, point);
- return true;
- }
- //畫整個蛇身
- public void DrawSnake(Graphics g)
- {
- foreach (Point point in SnakePoints)
- {
- base.Draw(g, new Pen(Color.Black), new SolidBrush(Color.YellowGreen),point);
- }
- }
- //畫蛇頭
- public void DrawHead(Graphics g)
- {
- base.Draw(g, new Pen(Color.Black), new SolidBrush(Color.YellowGreen),Point);
- }
- }
食物類就比較簡單了
Food.cs
- /// <summary>
- /// 定義食物類型,以後擴展用,目前這個版本沒用到
- /// </summary>
- public enum FoodType
- {
- Normal,Fast,Slow,Long
- }
- public class Food:CommonMethod
- {
- public FoodType FoodType { get; set; }
- public void DrawFood(Graphics g)
- {
- base.Draw(g, new Pen(Color.Black), new SolidBrush(Color.Orange),Point);
- }
- }