网页功能: 加入收藏 设为首页 网站搜索  
流星之舟地图遮挡算法(第一稿)
发表日期:2007-01-17作者:[转贴] 出处:  

  下面的文字将叙述成都金点工作组所设计的RPG游戏《流星之舟》的地图遮挡算法,游戏地图采用斜45度的视角,屏幕分为了20*15个菱形图块,每个图块的大小为64*32(像素点)。
  首先看一下这张图,我的算法是当扫描到物体编号点后,先画出物体,然后搜索左右两个修正区,如果修正区中有其他物体的编号,那么先画出该物体,然后搜索新找到物体的两个修正区,这样不断递归进行搜索,直到全部搜索完毕。



  拒我的测试,这个算法的速度还是可以,但是还存在一定的缺陷,如:有可能掉入死循环(属于特殊情况,一般不会发生)、对于下小上大的物体(如:树冠很大的树)有可能出现错误遮挡。
  下面的代码就是《流星之舟》中用到的场景遮挡算法,我把其中一些不必要的东西清除了,然后加上了详细的注释。

//显示一个场景中的所有物体,包括角色(我把角色当作景物进行处理)
void ShowMap()
{
    //画景物(pm.SX,pm.SY)是当前屏幕相对于整张地图的坐标
    for(j=pm.SY; j<pm.SY+16+10; j++)
    {
        //在地图Y轴范围之内(Height:地图高度)
        if( j<Height )
        {
            //先画偶数行物体
            for(i=pm.SX-6; i<pm.SX+21+6; i+=2)
            {
                //在地图X轴范围内(Width:地图宽度)
                if( i>=0 && i<Width )
                {
                    int Cover=Data[Width*j+i].CoverID; //取当前图块中的景物数据
                    if( Cover != 0 ) //显示物体(0:无物体)
                    {
                        Cover-=16; //这是我做的一个变换,无实际意义
                        Blt(lpDDSBack, ((i-pm.SX)<<5)-pm.DX - Objects[Cover].x, ((j-pm.SY)<<5)-pm.DY - Objects[Cover].y +32 ,lpDDSObj[ Objects[Cover].Surf ], Objects[Cover].rect, TRUE); //画出物体
                        FixMap(i,j,Cover); //修正大物体的遮挡关系(最重要的部分)
                    }
                }
            }
            //后画奇数行物体
            for(i=pm.SX+1-6; i<pm.SX+21+6; i+=2)
            {
                //在地图X轴范围内
                if( i>=0 && i<Width )
                {
                    int Cover=Data[Width*j+i].CoverID;
                    if( Cover != 0 ) //显示物体
                    {
                        Cover-=16;
                        Blt(lpDDSBack, ((i-pm.SX)<<5)-pm.DX - Objects[Cover].x, ((j-pm.SY)<<5)-pm.DY - Objects[Cover].y + 48 ,lpDDSObj[ Objects[Cover].Surf ], Objects[Cover].rect, TRUE);
                        FixMap(i,j,Cover);
                    }
                }
            }
        }
    }
}


//****************************
//修正物体的阻挡(这个函数中用到了很多其他东西,所以可能很难读懂,不过只要你理解了我的方法,我想你可以写出更好代码来)
void FixMap(int x, int y, int Cover)
{
    int Ox, Oy, Vx, Vy;
    int tx, ty; //临时变量
    //左边
    if( Objects[Cover].Lx>0 )
    {
        //转化成斜坐标系
        Ver2Oblique(x, y, Ox, Oy);
        //求三角型顶点
        Ox-=Objects[Cover].Lx;
        Oy+=1;
        for( int i=0; i<Objects[Cover].Lx; i++)
            for( int j=0; j<=i; j++)
            {
                tx=Ox+j;
                ty=Oy+i-j;
                //转化成直坐标系
                Oblique2Ver(tx,ty, Vx, Vy);
                int ID=Data[Width*Vy+Vx].CoverID;
                if( NpcData[ Width*Vy+Vx ] != 0 )
                {
                    ShowRoles(NpcData[ Width*Vy+Vx] );
                }
                if( ID != 0 )
                {
                    ID-=16;
                    if( Vx%2==0 )
                        Blt(lpDDSBack, ((Vx-pm.SX)<<5)-pm.DX - Objects[ID].x, ((Vy-pm.SY)<<5)-pm.DY - Objects[ID].y +32 ,lpDDSObj[ Objects[ID].Surf ], Objects[ID].rect, TRUE);
                    else
                        Blt(lpDDSBack, ((Vx-pm.SX)<<5)-pm.DX - Objects[ID].x, ((Vy-pm.SY)<<5)-pm.DY - Objects[ID].y +48 ,lpDDSObj[ Objects[ID].Surf ], Objects[ID].rect, TRUE);
                    FixMap(Vx, Vy, ID); //递归
                }
            }
    }

    //右边
    if( Objects[Cover].Ly>0 )
    {
        //转化成斜坐标系
        Ver2Oblique(x, y, Ox, Oy);
        //求三角型顶点
        Oy-=Objects[Cover].Ly;
        Ox+=1;
        for( int i=0; i<Objects[Cover].Ly; i++)
            for( int j=0; j<=i; j++)
            {
                tx=Ox+j;
                ty=Oy+i-j;
                //转化成直坐标系
                Oblique2Ver(tx,ty, Vx, Vy);
                int ID=Data[Width*Vy+Vx].CoverID;
                if( NpcData[ Width*Vy+Vx ] != 0 )
                {
                    ShowRoles( NpcData[ Width*Vy+Vx ] );
                }
                if( ID != 0 )
                {
                    ID-=16;
                    if( Vx%2==0 )
                        Blt(lpDDSBack, ((Vx-pm.SX)<<5)-pm.DX - Objects[ID].x, ((Vy-pm.SY)<<5)-pm.DY - Objects[ID].y +32 ,lpDDSObj[ Objects[ID].Surf ], Objects[ID].rect, TRUE);
                    else
                        Blt(lpDDSBack, ((Vx-pm.SX)<<5)-pm.DX - Objects[ID].x, ((Vy-pm.SY)<<5)-pm.DY - Objects[ID].y +48 ,lpDDSObj[ Objects[ID].Surf ], Objects[ID].rect, TRUE);
                    FixMap(Vx, Vy, ID); //递归
                }
            }
        }
}

  上面的代码仅仅是想帮助你更好的理解算法,但是如果你很难看懂的话,就请不要再继续浪费时间,因为它本来就太乱了,如果大家对这个算法感兴趣的话,我可以把上面的代码规范化。但我并不能保证这种方法是正确、高效的,因为这仅仅是我个人凭空想出来的(《流星之舟》是它的唯一一个实例,你可以到http://www.gpgame.com下载范例)。

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 流星之舟地图遮挡算法(第一稿)
本类热点文章
  脚本系统的实现
  C++基本功和 Design Pattern系列(2) Ty..
  C++基本功和 Design Pattern系列(1) - ..
  斜45度游戏开发(提高篇)
  睱酵笴栏祘Α砞璸?? - [秈顶絞]
  斜45度游戏开发(二)
  第一次写技术文献。Collision AI
  斜视角游戏中遮挡的判断
  C语言基本功教程系列(5) - 文件, Socke..
  用rand()和srand()产生伪随机数的方法总..
  C++基本功和 Design Pattern系列(3) co..
  C语言基本功教程系列(1)
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00456