通常的概念中,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:ceponline@yahoo.com.cn
*
@version
0.1
*/
public
class
Test25D
extends
Panel
{
/**
*
*/
private
static
final
long
serialVersionUID
=
1L
;
final
static
int
frameWidth
=
490
;
final
static
int
frameHeight
=
330
;
Bitmapfloor,tile,role;
Imagescreen;
Graphicsgraphics;
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(Graphicsg)
{
paint(g);
}
public
void
paint(Graphicsg)
{
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
++
)
{
//
轉換為斜角坐標
Pointp
=
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
)
{
Pointp
=
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();
Pointp
=
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
PointreviseXY(
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()
{
Framefrm
=
new
Frame(
"
Java2.5D地圖構建
"
);
frm.setResizable(
false
);
frm.setSize(frameWidth,frameHeight);
frm.add(
new
Test25D());
frm.addWindowListener(
new
WindowAdapter()
{
public
void
windowClosing(WindowEvente)
{
System.exit(
0
);
}
}
);
frm.setLocationRelativeTo(
null
);
frm.setVisible(
true
);
}
}
);
}
}
效果圖如下:
明天晚上有時間再繼續……趕緊睡覺……
而所謂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









































































































































































效果圖如下:

明天晚上有時間再繼續……趕緊睡覺……
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
