Direct Draw でアニメーション

C# の Direct Draw で画像を切り出してアニメーションします。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. 次のファイルを格納して下さい。
    /********************************************/
    /*★ Girl.bmp でアニメーション    前田 稔 ★*/
    /********************************************/
    using System;
    using System.Drawing;
    using System.Windows.Forms;
    using Microsoft.DirectX;
    using Microsoft.DirectX.DirectDraw;
    
    namespace DXDraw
    {
        public class DXDraw : Form
        {
            String      ImgFile = "C:\\Data\\Test\\girl.bmp";
            const int   NH = 7;             // Sprite の枚数
            Device      draw = null;        // DrawDevice object.
            Surface     primary = null;     // primary destination surface.
            Surface     image = null;       // Image surface.
            Surface     offscreen = null;   // offscreen surface
            Rectangle   dest,sou,win;       // 受取側と送り側とウインドウの矩形領域
            int         width, height;      // Image Size
            int         sp_no= 0;           // Sprite Number
    
            public DXDraw()
            {
                Text = "DXDraw";
                Bitmap bmp = new Bitmap(ImgFile);
                width = bmp.Width;
                height = bmp.Height;
                bmp.Dispose();
                ClientSize = new System.Drawing.Size(width/NH, height);
                CreateSurfaces();
            }
    
            // This function Draws the offscreen bitmap surface to the primary visible surface.
            private void Draw()
            {
                if (null == primary)    return;
                if (FormWindowState.Minimized == WindowState)   return;
                // offscreen に Sprite を描画
                int tickCurrent = (Environment.TickCount/200)%7;
                if (tickCurrent==sp_no)     return;
                sp_no= tickCurrent;
                sou.X= sp_no*width/NH;
                offscreen.ColorFill(Color.White);
                offscreen.DrawFast(dest.X, dest.Y, image, sou, DrawFastFlags.DoNotWait | DrawFastFlags.SourceColorKey);
                try
                {
                    win = new Rectangle(PointToScreen(new Point(0, 0)), ClientSize);
                    primary.Draw(win, offscreen, DrawFlags.Wait);
                }
                catch(SurfaceLostException)
                {
                    CreateSurfaces();       // Surface was lost. Recreate them.
                }
            }
    
            // This function is where the surfaces and clipper object are created.
            private void CreateSurfaces()
            {
                // Create new DrawDevice.  coop level normal windowed mode.
                draw = new Device();
                draw.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
                // Create primary surface.
                SurfaceDescription description = new SurfaceDescription();
                description.SurfaceCaps.PrimarySurface = true;
                primary = new Surface(description, draw);
                // Create image surface.
                description.Clear();
                image = new Surface(ImgFile, description, draw);
                // Create a new colorkey.
                ColorKey ck = new ColorKey();
                image.SetColorKey(ColorKeyFlags.SourceDraw, ck);
                // Create offscreen surface.
                description.Clear();
                description.SurfaceCaps.OffScreenPlain = true;
                description.Width = this.Width;
                description.Height = this.Height;
                offscreen = new Surface(description, draw);
                offscreen.ColorFill(Color.White);
                // 一番目の Sprite を描画
                sou = new Rectangle(0, 0, width / NH, height);
                dest = new Rectangle(10, 20, width / NH, height);
                offscreen.DrawFast(dest.X, dest.Y, image, sou, DrawFastFlags.DoNotWait | DrawFastFlags.SourceColorKey);
            }
    
            //☆ Main() メソッド
            static void Main()
            {
                // using で資源の解放を確実に行う
                using (DXDraw frm = new DXDraw())
                {
                    frm.CreateSurfaces();      // Create Draw Surfaces
                    frm.Show();
    
                    // メッセージループ
                    while(frm.Created)
                    {
                        frm.Draw();
                        Application.DoEvents();
                    }
                }
            }
        }
    }
    
  2. ImgFile はアニメーションをする画像ファイルの名前です。
    image は画像ファイルを入力してイメージを生成する領域です。
    offscreen は primary と同じサイズで、アニメーションイメージを描画して primary に一括転送する領域です。
    dest, sou, win は受取側と送り側とウインドウの矩形領域です。
    width, height は画像の幅と高さを格納する領域です。
    sp_no は描画するアニメーション画像(Sprite)の番号です。
        public class DXDraw : Form
        {
            String      ImgFile = "C:\\Data\\Test\\girl.bmp";
            const int   NH = 7;             // Sprite の枚数
            Device      draw = null;        // DrawDevice object.
            Surface     primary = null;     // primary destination surface.
            Surface     image = null;       // Image surface.
            Surface     offscreen = null;   // offscreen surface
            Rectangle   dest,sou,win;       // 受取側と送り側とウインドウの矩形領域
            int         width, height;      // Image Size
            int         sp_no= 0;           // Sprite Number
        
  3. surface を取得する CreateSurfaces です。
    primary surface を取得します。
    画像を入力して image surface を生成します。
    ColorKey(透明色)の Object を生成して image に設定します。
    primary surface と同じサイズの offscreen surface を生成します。
    offscreen surface に一枚目のアニメーション画像を描画します。
        private void CreateSurfaces()
        {
            // Create new DrawDevice.  coop level normal windowed mode.
            draw = new Device();
            draw.SetCooperativeLevel(this, CooperativeLevelFlags.Normal);
            // Create primary surface.
            SurfaceDescription description = new SurfaceDescription();
            description.SurfaceCaps.PrimarySurface = true;
            primary = new Surface(description, draw);
            // Create image surface.
            description.Clear();
            image = new Surface(ImgFile, description, draw);
            // Create a new colorkey.
            ColorKey ck = new ColorKey();
            image.SetColorKey(ColorKeyFlags.SourceDraw, ck);
            // Create offscreen surface.
            description.Clear();
            description.SurfaceCaps.OffScreenPlain = true;
            description.Width = this.Width;
            description.Height = this.Height;
            offscreen = new Surface(description, draw);
            offscreen.ColorFill(Color.White);
            // 一番目の Sprite を描画 
            sou = new Rectangle(0, 0, width / NH, height);
            dest = new Rectangle(10, 20, width / NH, height);
            offscreen.DrawFast(dest.X, dest.Y, image, sou, DrawFastFlags.DoNotWait | DrawFastFlags.SourceColorKey);
        }
        
  4. メッセージループから呼び出される Draw() メソッドです。
    TickCount で時刻を取得して自動的に画像を切り替えます。
    sp_no が Sprite の番号で、前回と同じ画像のときはパスします。
    ColorKey を使うときは DrawFast() で描画して下さい。
        private void Draw()
        {
            if (null == primary)    return;
            if (FormWindowState.Minimized == WindowState)   return;
            // offscreen に Sprite を描画
            int tickCurrent = (Environment.TickCount/200) % 7;
            if (tickCurrent==sp_no)     return;
            sp_no= tickCurrent;
            sou.X= sp_no*width/NH;
            offscreen.ColorFill(Color.White);
            offscreen.DrawFast(dest.X, dest.Y, image, sou, DrawFastFlags.DoNotWait | DrawFastFlags.SourceColorKey);
            try
            {
                win = new Rectangle(PointToScreen(new Point(0, 0)), ClientSize);
                primary.Draw(win, offscreen, DrawFlags.Wait);
            }
            catch(SurfaceLostException)
            {
                CreateSurfaces();       // Surface was lost. Recreate them.
            }
        }
        

【演習】

  1. 他の画像でもアニメーションできるようにプログラムして下さい。
    そのためには画像ファイル名と横方向と縦方向の Sprite の枚数が必要になります。
    下記の領域を修正すれば、他の画像でもアニメーション出来るようにプログラムを修正して下さい。
        const string  ImgFile = "c:\\data\\test\\girl.bmp";
        const int   WNum = 7;           //横方向の Sprite 枚数
        const int   HNum = 1;           //縦方向の Sprite 枚数
        

【NOTE】

offscreen.DrawFast(dest.X, dest.Y, image, sou, DrawFastFlags.DoNotWait | DrawFastFlags.SourceColorKey); の説明です。
DrawFast() を右クリックして「定義へ移動」を選択すると、メソッドの形式が表示されます。
パラメータ 説明
dest.X, dest.Y 描画する座標(X, Y)
image 画像が格納されている Surface
sou 転送元(image)の矩形領域
Flags 描画フラグ

超初心者のプログラム入門(C# Frame Work)