七、二维显示
在DirectX中大部分二维显示都由Sprite来完成,如动画、公告板、二维文字等。在DirectX中有专门的Sprite类用于简化sprite的绘制和处理,下面来看一下Sprite类的一些方法:
方法 |
定义 |
说明 |
Begin |
public void Begin( SpriteFlags flags); |
开始绘制Sprite |
Dispose |
public override void Dispose(); |
立即释放用Sprite托管的资源 |
Draw |
public void Draw( Texture srcTexture, Rectangle srcRectangle, Vector3 center, Vector3 position, Color color); |
绘制一个Sprite对象(如图片) |
Draw2D |
public void Draw2D( Texture srcTexture, Point rotationCenter, float rotationAngle, Point position, Color color ); |
绘制一个Sprite对象用于二维空间中显示 |
End |
public void End(); |
结束绘制Sprite |
SetWorldViewLH |
public void SetWorldViewLH( Matrix world, Matrix view ); |
为Sprite设置一个左手法则的世界—视图变换,该方法要用于billboarding(电子版)之前 |
SetWorldViewRH |
public void SetWorldViewRH( Matrix world, Matrix view ); |
为Sprite设置一个右手法则的世界—视图变换,该方法要用于billboarding(电子版)之前 |
Sprite |
public Sprite(Device); |
初始化一个Sprite类 |
1、显示图片
首先在全局中定义图片对象变量,如下代码:
Texture showPicture;//定义图片对象
然后在初始化时导入图片,在InitializeDirect3D()函数中添加如下代码:
string imagePath = @"D:/My Documents/My Pictures/xzy.bmp";
showPicture = TextureLoader.FromFile(device, imagePath);
最后,在渲染函数Render()中添加用Sprite绘制图片的代码,如下代码:
Sprite sprite;//定义Sprite对象
sprite = new Sprite(device);//实例化Sprite对象
sprite.Begin(SpriteFlags.AlphaBlend);
System.Drawing.Point rotationPoint=new Point();
System.Drawing.Point position=new Point();
position.X = 100;
position.Y = 150;
sprite.Draw2D(showPicture, rotationPoint,0f, position, Color.White);
sprite.End();
运行程序,其结果如下图所示:
上面的代码中每次在调用Render()函数时都将创建一个Sprite,这将导致系统内存不断增加,为了避免重复地创建Sprite,可以采用如下两种方式:
1)方式一
在全局中定义Sprite,如下代码:
private Sprite sprite;//定义Sprite对象
然后在初始化函数InitializeDirect3D()中添加Sprite变量的实例化代码,如下代码:
sprite = new Sprite(device);
最后在Render()函数中添加如下代码:
sprite.Begin(SpriteFlags.AlphaBlend);
System.Drawing.Point rotationPoint = new Point();
System.Drawing.Point position = new Point();
position.X = 100;
position.Y = 150;
sprite.Draw2D(showPicture, rotationPoint, 0f, position, Color.White);
sprite.End();
2)方式二
如果不采用前面的方式,也可以直接在代码“sprite.End();”后添加如下代码:
sprite.Dispose();//释放Sprite对象
前面显示图片是采用Sprite的Draw2D()方法来实现,下面介绍采用Sprite的Draw ()方法来实现:
1)首先在全局中定义Sprite变量及图片对象,如下代码:
private Sprite sprite;//定义Sprite对象
private Texture showPicture;//定义图片对象
2)在初始化函数InitializeDirect3D()中添加Sprite变量和图片对象的实例化代码,如下代码:
sprite = new Sprite(device);
string imagePath = @"D:/My Documents/My Pictures/xzy.png";
showPicture = TextureLoader.FromFile(device, imagePath);
3)在渲染Render()函数中添加显示图片,如下代码:
int spriteX = 10;
sprite.Begin(SpriteFlags.AlphaBlend);
sprite.Draw(showPicture, Vector3.Empty, new Vector3(spriteX, 50, 0), Color.White.ToArgb());
spriteX += showPicture.GetLevelDescription(0).Width + 10;
sprite.Draw(showPicture, new Rectangle(4, 4, 100, 100), Vector3.Empty, new Vector3(spriteX, 50, 0), Color.Green);
spriteX += showPicture.GetLevelDescription(1).Width;
sprite.Draw(showPicture, Rectangle.Empty, Vector3.Empty, new Vector3(spriteX, 50, 0), Color.Yellow);
sprite.End();
上面采用Sprite的Draw ()方法的几种不同的重载函数,运行程序,其结果如下图所示:
2、二维图片动画
图片动画其实就是由一系列图片随着时间变化形成的,所以首先在全局中定义如下变量:
private const int frameCount = 8;//定义动画帧数目
private int currentFrame=0;//定义当前动画帧
private System.Windows.Forms.Timer aniTimer;//定义计时器
然后在初始化函数InitializeDirect3D()中设置图片、计时器等,首先修改图片来源为如下:
string imagePath = @"E:/DirectX/DirectX_C#/Media/火焰/fire.png";
接着就设置计时器的一些相关属性,如下代码:
aniTimer = new Timer();
aniTimer.Enabled = true;
aniTimer.Interval = 100;
aniTimer.Tick += new System.EventHandler(this.aniTimer_Tick);
其中最后一句代码是定义计时器的事件连接,所以对应定义事件函数aniTimer_Tick(),如下代码:
private void aniTimer_Tick(object sender, EventArgs e)
{
if (currentFrame >= frameCount-1)
{
currentFrame = 0;
}
else
{
currentFrame++;
}
}
最后在渲染函数Render()中sprite.Begin()和sprite.End()之间添加绘制图片,如下代码:
Rectangle originPicRect = new Rectangle(64 * currentFrame, 0, 64, 128);
sprite.Draw(showPicture, originPicRect, Vector3.Empty, new Vector3(50, 50, 0), Color.White.ToArgb());
运行程序,其结果如下图所示:
3、显示二维文字
首先在全局中定义Sprite及Font等变量,如下代码:
private Sprite sprite;//定义Sprite对象
private System.Drawing.Font currentFont;//定义字体
private Microsoft.DirectX.Direct3D.Font myFont;//定义文字对象
然后在初始化函数InitializeDirect3D()中添加Sprite变量和文字对象的实例化代码,如下代码:
sprite = new Sprite(device);//实例化Sprite对象
currentFont = new System.Drawing.Font("Times New Roman", 28, FontStyle.Regular);//设置字体
myFont = new Microsoft.DirectX.Direct3D.Font(device, currentFont);//创建文字对象
最后在渲染函数Render()中添加绘制文字代码,如下代码:
sprite.Begin(SpriteFlags.AlphaBlend);
myFont.DrawText(sprite, "Hello,DirectX!", 200, 100, Color.Yellow);
sprite.End();
运行程序,其结果如下图所示:
通过指定前面代码sprite.Begin()方法中的参数SpriteFlags可以优化和提高性能,SpriteFlags的值有如下几种:
值 |
说明 |
SpriteFlags.SortTexture |
在将图像绘制到屏幕之前先对图像进行排序,以便加快切换纹理的速度 |
SpriteFlags.AlphaBlend |
可正确呈现字体,尤其适用于具有透明或半透明区域的子画面 |
SpriteFlags.SortDepthBackToFront |
按照从前向后的顺序对子画面进行排序;如果您拥有几个要互相绘制到对方顶部的透明或半透明子画面,就可以使用此值 |
SpriteFlags.DoNotSaveState |
可提高那些不能使用指定呈现状态的应用程序的性能 |
SpriteFlags.DoNotModifyRenderState |
可通过使用当前呈现状态优化性能,且可用来获得特殊效果 |
SpriteFlags.ObjectSpace 和SpriteFlags.Billboard |
可以绘制出具有各种不同的特殊效果的图像 |