- 浏览: 148190 次
- 性别:
- 来自: 南京
最新评论
-
rex0654335:
一下4年过去了
华为面试小结 -
qalong:
楼主好人啊,连资料都附带了
BOX2D的选择建议 -
zzmmzzzzm:
...
Unity3D做2D横版游戏小demo(源码) -
Perfect_ff:
新手非常需要这样的demo啊
Unity3D做2D横版游戏小demo(源码) -
leecong1p:
<div class="quote_title ...
斜45度地图简介、坐标系转换以及数据碰撞
手机平台上开发斜45度地图系统的游戏,相信做惯了正面俯视的开发者刚接触总很不习惯。所谓斜45度游戏,也就是常说的2.5D游戏,用斜方向俯视的角度来增强立体感的一种技术。这种技术在PC平台上早就流行了,手机平台由于屏幕表现力的限制,大部分使用正面视角。但随着手机屏幕分辨率不断增大,斜45度视角的游戏出现得越来越多。
斜45度地图系统分Staggered、Slide、Diamond等几种,除了起始位置的区别,与正视地图系统的主要区别在于使用菱形的图块。关于什么是45度地图系统以及其原理,我不想再多说,网上有很多的资料,下面主要讲一讲坐标系的转换。
图1
图2(该图来自云风的博客http://www.codingnow.com/)
如图1,虽然图块是菱形拼接,但图片还是矩形,绘制地图就是要矩形的图片映射到正确的屏幕坐标系上,使图片无缝地拼接起来。如图2,以Diamond地图系统为例,为了简化,掠过滚屏等问题,假设始终从屏幕左上角开始绘制0,0的数据,图中所标的数字是指图块数据下标(data[j][i]中的(j,i))。通过观察你会发现:图片的X位置为数据j,i之差乘以图片宽度的一半,Y位置为数据j,i之和乘以高度的一半,即公式1:
px = (CHIP_W >> 1) * (i - j);
py = (CHIP_H >> 1) * (i + j);
通过公式1,我们就能根据数据数组的下标值获得对应图块在屏幕坐标系中的位置。逆推,得到公式2:
i = 0.5f * (y / (CHIP_H >> 1) + x / (CHIP_W >> 1));
j = 0.5f * (y / (CHIP_H >> 1) - x / (CHIP_W >> 1));
通过公式2,可以把图块位置映射到对应的数据坐标。
下面开始绘制地图内容。传统的俯视角度游戏地图绘制,都是记录屏幕(或摄像机)所在的数据j,i位置,计算屏幕能容纳多少个图块,用一个嵌套循环完成地图的绘制。如下所示:
for(int j=0;j<SCREEN_HEIGHT/CHIP_H;j++)
{
for(int i=0;i<SCREEN_WIDTH/CHIP_W;i++)
{
......//do draw
}
}
图3
但是如图3所示,斜45度地图是斜的,无法用数组的循环遍历来绘制。不过既然有了转换公式,我们可以把屏幕分割成CHIP_W/2*CHIP_H/2的若干个区域,通过“遍历”这些区域的坐标,可以用公式知道,要在这个坐标上画哪张图片。算法如下:
//当paintY为CHIP_H / 2的奇数倍时,paintX需要偏移CHIP_W / 2 int offset = 0; for (int paintY = 0; paintY <= SCREEN_H + CHIP_H; paintY += CHIP_H / 2) { for (int paintX = 0; paintX <= SCREEN_W + CHIP_W; paintX += CHIP_W) { int gx = getGx(paintX + offset, paintY) + startCol; int gy = getGy(paintX + offset, paintY) + startRow; if (gy < 0 || gx < 0 || gy > 10 || gx > 10) { continue; } drawTile(g, data[gy][gx], paintX + offset, paintY); } offset = offset == 0 ? CHIP_W / 2 : 0; }
//屏幕坐标转换成游戏坐标 int getGx(int x, int y) { return (int) (0.5f * (y / (CHIP_H >> 1) + x / (CHIP_W >> 1))); } int getGy(int x, int y) { return (int) (0.5f * (y / (CHIP_H >> 1) - x / (CHIP_W >> 1))); }
关于地图上的碰撞与拾取。当你需要判断精灵所处地图数据位置的时候用公式2,会发现判断误差很严重,仔细想一下不难解释:逆推过来的公式是根据图片之间的坐标系来定义的,而菱形切片之间透明的部分都是重叠的,所以当你判断重叠部分的碰撞时就无法预计判断是那一块数据了,所以用公式2进行地图数据的碰撞判断不可行。
图4
图5 图6
介绍一下我的碰撞方法。如图4,要判断屏幕中任意一点X,Y于数据中的位置。首先按图块的图片尺寸将屏幕分割,计算X,Y位于图中绿色矩形框选的哪个图片中,初步得到j,i。知道了位于哪张图块图片中,如图5,再判断X,Y位于图5中四个角落哪一个区域。结合图6,如果都不位于这四个角落,那X,Y就属于j,i。位于左上角的红色区域,对应i-1,其它三个角落同理。这里的难点在于如何判断红色区域,建议用三角形与点碰撞的算法。这种碰撞拾取算法的优点是精确无误差,而且无论菱形图块比例是32:15 、2:1还是其他比例都可以检测。
数据碰撞检测的主要代码:
int[] checkInDataIJ(int x, int y) { final int I = 0; final int J = 1; int[] data = new int[] { 0, 0 }; Log.e("", "click:" + x + "," + y); int xd = x / CHIP_W; int yd = y / CHIP_H; if (x < 0) { xd -= 1; } if (y < 0) { yd -= 1; } Log.e("", "xd:" + xd + " yd:" + yd); data[I] = yd + xd; data[J] = yd - xd; //计算触摸点位于矩形中,与菱形的位置 int cx = x % CHIP_W; if (cx < 0) { cx += CHIP_W; } int cy = y % CHIP_H; if (cy < 0) { cy += CHIP_H; } //是否位于左上角的三角形 if (MyMath.isInsideTriangle(cx, cy, new int[] { 0, CHIP_W / 2, 0 }, new int[] { 0, 0, CHIP_H / 2 })) { data[I] -= 1; } //是否位于右上角的三角形 else if (MyMath.isInsideTriangle(cx, cy, new int[] { CHIP_W / 2, CHIP_W, CHIP_W }, new int[] { 0, 0, CHIP_H / 2 })) { data[J] -= 1; } //是否位于右下角的三角形 else if (MyMath.isInsideTriangle(cx, cy, new int[] { CHIP_W, CHIP_W, CHIP_W / 2 }, new int[] { CHIP_H / 2, CHIP_H, CHIP_H })) { data[I] += 1; } //是否位于左下角的三角形 else if (MyMath.isInsideTriangle(cx, cy, new int[] { 0, CHIP_W / 2, 0 }, new int[] { CHIP_H / 2, CHIP_H, CHIP_H })) { data[J] += 1; } Log.e("debug", "get(:" + data[J] + "," + data[I] + ")"); return data; }
三角形检测算法:
public static boolean isInsideTriangle(int cx, int cy, int[] x, int[] y) { float vx2 = cx - x[0]; float vy2 = cy - y[0]; float vx1 = x[1] - x[0]; float vy1 = y[1] - y[0]; float vx0 = x[2] - x[0]; float vy0 = y[2] - y[0]; float dot00 = vx0 * vx0 + vy0 * vy0; float dot01 = vx0 * vx1 + vy0 * vy1; float dot02 = vx0 * vx2 + vy0 * vy2; float dot11 = vx1 * vx1 + vy1 * vy1; float dot12 = vx1 * vx2 + vy1 * vy2; float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); float u = (dot11 * dot02 - dot01 * dot12) * invDenom; float v = (dot00 * dot12 - dot01 * dot02) * invDenom; return ((u > 0) && (v > 0) && (u + v < 1)); }
评论
if (gy < 0 || gx < 0 || gy > 10 || gx > 10)
{
continue;
}
其中的10是代表什么意思呢?
地图数据的边界
if (gy < 0 || gx < 0 || gy > 10 || gx > 10)
{
continue;
}
其中的10是代表什么意思呢?
发表评论
-
手把手教你通过Java(RoboVM)创建IOS应用
2014-02-19 18:01 5797之前的文章多次提到RoboVm、Libgdx ... -
开发手游服务端,网络连接框架的选择
2013-07-19 16:04 5976JAVA有很多优秀的网络连接框架。Mina、 ... -
Android游戏设计中的音频控制——音量调整
2013-05-10 17:55 1531音量主要是通过AudioManager的setStreamV ... -
Android游戏设计中的音频控制经验分享
2013-04-20 01:40 2040游戏里用到BGM和音效,常用播放音频的方法主要通过Sound ... -
用intel驱动提升android模拟器速度
2013-03-14 16:09 7328感谢一碗豆腐向我推荐。 android模拟器是模拟ARM的 ... -
用JAVA开发IOS程序
2013-03-11 21:52 13470一度开发IOS程序只有obj ... -
Android中利用颜色过滤调整图象风格
2012-09-11 17:04 2384做游戏经常遇到这个情况,一张图片,从完全透明,渐渐过渡到不透明 ... -
解决Android创建AVD失败
2012-03-21 21:37 1368有时候我们重新下载了一份Android SDK,或者把SDK路 ... -
Android限制EditText输入字数
2012-03-21 21:36 993XML布局里设置的话只要设置maxLength属性就可以了。 ... -
JBOX2D与LibgdxBOX2D效率对比
2012-02-14 17:23 2090程序很简单, ... -
关于SurfaceView主线程与UI线程的问题
2011-12-26 17:38 4373好久没更新博客了,最近工作太忙了,也没什么时 ... -
Android中混淆的一些问题
2011-08-16 18:07 1329什么是混淆什么是proguard我就不解释了。Android2 ... -
Unity3D做2D横版游戏小demo(源码)
2011-08-05 14:12 51187用Unity3D做的一个小demo ... -
(转)就不能有点想象力吗?电子游戏开发商的七大陋习
2011-07-21 10:16 1433文章不错,转自3DM,原 ... -
推荐一些手机游戏开发会用到的网站
2011-07-07 17:53 2294像素图资源类(RPGmaker风格的精灵、地图图块等资源): ... -
Android游戏开发常碰到的几个问题
2011-06-02 18:00 2102做Android游戏开发的时候 ... -
深海猎手(捕鱼达人)正在开发中
2011-05-31 15:54 3521其实这个游戏去年我就有想法做了,工作太忙,一直没开 ... -
动态的水波时钟源码
2011-04-11 22:51 1309在网上找粒子特效的资料,竟然发现我两年前做的一个小水波时钟的程 ... -
J2ME中3D场景漫游的实现
2011-04-11 13:30 1529好吧,你该知道为什么我这叫跳票工厂,其实这玩意还没做 ... -
BOX2D的选择建议
2011-04-08 12:06 4801BOX2D越来越火了,基本上已经稳固了自己在游戏开发 ...
相关推荐
1. **坐标系统转换**:在2D游戏中,我们通常使用笛卡尔坐标系,其中x轴代表水平方向,y轴代表垂直方向。但在45度斜角地图中,我们需要将这些坐标转换为新的角度。这涉及到数学中的向量旋转和平移,可以使用矩阵运算...
这涉及到坐标系的转换,例如,开发者可能需要将屏幕坐标转换为世界坐标,然后再进行旋转和平移操作。DirectX中的Matrix类提供了矩阵运算,可以方便地实现这些变换。 渲染方面,开发者需要利用DirectX的设备对象和...
这通常通过计算角色与视口的关系来实现,调整地图坐标系使得角色位置始终保持在视口中心。 接着,"碰撞检测"是游戏中判断两个或多个对象是否发生接触的过程。在2D游戏中,常见碰撞检测方法有轴对齐边界框(AABB)、...
1. **坐标系统转换**:在J2ME中,图形通常是以直角坐标系绘制的,而斜45度视角需要在棋盘格状的坐标系统中操作。因此,开发者需要将游戏逻辑坐标转换为屏幕显示坐标。 2. **图形渲染**:由于J2ME的限制,开发者可能...
这涉及到从直角坐标到45度坐标系的转换。一个简单的转换方法是使用矩阵运算,将(x, y)坐标通过旋转矩阵R进行转换,公式如下: `(x', y') = R * (x, y) = [cos(45°), -sin(45°); sin(45°), cos(45°)] * (x, y)` ...
4. 网络游戏中的坐标转换,包括从参心坐标系到局部坐标系的转换,以及不同坐标系间的换算。 5. 性能优化策略,如减少计算负载、提高定位更新频率、优化数据传输等。 6. 示例和案例研究,展示实际的网络游戏应用情况...
1. **坐标系对齐**:首先,确保点云数据与栅格地图的坐标系一致。这可能需要进行旋转和平移操作。 2. **分辨率设定**:确定栅格的大小,这直接影响到地图的精度和内存消耗。分辨率小则地图精确,但占用内存大;反之...
3.1 坐标转换:菱形地图的坐标系统与常见的笛卡尔坐标系不同,需要进行特殊的坐标转换算法,确保每个单元格的位置正确显示。 3.2 图像处理:由于菱形的形状,渲染时要考虑相邻单元格的重叠,以避免出现空隙或重叠的...
【知识点详解】 1. **坐标方法的简单应用** ...通过以上内容,我们可以看到平面直角坐标系在描述地理位置、解决实际问题以及在游戏和几何学中的广泛应用。理解和掌握这些知识点对于解决相关问题至关重要。
这可能是一个二维平面坐标系,或者更复杂的空间坐标系,根据游戏的需求进行选择。 2. **地图切片**:由于大地图的图像可能会非常大,无法一次性加载到内存,所以通常会将地图切分成多个小块,称为地图切片或瓦片,...
这可能涉及到对地图和角色坐标系的转换,确保角色始终在视口中央,同时保持地图的连续性和无缝感。 4. **坐标系统**:游戏中的每个对象通常都有一个独立的坐标系统,角色、地图和视口之间需要进行坐标转换。例如,...
2. **投影转换**:由于GIS数据通常使用不同的坐标系统,osgGIS 提供了坐标系转换功能,使得不同投影的地理数据可以在同一场景中正确对齐。 3. **地理坐标与屏幕坐标转换**:osgGIS 实现了将地球坐标转换为3D场景中...
这通常涉及将OSM的坐标(基于WGS84坐标系)转换为UE4的本地坐标系统,并将地物(如道路、建筑物)转化为UE4的Actor或StaticMesh组件。 4. **创建地形**: 地形是OSM数据中的一个重要部分。可以使用OSM的海拔信息来...
3. **地理坐标转换**:MapX支持多种坐标系间的转换,包括UTM、经纬度等。这对于处理不同来源的数据非常关键。 4. **数据加载**:MapX可以直接读取各种地理数据文件,如Shapefile、DTED、TIGER等,也可以通过ODBC...
其中R是一个矩阵,它将向量转换到中间坐标系XTP中,即XTP = RX0P = (xTP, yTP, zTP)。这种变换可以通过将XTP的方向表示为绕坐标轴的一系列旋转来实现,这些旋转的角度被统称为“欧拉角”,用符号ϕ(phi)、θ...
我们可以遍历Polygon的每个顶点,利用 Leaflet 的 geometry utility 方法,如 `latLngToLayerPoint` 和 `layerPointToLatLng`,将地理坐标转换为像素坐标,然后进行碰撞检测,以确定点是否在区域内。 以下是一个...
在实际应用中,机器人需要将超声波测得的距离数据从车载坐标系转换到全局坐标系,以便进行路径规划。这通常涉及到一个旋转角度λ,用于描述车载坐标系相对于全局坐标系的位置。 6. 研究现状与意义 自主移动机器人的...
首先,它需要解析Halo Online的地图文件(通常为Sbsp格式),这种文件包含了地图的几何信息、纹理坐标、碰撞数据等关键元素。这一步骤需要深入理解游戏的文件结构和数据编码方式,对于非专业人士来说极具挑战性。...
5. **定位服务**:定位服务提供GPS定位和坐标转换功能,帮助应用获取用户的实时位置信息,或者将不同坐标系之间的数据进行转换。 6. **身份验证和授权**:ArcGIS Server支持多种安全模型,如OAuth2.0、Kerberos等,...
2. **坐标系统**:在二维地图中,通常采用笛卡尔坐标系,即X轴和Y轴。用户在界面上的每次点击会生成一个(X, Y)坐标,这些坐标对应于二维数组的索引。 3. **路径生成**:用户可以按照特定顺序点击单元格,软件会记录...