通常的概念中,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

package org.loon.framework.game.test;

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

import org.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:[email]ceponline@yahoo.com.cn[/email]
 * @version 0.1
 */
public class Test25D extends Panel {
    
    /**
     * 
     */
    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);
            }
        });
    }

}

效果图如下:

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

本文转自 cping 51CTO博客,原文链接:http://blog.51cto.com/cping1982/130076

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. 斜45度瓦片地图(Staggered Tiled Map)里的简单数学

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. 微软亚洲研究院副院长周明离职,将加入创新工场
  2. 我在北京工作这几年 – 一个软件工程师的反省
  3. MySQL 清理slowlog方法
  4. linux创建永不过期用户,linux下如何设置用户密码永不过期_网站服务器运行维护...
  5. Texture Inspection 纹理检验halcon算子,持续更新
  6. miui替换官方文件解决无服务器,miui 关掉云服务器
  7. 使用HBuilder新建项目
  8. plsql轻量版存储过程和存储函数
  9. php csv to array (csv 转数组)
  10. Razor的主版页面框架
  11. 思科被发现使用华为代码,解释:忘了删
  12. 1 在c语言中不正确的常量是 a0xf6,C语言第三章在线测试题目及答案
  13. Vue将汉字转为拼音,取出首字母
  14. 很简单的源码剖析-SpringBoot内嵌Tomcat原理
  15. 计算机控制器的简写,工业控制常用英语及缩写
  16. 程序员年薪40万被国企同学怒怼:没啥贡献,凭什么工资这么高!
  17. 用python实现围棋(动图演示+源码分享)
  18. slf4j日志门面担当
  19. 十二月,我们一起在云台山风景区赏雪
  20. 网工学习 第十一章 网络管理 网络管理基础 网络管理协议五大标准 SNMP协议 RMON

热门文章

  1. l oracle红酒,2009 Miner Family Vineyards Oracle Red, Napa Valley, USA
  2. HDMI 2.1特性
  3. 用计算机怎么计算r角度,R语言中的数学计算
  4. 分布式认知工业互联网如何赋能工业企业数字化转型?
  5. 2021国开计算机应用基础形考任务答案,2021电大计算机应用基础形考试题答案解析.doc...
  6. 【实验四 循环结构】7-4 sdut-C语言实验-求阶乘(循环结构)
  7. 【OpenCV 例程 300 篇】105. 湍流模糊退化模型
  8. 4 支付宝手机网站支付demo讲解
  9. ubuntu安装android应用程序,Anbox将使Ubuntu手机能运行Android应用程序
  10. 港科夜闻|香港科大新研究显示预期接种疫苗和加强针后产生的T细胞免疫屏障将能继续保护人体并减少被Omicron等病毒变异的感染机率...