/// <summary> /// 精灵类 /// </summary> public class Sprite { /// <summary> /// 顶点数量 /// </summary> const int VertexAmount = 6; //2个三角形 /// <summary> /// 顶点坐标 /// </summary> Vector[] _vertexPositions = new Vector[VertexAmount]; /// <summary> /// 顶点色彩(局部色彩) /// </summary> GlColor[] _vertexColors = new GlColor[VertexAmount]; /// <summary> /// 顶点映射(纹理贴图用于渲染多边形的特定部分) /// </summary> GlPoint[] _vertexUVs = new GlPoint[VertexAmount]; /// <summary> /// 纹理 /// </summary> Texture2D _texture = new Texture2D(); /// <summary> /// 获取或设置精灵纹理 /// </summary> public Texture2D Texture { get { return _texture; } set { _texture = value; //默认使用纹理自身的宽高 InitVertexPositions(CenterPosition, _texture.Width, _texture.Height); } } /// <summary> /// 获取顶点数组 /// </summary> public Vector[] VertexPositions { get { return _vertexPositions; } } /// <summary> /// 获取顶点颜色数组 /// </summary> public GlColor[] VertexColors { get { return _vertexColors; } } /// <summary> /// 获取顶点坐标数组 /// </summary> public GlPoint[] VertexUVs { get { return _vertexUVs; } } /// <summary> /// 获取或设置宽度 /// </summary> public double Width { get { // 获取实际显示在屏幕上的宽度 return _vertexPositions[1].X - _vertexPositions[0].X; } set { InitVertexPositions(CenterPosition, value, Height); } } /// <summary> /// 获取或设置高度 /// </summary> public double Height { get { // topleft - bottomleft return _vertexPositions[0].Y - _vertexPositions[2].Y; } set { InitVertexPositions(CenterPosition, Width, value); } } /// <summary> /// 创建一个精灵 /// </summary> public Sprite() { InitVertexPositions(Vector.Zero, 1, 1); SetColor(GlColor.GetWhite()); SetUVs(new GlPoint(0, 0), new GlPoint(1, 1)); //正确设置默认的初始位置 _currentPosition = new Vector( _vertexPositions[0].X + Width / 2, _vertexPositions[0].Y - Height / 2, _vertexPositions[0].Z); } /// <summary> /// 初始化顶点信息 /// </summary> void InitVertexPositions(Vector center, double width, double height) { double halfWidth = width / 2; double halfHeight = height / 2; //顺时针创建两个三角形构成四方形 // TopLeft, TopRight, BottomLeft _vertexPositions[0] = new Vector(center.X - halfWidth, center.Y + halfHeight, center.Z); _vertexPositions[1] = new Vector(center.X + halfWidth, center.Y + halfHeight, center.Z); _vertexPositions[2] = new Vector(center.X - halfWidth, center.Y - halfHeight, center.Z); // TopRight, BottomRight, BottomLeft _vertexPositions[3] = new Vector(center.X + halfWidth, center.Y + halfHeight, center.Z); _vertexPositions[4] = new Vector(center.X + halfWidth, center.Y - halfHeight, center.Z); _vertexPositions[5] = new Vector(center.X - halfWidth, center.Y - halfHeight, center.Z); } /// <summary> /// 获取或设置中心位置 /// </summary> public Vector CenterPosition { get { return _currentPosition; } set { Matrix m = new Matrix(); m.SetTranslation(value - _currentPosition); ApplyMatrix(m); _currentPosition = value; } } /// <summary> /// 设置颜色 /// </summary> public void SetColor(GlColor color) { for (int i = 0; i < Sprite.VertexAmount; i++) { _vertexColors[i] = color; } } /// <summary> /// 设置UV,进行纹理映射 /// </summary> public void SetUVs(GlPoint topLeft, GlPoint bottomRight) { // TopLeft, TopRight, BottomLeft _vertexUVs[0] = topLeft; _vertexUVs[1] = new GlPoint(bottomRight.X, topLeft.Y); _vertexUVs[2] = new GlPoint(topLeft.X, bottomRight.Y); // TopRight, BottomRight, BottomLeft _vertexUVs[3] = new GlPoint(bottomRight.X, topLeft.Y); _vertexUVs[4] = bottomRight; _vertexUVs[5] = new GlPoint(topLeft.X, bottomRight.Y); } /// <summary> /// 应用矩阵操作 /// </summary> public void ApplyMatrix(Matrix m) { for (int i = 0; i < VertexPositions.Length; i++) { VertexPositions[i] *= m; } } }
/// <summary> /// 动画精灵 /// </summary> public class AnimatedSprite : Sprite { /// <summary> /// 总帧数 /// </summary> int _totalFrame; /// <summary> /// 帧宽 /// </summary> double _frameWidth; /// <summary> /// 帧高 /// </summary> double _frameHeight; /// <summary> /// 当前帧 /// </summary> int _currentFrame; /// <summary> /// 当前帧的计时 /// </summary> double _currentFrameTime; /// <summary> /// 获取或设置每一帧持续的时间 /// </summary> public double FrameDuration { get; set; } /// <summary> /// 是否循环播放 /// </summary> public bool Looping { get; set; } /// <summary> /// 是否播放结束 /// </summary> public bool Finished { get; private set; } /// <summary> /// 获取一行的帧数量 /// </summary> public int RowFrame { get { return (int)Math.Round(Width / _frameWidth); } } /// <summary> /// 创建一个可播放的动画精灵 /// </summary> public AnimatedSprite() { Looping = false; Finished = false; FrameDuration = 0.05; _frameHeight = 0; _frameWidth = 0; _currentFrame = 0; _totalFrame = 1; _currentFrameTime = FrameDuration; } /// <summary> /// 拨动到下一帧 /// </summary> public void AdvanceFrame() { _currentFrame = (_currentFrame + 1) % _totalFrame; } /// <summary> /// 获取帧值在图源中的位置索引 /// </summary> GlPoint GetIndexFromFrame(int frame) { GlPoint point = new GlPoint(); point.Y = frame / RowFrame; point.X = frame - (point.Y * RowFrame); return point; } /// <summary> /// 更新显示数据 /// </summary> void UpdateDisplay() { GlPoint index = GetIndexFromFrame(_currentFrame); Vector startPosition = new Vector(index.X * _frameWidth, index.Y * _frameHeight); Vector endPosition = startPosition + new Vector(_frameWidth, _frameHeight); SetUVs(new GlPoint((float)(startPosition.X / Width), (float)(startPosition.Y / Height)), new GlPoint((float)(endPosition.X / Width), (float)(endPosition.Y / Height))); } /// <summary> /// 通知动画精灵的总帧数 /// </summary> public void SetTotalFrame(int totalFrame) { _totalFrame = totalFrame; _currentFrame = 0; _currentFrameTime = FrameDuration; UpdateDisplay(); } /// <summary> /// 通知动画精灵的帧大小,每一帧将应用一致的尺寸 /// </summary> public void SetFrameSize(double width, double height) { _frameWidth = width; _frameHeight = height; UpdateDisplay(); } /// <summary> /// 处理更新 /// </summary> public override void Process(double elapsedTime) { if (_currentFrame == _totalFrame - 1 && Looping == false) { Finished = true; return; } _currentFrameTime -= elapsedTime; if (_currentFrameTime < 0) { _currentFrameTime = FrameDuration; AdvanceFrame(); UpdateDisplay(); } } /// <summary> /// 缩放时维护帧大小 /// </summary> public override void SetScale(double x, double y) { _frameWidth /= _scaleX; _frameHeight /= _scaleY; base.SetScale(x, y); _frameWidth *= x; _frameHeight *= y; UpdateDisplay(); } }
public void ProcessTest() { AnimatedSprite target = new AnimatedSprite(); target.Texture = new Texture2D(0, 256, 256); target.SetTotalFrame(16); target.SetFrameSize(64, 64); target.CenterPosition = Vector.Zero; Assert.IsTrue(target.CurrentFrame == 0); Assert.IsTrue(target.Finished == false); double elapsedTime = 0.32; MultiProcess(target, elapsedTime); Assert.IsTrue(target.CurrentFrame == 3); MultiProcess(target, elapsedTime); MultiProcess(target, elapsedTime); MultiProcess(target, elapsedTime); MultiProcess(target, elapsedTime); MultiProcess(target, elapsedTime); MultiProcess(target, elapsedTime); MultiProcess(target, elapsedTime); Assert.IsTrue(target.Finished == true); Assert.IsTrue(target.CurrentFrame == 15); }
原文地址:http://blog.csdn.net/u011453312/article/details/38556527