通常的概念中,2D也就是所谓的二维,也就是平面图形——即由X与Y坐标构成的图形,其内容由水平的X轴向与垂直的Y轴描绘确定,也就是由长和高的形成所谓的二维平面。

而所谓3D,也称之为三维。其图形内容除了有水平的X轴向与垂直的Y轴向外还有进深的Z轴,故称三维(XYZ),也就是由长、宽、高三项要素形成所谓的三维立体。

2D与3D的主要区别在于,3D可以包含360度的信息,能从各个角度去表现,构成近似于现实空间的有质感视角;而2D通常只能表现如表格、棋盘版的平面数据。 3D的立体感、光景效果要比二维平面图形要好的多,因为它的立体、光线、阴影都是相对真实存在的,而2D显然不具备这些优势。高拟真度、高自由度使得3D图形大受欢迎。

所以渐渐的3D图形开始成为主流,充斥于电影、电视乃至游戏的各个角落。但是,由于3D技术实现的复杂性及对用户环境的高要求,在所有领域都完全使用3D构图还并不现实,由此引发了另一种图形表现形式的出现——2.5D图形。

所谓的2.5D,介乎于模真的3D与完全平面的2D之间。即模拟了3D的空间感,也兼具2D的灵动简单,是一种“优势”的综合体。就我个人认为,诚然2.5D最早的出现动机只是为了2D到3D间过渡。但就其应用而讲,好的2.5D图形即有3D的自由度与质感,又能利用2D图形将漫画式人物塑造得惟妙惟肖,使其拥有纯3D还无法做到的优势。因此2.5D在现在乃至未来的一段较长时间里还会和3D并存,直到3D图形的开发效率及表现形式能彻底取代2.5D为止。

目前2.5D有两种大方向的实现思路:

一、纯2D模拟实现,是由2D人物及2D模拟3D场景:比较常见的如《神奇传说》、《皇家骑士团》、《超时空英雄传说》(PS:我从1开始玩的,也由此和宇峻游戏结缘,虽然我不是游戏开发人员,但遥想当年宇峻科技刚开张时,李玉山一个人写出超时空英雄传说1所有程序代码[虽然有部分是国外引擎改的]的功力我至今望尘莫及,其不愧为我等程序员之楷模)《魔力宝贝online》等,利用近大远小的视觉差模拟3D物体,令用户产生在使用3D图形的错觉,通常为一个左或右偏的45度角,当然也有偏55度或其他不同的角度可供选择。

二、2D+3D实现,是由3D场景加2D人物贴图:比如《MU奇迹online》、《RO仙境传说online》(PS:在RO中我练的高INT创造者,爱好是城战丢硫酸瓶毁对方装备……),由于场景采用3D绘制,可以360度自由旋转视角,真实感较强。纯2D的角色与遮挡关系处理简单。相对于纯3D来说代码量少且简单。美术方面工作量较少。比之纯3D占用系统资源也更少。

平心而论,个人比较推崇2D+3D哪种类RO的表现方式,但由于吾辈是Java程序员且非游戏开发人员并不熟悉Java3D的关系,只能采用Java2D来进行演示。

在当采用2D模拟3D实现2.5D(斜视角)时,我认为难点只有两个:

1.你要有美工帮你做好斜视的tile及role

2.你要转换2D坐标为2.5D坐标

对于第一点,神仙都爱莫能助……没有美工就自己画吧……

而对于第二点,也就是斜视图的坐标变换,大多数人最直接的想法可能就是利用三角函数。是的,从某种意义上说,俯视角度与正斜视角度的变化就是三角函数的应用,我也见过这类的45度斜视用例。但是,利用cos在Java中进行三角函数的运算,首先速度不能达到要求,其次图像衔接度结果并不理想,结果可能令图像有锯齿状偏移,所以我并不推荐使用。

对于如类的菱形斜视图像,我们可以利用一个简单的行列运算获得俯视角度地砖的绘制坐标与斜视角度地砖的绘制坐标的变换,公式如下:

X:2.5D图形中X轴位置=(目标图像Width/2)*(2D图形中X-2D图形中Y)

Y:2.5D图形中Y轴位置=(目标图像Height/2)*(2D图形中X+2D图形中Y)/2

当然,这个公式并不是绝对的,尤其是在图像数据有所偏移时。比如斜视角的地砖的宽与高的比例理论上应该是2:1的关系,即如果高度是12的话,那么物体宽度就应该是24,这个在数学上讲和绘制地图上的时候是没有错的。但是问题出现在美工可能做不出来这么一个图(比如我,做了三个演示用图基准线全不一样|||)。

因为美工在画图的时候,肯定是要找一个基准线(一般是水平方向上的中分线,因为这个方向是高度,而高度的比例是单位1),然后对称的画图的,在开始的时候问题不会出现,但是在画到后面的时候就会发现,无论如何都没有办法把另一个方向上的顶点画出来,总是没有办法在指定的范围内相交。这是因为计算机的绘图是按照像素点一个个绘制出来的,总是没0.5个像素的时候,所以就出现了这个情况。于是,美工一般为了在指定的范围划出来一个菱形往往会画花2个像素,也就是24*12的图像很有可能会被画成22*12……

此时这是我们就需要增或者减公式中的数值,令基准线和图形的实际保持一致,大家可以自己推导。

演算后图形表现应如上图所示。

下面,我给出一个在Java中此公式的实际实现代码。

Test25D.java

packageorg.loon.framework.game.test;

importjava.awt.Color;
importjava.awt.Frame;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Panel;
importjava.awt.Point;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;

importorg.loon.framework.game.image.Bitmap;

/** *//**
 * <p>
 * Title: LoonFramework
 * </p>
 * <p>
 * Description:Java2.5D地图构建
 * </p>
 * <p>
 * Copyright: Copyright (c) 2007
 * </p>
 * <p>
 * Company: LoonFramework
 * </p>
 * 
 * @author chenpeng
 * @email:ceponline@yahoo.com.cn
 * @version 0.1
 */
publicclassTest25D extendsPanel ...{
    
    /** *//**
     * 
     */
    private static final long serialVersionUID = 1L;

    final static int frameWidth = 490;

    final static int frameHeight = 330;

    Bitmap floor, tile,role;

    Image screen;

    Graphics graphics;

    int[][] map = ...{ 
            ...{ 1, 1, 1, 1, 1, 1, 1, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 1, 0, 0, 0, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 1, 0, 1 },
            ...{ 1, 0, 0, 0, 0, 0, 0, 1 }, 
            ...{ 1, 1, 1, 1, 1, 1, 1, 1 } };

    public Test25D() ...{
        
        setBackground(Color.WHITE);
        
        floor = new Bitmap("./imagerpg/floor.gif");
        tile = new Bitmap("./imagerpg/tile.gif");
        role = new Bitmap("./imagerpg/obj.gif");
        //定位为X=1,Y=2(由0开始)
        role.setDrawXY(1, 2);
        screen = new Bitmap(frameWidth, frameHeight).getImage();
        graphics = screen.getGraphics();

    }

    public void update(Graphics g) ...{
        paint(g);
    }

    public void paint(Graphics g) ...{
        int X, Y;
        //将图像位置向x点坐标校正180,y点校正50
        int offsetX = 180;
        int offsetY = 50;
        int floorWidth = floor.getWidth();
        int floorHeight = floor.getHeight();
        for (int i = 0; i < map.length; i++)
            for (int j = 0; j < map[i].length; j++) ...{
                //转换为斜角坐标
                Point p = reviseXY(floorWidth,floorWidth, j, i, offsetX, offsetY);
                X = p.x;
                Y = p.y;
                if (map[i][j] == 0) ...{
                    graphics.drawImage(floor.getImage(), X, Y, X + floorWidth,
                            Y + floorHeight, 0, 0, floorWidth, floorHeight,
                            this);
                }
            }
        int blackWidth = tile.getWidth();
        int blackHeight = tile.getHeight();
        for (int i = 0; i < map.length; i++)
            for (int j = 0; j < map[i].length; j++) ...{
                if (map[i][j] != 0) ...{
                    Point p = reviseXY(blackWidth,blackWidth, j, i, offsetX, offsetY);
                    X = p.x;
                    Y = p.y - (blackHeight - floorHeight);
                    graphics.drawImage(tile.getImage(), X, Y, X + blackWidth,
                            Y + blackHeight, 0, 0, blackWidth, blackHeight,
                            this);
                }
            }
        
        //绘制移动角色
        int roleWidth = role.getWidth();
        int roleHeight = role.getHeight();
        Point p = reviseXY(roleWidth,roleWidth, role.getDrawX(), role.getDrawY(), offsetX, offsetY);
        X = p.x;
        Y = p.y-15;
        graphics.drawImage(role.getImage(), X, Y, X + roleWidth,
                Y + roleHeight, 0, 0, roleWidth, roleHeight,
                this);
        //在伪45度图像构建时,需要处理角色和建筑间的遮挡关系,我在这里只使用了简单的重绘
        //即如果构成和角色相遮挡的物体,首先绘制角色,而后用建筑遮挡该角色。
        //比如x+1=1即前方有物体存在时,重绘遮挡物以遮挡角色
        if(map[role.getDrawY()][role.getDrawX()+1]==1)...{
             p = reviseXY(blackWidth,blackWidth, role.getDrawX()+1, role.getDrawY(), offsetX, offsetY);
            X = p.x;
            Y = p.y - (blackHeight - floorHeight);
            graphics.drawImage(tile.getImage(), X, Y, X + blackWidth,
                    Y + blackHeight, 0, 0, blackWidth, blackHeight,
                    this);
        }
   

        g.drawImage(screen, 0, 0, this);
    }

    /** *//**
     * 修正为斜角坐标
     * @param width
     * @param x
     * @param y
     * @param offsetX
     * @param offsetY
     * @return
     */
    private Point reviseXY(int width, int height,int x, int y, int offsetX, int offsetY) ...{
        int x1 = x * (width / 2);
        int y1 = y * (height / 2);
        int nx = x1 - y1;
        int ny = (x1 + y1)/2;
        return new Point(nx + offsetX, ny + offsetY);
    }

    public static void main(String[] args) ...{
        java.awt.EventQueue.invokeLater(new Runnable() ...{
            public void run() ...{
                Frame frm = new Frame("Java2.5D地图构建");
                frm.setResizable(false);
                frm.setSize(frameWidth, frameHeight);
                frm.add(new Test25D());
                frm.addWindowListener(new WindowAdapter() ...{
                    public void windowClosing(WindowEvent e) ...{
                        System.exit(0);
                    }
                });
                frm.setLocationRelativeTo(null);
                frm.setVisible(true);
            }
        });
    }

}

效果图如下:

明天晚上有时间再继续……赶紧睡觉……

Java中2 5D游戏(斜45度角)的设计与实现 1相关推荐

  1. Java中2.5D游戏的设计与实现(3)—八方走法实现原理及相关代码

    Java中2.5D游戏的设计与实现(3)-八方走法实现原理及相关代码 2.5D游戏,虽然在外观上近似于3D游戏,却又不是严格意义上讲的3D游戏,故此2.5D游戏又常被称为[伪3D游戏]. 在笔者的观念 ...

  2. 45 度角地图-----斜45度角地图拼接

    45 度角地图, 可以分为 Staggered, slid 和 Diamond 三种类型 先看看地图元素: 可以看出来是个扁的菱形.这个地图元素的大小是64X32,你可以随意决定元素长宽,在设计程序时 ...

  3. Java中2.5D游戏(斜45度角)的设计与实现(1)

    通常的概念中,2D也就是所谓的二维,也就是平面图形--即由X与Y坐标构成的图形,其内容由水平的X轴向与垂直的Y轴描绘确定,也就是由长和高的形成所谓的二维平面. 而所谓3D,也称之为三维.其图形内容除了 ...

  4. 斜45度瓦片地图(Staggered Tiled Map)里的简单数学

    瓦片地图(Tiled Map)系列文章: 斜45度瓦片地图(Staggered Tiled Map)里的简单数学 瓦片地图注意事项 前段时间在做游戏的地图编辑功能,我们是在一个斜45度视角的场景上,对 ...

  5. Tiled实现斜45度瓦片地图

    首先是我最近在做的一个项目的需求,要做一个斜45度角的大地图,里面有很多的建筑,会有人在里面走来走去.一个手指按住滑动可以拖动地图,两个手指按下可以调整地图的放大和缩小. 1.tiled新建地图,加入 ...

  6. cocos2dx使用TiledMap模拟3D地图场景----斜45度2D地图的靠墙直线移动

     基于cocos2dx引擎的第三人称射击游戏,角色使用3D模型,地图采用2.5D.  定制地图编辑系统抛开不谈,这里最大可能的挖掘现有工具TiledMap的潜力,完成超2.5D地图的实现.  使用2D ...

  7. 编写简易斜45度地图编辑器

    最近在研究cocos2dx的地图,最开始使用的是Tiled,这个编辑器做比较小的地图还是比较强大的,不过做大地图的时候,有一些功能不太方便并且有缺陷(包括刷图繁琐以及坐标体系过于复杂,导致寻路比较看起 ...

  8. 可视化:在窗口中显示一个球,该球以与水平成45度夹角作直线运动,当遇到边界时,反弹回来,仍与水平成45度角继续运动。

    在窗口中显示一个球,该球以与水平成45度夹角作直线运动,当遇到边界时,反弹回来,仍与水平成45度角继续运动. #include<windows.h> #include<stdlib. ...

  9. 45度角Tile地图通过具体位置获得地图的行列数详解

    //45度角地图通过具体位置获得地图的行列数 CCPoint TileMapMove::convertto2d(float x,float y) { CCTMXTiledMap *tileMap=(C ...

  10. 45度角地图坐标计算 和 层级计算

    //2个方块x的距离 xdis = 38 //2个方块y的距离 ydis = -19 //传入 XY 下标 获取坐标   45度角地图 getPositonByXY(_x :number, _y :  ...

最新文章

  1. nyoj 1272 表达式求值(中缀式转后缀式)
  2. 细胞冻存及细胞计数的技巧
  3. 使用应用程序(Java/Python)访问MaxCompute Lightning进行数据开发
  4. py-faster-rcnn + ZF 实现自己的数据训练与检测(二)
  5. 慕课网高并发实战(一)-并发与高并发基本概念
  6. python归一化 增大差异_Python逻辑回归模型原理及实际案例应用
  7. python如何引发和处理异常_在python3.6中,如何捕捉异常并引发异常以便稍后处理?...
  8. ❤️Docker教程小白实操入门 教程合集❤️
  9. Hermite多项式
  10. 二 Python 基本数据类型
  11. hdfs API命令操作京东云主机,采坑记录
  12. 梯度下降法计算二次函数极值、拟合一次曲线、拟合二次曲线
  13. 上传附件,附件类型问题
  14. ClickHouse函数操作大全
  15. 利用vue实现树表格分页
  16. [华为机试真题]69.姓名的夫妻相
  17. 2019华为实习面经
  18. linux的常用备份方法,Linux系统下常用的数据备份方法
  19. 计算机信息安全论文参考文献,信息安全学论文参考文献 信息安全核心期刊参考文献哪里找...
  20. 我是一个坚持“朝九晚五”的程序员

热门文章

  1. 听课笔记-名校启程大学规划课
  2. 2021-2027全球与中国教育ERP套件软件市场现状及未来发展趋势
  3. 寿司之神--小野二郎
  4. 决策树Gini系数计算过程详细解答
  5. H5互动小游戏开发案例
  6. java中style的用法
  7. OCR--PC单机版车牌识别技术
  8. 小米路由器3 mysql_小米路由器3 opkg安装
  9. 美通企业日报 | 洲际集团酒店将撤除一次性小包装洗护用品;新能源汽车同时面临新老质量问题...
  10. 服装吊牌如何在条码打印软件中制作?