程序清单8-6 渲染CObjGem类
/// <summary>
/// Draw the gem to the screen
/// </summary>
public override void Render(Graphics gfx, float interpFactor)
{
System.Drawing.Imaging.ImageAttributes imgAttributes;
base.Render(gfx, interpFactor);
// Create the transparency key for the gem graphics
imgAttributes = new System.Drawing.Imaging.ImageAttributes();
imgAttributes.SetColorKey(Color.Black, Color.Black);
// If this is not a rainbow gem...
if (_gemColor != CGemDropsGame.GEMCOLOR_RAINBOW)
{
// Then just draw its image
gfx.DrawImage(_game.GameGraphics["Gems"], GetRenderRectangle(interpFactor),
_gemColor * (int)Width, 0, (int)Width, (int)Height,
GraphicsUnit.Pixel, imgAttributes);
}
else
{
// This is a rainbow gem so we need to cycle its color.
// Add the elapsed time to our class variable
_rainbowGemUpdateTime += GameEngine.TimeSinceLastRender;
// Has 0.1 seconds elapsed?
if (_rainbowGemUpdateTime > 0.1f)
{
// Yes, so advance to the next color
_rainbowGemUpdateTime = 0;
_rainbowGemFrame += 1;
// If we reach the rainbow gem position (pass the final
// actual gem color), move back to the first
if (_rainbowGemFrame == CGemDropsGame.GEMCOLOR_RAINBOW) _rainbowGemFrame=0;
}
// Ensure the gem is considered as moved so that it re-renders in its
// new color.
// This is important so that it still cycles when in the "next gem"
// display which isn't otherwise moving.
HasMoved = true;
// Draw its image
gfx.DrawImage(_game.GameGraphics["Gems"], GetRenderRectangle(interpFactor),
_rainbowGemFrame * (int)Width, 0, (int)Width, (int)Height,
GraphicsUnit.Pixel, imgAttributes);
}
}
宝石图像的透明区域使用黑色背景,所以代码中首先创建了一个ImageAttributes对象并指定黑色为颜色键,然后调用DrawImage函数来绘制该对象所代表的宝石。对于普通的宝石,我们要根据宝石颜色索引乘以宝石的宽度来计算出源图像中需要选取的区域。这能够索引宝石图像,得到想要的颜色的宝石。
对于彩虹宝石,我们用_rainbowGemUpdateTime来累计上一次调用Render函数后所过去的时间,通过游戏引擎的TimeSinceLastRender属性来得到该值。每当该值累计达到0.1秒,我们就增加_rainbowGemFrame的值,并将_rainbowGemUpdateTime的值重置为0。通过修改时间上限(即用于同_rainbowGemUpdateTime进行比较的值,在这里为0.1),我们可以使彩虹宝石按照我们想要的频率来变换色彩。
CObjGem类还对基类中的一些属性进行了重写:XPos、YPos、Width及Height属性的get部分都被重写了。这样我们就可以根据自己的需要来计算这些属性值,而不是对象每发生一点变化都要进行更新。
对于XPos和YPos属性,我们要利用在CGemDropsGame.Prepare函数中设置好的抽象坐标系。通过初始化坐标系时计算得到的BoardLeft值和BoardTop值来计算位置。函数把宝石的宽和高乘到这些值上。这里不包含绝对坐标和硬编码的坐标。这个简单的方法能够保证在所有支持的屏幕分辨率上游戏都能正确地显示。
对于Width属性和Height属性,只需要通过CGemDropsGame对象就可以得到宝石的尺寸。同样,这些值也是在调用Prepare方法时就计算好的。如果手机方向改变,导致加载另一套图形集(因此宝石的Width和Height属性会改变),那么这样可以确保这两个属性值始终能返回正确的值,而不需要通知发生了变化。
游戏引擎会用到所有这4个属性的重写版本,它们可以很方便地为游戏对象提供所需的值,这些属性的代码如程序清单。