在Part I中建立了一个框架, 这一节则把它的功能完善起来.
[code]
1.全屏模式和窗口模式
private void InitDirectDraw()
{
display = new Device(); // 创建显示设备.
description = new SurfaceDescription();// 新建一个页面描述
if(IsFullScreen)//全屏模式
{
display.SetCooperativeLevel(this.Window,CooperativeLevelFlags.FullscreenExclusive);//全屏独占模式
display.SetDisplayMode(ScreenWidth, ScreenHeight, BitPerPixel, 0, false);//设置分辨率,色深
description.SurfaceCaps.PrimarySurface = true;//为主页面
description.SurfaceCaps.Flip = true;//有换页链
description.SurfaceCaps.Complex = true;//有后台缓存
description.BackBufferCount = 1;//一个后台缓存
front = new Surface(description, display);//得到主页面
SurfaceCaps caps = new SurfaceCaps();
caps.BackBuffer = true;
back = front.GetAttachedSurface(caps);//缓冲页面
}
else//窗口模式
{
display.SetCooperativeLevel(this.Window,CooperativeLevelFlags.Normal);
description.SurfaceCaps.PrimarySurface = true; // 仅设为主页面
front = new Surface(description, display);//得到主页面
clip = new Clipper(display);//裁剪器
clip.Window = Window;
front.Clipper = clip;
description.Clear(); // 每次新建一个页面时,页面描述要清空一下
description.SurfaceCaps.OffScreenPlain=true;
back = new Surface(new Bitmap(ScreenWidth,ScreenHeight),description, display);
this.Window.Paint += new System.Windows.Forms.PaintEventHandler(this.Windowed_Paint);
this.Window.Resize += new System.EventHandler(this.Windowed_SizeChanged);
this.Window.SizeChanged += new System.EventHandler(this.Windowed_SizeChanged);
}
}
2.导入多种图像格式
/// <summary>
/// 图像资源由Tile类来处理
/// </summary>
public class Tile
{
public string Name="";
public Bitmap ImageData;
public bool UseColorKey=false;
public int Width=0;
public int Height=0;
public int Rows=1;
public int Columns=1;
public int TileWidth;
public int TileHeight;
public Tile(Bitmap bitmap)
{
ImageData=bitmap;
TileWidth=Width=ImageData.Width;
TileHeight=Height=ImageData.Height;
}
public Tile(string filename):this(filename,filename){}
public Tile(string tilename,string filename)//支持BMP,JEPG,GIF,WMF,EMF,ICO,PNG,TIFF
{
Name=tilename;
ImageData=new Bitmap(Image.FromFile(filename));//GDI+不支持所给的文件格式时,抛出内存不足的异常
TileWidth=Width=ImageData.Width;
TileHeight=Height=ImageData.Height;
}
public Tile(string filename,int row,int col):this(filename,filename,row,col){}
public Tile(string tilename,string filename,int row,int col)
{
Name=tilename;
ImageData=new Bitmap(Image.FromFile(filename));
Width=ImageData.Width;
Height=ImageData.Height;
Rows=row;
Columns=col;
TileWidth=Width/Columns;
TileHeight=Height/Rows;
}
3.设置颜色键
public Color ColorKey
{
set
{
int key=value.ToArgb();
int black=Color.Black.ToArgb();
if(key==black)
{
UseColorKey=true;
return;
}
Color Fblack=Color.FromArgb(0,0,8);
for(int i=0;i<ImageData.Width;i++)
{
for(int j=0;j<ImageData.Height;j++)
{
int pixel=ImageData.GetPixel(i,j).ToArgb();
if(pixel==black)
{
ImageData.SetPixel(i,j,Fblack);
}
else if(pixel==key)
{
ImageData.SetPixel(i,j,Color.Black);
}
}
}
UseColorKey=true;
}
}
4.设置透明色和透明度
public Color AlphaColor
{
set{ImageData.MakeTransparent(value);}
}
public int Alphavalue
{
set
{
for(int i=0;i<ImageData.Width;i++)
{
for(int j=0;j<ImageData.Height;j++)
{
Color pixel=ImageData.GetPixel(i,j);
ImageData.SetPixel(i,j,Color.FromArgb(value,pixel.R,pixel.G,pixel.B));
}
}
}
}
5.把图像分成小格子
public Tile this[int i,int j]
{
get
{
Rectangle rect=this.Rectangles(i,j);
Tile subtile=this.GetSubTile(rect);
subtile.Name=this.Name+i+j;
return subtile;
}
}
public Rectangle Rectangles(int i,int j)
{
if(i<1||i>Rows||j<1||j>Columns)
throw new IndexOutOfRangeException("Tile index");
int x=(j-1)*TileWidth;
int y=(i-1)*TileHeight;
return new Rectangle(x,y,TileWidth,TileHeight);
}
public Tile GetSubTile(Rectangle rect)
{
Bitmap bm=this.ImageData.Clone(rect,ImageData.PixelFormat);
Tile tile=new Tile(bm);
tile.UseColorKey=this.UseColorKey;
return tile;
}
6.图像加入绘图设备
public void AddTiles(params Tile[] tiles)
{
foreach(Tile t in tiles)
{
this.AddTile(t);
if(t.Rows>1||t.Columns>1)
{
for(int i=1;i<=t.Rows;i++)
{
for(int j=1;j<=t.Columns;j++)
{
this.AddTile(t[i,j]);
}
}
}
}
}
void AddTile(Tile tile)
{
this.Tiles.Add(tile.Name,CreateSurface(tile));
}
Surface CreateSurface(Tile tile)
{
description.Clear();
description.SurfaceCaps.OffScreenPlain=true;
Surface surface=new Surface(tile.ImageData,description,display);
if(tile.UseColorKey)
{
ColorKey ck=new ColorKey();
surface.SetColorKey(ColorKeyFlags.SourceDraw,ck);
}
return surface;
}
7.绘制图像--普通绘制
public void DrawTile(int x,int y,string tilename)
{
back.DrawFast(x,y,(Surface)Tiles[tilename],DrawFastFlags.Wait);
}
8.绘制图像--颜色键绘制
public void DrawTile(int x,int y,Tile tile)
{
if(tile.UseColorKey)
{
back.DrawFast(x,y,(Surface)Tiles[tile.Name],DrawFastFlags.Wait|DrawFastFlags.SourceColorKey);
}
else
{
back.DrawFast(x,y,(Surface)Tiles[tile.Name],DrawFastFlags.Wait);
}
}
9.绘制图像--Alpha混合绘制
public void DrawTileAlpha(int x,int y,Tile pic)
{
IntPtr MyDC = back.GetDc();
Graphics MyDraw = Graphics.FromHdc(MyDC);//暂时由GDI+来实现
MyDraw.DrawImage(pic.ImageData,x,y);
MyDraw.Dispose();
back.ReleaseDc(MyDC);
}
10.绘制图像--图像RECT裁减绘制
public void DrawTile(int x,int y,Tile tile,Rectangle rect)
{
Tile pic=tile.GetSubTile(rect);
DrawTile(x,y,pic,true);
}
public void DrawTile(int x,int y,Tile pic,bool docut)
{
int w=pic.Width;
int h=pic.Height;
Bitmap bm=pic.ImageData;
bool cut=false;
if(pic.Width>ScreenWidth-x)
{
w=ScreenWidth-x;
cut=true;
}
if(pic.Height>ScreenHeight-y)
{
h=ScreenHeight-y;
cut=true;
}
if(cut)
{
Rectangle srcRect=new Rectangle(0,0,w,h);
bm=pic.ImageData.Clone(srcRect,pic.ImageData.PixelFormat);
}
description.Clear();
description.SurfaceCaps.OffScreenPlain=true;
Surface surface=new Surface(bm,description,display);
if(pic.UseColorKey==false)
{
back.DrawFast(x,y,surface,DrawFastFlags.Wait);
}
else
{
ColorKey ck=new ColorKey();
surface.SetColorKey(ColorKeyFlags.SourceDraw,ck);
back.DrawFast(x,y,surface,DrawFastFlags.Wait|DrawFastFlags.SourceColorKey);
}
surface.Dispose();
}
11.设置前景色,字体 以及绘制字体
public Color ForeColor
{
get{return back.ForeColor;}
set{back.ForeColor=value;}
}
public Font Font
{
set{back.FontHandle=value.ToHfont();}
}
public Color FontBackColor
{
get{return back.FontBackColor;}
set{back.FontBackColor=value;}
}
public bool FontTransparency
{
get{return back.FontTransparency;}
set{back.FontTransparency=value;}
}
public void DrawText(int x,int y,string text)
{
back.DrawText(x,y,text,false);
}
12. 设置填充色, 以及清屏
public Color FillColor
{
get{return back.FillColor;}
set{back.FillColor=value;}
}
public void Clear(Color color)
{
back.ColorFill(color);
}
13.绘制直线,矩形,圆角矩形,圆,椭圆
public int DrawWidth
{
get{return back.DrawWidth;}
set{back.DrawWidth=value;}
}
public int DrawStyle
{
get{return back.DrawStyle;}
set{back.DrawStyle=value;}
}
public int FillStyle
{
get{return back.FillStyle;}
set{back.FillStyle=value;}
}
public void DrawLine(int x1,int y1,int x2,int y2)
{
back.DrawLine(x1,y1,x2,y2);
}
public void DrawBox( int left,int top,int right,int bottom)
{
back.DrawBox(left,top,right,bottom);
}
public void DrawBox( int left,int top,int right,int bottom,int rw,int rh)
{
back.DrawRoundedBox(left,top,right,bottom,rw,rh);
}
public void DrawCircle( int x,int y,int radius)
{
back.DrawCircle(x,x,radius);
}
public void DrawEllipse(int x1,int y1,int x2,int y2)
{
back.DrawEllipse(x1,y1,x2,y2);
}
14.主循环以及显示帧频
public void MainLoop()
{
if(IsFullScreen)
{
int onesecond=10000000;
long begin,end;
begin=DateTime.Now.Ticks;
int total=0;
int count=0;
while(this.Window.Created)
{
this.FullScreenDraw();
Application.DoEvents();
end=DateTime.Now.Ticks;
total+=(int)(end-begin);
count++;
begin=end;
if(total>onesecond)
{
FPS=onesecond/(total/count);//计算帧频
total=0;
count=0;
}
}
}
else
{
}
}
void FullScreenDraw()
{
if (front == null)
{
return;
}
try
{
front.Flip(back, FlipFlags.Wait);
this.OnDraw(this);
#if DEBUG
this.FontTransparency=false;
this.FontBackColor=Color.Black;
this.ForeColor=Color.Green;
this.DrawText(5,5,"FPS="+FPS.ToString());
this.FontTransparency=true;
#endif
}
catch(WasStillDrawingException)
{
return;
}
catch(SurfaceLostException)
{
RestoreSurfaces();//恢复页面
}
}
private void RestoreSurfaces()
{
display.RestoreAllSurfaces();
this.OnDraw(this);
return;
}