游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3316|回复: 2

使用Manged DirectX 9.0 --- Part III

[复制链接]

21

主题

78

帖子

103

积分

注册会员

Rank: 2

积分
103
发表于 2003-8-16 14:35:00 | 显示全部楼层 |阅读模式
在Part I中建立了一个框架, 这一节则把它的功能完善起来.

  1. 1.全屏模式和窗口模式
  2.    
  3. private void InitDirectDraw()
  4. {            
  5.     display = new Device(); // 创建显示设备.
  6.     description = new SurfaceDescription();// 新建一个页面描述
  7.     if(IsFullScreen)//全屏模式
  8.     {
  9.         display.SetCooperativeLevel(this.Window,CooperativeLevelFlags.FullscreenExclusive);//全屏独占模式
  10.         display.SetDisplayMode(ScreenWidth, ScreenHeight, BitPerPixel, 0, false);//设置分辨率,色深
  11.         description.SurfaceCaps.PrimarySurface = true;//为主页面
  12.         description.SurfaceCaps.Flip = true;//有换页链
  13.         description.SurfaceCaps.Complex = true;//有后台缓存
  14.         description.BackBufferCount = 1;//一个后台缓存
  15.         front = new Surface(description, display);//得到主页面
  16.         SurfaceCaps caps = new SurfaceCaps();
  17.         caps.BackBuffer = true;
  18.         back = front.GetAttachedSurface(caps);//缓冲页面
  19.     }
  20.     else//窗口模式
  21.     {
  22.         display.SetCooperativeLevel(this.Window,CooperativeLevelFlags.Normal);
  23.         description.SurfaceCaps.PrimarySurface = true; // 仅设为主页面

  24.         front = new Surface(description, display);//得到主页面
  25.         clip = new Clipper(display);//裁剪器
  26.         clip.Window = Window;
  27.         front.Clipper = clip;

  28.         description.Clear(); // 每次新建一个页面时,页面描述要清空一下
  29.         description.SurfaceCaps.OffScreenPlain=true;
  30.         back = new Surface(new Bitmap(ScreenWidth,ScreenHeight),description, display);
  31.         this.Window.Paint += new System.Windows.Forms.PaintEventHandler(this.Windowed_Paint);
  32.         this.Window.Resize += new System.EventHandler(this.Windowed_SizeChanged);
  33.         this.Window.SizeChanged += new System.EventHandler(this.Windowed_SizeChanged);
  34.     }   
  35. }
  36.    

  37. 2.导入多种图像格式
  38.    
  39. /// <summary>
  40. /// 图像资源由Tile类来处理
  41. /// </summary>
  42. public class Tile
  43. {
  44.     public string Name="";
  45.     public Bitmap ImageData;
  46.     public bool UseColorKey=false;
  47.     public int Width=0;
  48.     public int Height=0;
  49.     public int Rows=1;
  50.     public int Columns=1;
  51.     public int TileWidth;
  52.     public int TileHeight;
  53.     public Tile(Bitmap bitmap)
  54.     {
  55.         ImageData=bitmap;
  56.         TileWidth=Width=ImageData.Width;
  57.         TileHeight=Height=ImageData.Height;
  58.     }
  59.     public Tile(string filename):this(filename,filename){}
  60.     public Tile(string tilename,string filename)//支持BMP,JEPG,GIF,WMF,EMF,ICO,PNG,TIFF
  61.     {
  62.         Name=tilename;
  63.         ImageData=new Bitmap(Image.FromFile(filename));//GDI+不支持所给的文件格式时,抛出内存不足的异常
  64.         TileWidth=Width=ImageData.Width;
  65.         TileHeight=Height=ImageData.Height;
  66.     }
  67.     public Tile(string filename,int row,int col):this(filename,filename,row,col){}
  68.     public Tile(string tilename,string filename,int row,int col)
  69.     {
  70.         Name=tilename;
  71.         ImageData=new Bitmap(Image.FromFile(filename));
  72.         Width=ImageData.Width;
  73.         Height=ImageData.Height;
  74.         Rows=row;
  75.         Columns=col;
  76.         TileWidth=Width/Columns;
  77.         TileHeight=Height/Rows;
  78.     }
  79.    

  80. 3.设置颜色键
  81.    
  82. public Color ColorKey
  83. {
  84.     set
  85.     {
  86.         int key=value.ToArgb();
  87.         int black=Color.Black.ToArgb();
  88.         if(key==black)
  89.         {
  90.             UseColorKey=true;
  91.             return;
  92.         }
  93.         Color Fblack=Color.FromArgb(0,0,8);
  94.         for(int i=0;i<ImageData.Width;i++)
  95.         {
  96.             for(int j=0;j<ImageData.Height;j++)
  97.             {
  98.                 int pixel=ImageData.GetPixel(i,j).ToArgb();
  99.                 if(pixel==black)
  100.                 {
  101.                     ImageData.SetPixel(i,j,Fblack);
  102.                 }
  103.                 else if(pixel==key)
  104.                 {
  105.                     ImageData.SetPixel(i,j,Color.Black);
  106.                 }
  107.             }
  108.         }
  109.         UseColorKey=true;
  110.     }
  111. }
  112.    
  113. 4.设置透明色和透明度
  114. public Color AlphaColor
  115. {
  116.     set{ImageData.MakeTransparent(value);}
  117. }
  118. public int AlphaValue
  119. {
  120.     set
  121.     {
  122.         for(int i=0;i<ImageData.Width;i++)
  123.         {
  124.             for(int j=0;j<ImageData.Height;j++)
  125.             {
  126.                 Color pixel=ImageData.GetPixel(i,j);
  127.                 ImageData.SetPixel(i,j,Color.FromArgb(value,pixel.R,pixel.G,pixel.B));
  128.             }
  129.         }
  130.     }
  131. }
  132. 5.把图像分成小格子
  133.    
  134. public Tile this[int i,int j]
  135. {
  136.     get
  137.     {
  138.         Rectangle rect=this.Rectangles(i,j);
  139.         Tile subtile=this.GetSubTile(rect);
  140.         subtile.Name=this.Name+i+j;
  141.         return subtile;
  142.     }
  143. }
  144. public Rectangle Rectangles(int i,int j)
  145. {
  146.     if(i<1||i>Rows||j<1||j>Columns)
  147.         throw new IndexOutOfRangeException("Tile index");
  148.     int x=(j-1)*TileWidth;
  149.     int y=(i-1)*TileHeight;
  150.     return new Rectangle(x,y,TileWidth,TileHeight);
  151. }
  152. public Tile GetSubTile(Rectangle rect)
  153. {
  154.     Bitmap bm=this.ImageData.Clone(rect,ImageData.PixelFormat);
  155.     Tile tile=new Tile(bm);
  156.     tile.UseColorKey=this.UseColorKey;
  157.     return tile;
  158. }
  159.    
  160. 6.图像加入绘图设备
  161.    
  162. public void AddTiles(params Tile[] tiles)
  163. {
  164.     foreach(Tile t in tiles)
  165.     {
  166.         this.AddTile(t);
  167.         if(t.Rows>1||t.Columns>1)
  168.         {
  169.             for(int i=1;i<=t.Rows;i++)
  170.             {
  171.                 for(int j=1;j<=t.Columns;j++)
  172.                 {
  173.                     this.AddTile(t[i,j]);
  174.                 }
  175.             }
  176.         }
  177.     }
  178. }
  179. void AddTile(Tile tile)
  180. {
  181.     this.Tiles.Add(tile.Name,CreateSurface(tile));
  182. }
  183. Surface CreateSurface(Tile tile)
  184. {
  185.     description.Clear();
  186.     description.SurfaceCaps.OffScreenPlain=true;
  187.     Surface surface=new Surface(tile.ImageData,description,display);
  188.     if(tile.UseColorKey)
  189.     {
  190.         ColorKey ck=new ColorKey();
  191.         surface.SetColorKey(ColorKeyFlags.SourceDraw,ck);
  192.     }
  193.     return surface;
  194. }
  195.    
  196. 7.绘制图像--普通绘制
  197.    
  198. public void DrawTile(int x,int y,string tilename)
  199. {
  200.     back.DrawFast(x,y,(Surface)Tiles[tilename],DrawFastFlags.Wait);
  201. }
  202.    
  203. 8.绘制图像--颜色键绘制
  204.    
  205. public void DrawTile(int x,int y,Tile tile)
  206. {
  207.     if(tile.UseColorKey)
  208.     {
  209.         back.DrawFast(x,y,(Surface)Tiles[tile.Name],DrawFastFlags.Wait|DrawFastFlags.SourceColorKey);
  210.     }
  211.     else
  212.     {
  213.         back.DrawFast(x,y,(Surface)Tiles[tile.Name],DrawFastFlags.Wait);
  214.     }
  215. }
  216.    
  217. 9.绘制图像--Alpha混合绘制
  218.    
  219. public void DrawTileAlpha(int x,int y,Tile pic)
  220. {
  221.     IntPtr MyDC = back.GetDc();
  222.     Graphics MyDraw = Graphics.FromHdc(MyDC);//暂时由GDI+来实现

  223.     MyDraw.DrawImage(pic.ImageData,x,y);

  224.     MyDraw.Dispose();
  225.     back.ReleaseDc(MyDC);
  226. }
  227.    
  228. 10.绘制图像--图像RECT裁减绘制
  229.    
  230. public void DrawTile(int x,int y,Tile tile,Rectangle rect)
  231. {
  232.     Tile pic=tile.GetSubTile(rect);
  233.     DrawTile(x,y,pic,true);
  234. }
  235. public void DrawTile(int x,int y,Tile pic,bool docut)
  236. {
  237.     int w=pic.Width;
  238.     int h=pic.Height;
  239.     Bitmap bm=pic.ImageData;
  240.     bool cut=false;
  241.     if(pic.Width>ScreenWidth-x)
  242.     {
  243.         w=ScreenWidth-x;
  244.         cut=true;
  245.     }
  246.     if(pic.Height>ScreenHeight-y)
  247.     {
  248.         h=ScreenHeight-y;
  249.         cut=true;
  250.     }
  251.     if(cut)
  252.     {
  253.         Rectangle srcRect=new Rectangle(0,0,w,h);
  254.         bm=pic.ImageData.Clone(srcRect,pic.ImageData.PixelFormat);
  255.     }
  256.     description.Clear();
  257.     description.SurfaceCaps.OffScreenPlain=true;
  258.     Surface surface=new Surface(bm,description,display);

  259.     if(pic.UseColorKey==false)
  260.     {
  261.         back.DrawFast(x,y,surface,DrawFastFlags.Wait);
  262.     }
  263.     else
  264.     {
  265.         ColorKey ck=new ColorKey();
  266.         surface.SetColorKey(ColorKeyFlags.SourceDraw,ck);
  267.         back.DrawFast(x,y,surface,DrawFastFlags.Wait|DrawFastFlags.SourceColorKey);
  268.     }
  269.     surface.Dispose();
  270. }

  271.    
  272. 11.设置前景色,字体 以及绘制字体
  273.    
  274. public Color ForeColor
  275. {
  276.     get{return back.ForeColor;}
  277.     set{back.ForeColor=value;}
  278. }
  279. public Font Font
  280. {
  281.     set{back.FontHandle=value.ToHfont();}
  282. }
  283. public Color FontBackColor
  284. {
  285.     get{return back.FontBackColor;}
  286.     set{back.FontBackColor=value;}
  287. }
  288. public bool FontTransparency
  289. {
  290.     get{return back.FontTransparency;}
  291.     set{back.FontTransparency=value;}
  292. }
  293. public void DrawText(int x,int y,string text)
  294. {
  295.     back.DrawText(x,y,text,false);
  296. }
  297.    
  298. 12. 设置填充色, 以及清屏
  299. public Color FillColor
  300. {
  301.     get{return back.FillColor;}
  302.     set{back.FillColor=value;}
  303. }

  304. public void Clear(Color color)
  305. {
  306.     back.ColorFill(color);
  307. }
  308. 13.绘制直线,矩形,圆角矩形,圆,椭圆
  309. public int DrawWidth
  310. {
  311.     get{return back.DrawWidth;}
  312.     set{back.DrawWidth=value;}
  313. }
  314. public int DrawStyle
  315. {
  316.     get{return back.DrawStyle;}
  317.     set{back.DrawStyle=value;}
  318. }
  319. public int FillStyle
  320. {
  321.     get{return back.FillStyle;}
  322.     set{back.FillStyle=value;}
  323. }
  324. public void DrawLine(int x1,int y1,int x2,int y2)
  325. {
  326.     back.DrawLine(x1,y1,x2,y2);
  327. }
  328. public void DrawBox( int left,int top,int right,int bottom)
  329. {
  330.     back.DrawBox(left,top,right,bottom);
  331. }
  332. public void DrawBox( int left,int top,int right,int bottom,int rw,int rh)
  333. {
  334.     back.DrawRoundedBox(left,top,right,bottom,rw,rh);
  335. }
  336. public void DrawCircle( int x,int y,int radius)
  337. {
  338.     back.DrawCircle(x,x,radius);
  339. }
  340. public void DrawEllipse(int x1,int y1,int x2,int y2)
  341. {
  342.     back.DrawEllipse(x1,y1,x2,y2);
  343. }
  344. 14.主循环以及显示帧频
  345. public void MainLoop()
  346. {
  347.     if(IsFullScreen)
  348.     {
  349.         int onesecond=10000000;
  350.         long begin,end;
  351.         begin=DateTime.Now.Ticks;
  352.         int total=0;
  353.         int count=0;
  354.         while(this.Window.Created)
  355.         {
  356.             this.FullScreenDraw();
  357.             Application.DoEvents();

  358.             end=DateTime.Now.Ticks;
  359.             total+=(int)(end-begin);
  360.             count++;
  361.             begin=end;
  362.             if(total>onesecond)
  363.             {
  364.                 FPS=onesecond/(total/count);//计算帧频
  365.                 total=0;
  366.                 count=0;
  367.             }

  368.         }
  369.     }
  370.     else
  371.     {
  372.     }
  373. }
  374. void FullScreenDraw()
  375. {
  376.     if (front == null)
  377.     {
  378.         return;
  379.     }
  380.     try
  381.     {
  382.         front.Flip(back, FlipFlags.Wait);
  383.         this.OnDraw(this);
  384. #if DEBUG
  385.         this.FontTransparency=false;
  386.         this.FontBackColor=Color.Black;
  387.         this.ForeColor=Color.Green;
  388.         this.DrawText(5,5,"FPS="+FPS.ToString());
  389.         this.FontTransparency=true;
  390. #endif
  391.     }
  392.     catch(WasStillDrawingException)
  393.     {
  394.         return;
  395.     }
  396.     catch(SurfaceLostException)
  397.     {
  398.         RestoreSurfaces();//恢复页面
  399.     }
  400. }
  401. private void RestoreSurfaces()
  402. {
  403.     display.RestoreAllSurfaces();
  404.     this.OnDraw(this);
  405.     return;
  406. }
复制代码

21

主题

78

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2003-8-21 10:17:00 | 显示全部楼层

Re:使用Manged DirectX 9.0 --- Part III

发现public void DrawTile(int x,int y,Tile pic,bool docut)函数的效率太低,
混用GDI+和DirectDraw的结果还不如纯粹用GDI+来的快.
现在的问题是当图片的宽高大于显示设备的宽高时, 如何给这个图片创建Surface? [em24]

21

主题

78

帖子

103

积分

注册会员

Rank: 2

积分
103
 楼主| 发表于 2003-8-21 21:42:00 | 显示全部楼层

Re: Re:使用Manged DirectX 9.0 --- Part III

突然发现不使用这个函数时,帧频达到了90!
而以前只有30,看来算法很重要.
sf_2003821214225.jpg
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2024-4-30 16:07

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表