zoukankan      html  css  js  c++  java
  • 2d游戏斜视角地图的实现

    2d游戏斜视角地图的实现
    本文例子代码下载(radasm工程文件)

    说明:



     一、本程序是一个斜视角地图的滚屏演示。本程序在实现的时候并没有考虑屏幕渲染效率和内存空间的节省问题。所以地图绘制函数并没有对不可视的图块部分进行排除。本程序的实现完全采用了win32汇编语言,因此采用gdi接口也能获得较好的帧速。

    二、本程序反映了2d游戏地图的控制思路。即,核心问题是几个坐标变换问题,解决了坐标变换就可以了。
     
        1、保存地图的一维数据索引。需要把这个一维数组索引转变成地图坐标,即(列号,行号)。 完成这一步以后,绘图程序才能遍历整个一维数组,就象遍历
           一个二维的地图块数组一样。即通过数组索引确定它是在地图上的坐标。

        2、地图坐标----图块列号、行号。地图坐标转变成屏幕贴图坐标。因为地图坐标是(列号、行号),所以必须要通过地图坐标求解出地图块左上角的像素坐标,即贴图坐标。

        3、进行视变换。即,地图很大的时候,把视口举行在地图上进行平移就可以实现地图的滚动,看到不同的部分。所以,一旦视口的左上角在地图上的绝对坐标确定下来,那么一个地图 块在视口内部的相对坐标------最终的窗口客户区贴图坐标就可以求出。

        4、经过上面几步变换,一个地图块就真正的可以被绘制到窗口里面。

    三、帧速控制:

      a、用变量timeOld记录上次计算帧速结束的时间。
      b、变量timeNew记录当前时间。
      c、用变量frameCount记录从timeOld到timeNew的间隔里一共播放的帧数。

      d、每次获取当前时间timeNew以后,求自从
         上次计算帧速结束到现在一共有多少时间(ms):timeNew - timeOld

       当这个时间间隔大于1秒,就进行一次帧速计算,并且令
       timeOld = timeNew,frameCount也归零,准备从现在重新记录
         帧播放,以备在下一秒进行计算。

      e、用timeCur进行时间跟踪,以便帧速控制。
       timeCur记录上次播放一帧结束的时间。timeNew - timeCur表示
         自从上次播放一帧到现在经过了多少时间。
       所以如果每次当 timeNew - timeCur > 10的时候才进行一帧的
          播放,然后令timeCur = timeNew,以便进行下一帧播放时间间隔的
          控制。这样我们就可以控制在每个10ms内最多播放一帧,即对帧速进行
          了控制。

    代码说明:

    本例子主要的代码是地图绘制函数,地图绘制函数实现了几个坐标变换。

    DrawMap proc hdc1:HDC
     LOCAL i:DWORD
     LOCAL row:DWORD
     LOCAL col:DWORD
     LOCAL xAbs:DWORD
     LOCAL yAbs:DWORD
     LOCAL vx:DWORD
     LOCAL vy:DWORD
     LOCAL vp:POINT
     
     invoke BitBlt,buffer,0,0,640,480,bgDC,0,0,SRCCOPY
     mov i,0 
     .repeat
      ;把数组索引转变成地图坐标
      xor edx,edx
      mov eax,i
      mov ebx,20
      div ebx
      mov row,edx
      mov col,eax  
      ;把地图坐标转变成贴图坐标(绝对坐标)
      mov eax,row
      mov ebx,64/2
      mul ebx
      mov xAbs,eax
      mov eax,col
      mul ebx
      sub xAbs,eax
      mov eax,xstart
      add xAbs,eax
      
      mov eax,col
      mov ebx,32/2
      mul ebx
      mov yAbs,eax
      mov eax,row
      mul ebx
      add yAbs,eax
      mov eax,ystart
      add yAbs,eax
      ;根据视口坐标,把贴图坐标转变成窗口(视口)坐标
      mov eax,xAbs
      sub eax,viewRect.left
      mov vx,eax
      mov eax,yAbs
      sub eax,viewRect.top
      mov vy,eax
      ;进行屏幕贴图
      mov eax,i
      .if mapInfo[eax]==0
       invoke BitBlt,buffer,vx,vy,64,32,tile0,64,0,SRCAND
       invoke BitBlt,buffer,vx,vy,64,32,tile0,0,0,SRCPAINT
      .elseif mapInfo[eax]==1
       invoke BitBlt,buffer,vx,vy,64,32,tile1,64,0,SRCAND
       invoke BitBlt,buffer,vx,vy,64,32,tile1,0,0,SRCPAINT
      .elseif mapInfo[eax]==2
       invoke BitBlt,buffer,vx,vy,64,32,tile2,64,0,SRCAND
       invoke BitBlt,buffer,vx,vy,64,32,tile2,0,0,SRCPAINT
      .else
       invoke BitBlt,buffer,vx,vy,64,32,tile3,64,0,SRCAND
       invoke BitBlt,buffer,vx,vy,64,32,tile3,0,0,SRCPAINT
      .endif
      ;
      add i,1
     .until i==400
     
     ; 处理景物
     mov i,0 
     .repeat
      ;把数组索引转变成地图坐标
      xor edx,edx
      mov eax,i
      mov ebx,20
      div ebx
      mov row,edx
      mov col,eax  
      ;把地图坐标转变成贴图坐标(绝对坐标)
      mov eax,row
      mov ebx,64/2
      mul ebx
      mov xAbs,eax
      mov eax,col
      mul ebx
      sub xAbs,eax
      mov eax,xstart
      add xAbs,eax
      
      mov eax,col
      mov ebx,32/2
      mul ebx
      mov yAbs,eax
      mov eax,row
      mul ebx
      add yAbs,eax
      mov eax,ystart
      add yAbs,eax
      ;根据视口坐标,把贴图坐标转变成窗口(视口)坐标
      mov eax,xAbs
      sub eax,viewRect.left
      mov vx,eax
      mov eax,yAbs
      sub eax,viewRect.top
      mov vy,eax
      ;进行屏幕贴图
      mov eax,i
      .if sceneInfo[eax]==1
       add vx,7
       sub vy,44
       invoke BitBlt,buffer,vx,vy,50,60,scene1,50,0,SRCAND
       invoke BitBlt,buffer,vx,vy,50,60,scene1,0,0,SRCPAINT
      .elseif sceneInfo[eax]==2
       add vx,7
       sub vy,30
       invoke BitBlt,buffer,vx,vy,50,60,scene2,50,0,SRCAND
       invoke BitBlt,buffer,vx,vy,50,60,scene2,0,0,SRCPAINT
      .endif
      ;
      add i,1
     .until i==400
     
     ;<<<<<<<<<<<<<<<<<<处理精灵<<<<<<<<<<<<<<<<<<<<<<<<<<<<
     mov eax,viewRect.left
     mov vp.x,eax
     mov eax,viewRect.top
     mov vp.y,eax
     invoke GetStatus
     .if eax==0
      invoke SetDir
     .endif
     invoke DrawSprite,buffer,vp
      ; 打印程序信息  
      invoke SetBkMode,buffer,TRANSPARENT
      invoke TextOut,buffer,50,300,addr frameInfo,28
      invoke TextOut,buffer, 50,350,addr appInfo,sizeof appInfo - 1
      invoke TextOut,buffer,55, 400,addr authInfo,sizeof authInfo - 1
      invoke SetBkMode,buffer,OPAQUE
      invoke BitBlt,hdc1,0,0,640,480,buffer,0,0,SRCCOPY
     ret

    DrawMap endp





  • 相关阅读:
    k8s前期部署准备
    树莓派安装Gitlab-runner
    GitLab CI/CD 报错
    测试
    LVS结合keepalive
    LVS实现负载均衡安装配置详解
    LVS实现负载均衡原理
    私有仓库 gitlab 部署笔记
    Docker 案例: 在容器中部署静态网站
    docker 容器的启动方式
  • 原文地址:https://www.cnblogs.com/worldreason/p/1214610.html
Copyright © 2011-2022 走看看