开源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来分钟;于是乎就出了这么一段代码:
CDXControl 是一个可视组件,是唯一可以添加到工具栏上的,等同于Surface的管理器,负责控制显示设备的刷新、控制属性等等方面;
CDXSprite 就是一个精灵基类,它提供了Draw的方法,可以制定绘制到某个Surface,当然这样做很灵活,其实也可以再增加一个精灵管理类,统一管理绘制、移动、碰撞检测、消亡。
CDXTile 负责管理Tile,比如连续的图块,它用于切割和制定存储方式(系统内存、显存)
CDXAnimation 用于管理图块的动画顺序,被CDXSprite CDXMap用到;
CDXTimer 高分辨率计时器(我一直这样称呼的),很精确,比不负责任的Time消息好多了
CDXInput 收集键盘和鼠标的消息
为了出第一个EXE,暂时这些足够了;
这个MCDX给我的第一影响,是结构比较清晰,但还不强大,有些部分可能和我原来的设计思路有点不一致,感觉有点别扭;不过仔细想想,却是比较灵活多变,见仁见智吧,反正有源码,不顺眼马上改改得了。
首先,先做个小人在屏幕上跑动看看
添加CDXControl 到Form上,设置 UseGameLoop = true;
在CDXControl 的 InitializeObjects 事件中初始化Sprite 和相关的元素;
现在要做的就是绘制图形,在CDXControl 的 DrawFrame 事件里
更新画面,在CDXControl 的 MoveFrame 事件里
现在可以看到了运行结果;
可以看到MCDX确实简化了许多工作量,简单好用,不过还是太简单了点,嘿嘿;看来我想真正做好这个生日礼物还得再改改它了~
想试试的,建议看看MCDX带的演示;
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;
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, this, true, true, false); //建立键盘管理,支持手柄的
//建立sprite的图像元素切割器,48/57是人物每帧画面的大小,16是总帧数
playerTile = new CDXTile(cdxControl1.Screen, "player1.bmp",48, 57, 16, MemTypes.SystemOnly);
//制定透明色,这里是用的紫色
playerTile.ColorKey = Color.FromArgb(255, 0, 255);
//创建sprite
player = new CDXSprite(playerTile,-1);
int[] anim;
anim = new int[7] {1, 2, 3, 4 , 3 , 2, 1}; //创建动画关键帧
player.Animation = new CDXAnimation(); //这里要手动实例化
player.Animation.AddAnimation(2, 1, true, anim); //制定动画时间,帧
player.TileNumber = -1;
player.PosX = 100; //起始坐标
player.PosY = 100;
player.VelX = 0; //下一帧移动的步长与方向
player.VelY = 0;
timer = new CDXTimer(); //建立计时器
timer.DesiredFps = 30; //制定FPS
//建立sprite的图像元素切割器,48/57是人物每帧画面的大小,16是总帧数
playerTile = new CDXTile(cdxControl1.Screen, "player1.bmp",48, 57, 16, MemTypes.SystemOnly);
//制定透明色,这里是用的紫色
playerTile.ColorKey = Color.FromArgb(255, 0, 255);
//创建sprite
player = new CDXSprite(playerTile,-1);
int[] anim;
anim = new int[7] {1, 2, 3, 4 , 3 , 2, 1}; //创建动画关键帧
player.Animation = new CDXAnimation(); //这里要手动实例化
player.Animation.AddAnimation(2, 1, true, 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,这里不需要手工换页
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;
}
}
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带的演示;