GDI图形编程(14)

 

程序清单3-11  绘制多帧动画中单独的一帧

// A variable to store the current animation frame.

int animFrame = 0;

Private void Form1_Paint(object sender, PaintEventArgs e)

{

const int frameWidth = 75; // The width of each animation frame

const int frameHeight = 75; // The height of each animation frame

// Create the source rectangle.

// This will have a width and height of 75 (the size of our animationframe).

// The x-coordinate will specify the position within the source image 

// from which we want to copy. Multiplying the animation frame number by 

the frame width 

// results in a coordinate at the left of the frame that we are going to 

// copy.

Rectangle srcRect = new Rectangle(animFrame * frameWidth, 0, frameWidth, frameHeight);

// Draw the bitmap at coordinate (100, 100)

e.Graphics.DrawImage(myBitmap, 100, 100, srcRect, GraphicsUnit.Pixel);

// Move to the next animation frame for the next Paint

animFrame += 1;

}

接下来对函数DrawImage中传递的参数进行解释:

● 第一个参数为需要在屏幕上进行绘制的Bitmap对象(myBitmap)。

● 接下来指定图像所要显示的位置,用x坐标和y坐标的形式,在本例中为(100,100)。

● 接下来再指定源图像中要绘制的区域的位置及大小(srcRect)。

● 与该函数的桌面版一样,其.NET CF版也让我们提供GraphicsUnit来测量Rectangles。由于现在的.NET CF版本中只支持像素,所以我们只能将GraphicsUnit.Pixel作为该参数的值。

2. 缩放

除了能够通过一个矩形来读取指定源图像的某个区域,我们还可以提供另一个矩形来指定绘制目标区域,而不像以前那样简单地使用坐标。如果目标矩形与原始矩形大小不同,那么位图会被缩放来适应目标矩形的尺寸。

这个功能具有潜在的作用,但是,对源位图进行缩放是个相当慢的操作,可能会影响游戏的运行速度。偶尔适当地使用一下缩放会产生有用的效果,但不能将它作用于大量的图像上,否则游戏的帧率会大幅下降。

要使用该功能的话,需要像指定源Rectangle对象和目标Rectangle对象,如程序清单3-12所示。如果两个矩形尺寸不一致,那么图像就会根据情况进行缩放。

程序清单3-12  将位图的宽与高放大到原来的两倍

private void Form1_Paint(object sender, PaintEventArgs e)

{

// Create the source rectangle to match the size of the bitmap.

Rectangle srcRect = new Rectangle(0, 0, myBitmap.Width, myBitmap.Height);

// Create the destination rectangle at double the size of the source rectangle.

Rectangle destRect = new Rectangle(100, 100, srcRect.Width * 2, srcRect.Height * 3);

// Draw the bitmap

e.Graphics.DrawImage(myBitmap, destRect, srcRect, GraphicsUnit.Pixel);

}

3. 颜色键

DrawImage函数最后要提到的这个功能可能是最重要的一个功能:绘制图像时使图像的某个区域透明。我们现在为止所看到的示例都是将图像完全不变地复制到屏幕的矩形区域中,将该区域原来的东西完全覆盖。绝大部分情况下,我们都会希望要绘制的图像与已存在的图像重叠时,不要出现那些矩形的空白。

图3-14展示了DrawImage函数标准的绘图行为。您可以看到第二个圆形图像的左侧将第一个图像剪切出了一个空白区域。而在右边的图中,这两个圆互不妨碍地重叠在一起。

 

图3-14  在绘图时没有采用颜色键的效果(左图)与采用颜色键的效果(右图)

使用一个颜色键可以得到图3-14右图的效果,我们将指定源图像中的某一种想要使之成为透明的颜色,然后将该颜色传递给DrawImage函数。在屏幕上绘图时任何一个与该颜色匹配的像素都会变为透明。这些透明的像素不只会像本例中那样只是出现在图像的外部,它们可以出现在任何需要进行透明处理的地方。因此,您需要选择一个图像中还没有使用的颜色。

颜色键只能使位图像素完全透明(对于那些与颜色键相匹配的像素)或者完全不透明(对于所有其他像素)。它不支持GDI提供的透明度或者半透明绘制(在第10章介绍OpenGL ES时您就会看到在绘图中如何处理透明度)。

要指定颜色键,需要创建一个ImageAttributes对象。这又是一个桌面版.NET类的精简版本,实际上,该类中只保留了SetColorKey和ClearColorKey这两个有用的函数。

通过调用SetColorKey函数来指定要透明化的颜色。您会发现该函数实际要接受两个Color类的参数,参数名分别为colorLow和colorHigh。其原因是要与其桌面版.NET函数保持一致,在桌面版的.NET函数中可以指定一个颜色范围。然而,.NET CF只支持单个颜色,所以要为这两个参数指定同一个颜色。程序清单3-13向屏幕绘制图像时令所有白色的像素为透明。

读书导航