概述 图形是直接在屏幕而非在3D空间上绘制,图形通常用来向玩家显示诸如生命槽、命数或者是显示 分数的文字。一些游戏,尤其是一些老游戏,几乎全部由图形组成。 要绘制一个图形,你必须要建立一个SpriteBatch对象,通过调用SpriteBatch.Begin()来进行初 始化,接着为每一个图形调用Draw方法。一个图形的位图信息是从一个Texture对象来取得。这个文 本可能包含alpha通道信息以此来令部分文本透明或者半透明。你可以通过Draw方法来对图形进行着 色、旋转和缩放等操作。这个方法也给了你只在屏幕上绘制部分文本的选项。 绘制图形时最重要的概念是图形原点。这个原点是图形上的一个特殊的点--默认的是图形左上方 的点(0,0)。Draw方法在屏幕上你所指定的位置绘制图形的原点。当你旋转一个图形,Draw方法 利用圆点作为旋转的中心。鉴于此,当你要计算在屏幕何处绘制图形的时候,通常利用图形的中心 点作为原点。 在绘制任何一个图形之前,你必须调用SpriteBatch.Begin()作为渲染循环的一部分。在绘制完图 形后,在调用GraphicsDevice.Present()之前先调用End(). 绘制图形 这篇文章重点讲述如何通过使用SpriteBatch类来绘制图形。 要绘制图形: 如How to:Create a Simple Game Loop中所述,从Game类中继承一个类。 定义一个SpriteBatch对象作为你的game类的一个域。 如How to:Load Resources中所述,初始化来加载资源。 在你的LoadResources方法中,构造SpriteBatch对象,passing当前的图形设备。 在LoadRecoures中加载那些将要在绘制图形中使用的文本。这种情况下,示例利用FromFile来从 磁盘加载文本。文本位置必须和游戏执行的目录相同。在C# Express中,向项目中添加文本时设置" copy if newer"来保证这个texture在运行时可用。 private Texture2D SpriteTexture; private SpriteBatch ForegroundBatch; protected virtual void LoadResources() { //在这里加载资源(文本、网格、声音) ForegroundBatch = new SpriteBatch( graphics.GraphicsDevice ); SpriteTexture = Texture2D.FromFile( graphics.GraphicsDevice, "sprite.dds" ); } 调用绘制方法之前,首先调用Clear和BeginScene方法。 BeginScene之后,调用SpriteBatch对象的SpriteBatch.Begin()方法。 创建一个Vector2来代表图形在屏幕上的位置。 调用SpriteBatch对象的Draw方法,传递要绘制的文字、屏幕位置以及应用的颜色。用白色绘制文 字时没有任何色彩效果。 当所有的图形都绘制完毕,调用SpriteBatch对象的End方法。 当所有的图形对象都已经绘制完毕,调用EndScene和GraphicsDevice.Present()。 protected override void Draw() { if (!graphics.EnsureDevice()) return; graphics.GraphicsDevice.Clear( Color.CornflowerBlue ); graphics.GraphicsDevice.BeginScene(); // 在这里添加你的绘图代码 ForegroundBatch.Begin(); Vector2 pos = new Vector2( 0,0 ); ForegroundBatch.Draw( SpriteTexture, pos, Color.White ); ForegroundBatch.End(); //让GameComponents来进行绘制 DrawComponents(); graphics.GraphicsDevice.EndScene(); graphics.GraphicsDevice.Present(); } C# using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Components; using Microsoft.Xna.Framework.Graphics; private Texture2D SpriteTexture; private SpriteBatch ForegroundBatch; protected virtual void LoadResources() { //在这里加载资源(文本、网格、声音) ForegroundBatch = new SpriteBatch( graphics.GraphicsDevice ); SpriteTexture = Texture2D.FromFile( graphics.GraphicsDevice, "sprite.dds" ); } protected override void Draw() { if (!graphics.EnsureDevice()) return; graphics.GraphicsDevice.Clear( Color.CornflowerBlue ); graphics.GraphicsDevice.BeginScene(); // 在这里添加你的绘图代码 ForegroundBatch.Begin(); Vector2 pos = new Vector2( 0,0 ); ForegroundBatch.Draw( SpriteTexture, pos, Color.White ); ForegroundBatch.End(); // 让GameComponents来进行绘制 DrawComponents(); graphics.GraphicsDevice.EndScene(); graphics.GraphicsDevice.Present(); } 制作动画 这篇文章重点介绍如何通过一个 示例中的源代码假定被加载的文字是一系列等大小的图片。在这个例子里,提供的文字都是有4帧 结构的256x64的文字。 要实现一个动画: 遵循How to:Draw a Sprite中的1-4步。 加载文字或是向动画提供图片数据的文字。在示例中,AnimatedTexture类加载了一个单独的文字 ,并把它分解为动画的帧。 private AnimatedTexture SpriteTexture; private SpriteBatch ForegroundBatch; protected virtual void LoadResources() { //TODO: Load Resources (textures, meshes, sounds) here. ForegroundBatch = new SpriteBatch( graphics.GraphicsDevice ); SpriteTexture.Load( graphics.GraphicsDevice, "viperanimated.dds", 4 ); } 为了保证动画的流畅,设定你的游戏循环在固定的间隔内调用更新。在你的OnStarting方法中, 设定IsFixedTimeStep为真,并为TargetElapsedTime赋值。在示例中,我们设定游戏循环每秒钟调 用Update 4次。 protected override void OnStarting() { base.OnStarting(); LoadResources(); graphics.DeviceReset += new EventHandler( graphics_DeviceReset ); // Call Update() 4 times per second IsFixedTimeStep = true; TargetElapsedTime = new TimeSpan( 2500000 ); } 在你游戏的Update方法中,决定动画的那一帧要进行显示。 //The time since Update was called last float elapsed = (float)ElapsedTime.TotalSeconds; //在这里添加你的游戏逻辑 CurrentFrame++; //令当前帧保持在0至3之间 CurrentFrame = CurrentFrame % 3; 利用包含所要求的动画的文字subrectangle来绘制图形。 protected override void Draw() { ... ForegroundBatch.Begin(); SpriteTexture.DrawFrame( ForegroundBatch, CurrentFrame, Vector2.Zero ); ForegroundBatch.End(); ... } public void DrawFrame( SpriteBatch Batch, int Frame, Vector2 screenpos ) { int FrameWidth = TextureInfo.Width / FrameCount; Rectangle sourcerect = new Rectangle( FrameWidth * Frame, 0, FrameWidth, TextureInfo.Height ); Batch.Draw( myTexture, screenpos, sourcerect, Color.White ); } 当所有的图形绘制完毕,调用SpriteBatch对象的End方法。 当所有的图形对象绘制完毕,调用EndScene和GraphicsDevice.Present()方法。 C# public class AnimatedTexture { private int FrameCount; private Texture2D myTexture; private TextureInformation TextureInfo; public void Load( GraphicsDevice device, string filename, int Frames ) { FrameCount = Frames; myTexture = Texture2D.FromFile( device, filename ); TextureInfo = Texture2D.GetTextureInformation( filename ); } public void DrawFrame( SpriteBatch Batch, int Frame, Vector2 screenpos ) { int FrameWidth = TextureInfo.Width / FrameCount; Rectangle sourcerect = new Rectangle( FrameWidth * Frame, 0, FrameWidth, TextureInfo.Height ); Batch.Draw( myTexture, screenpos, sourcerect, Color.White ); } } 制作有图形遮蔽的文件 这篇文章将要解释如何使用.png或.bmp格式的文件以及DirectX Texture工具来制作一个带遮盖层 (透明度)的文本。 利用.png文件来制作透明文本: 在.png文件编辑器里,创建或者拷贝你所希望用到文本上的图片,并为文件设置透明区域。 在DirectX Texture 工具中,创建一个和.png文件尺寸相同的新的文本。 选择一个拥有alpha通道的文本格式,例如A8R8G8B8。 在DirectX Texture工具中,点击Open Onto This Surface并选择该.png文件。 最后在DirectX Texture工具中生成的文本现在应含有和.png文件相同的图形以及透明区域。 利用.bmp文件来制作透明文本: 在.bmp文件编辑器(例如Windows画图程序),创建或者拷贝你所希望用到文本上的.bmp图片。 再创建一个"遮蔽"bmp文件,文本不透明的部分用白色像素,而透明部分用黑色像素。 在DirectX Texture工具中,创建一个和.bmp文件尺寸相同的新的文本。 选择一个拥有alpha通道的文本格式,例如A8R8G8B8。 在DirectX Texture工具中,点击Open Onto This Surface并选择第一个.bmp文件。 在DirectX Texture工具中,点击Open Onto Alpha Channel Of This Surface并选择第二个.bmp 文件。 最后在DirectX Texture工具中生成的文本现在应含有和第一个.bmp文件相同的图形以及和第二个 .bmp文件相同的透明区域。 p.s:不是图形专业的,好多名词可能都不对,见谅。供大家参考修改。。。 |