HOW TO:使用精靈

更新:2007 年 11 月

您可以使用精靈 (Sprite) 將影像和文字描繪到螢幕上。這個範例示範如何描繪和呈現。

這個程式碼範例的表單具有下列物件:

此程式碼範例會從檔案載入紋理以建立精靈。您將需要在部署至裝置或模擬器的專案中,包含一個小型點陣圖。

表單的建構函式會指定裝置之 PresentationParameters 屬性的設定、建立 Device 物件,並呼叫裝置的 Reset 方法。它也會建構 Font 物件。

下表描述呈現精靈的範例方法。

注意事項:

Managed Direct3D Mobile 應用程式需要適用於 Pocket PC 和 Smartphone 的 Windows Mobile 5.0 版軟體。如需 Windows Mobile 軟體和 SDK 的詳細資訊,請參閱 .NET Compact Framework 的外部資源

方法

動作

OnDeviceReset

  • 從點陣圖檔案載入紋理。

OnPaint

  1. 開始場景。

  2. 指定 SpriteFlags 旗標。如需詳細資料,請參閱本主題稍後的「穩固的程式設計」一節。

  3. 將精靈和文字描繪到螢幕上。

  4. 結束場景。

範例

下列程式碼範例會提供完整的表單。此範例使用提供的點陣圖來描繪精靈。

Class Sprites
    Inherits Form
    ' The objects that will be used to show
    ' the uses of the Sprite class
    Private device As Device
    Private d3dFont As Microsoft.WindowsMobile.DirectX.Direct3D.Font
    Private sprite As Sprite
    Private texture As Texture


    Public Sub New() 
        Dim present As PresentParameters
        Dim gdiFont As System.Drawing.Font

        Me.Text = "Using Sprites"

        ' Give the application a way to be closed.
        ' This must be done before the device is created
        ' as it will cause the hwnd of the Form to change.
        Me.MinimizeBox = False

        present = New PresentParameters()
        present.Windowed = True
        present.SwapEffect = SwapEffect.Discard

        device = New Device(0, DeviceType.Default, Me, CreateFlags.None, present)
        AddHandler device.DeviceReset, AddressOf OnDeviceReset

        ' Construct a new Sprite.
        ' Sprites do not need to be recreated
        ' when a device is reset.
        sprite = New Sprite(device)

        gdiFont = New System.Drawing.Font(FontFamily.GenericSansSerif, 10F, FontStyle.Regular)

        ' Construct a new font. Fonts do not need
        ' to be recreated when a device is reset.
        d3dFont = New Microsoft.WindowsMobile.DirectX.Direct3D.Font(device, gdiFont)

        OnDeviceReset(Nothing, EventArgs.Empty)

    End Sub


    Private Sub OnDeviceReset(ByVal sender As Object, ByVal e As EventArgs) 
        ' Textures must be recreated whenever a device is reset
        ' no matter what pool they are created in.
        texture = TextureLoader.FromFile(device, "image.bmp")

    End Sub


    Protected Overrides Sub OnPaintBackground(ByVal e As PaintEventArgs) 
        ' Do nothing.
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        ' Begin the scene and clear the back buffer to black
        device.BeginScene()
        device.Clear(ClearFlags.Target, Color.Black, 1.0F, 0)

        ' When using sprites it is important to
        ' specify sprite flags passed to Sprite.Begin
        sprite.Begin(SpriteFlags.SortTexture Or SpriteFlags.AlphaBlend)

        ' Draw an image to the screen using Sprite.Draw
        Dim spriteY As Integer = 5

        sprite.Draw(texture, Vector3.Empty, New Vector3(0, spriteY, 0), Color.White.ToArgb())
        spriteY += texture.GetLevelDescription(0).Height + 5

        ' Draw a portion of an image to the screen
        ' using Sprite.Draw. This shall be drawn such
        ' that the image is modulated with the color green.
        sprite.Draw(texture, New Rectangle(4, 4, 24, 24), Vector3.Empty, New Vector3(0, spriteY, 0), Color.Green)

        spriteY += 30

        ' Draw text to the screen. Using a sprite to draw text
        ' to the  screen is essential for good performance.
        ' Otherwise the font object will perform a
        ' Sprite.Begin/Sprite.End internally for
        ' each call to Font.DrawText. This can cause severe
        ' performance problems.
        spriteY = 150

        d3dFont.DrawText(sprite, "This is text.", 5, spriteY, Color.Red)
        spriteY += d3dFont.Description.Height + 5

        d3dFont.DrawText(sprite, "This is another line of text.", 5, spriteY, Color.Green)
        spriteY += d3dFont.Description.Height + 5

        d3dFont.DrawText(sprite, "Only one call to Sprite.Begin.", 5, spriteY, Color.Blue)

        ' End drawing using this sprite. This will cause the
        ' sprites to be flushed to the graphics driver and will
        ' reset the transformation matrices, textures states,
        ' and renderstates if the SpriteFlags specified in Begin
        ' call for that to happen.
        sprite.End()

        ' Finish the scene and present it on the screen.
        device.EndScene()
        device.Present()

    End Sub


    Shared Sub Main() 
        Application.Run(New Sprites())

    End Sub
End Class
class Sprites : Form
{
    // The objects that will be used to show
    // the uses of the Sprite class
    private Device device;
    private Microsoft.WindowsMobile.DirectX.Direct3D.Font d3dFont;
    private Sprite sprite;
    private Texture texture;

    public Sprites()
    {
        PresentParameters present;
        System.Drawing.Font gdiFont;

        this.Text = "Using Sprites";

        // Give the application a way to be closed.
        // This must be done before the device is created
        // as it will cause the hwnd of the Form to change.
        this.MinimizeBox = false;

        present = new PresentParameters();
        present.Windowed = true;
        present.SwapEffect = SwapEffect.Discard;

        device = new Device(0, DeviceType.Default, this,
            CreateFlags.None, present);
        device.DeviceReset += new EventHandler(OnDeviceReset);

        // Construct a new Sprite.
        // Sprites do not need to be recreated
        // when a device is reset.
        sprite = new Sprite(device);

        gdiFont = new System.Drawing.Font
            (FontFamily.GenericSansSerif,
        10.0f, FontStyle.Regular);

        // Construct a new font. Fonts do not need
        // to be recreated when a device is reset.
        d3dFont= new Microsoft.WindowsMobile.DirectX.Direct3D.Font
            (device, gdiFont);

        OnDeviceReset(null, EventArgs.Empty);
    }

    private void OnDeviceReset(object sender, EventArgs e)
    {
        // Textures must be recreated whenever a device is reset
        // no matter what pool they are created in.
        texture = TextureLoader.FromFile(device, "image.bmp");
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // Do nothing.
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        // Begin the scene and clear the back buffer to black
        device.BeginScene();
        device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);

        // When using sprites it is important to
        // specify sprite flags passed to Sprite.Begin

        sprite.Begin(SpriteFlags.SortTexture | SpriteFlags.AlphaBlend);

        // Draw an image to the screen using Sprite.Draw

        int spriteY = 5;

        sprite.Draw(texture, Vector3.Empty, new Vector3(0,
            spriteY, 0),
            Color.White.ToArgb());
        spriteY += texture.GetLevelDescription(0).Height + 5;

        // Draw a portion of an image to the screen
        // using Sprite.Draw. This shall be drawn such
        // that the image is modulated with the color green.

        sprite.Draw(texture, new Rectangle(4, 4, 24, 24),
            Vector3.Empty,
            new Vector3(0, spriteY, 0), Color.Green);

        spriteY+= 30;

        // Draw text to the screen. Using a sprite to draw text
        // to the  screen is essential for good performance.
        // Otherwise the font object will perform a
        // Sprite.Begin/Sprite.End internally for
        // each call to Font.DrawText. This can cause severe
        // performance problems.

        spriteY = 150;

        d3dFont.DrawText(sprite, "This is text.",
            5, spriteY, Color.Red);
        spriteY += d3dFont.Description.Height + 5;

        d3dFont.DrawText(sprite, "This is another line of text.",
            5, spriteY, Color.Green);
        spriteY += d3dFont.Description.Height + 5;

        d3dFont.DrawText(sprite, "Only one call to Sprite.Begin.",
            5, spriteY, Color.Blue);

        // End drawing using this sprite. This will cause the
        // sprites to be flushed to the graphics driver and will
        // reset the transformation matrices, textures states,
        // and renderstates if the SpriteFlags specified in Begin
        // call for that to happen.
        sprite.End();

        // Finish the scene and present it on the screen.
        device.EndScene();
        device.Present();
    }

    static void Main()
    {
        Application.Run(new Sprites());
    }
}

編譯程式碼

這個範例需要下列命名空間的參考:

穩固程式設計

請在表單的建構函式中建立精靈 (Sprite) 和字型,如此就不需要在裝置重設時重新建立。

為了達到良好的效能,請使用精靈來描繪文字。否則,字型物件便會為對於 DrawText 的每次呼叫,在內部執行精靈 BeginEnd 方法。

如果可能,當每一格使用一個精靈時,將精靈巢狀化至精靈的 BeginEnd 方法呼叫。

請指定下列 SpriteFlags 值,以最佳化呈現並改進效能:

  • SortTexture 會在描繪至螢幕前先排序影像,如此即可使切換紋理更為快速。

  • AlphaBlend 會正確呈現字型,這對具有透明和半透明區域的精靈尤其有效。

  • SortDepthBackToFront 會以由上層至後層的順序來排序精靈,當您擁有數個半透明或透明精靈重疊描繪時,這個值就會相當有用。

  • DoNotSaveState 會改進無法使用指定呈現狀態之應用程式的效能。

  • DoNotModifyRenderState 會使用目前的呈現狀態來最佳化效能,而且可以用來產生特殊效果。

  • ObjectSpaceBillboard 會啟用以不同的特殊效果來描繪影像。

請參閱

概念

.NET Compact Framework HOW TO 主題

其他資源

.NET Compact Framework 中的 Mobile Direct3D 程式設計