黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

jMonkeyEngine譯文 FlagRush5(2)——跟隨的攝像

系統(tǒng) 2179 0

5.4 、讓我們?cè)黾油婕?

對(duì)于這個(gè)向?qū)В覀儗⒅皇鞘褂靡粋€(gè)占位符代替交通工具。我們將在之后載入模型,但那只是沒(méi)價(jià)值的工作,我們想要先讓游戲的核心能運(yùn)作。一個(gè) Box 是一個(gè)好的占位符,因?yàn)樗俏覀兘煌üぞ叩幕A(chǔ)模型。

所以,讓我們先增加一個(gè) buildPlayer 的方法并在 initGame 中調(diào)用它。我們將接著創(chuàng)建一個(gè) box 做為玩家的幾何體并把這個(gè) Box attach node 。這個(gè)玩家 Node 將會(huì)是一個(gè)類變量,以便我們能在 update 期間訪問(wèn)它。我將創(chuàng)建一個(gè)中心為 (0,0,0) 和大小為 (0.35,0.25,0.5) ,讓它看起來(lái)長(zhǎng)和寬。 Node 接著被移到坐標(biāo) (100,0,100) 。我還沒(méi)設(shè)置它的高度,我將在之后才那么做。

private void buildPlayer() {

//box 代替

Box b = new Box( "box" , new Vector3f(), 0.35f,0.25f,0.5f);

b.setModelBound( new BoundingBox());

b.updateModelBound();

player = new Node( "Player Node" );

player .setLocalTranslation( new Vector3f(100,0, 100));

scene .attachChild( player );

player .attachChild(b);

player .updateWorldBound();

}

如果你現(xiàn)在運(yùn)行這個(gè),實(shí)際上不會(huì)看到 player ,因?yàn)樗钕菰? terrain 下面。我們?cè)? update 里面設(shè)置 height ,這是因?yàn)槲覀儗⒑芸熳尳煌üぞ咴谄矫嫔弦苿?dòng),并需要讓它保持在 terrain 上。所以,為了保持 box 在地面的頂部行駛,增加:

// 確保當(dāng)玩家離開(kāi)平面時(shí)我們不會(huì)墜落。

// 當(dāng)我們?cè)黾記_突時(shí), fence 將做它自己的工作并保持玩家在里面。

float characterMinHeight =

tb .getHeight( player .getLocalTranslation()) +

((BoundingBox) player .getWorldBound()). yExtent ;

if (

!Float. isInfinite (characterMinHeight) &&

!Float. isNaN (characterMinHeight)

)

player .getLocalTranslation(). y = characterMinHeight;

首先,我們獲取玩家當(dāng)前位置對(duì)應(yīng)的 terrain 的高度。接著加上 BoundingBix 的偏移,我們這么做是因?yàn)? Box 位置的點(diǎn)是 Box 的中心。如果我們沒(méi)加上偏移, box 將有一半沉入地下。我們使用包圍對(duì)象的 BoundingBox 去獲取對(duì)象的高度( yExtent )(但實(shí)際上如果你對(duì)模型了解得很好,你可以使用值代替)。最后,我們檢查獲取的高度去確認(rèn)沒(méi)有得到一些糟糕的值(非數(shù)字、無(wú)窮大等)。我們這么做是因?yàn)槟壳拔覀儧](méi)做任何事去阻止玩家駕駛出 terrain

我們現(xiàn)在已經(jīng)在 terrain 上擁有了玩家!

jMonkeyEngine譯文 FlagRush5(2)——跟隨的攝像機(jī)(ChaseCamera)

( 現(xiàn)在你可能還看不到這個(gè)畫(huà)面,別急,后面會(huì)看到的 )

5.5 、跟隨攝像機(jī)( ChaseCamera

好了,現(xiàn)在我們有了玩家,我們應(yīng)該有能力移動(dòng)它。這將是一個(gè)第三人稱游戲,意味我們?cè)谕嬗螒虻臅r(shí)候能看到自己的玩家(而不是以 player 的眼睛去看)。所以我們想要攝像頭一直指向玩家并跟隨他。為了這么做,我們將使用 ChaseCamera ChaseCamera 將通過(guò)定義它跟隨距離的參數(shù)一直追蹤一個(gè)給出的對(duì)象。 ChaseCamera 也定義一些值讓它平滑跟隨。那就是它不能突然轉(zhuǎn)向玩家。這種突然性的效果當(dāng)然也是可以定義的。

所以,當(dāng)我們使用 ChaseCamera ,視圖將一直對(duì)著玩家。鼠標(biāo)將允許 camera 在玩家四周旋轉(zhuǎn)并一直面向它。鼠標(biāo)滾輪將允許 camera 縮放(盡管在這個(gè)例子中縮放值很小)。

因此,創(chuàng)建一個(gè) buildChaseCamera 方法并從 initGame 中調(diào)用它。我們?cè)谶@里設(shè)置 ChaseCamera 的參數(shù)并創(chuàng)建它。 ChaseCamera 對(duì)象將成為一個(gè)類變量以致我們能 update 它(所以把它加到類的頂部)。

我們相對(duì) ChaseCamera 設(shè)置的參數(shù)有一些。首先,我們將設(shè)置 Camera 的目標(biāo)偏移玩家。我們通常想讓 camera 看起來(lái)在玩家上一點(diǎn)。所以我們?cè)O(shè)置偏移( offset )值為( 0 ,玩家的 Y*1.5 0 . 這將讓 camera 指向指向一個(gè)在玩家原始高度上面多一半的一個(gè)點(diǎn)。下一步,我們將設(shè)置滾動(dòng)( rollout )值。這些值決定了我們能拉近或推遠(yuǎn)攝像機(jī)多少。我這里不想給太多自由,因此這個(gè)級(jí)別實(shí)際上很小。所以我們?cè)O(shè)置最大為 6 個(gè)單元,而最小為 3 個(gè)單元。下一步我們將設(shè)置 camera 能向上轉(zhuǎn)動(dòng)多高,在這個(gè)例子中為 45 度,注意是弧度。最后,我們將為 camera 設(shè)置開(kāi)始起點(diǎn)的球形坐標(biāo), roll out 5 并升高 30 度。因?yàn)? camera 在一個(gè)“彈簧”系統(tǒng)中,如果交通工具行駛太快時(shí),它能延遲落后一定距離。因此,我們將增加 camera 能落后的最小和最大值。 8 2 應(yīng)該是可以的。

我們?cè)谝粋€(gè) hash map 中設(shè)置這些參數(shù)。

private void buildChaseCamera() {

Vector3f targetOffset = new Vector3f();

targetOffset. y =

((BoundingBox) player .getWorldBound()). yExtent *1.5f;

HashMap<String, Object> props = new HashMap<String, Object>();

props.put(ThirdPersonMouseLook. PROP_MAXROLLOUT , "6" );

props.put(ThirdPersonMouseLook. PROP_MINROLLOUT , "3" );

props.put(

ThirdPersonMouseLook. PROP_MAXASCENT ,

"" +45*FastMath. DEG_TO_RAD

);

props.put(

ChaseCamera. PROP_INITIALSPHERECOORDS ,

new Vector3f(5,0,30*FastMath. DEG_TO_RAD )

);

props.put(ChaseCamera. PROP_TARGETOFFSET , targetOffset);

chaser = new ChaseCamera( cam , player , props);

chaser .setMaxDistance(8);

chaser .setMinDistance(2);

}

我們現(xiàn)在已經(jīng)設(shè)置好了自己的 ChaseCamera ,但它在調(diào)用 update 方法之前不會(huì)產(chǎn)生任何作用。因此在 update 中加入:

chaser . update (interpolation);

現(xiàn)在,當(dāng)應(yīng)用程序運(yùn)行時(shí),你能看到 camera 在它初始化的位置并光滑地把鏡頭拉近直到最大的 6 個(gè)單元。你能接著移動(dòng)鼠標(biāo)去圍繞 box 旋轉(zhuǎn) camera ,也能滾動(dòng)鼠標(biāo)滑輪去將 camera 拉近或推遠(yuǎn)一點(diǎn)。那就是所激動(dòng)的,但沒(méi)有什么東西可以追蹤,因?yàn)? box 只是停在那里。讓我們糾正那個(gè)。

這里補(bǔ)充一點(diǎn)是作者漏掉的,我們還需要在 game update 方面里面加入下面代碼以保證 camera 的位置一直在 terrain 上面:

// 我們不想 chase camera 走到世界下面,因此讓它一直在水平面上 2 個(gè)單元。

if ( cam .getLocation(). y < ( tb .getHeight( cam .getLocation())+2)) {

cam .getLocation(). y = tb .getHeight( cam .getLocation()) + 2;

cam .update();

}

5.6 、我們自定義的輸入處理

我們將創(chuàng)建自己的輸入處理器( InputHandler )從而允許我們駕駛交通工具。這個(gè) handler 的目標(biāo)是允許我們行駛向前、向后和轉(zhuǎn)向。我想這些控制的鍵被設(shè)置為: WASD 。幸運(yùn)的是,為了做到這個(gè),我們將能使用在 jME 中構(gòu)建的 action 。名字是, KeyNodeForwardAction KeyNodeBackwardAction KeyNodeRotateRightAction KeyNodeRotateLeftAction 。這些 action 處理一個(gè) node 的旋轉(zhuǎn)和移動(dòng),這些都基于速度和傳入的時(shí)間。

InputAction 很直觀。你簡(jiǎn)單將觸發(fā)器( trigger )賦給 action ,并把鍵( key )賦給這些觸發(fā)器。然后在每次 update 期間它將檢查是否有任何鍵被按下,如果它們是 trigger 賦予的按鍵,那么則讓 trigger 去調(diào)用相應(yīng)的 action

創(chuàng)建一個(gè)新的叫做 FlagRushInputHandler 的類,它繼承自 InputHandler 。這個(gè)類將只有 2 個(gè)方法, setKeyBindings setActions setKeyBindings 將創(chuàng)建 KeyBindingManager 并賦予 W,A,S,D 到相應(yīng)的 trigger 名字,而 setActions 將為每個(gè) trigger 創(chuàng)建 InputAction

FlagRushInputHandler.java

import com.jme.input.InputHandler;

import com.jme.input.KeyBindingManager;

import com.jme.input.KeyInput;

import com.jme.input.action.KeyNodeBackwardAction;

import com.jme.input.action.KeyNodeForwardAction;

import com.jme.input.action.KeyNodeRotateLeftAction;

import com.jme.scene.Spatial;

/**

* 游戲的 InputHnadler 。這控制了一個(gè)給出的 Spatial

* 允許我們?nèi)グ阉耙啤⑼笠坪妥笥倚D(zhuǎn)。

* @author John

*

*/

public class FlagRushInputHandler extends InputHandler {

/**

* 提供用于控制的 node api 將處理 input 的創(chuàng)建

* @param node 我們想移動(dòng)的那個(gè) node

* @param api library 將處理 input 的創(chuàng)建

*/

public FlagRushInputHandler(Spatial node, String api){

setKeyBindings(api);

setActions(node);

}

/**

* action 類賦給 trigger 。這些 action 處理結(jié)點(diǎn)前移、后移和旋轉(zhuǎn)

* @param node 用于控制的結(jié)點(diǎn)

*/

private void setActions(Spatial node) {

KeyNodeForwardAction forward =

new KeyNodeForwardAction(node,30f);

addAction(forward, "forward" , true );

KeyNodeBackwardAction backward =

new KeyNodeBackwardAction(node,15f);

addAction(backward, "backward" , true );

KeyNodeRotateLeftAction rotateLeft =

new KeyNodeRotateLeftAction(node,5f);

rotateLeft.setLockAxis(

node.getLocalRotation().getRotationColumn(1)

);

addAction(rotateLeft, "turnLeft" , true );

KeyNodeRotateRightAction rotateRight =

new KeyNodeRotateRightAction(node,5f);

rotateRight.setLockAxis(

node.getLocalRotation().getRotationColumn(1)

);

addAction(rotateRight, "turnRight" , true );

}

/**

* 創(chuàng)建 keyboard 對(duì)象,當(dāng)鍵被按下時(shí)允許我們獲取鍵盤(pán)的值。

* 它接著設(shè)置 action 作為觸發(fā)器的基礎(chǔ),如果確認(rèn)了鍵被按下( WASD

* @param api

*/

private void setKeyBindings(String api) {

KeyBindingManager keyboard =

KeyBindingManager. getKeyBindingManager ();

keyboard.set( "forward" , KeyInput. KEY_W );

keyboard.set( "backward" , KeyInput. KEY_S );

keyboard.set( "turnLeft" , KeyInput. KEY_A );

keyboard.set( "turnRight" , KeyInput. KEY_D );

}

}

當(dāng)這個(gè)類真的寫(xiě)完后,我們?cè)谧约旱挠螒蛑惺褂谩?chuàng)建一個(gè) buildInput 方法,由 initGame 方法調(diào)用。這個(gè)方法將只有一行:

input = new FlagRushInputHandler(

player ,

settings . getRenderer ()

);

正如你所猜的,這里 input 也是類變量。為什么要在類里面呢?因?yàn)槟銓⒃谟螒虻? update 期間調(diào)用它的 update

就是那樣!不管相信與否,我們現(xiàn)在具有做游戲的條件。 Box 能被駕駛。現(xiàn)在試試看。注意 ChaseCamera 將會(huì)落后于 box 一點(diǎn)然后嘗試趕上,帶來(lái)更平滑和真實(shí)的感覺(jué)。

接下來(lái),我們將改進(jìn) box 的移動(dòng)以便它能加速和減速。我們也將讓它和環(huán)境交互得更好。繼續(xù)收看!

jMonkeyEngine譯文 FlagRush5(2)——跟隨的攝像機(jī)(ChaseCamera)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論