开源DirectDraw 2D引擎MCDX首次试用笔记

今天把原来用delphi编写的单机泡泡堂源码发布到delphi盒子里去了  ;原来计划完善这个游戏也到此告一段落,游戏没写完,不是做不聊,就是没有时间再开启delphi去写代码,只能每天打开vs.net;所以想把游戏移植到.net平台上,反正还是学习+娱乐。PS:老婆生日快到了,去年就是写这个游戏做生日礼物,今年也不例外。

BNB,是纯2d的,也不需要特效,所以使用DirectDraw足够了;于是装了个DXSDK 9.0c,准备做一个2D的基础库,实现Sprite ,input,Screen,Font,GUI,Time 的管理;但毕竟还是造‘车轮’的工作;干脆找个完善的2d 引擎。(为什么不用D3d,原因是我还刚入门,5.7号才去书店买书啊……但DDraw却用了很长时间了)

想起以前在sf.net上看到的MCDX还不错,C#开发的,纯ddraw的封装;从名字上看应该是受了XX年前的C++版CDX的影响(当时CDX我还学过,以为做游戏有它足够了);马上下载了一份,mcdx已经更新到2.0 了,大致看了一下,结构还不错,上手大概就是10来分钟;于是乎就出了这么一段代码:

    private MCDX.CDXControl cdxControl1;
    
private CDXSprite player;
    
private CDXTile playerTile;
    
private CDXTimer timer;
    
private CDXInput input;


CDXControl 是一个可视组件,是唯一可以添加到工具栏上的,等同于Surface的管理器,负责控制显示设备的刷新、控制属性等等方面;

CDXSprite 就是一个精灵基类,它提供了Draw的方法,可以制定绘制到某个Surface,当然这样做很灵活,其实也可以再增加一个精灵管理类,统一管理绘制、移动、碰撞检测、消亡。

CDXTile 负责管理Tile,比如连续的图块,它用于切割和制定存储方式(系统内存、显存)

CDXAnimation 用于管理图块的动画顺序,被CDXSprite CDXMap用到;

CDXTimer 高分辨率计时器(我一直这样称呼的),很精确,比不负责任的Time消息好多了

CDXInput 收集键盘和鼠标的消息

为了出第一个EXE,暂时这些足够了;

这个MCDX给我的第一影响,是结构比较清晰,但还不强大,有些部分可能和我原来的设计思路有点不一致,感觉有点别扭;不过仔细想想,却是比较灵活多变,见仁见智吧,反正有源码,不顺眼马上改改得了。

首先,先做个小人在屏幕上跑动看看

添加CDXControl 到Form上,设置 UseGameLoop = true;

在CDXControl 的 InitializeObjects 事件中初始化Sprite 和相关的元素;

      input = new CDXInput(cdxControl1.Screen, thistruetruefalse); //建立键盘管理,支持手柄的
        //建立sprite的图像元素切割器,48/57是人物每帧画面的大小,16是总帧数
      playerTile 
= new CDXTile(cdxControl1.Screen, "player1.bmp",485716, MemTypes.SystemOnly);
        //制定透明色,这里是用的紫色
      playerTile.ColorKey 
= Color.FromArgb(2550255);

        //创建sprite
      player 
= new CDXSprite(playerTile,-1);

      
int[] anim;
      anim 
= new int[7{1234 , 3 , 21};  //创建动画关键帧
      player.Animation 
= new CDXAnimation(); //这里要手动实例化
      player.Animation.AddAnimation(
21true, anim); //制定动画时间,帧

      player.TileNumber 
= -1;
      player.PosX 
= 100; //起始坐标
      player.PosY 
= 100;
      player.VelX 
= 0; //下一帧移动的步长与方向
      player.VelY 
= 0;

      timer 
= new CDXTimer(); //建立计时器
      timer.DesiredFps 
= 30; //制定FPS

现在要做的就是绘制图形,在CDXControl 的 DrawFrame 事件里

      cdxControl1.Screen.BackSurface.ColorFill(Color.Black); //清屏,黑色,为了显示新图像
      player.Draw(cdxControl1.Screen.BackSurface, BltTypes.Trans); //制定绘制到目标surface,这里不需要手工换页

更新画面,在CDXControl 的 MoveFrame 事件里
if(timer.NextFrame()) {
        input.Update(); 
//更新输入状态

        
//这里是检查按键,已经按下,或者是按着不放成连续按键状态
        if(input.KeyState(MCDX.Keys.UpArrow) == KeyStates.Press || input.KeyState(MCDX.Keys.UpArrow) == KeyStates.Repeat){
          player.PosY 
-- ;
        }
else if(input.KeyState(MCDX.Keys.DownArrow) == KeyStates.Press || input.KeyState(MCDX.Keys.DownArrow) == KeyStates.Repeat){
          player.PosY 
++ ;
        }
else if(input.KeyState(MCDX.Keys.LeftArrow) == KeyStates.Press || input.KeyState(MCDX.Keys.LeftArrow) == KeyStates.Repeat){
          player.PosX 
-- ;
        }
else if(input.KeyState(MCDX.Keys.RightArrow) == KeyStates.Press || input.KeyState(MCDX.Keys.RightArrow) == KeyStates.Repeat){
          player.PosX 
++ ;
        }
else{
          
//这里就是放开了按键
          
//player.Animation.SetNextFrame(0); 这个方法是我增加的,为了直接制定当前显示的帧;原版没这个
        }


        player.NextFrame(); 
//移动到目标位置,如果VelX,VelY都为0,则该方法无效果(如果是怪物移动则可以选用这个方法)
        player.Animation.NextFrame(); //动画帧移位

        
//结束程序
        if(input.KeyState(MCDX.Keys.Escape) == KeyStates.Press)
          
this.Close();

        
//防止移动到屏幕外面
        if(player.PosX < 0{
          player.PosX 
= 0;
        }


        
if(player.PosY < 0{
          player.PosY 
= 0;
        }


        
if(player.PosX > cdxControl1.Screen.Width - playerTile.BlockWidth) {
          player.PosX 
= cdxControl1.Screen.Width - playerTile.BlockWidth;
        }


        
if(player.PosY > cdxControl1.Screen.Height - playerTile.BlockHeight) {
          player.PosY 
= cdxControl1.Screen.Height - playerTile.BlockHeight;
        }


      }


现在可以看到了运行结果;

可以看到MCDX确实简化了许多工作量,简单好用,不过还是太简单了点,嘿嘿;看来我想真正做好这个生日礼物还得再改改它了~

想试试的,建议看看MCDX带的演示;
posted @ 2005-05-10 01:05  suifei  阅读(10893)  评论(6编辑  收藏  举报