AS3-45度角坐标转换

AS3-45度角坐标转换

  (2012-01-31 09:52:06)

guan(我)的理解:







关于45度角地图中像素坐标和地图坐标之间的转换,网上有各种方法,其实坐标转换就是计算tite宽和tile高在像素坐标中的偏移值,本方法是针对 tite块原点坐标在菱形的顶点的位置的坐标转换,在45度角地图中,方块形状为菱形,你可以用flash cs工具或其他绘图工具很快的创建出这种菱形方块,按以下3个步骤就可以了:
1、 绘制一个任意大小的正方形;
2、 把这个正方形旋转45度;
3、 把旋转的正方形的高度缩放为原来的50%。
还有一点就是方块尺寸的问题,菱形方块的宽度是高度的2倍,其次方块尺寸比例应该是2:1。例如64像素X 32像素或100像素 X 50像素等,这样的尺寸刚好能使方块在地图铺设的时候很好地排列在屏幕上。
至于坐标间的转换其实大家看图就好理解了:

AS3-45度角坐标转换

图中是一个以红色(0,0)位置为原点,红点每向地图坐标系M轴上移动一个单位,原点相对像素坐标系X中的偏移值为:方块宽度/2
菱形方块宽 var tileW :Number;
菱形方块高 var tileH :Number;
地图的行数 var row :int;
地图的列数 var col :int;
红色原点坐标(像素坐标系) var originP : Point;
那么红色的原点坐标在地图坐标系中的位置为:
originP.x = row * tileW /2;
originP.y = 0;
原点坐标出来了,那么其它点的坐标呢?
思路是先求出在地图坐标系下(M方向或N方向)每移动一个单位的像素坐标系X轴和像素坐标系Y轴的像素偏移值。
如红色原点移动到黑色点的位置:
M在像素坐标系X轴的偏移像素 = tileW /2;(向右偏移)
M在像素坐标系Y轴的偏移像素 = tileH /2; (向下偏移)
N在像素坐标系X轴的偏移像素 = - tileW /2;(向左偏移)
N在像素坐标系Y轴的偏移像素 = tileH /2; (向下偏移)
假如有个地图坐标点(M,N),那么它对应的像素坐标系的点为var p:Point
p.x = 原点坐标X + M在像素坐标系X轴的偏移像素 × M + N在像素坐标系X轴的偏移像素 × N = originP.x + tileW /2 × M + (-tileW/2) × N = originP.x + (M – N) × tileW/2;
p.y = 原点坐标Y + M在像素坐标系Y轴的偏移像素 × M + N在像素坐标系Y轴的偏移像素 × N = originP.y + tileH/2 × M + tileH/2 × N = originP.y + (M + N) × tileH/2;



-------------------------------------------------------------------------------------------
   最早的有很多的2D游戏,地图看起来就像是俯视图一样,地图整体形状是个矩形的,地图的每一格也是个矩形,很多早期的RPG游戏就是这样。这样的地图实现 起来很方便,地图的信息一般就存储在一个二维数组中,描画、定位也很方便。不过这样的缺点就是不太逼真,所以在3D技术出现之前(或者是因为出于效率的原 因只能使用2D的情况下)有人想出了用2D的方式来模拟视觉上3D的效果,就是使用斜角地图块拼出的地图,这个斜角地图块的形状一般都是一个菱形,拼出后 整块的地图也是个菱形,如下图:
2.5D斜角地图

然后地图上有放置物体,比如建筑啊,自然物体,人物走动啊之类的,不少的游戏就是使用的这样的方式,比如:帝国时代;

       其实对于这样的斜角地图,地图网格数据依然是存储在一个二维数组之中的。仔细看这个地图其实就相当于把一块正放的图以左上角为圆星逆时针旋转了45度而已 (这只是一种理解方式,也可以认为是以左上角为圆心顺时针转了45度,区别在于写转换屏幕坐标和网格坐标的转换模块时不同)只不过描画时按照特定的方式来 描画,也就是给出地图的某一块格子,要知道这块画在屏幕上的坐标;反过来得到屏幕上的一个坐标点,如果这个坐标点正好位于地图之中,要知道这个点对应的是 二维数组中的哪块。解决了这个屏幕坐标到地图网格之间的映射关系的问题,实现一个2.5D斜角地图就变得相当容易了,噢,还有就是美工上的要求就是把原本 四方的地图单元格画成中间一个菱形其余部分为透明的四方的地图单元格^_^

       由于之前写的flash游戏里有遇到这方面的问题,所以特别花了点时间想了下,大多数情况下这种2.5D斜角地图应该都是菱形的,虽然不是菱形理论上也可以做到,但我写的这个转换类的还是基于菱形的,语言用的是AS3,代码如下:


public class SquintAngleTranslator
{
   private var m_mapWid:int = 0;
   private var m_mapHei:int = 0;
  
   private var m_orgX:Number = 0;
   private var m_orgY:Number = 0;
  
   private var m_xincX:Number = 0;
   private var m_xincY:Number = 0;
   private var m_yincX:Number = 0;
   private var m_yincY:Number = 0;
  
  
   //初始化,设置地图网格横向纵向的数量及显示时大地图的范围
   public function InitlalRhombusMap( mapWid:int, mapHei:int, mapRange:Rectangle ):void
   {
    m_mapWid = mapWid;
    m_mapHei = mapHei;
   
    var count:Number = mapWid + mapHei;
   
    m_orgX = mapRange.left + mapRange.width / count;
    m_orgY = mapRange.top + mapWid * mapRange.height / count;
   
    m_xincX = mapRange.width / count;
    m_xincY = - mapRange.height / count;
    m_yincX = mapRange.width / count;
    m_yincY = mapRange.height / count;
   
   }
  
   //重设地图原点位置的偏移(用于地图滑动)
   public function SetOrgin( xpos:Number, ypos:Number ):void
   {
    m_orgX = xpos;
    m_orgY = ypos;
   }
  
   //地图网格坐标转换到屏幕显示坐标(用于提供给描画用)
   public function GridToView( xpos:int, ypos:int ):Point
   {
    var pos:Point = new Point();
   
    pos.x = m_orgX + m_xincX * xpos + m_yincX * ypos;
    pos.y = m_orgY + m_xincY * xpos + m_yincY * ypos;
   
    return pos;
   }
  
   //屏幕坐标转换到地图网格坐标(比如在即时战略中用于确定鼠标点击的是哪一块)
   public function ViewToGrid( xpos:Number, ypos:Number ):Point
   {
    var pos:Point = new Point();
   
    var coordX:Number = xpos - m_orgX;
    var coordY:Number = ypos - m_orgY;
   
    pos.x = ( coordX * m_yincY - coordY * m_yincX ) / ( m_xincX * m_yincY - m_xincY * m_yincX );
    pos.y = ( coordX - m_xincX * pos.x ) / m_yincX;
  
    pos.x = Math.round( pos.x );
    pos.y = Math.round( pos.y );
   
    return pos;
   }
  
   //判断网格坐标是否在地图范围内
   public function LegalGridCoord( xpos:int, ypos:int ):Boolean
   {
    if ( xpos < 0 || ypos < 0 || xpos >= m_mapWid || ypos >= m_mapHei )
    {
     return false;
    }
   
    return true;
   }
  
   //判断屏幕坐标是否在地图范围内
   public function LegalViewCoord( xpos:Number, ypos:Number ):Boolean
   {
    var pos:Point = ViewToGrid( xpos, ypos );
   
    return LegalGridCoord( pos.x, pos.y );
   }
  
   //格式化屏幕坐标,即返回最接近该坐标的一个格子的标准屏幕坐标(通常用于在地图中拖动建筑物对齐网格用)
   public function FormatViewPos( xpos:Number, ypos:Number ):Point
   {
    var pos:Point = ViewToGrid( xpos, ypos );
   
    if ( LegalGridCoord( pos.x, pos.y ) )
    {
     pos = GridToView( pos.x, pos.y );
    }else
    {
     pos.x = xpos;
     pos.y = ypos;
    }
   
    return pos;
   }
  
}



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值