鱼C论坛

 找回密码
 立即注册
查看: 2469|回复: 6

[技术交流] 用VC6.0制作人物移动迷宫(中集)

[复制链接]
发表于 2013-9-28 13:43:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 新手学习中 于 2013-9-28 13:48 编辑

动画效果:动画就是多个图片连续的更新窗口。我们这里,就是让它在规定时间内更新窗口,去发送wm_paint消息,最后执行具体更新内容的函数。

1、人物行走的图片共有16幅,我们需要把这16幅图片都载入内存中

这里,当然就用for循环来完成16幅图片的载入。我们需要把图片文件按一定数学规律命名,因为这样才能用一定规律调用for循环。

这里我们需要16个指针来指向不同的图片。就需要创建一个数组指针。


2、使用定时器,让函数按照一定时间发出WM_PAINT重绘消息。

这一步,只需要使用SetTimer函数即可

3、在绘制的函数中,让其显示的图片在最后按一定规则变化

变化后,下一次重绘就会显示不同的图片








在函数中,我们让它每一次更新,都按照一定的规律变化更新的内容。这里自然就要用到for循环了。
我们用for循环,让每一次更新,都替换掉图片。图片读取自然需要图片名,所以这里的图片名我们要用一定规律命名。
比如1.1   1.2  1.3..... 2.1   2.2  ....一共16个图片,前面一位表示四种方向,后面一位表示前进的四种姿态,以递增形式。
这16种状态不是完全独立的,它是有方向的对应联系,所以需要一个二维数组指针来表示这16种状态。



CBitmap*bitmap[4][4];  //创建一个二维数组,有每维有4个元素,是0~3,用这个来代替之前的bitmap指针,把之前的这个指针变量给去掉。在类中添加这个数组指针

然后就是初始化数组指针,让每个元素都指向对应的CBitmap类对象,对象中放着对应的图片。这里就需要用for循环来实现。

GameWnd::GameWnd()
{
Create(NULL,"创建窗口");
mdc=new CDC;
CClientDC dc(this);
mdc->CreateCompatibleDC(&dc);

//我们要在前面先增加成员变量int i,j ;


char ch[8];  //这个数组用来储存文件名,文件名7字节最后还有个/0
for(i =0,i<4,i++)
{
for(j=0,j<4,j++)
{
sprintf(ch,"%d.%d.bmp",i+1,j+1);    //这一步是给字符串变量赋值,字符串变量赋值一般是:ch = "m.n.bmp" 但这里m,n就是纯字符而不是变量了,我们是需要把变量转换成字符,再赋值给字符串变量,这里就需要sprintf函数

后面是变量,前面的%d是把后面的变量以十进制转换,当然最后因为引号,里面的内容都是字符串。

bitmap
[j]=new CBitmap;
bitmap
[j]->m_hObject = LoadImage(NULL,ch,IMAGE_BITMAP,93,100,LR_LOADFROMFILE);//这一步,我们用ch表示图片名,把图片读入了内存中,注意,第二个参数是ch而不是"ch",如果加了引号那就变成读取ch文件名的图片了。到这一步,16幅载入内存完成
}
}


}


SetTimer函数设置发出重绘消息

我们需要在类中增加 wm_create 跟wm_timer 。对应生成oncreate函数跟ontimer函数。

在oncreate函数中,添加SetTimer(1,100,NULL); 1表示定时器的序号,我们这里只有一个定时器所以写1.  

100是毫秒,表示调用的间隔,NULL表示调用默认的回调函数。这里的回调函数就是自动生成的ontimer函数。

Settimer是设置定时器的,Ontimer是响应Settimer消息的。当Settimer设置的时间到了,就会自动调动Ontimer()函数。
在Ontimer()函数中,我们设置具体的图片显示代码,跟最后图片的变化规律。

注意:我们在Ontimer()函数中,使用的是CClientDC而不是CPaintDC ,如果是CPaintDC结果显示就是一副静止的画面,这原因比较复杂,定时器和界面刷新机制不同,不能相互替代。

在一个定时器周期里面,可能需要一次或者多次刷新界面,而触发时间也不一致,这种情况下,CPaintDC的机制不能满足需要。另外,其实还有其它问题,但记住,OnPaint之外,最好避免使用CPaintDC.

在Ontimer()函数中,我们让SelectObject载入兼容dc的图片,其图片名后面加上一个变量。

前面还需要一个总体的判断。因为我们需要让动画走完往前的四个图片,再去走向左的四个图片。。。。。直到16图走完,再重新开始。最后我们使用dc.BitBlt 载入 图片。


OnTimer函数具体代码如下:

void GameWnd::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
if (j<4)
{
mdc->SelectObject(bitmap
[j]);
dc.BitBlt(0,0,93,100,mdc,0,0,SRCCOPY);
j++;
}
else
{
j = 0;
i++;
if(i<4)
{

mdc->SelectObject(bitmap
[j]);
    dc.BitBlt(0,0,93,100,mdc,0,0,SRCCOPY);
j++;

}
else
{
i = 0;
mdc->SelectObject(bitmap
[j]);
    dc.BitBlt(0,0,93,100,mdc,0,0,SRCCOPY);
j++;
}


}

CFrameWnd::OnTimer(nIDEvent);
}




运行后,窗口中就出现了人物不断的朝着四面原地行走。


                               
登录/注册后可看大图

                               
登录/注册后可看大图




用键盘控制人物行走
我们需要的是用键盘控制人物行走,而非自动行走,所以我们把SetTimer函数取消掉,这样ontimer函数的内容也就失效了。

接受键盘信息,需要用到WM_KEYDOWN  添加后,会自动生成OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)函数。
我们按下键,其信息会存入VK_DOWN  上键 VK_UP  左键 VK_LEFT 右键VK_RIGHT

第一个参数nChar的数据类型,就与VK类型相同,这里我们可用于判断。
代码如下:
void GameWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
if (nChar == VK_DOWN)
{
dc.BitBlt(m,n,93,100,mdc,0,0,WHITENESS);//重绘图片时先用白色填充上一张图片,为了消除行走时的残影
n = n+20;
   if (i ==0)
   {
    j++;
    if(j<4)
    {
   
    mdc->SelectObject(bitmap
[j]);
       dc.BitBlt(m,n,93,100,mdc,0,0,SRCCOPY);
   
    }
    else
    {
    j = 0;
    mdc->SelectObject(bitmap
[j]);
       dc.BitBlt(m,n,93,100,mdc,0,0,SRCCOPY);
    }
   

   
   }
   else
   {
  
   i = 0;
   j = 0;
   mdc->SelectObject(bitmap
[j]);
   dc.BitBlt(m,n,93,100,mdc,0,0,SRCCOPY);
   }

}

CFrameWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}

运行后,如图:

                               
登录/注册后可看大图

我们可以通过下键控制人物移动。但这个窗口一开始是空白的,我们按下后才有人,需要一开始就有人的话,要在onpaint函数里放绘制函数。因为流程中,就是先在onpaint这里绘制第一次的。
我们设置其他方向,只需要复制一下,再修改个别的量,这里就不多说了,设置好四个方向后,运行如下:


                               
登录/注册后可看大图


这是为了在图片中看出行走效果,把//dc.BitBlt(m,n,93,100,mdc,0,0,WHITENESS);注释了起来。实际上这行是不能注释的,有了这个填充空白后,人物走起来就不会有残影了。


绘制整体布局————迷宫图





                               
登录/注册后可看大图



迷宫是由一块块蓝色小方块组成的。(准备好小方块图片)

迷宫横着有八块,竖着也有八块,第一步就是要让其绘制迷宫。

int maze[8][8]=
{

    1,1,1,1,1,1,2,1,    //第1行,值为2的元素代表入口
    3,0,0,1,0,0,0,1,  //第2行,值为3的元素代表出口
    1,1,0,0,0,1,1,1,  //第3行
    1,0,0,1,0,0,0,1,  //第4行
    1,1,1,1,0,1,1,1,  //第5行
    1,0,0,0,0,0,0,1,  //第6行
    1,0,1,0,1,0,0,1,  //第7行
    1,1,1,1,1,1,1,1  //第8行

};


我们把图划分成8行8列(以方块为单位),属于蓝色墙壁的,写上1 ,入口2,出口3,空白0

然后我就用for循环,对每个数组元素进行判断,如果是1,那就填上蓝色方块。

要填上方块,就必须知道其坐标。那么这个坐标就是数组序号* 方块长宽

如 maze[4][1];  他所表示的方块,其坐标就是 1*93,4*100   注意这里4是行,表示是纵向 。1是列,表示的是横向。

我们在ontimer函数中添加如下代码:

CClientDC dc(this);
for(a=0;a<8;a++)
{
   for (b=0;b<8;b++)
   {
       if (maze[a]
[b]==1)
    {
       mdc->SelectObject(wall);
       dc.BitBlt(b*93,a*100,93,100,mdc,0,0,SRCCOPY);
       }
   }

}

这样,运行后,就完成了迷宫的绘制:

6.JPG


这里有两个缺陷:

一、此程序是每隔0.1秒就重绘迷宫,其实我们只需要绘制一次就够了。

二、人物没有出现在入口,而且我们按移动键盘时,人物在另一端出现并移动。

解决第一个问题,只需要把以上代码前加入一个判断,把判断值初始化设为true,在最后又把它赋值为false就行,这样重绘就只执行一次。

第二个问题,人物出现在入口,我们只需要再加入一句BitBlt就行。然后再键盘控制代码中,用原始坐标+每次按键偏移量即可。



if (begin)
{


CClientDC dc(this);
  
  for (int a=0;a<8;a++)
  {
    for (int b=0;b<8;b++)
    {
      if (maze[a]
[b]==1)
      {
        mdc->SelectObject(wall);
        dc.BitBlt(b*93,a*100,93,100,mdc,0,0,SRCCOPY);
      }
      if(maze[a]
==2)
   {
        mdc->SelectObject(bitmap[0][0]);
     dc.BitBlt(b*93,a*100,93,100,mdc,0,0,SRCCOPY);

     x =b*93;  //这里是为了把人物初始坐标给记录下来,然后在键盘控制代码里添加即可
     y =a*100;
   
   }
    }
  }



  begin=false;
}



在人物键盘控制代码中,凡是出现dc.BitBlt 的,全部把其坐标m,n改为x+m,y+n,这样就完成了!运行后如图:

7.JPG

但是这个程序还有问题,那就是碰到墙壁会穿墙而过,墙壁没有起到阻挡的效果,如图:


                               
登录/注册后可看大图

[/b][/b]


游客,如果您要查看本帖隐藏内容请回复

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2013-9-28 20:37:46 | 显示全部楼层
学习了~!!!!!!!!{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-28 21:59:29 | 显示全部楼层
顶楼主啦..希望楼主多发精品好帖啦.....
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-9-29 18:03:59 | 显示全部楼层
不错呀 学习下吧 多谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-10-18 23:12:00 | 显示全部楼层
爲什麽又是圖片無法顯示?我的瀏覽器的問題嗎?

                               
登录/注册后可看大图
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-11-1 15:21:00 | 显示全部楼层
支持楼主
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2013-11-1 15:22:30 | 显示全部楼层
没有源码。可惜
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-22 09:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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