日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

jMonkeyEngine譯文 FlagRush2——從你的應用程

系統 1938 0

注:本系列教程全部翻譯完之后可能會以 PDF 的形式發布。

如果有什么錯誤可以留言或 EMAIL kakashi9bi@gmail.com 給我。

jME 版本 jME_2.0.1_Stable

開發工具: MyEclipse8.5

操作系統: Window7/Vista

這個向導中,我們將為 Flag Rush 構建基礎。我們將通過自己實現繼承 BaseGame 。我們將使用 BaseGame 做為父類,但之后可能改為其它的游戲類型,因為 BaseGame 簡單地盡可能快地進行 update render 。我們或許不必或不想使用這種類型的循環。然而,現在 BaseGame 是一個循環無關的類。在以后,改變 BaseGame 將不是重點,因為只是傳入 update render 方法的值不同而已。

我們將開始創建一個繼承自 BaseGame 的新類。你會注意到有 6 個需要實現的方法: update render initSystem initGame reinit 。現在,只需要為它們創建一個存根方法,我們將在后面將自己的邏輯填充進去。

import com.jme.app.BaseGame;

public class Lesson2 extends BaseGame{

public static void main(String[] args) {

}

protected void cleanup() {

}

protected void initGame() {

}

protected void initSystem() {

}

protected void reinit() {

}

protected void render( float arg0) {

}

protected void update( float arg0) {

}

}

2.1 Main

那么,讓我們從最初開始。我們在這里將再次創建 main 方法。它很像前一個向導的 main 方法,除了一個關鍵的地方不同。這次我們將顯示 FlagRush 的迷人的新 logo AbstractGame 定義了一對 setConfigShowMode 方法,其中的一個接受一個 URL 類用于加載 Image 。因此,我們將加載 FlagRush.png (迷人的 logo )并把它傳給這個方法。現在,當 PropertiesDialog 被顯示時,它將顯示新的 Logo

public static void main(String[] args) {

Lesson2 app = new Lesson2();

java.net.URL url =

app.getClass().getClassLoader()

.getResource( "jmetest/data/images/FlagRush.png" );

app.setConfigShowMode(ConfigShowMode. AlwaysShow ,url);

app.start();

}

現在,當 PropertiesDialog 出現時,它將像下面這個一樣(你應該在項目中新建一個 package —— jmetest.data.images ,然后里面有一張叫 FlagRush.png 的圖片):

jMonkeyEngine譯文 FlagRush2——從你的應用程序中移除SimpleGame

2.2 InitSystem

現在,你能運行你的應用程序,但它僅僅是顯示 PropertiesDialog ,除此之外不會做更多的工作。我們下一步將實現 initSystem 方法。這個方法在進入主循環之前由 BaseGame 調用。這正是我們設置 window display 的地方。我們將保存 width height depth frequency fullscreen 標志。我們將在后面使用這些值,假如用戶想改變分辨率的時候。所以,首先,讓我們創建變量去保存這些值:

public class Lesson2 extends BaseGame{

private int width , height ;

private int freq , depth ;

private boolean fullscreen ;

……………………….

我們也需要在我們的程序中保存 Camera ,所以我們也應該為那創建一個變量。

// 我們的 camera 對象,用于觀看 scene

private Camera cam ;

最后將初始化的一項是 Timer Timer 將允許我們獲取我們的幀率。所以,同樣的,這將是一個實例變量。

protected Timer timer ;

現在我們已經準備好我們的實例變量,并且我們將在 initSystem 中初始化它們。

protected void initSystem() {

// 保存屬性信息

width = settings .getWidth();

height = settings .getHeight();

depth = settings .getDepth();

freq = settings .getFrequency();

fullscreen = settings .isFullscreen();

try {

display = DisplaySystem. getDisplaySystem (

settings .getRenderer()

);

display .createWindow(

width , height , depth , freq , fullscreen

);

cam = display .getRenderer().createCamera( width , height );

} catch (JmeException e){

e.printStackTrace();

System. exit (-1);

}

// 設置背景為黑色

display .getRenderer().setBackgroundColor(ColorRGBA. black );

// 初始化攝像機

cam .setFrustumPerspective(

45.0f,

( float ) width /( float ) height ,

1f,

1000f

);

Vector3f loc = new Vector3f(0.0f,0.0f,25.0f);

Vector3f left = new Vector3f(-1.0f,0.0f,0.0f);

Vector3f up = new Vector3f(0.0f,1.0f,0.0f);

Vector3f dir = new Vector3f(0.0f,0.0f,-1.0f);

// 將攝像機移到正確位置和方向

cam .setFrame(loc, left, up, dir);

// 我們改變自己的攝像機位置和視錐的標志

cam .update();

// 獲取一個高分辨率用于 FPS 更新

timer = Timer. getTimer ();

display .getRenderer().setCamera( cam );

KeyBindingManager. getKeyBindingManager ().set(

"exit" ,

KeyInput. KEY_ESCAPE

);

}

這是一個長的方法,所以,我們將一點一點討論它。

// 保存屬性信息

width = settings .getWidth();

height = settings .getHeight();

depth = settings .getDepth();

freq = settings .getFrequency();

fullscreen = settings .isFullscreen();

首先,我們保存從 properties 對象( properties 是由 AbstractGame 創建的)獲取的值。通過保存這些值,當用戶以后從系統菜單改變屏幕設置的時候,我們可以很容易地修改它們中的一個或全部值。

try {

display = DisplaySystem. getDisplaySystem (

settings .getRenderer()

);

display .createWindow(

width , height , depth , freq , fullscreen

);

cam = display .getRenderer().createCamera( width , height );

} catch (JmeException e){

e.printStackTrace();

System. exit (-1);

}

下一步,我們獲取新的 DisplaySystem ,并通過先前獲得的屏幕參數創建一個本地窗口。我們接著使用 DisplaySystem 去創建一個 Camera 對象。你將注意到那用一個 try/catch 塊包圍。如果我們嘗試創建一個系統沒能力繪制的窗口,異常將在這里出現。目前,它只會退出,但之后,我們將讓這個顯示得更友好,并通知用戶。

// 設置背景為黑色

display .getRenderer().setBackgroundColor(ColorRGBA. black );

我們接著設置了窗口的背景顏色。當沒有其它數據被渲染的時候,這是顯示的默認顏色。我選擇黑色,這是因為它和我們后面將使用的任何文本形成鮮明的對比。不管怎樣,這都不是重點,因為當一切正常工作時,屏幕上通常覆蓋其它的數據。

// 初始化攝像機

cam .setFrustumPerspective(

45.0f,

( float ) width /( float ) height ,

1f,

1000f

);

Vector3f loc = new Vector3f(0.0f,0.0f,25.0f);

Vector3f left = new Vector3f(-1.0f,0.0f,0.0f);

Vector3f up = new Vector3f(0.0f,1.0f,0.0f);

Vector3f dir = new Vector3f(0.0f,0.0f,-1.0f);

// 將攝像機移到正確位置和方向

cam .setFrame(loc, left, up, dir);

// 我們改變自己的攝像機位置和視錐的標志

cam .update();

display .getRenderer().setCamera( cam );

下一步,我設置了 camera 。我想要一個標準的 camera ,正常情況下是右手坐標系統(向上是正 Y ,向右是正 X 和向屏幕里面是 -Z )。我同時設置了透視圖為 45 度視角。這個是大多數游戲里面的公認標準,而它將應用于 Flag Rush 。在 camera 數據設置之后,我們調用 update ,這將設置所有的 OpenGL 組件,例如視點(下文以 ViewPort 代替)和 Frustum

// 獲取一個高分辨率用于 FPS 更新

timer = Timer. getTimer ();

這里只是初始化 Timer ,從本地 Timer 獲取(例如 LWJGLTimer )。

KeyBindingManager. getKeyBindingManager ().set(

"exit" ,

KeyInput. KEY_ESCAPE

);

最后,我們創建一個新的 InputSystem ,將它綁定到我們的 KeyBindingManager 并設置一個輸入行為( Input action )。在這個框架中我們只關心一個按鍵—— Escape 。在這個例子中,我們設置 action exit ”給 Escape 鍵。 KeyBindingManager 是一個單例類,它使用單一的 get 調用,關注了所有 InputSystem 組件的初始化。

現在,如果你運行系統你將真正獲得一個屏幕顯示。它將充滿黑色(我們設置的背景顏色),沒有任何東西。

2.3 InitGame

現在,我們擁有一個窗口和 OpenGL 上下文環境,我們將加載我們的游戲數據(如上面前個向導的 Sphere

protected void initGame() {

scene = new Node( "Scene Graph Node" );

// 創建我們的球體

Sphere s = new Sphere( "sphere" , 30, 30, 25);

s.setLocalTranslation( new Vector3f(0, 0, -40));

s.setModelBound( new BoundingBox());

s.updateModelBound();

ts = display .getRenderer().createTextureState();

ts . setEnabled ( true );

ts .setTexture(

TextureManager. loadTexture (

Lesson2. class .getClassLoader()

.getResource( "res/logo.png" ),

Texture.MinificationFilter. Trilinear ,

Texture.MagnificationFilter. Bilinear

)

);

s.setRenderState( ts );

scene .attachChild(s);

// 更新 scene 用于渲染

scene .updateGeometricState(0.0f, true );

scene .updateRenderState();

}

我們現在保存我們自己的 Scene Graph 結點,我已經選擇把它命名為 scene ,但實際上怎樣命名都是沒關系。因為這是 scene 的根節點,它也是一個實例變量而它和其他實例變量一樣被聲明:

private Node scene ;

這個 Node 接著被實例化。接著我們創建了一個 Sphere TextureState (就像上一個的向導)。 Sphere 接著被 attach scene 。這個看起來將和我們上一個向導所做的很相似。然而,現在,我們還調用 updateGeometricState updateRenderState 。這些方法為 SceneGraph updates 調用。 updateGeometricState 是必須的,不管場景圖( Scene Graph )結構在何時改變(設置一個新的,改變另一個的參數,等等),在我們的例子中,我增加了一個 sphere 到到 scene 。不管 RenderState 在什么時候以何種方式發生改變, updateRenderState 都應該被調用(比如創建一個新的 RenderState 、改變它的參數等等),在我們的例子中,我們增加了 TextureState

我們現在擁有游戲中的數據,但它仍然沒被渲染到屏幕。

2.4 Render update

既然我們已經初始化了窗口并加載了數據,如果能看到它將更好。那就是 render 方法的到來。 BaseGame 調用 update 并根據它的能力盡可能快地 render render 的調用需要處理所有繪畫調用,而 update 應該處理任何的游戲邏輯。在我們的例子中,我們想要 update 做一點游戲邏輯,退出游戲。為了簡單退出游戲,我們將設置 finished 布爾值為 true

/*

* update 期間,我們只需尋找 Escape 按鈕

* 并更新 timer 去獲取幀率

*/

protected void update( float interpolation) {

// 更新 timer 去獲取幀率

timer .update();

interpolation = timer .getTimePerFrame();

// Escape 被按下時,我們退出游戲

if (KeyBindingManager. getKeyBindingManager ()

.isValidCommand( "exit" )

){

finished = true ;

}

}

你也將注意到 update 獲取最新的 timer 讀數并為此設置插值( interpolation )。 BaseGame 通常在調用 update 時發送 -1 ,所以我們將繼續并重用這個值去保存每幀真正的時間。

接下來,我們將渲染。

/*

* 繪制場景圖

*/

protected void render( float interpolation) {

// 清除屏幕

display .getRenderer().clearBuffers();

display .getRenderer().draw( scene );

}

這個直截了當。我們使用 clearBuffers 清除屏幕。我們接著畫了 scene ,這是包含我們 Sphere 的樹。

你現在能運行程序并看到:

正是和前一課的顯示一樣,只不過沒了燈光。

jMonkeyEngine譯文 FlagRush2——從你的應用程序中移除SimpleGame

2.5 reinit cleanup

最后我們將覆蓋的 2 個方法是 reinit cleanup 。當窗口需要重建時, Reinit 應該被調用,就像參數發生了變化。而在關閉的時候調用 cleanup

/*

* 如果分辨率改變將被調用

*/

protected void reinit() {

display .recreateWindow( width , height , depth , freq , fullscreen );

}

我們在這里所做的就只是傳遞新的值給 DisplaySystem 處理。僅此而已。

/*

* 清除 texture

*/

protected void cleanup() {

ts .deleteAll();

}

這簡單確保了 texture 被刪除。這不是特別必須的,因為 OpenGL 在它退出時將處理這個。但“寧可事先謹慎有余,切莫事后追悔莫及”。

2.6 、總結

很好,就是那樣。我們現在有一個很基本、可工作的框架。通過創建我們自己的應用程序類型,我們能完全保持對我們場景中一切的控制。隨著向導的繼續,我們將很明確地增強并構建基于這個類的程序。

2.7 、源碼

import com.jme.app.BaseGame;

import com.jme.bounding.BoundingBox;

import com.jme.image.Texture;

import com.jme.input.KeyBindingManager;

import com.jme.input.KeyInput;

import com.jme.math.Vector3f;

import com.jme.renderer.Camera;

import com.jme.renderer.ColorRGBA;

import com.jme.scene.Node;

import com.jme.scene.shape.Sphere;

import com.jme.scene.state.TextureState;

import com.jme.system.DisplaySystem;

import com.jme.system.JmeException;

import com.jme.util.TextureManager;

import com.jme.util.Timer;

public class Lesson2 extends BaseGame{

private int width , height ;

private int freq , depth ;

private boolean fullscreen ;

// 我們的 camera 對象,用于觀看 scene

private Camera cam ;

protected Timer timer ;

private Node scene ;

private TextureState ts ;

public static void main(String[] args) {

Lesson2 app = new Lesson2();

java.net.URL url = app.getClass().getClassLoader().getResource( "res/logo.png" );

app. setConfigShowMode (ConfigShowMode. AlwaysShow ,url);

app.start();

}

/*

* 清除 texture

*/

protected void cleanup() {

ts .deleteAll();

}

protected void initGame() {

scene = new Node( "Scene Graph Node" );

// 創建我們的球體

Sphere s = new Sphere( "sphere" , 30, 30, 25);

s.setLocalTranslation( new Vector3f(0, 0, -40));

s.setModelBound( new BoundingBox());

s.updateModelBound();

ts = display .getRenderer().createTextureState();

ts .setEnabled( true );

ts .setTexture(

TextureManager. loadTexture (

Lesson2. class .getClassLoader().getResource( "res/logo.png" ),

Texture.MinificationFilter. Trilinear ,

Texture.MagnificationFilter. Bilinear

)

);

s.setRenderState( ts );

scene .attachChild(s);

// 更新 scene 用于渲染

scene .updateGeometricState(0.0f, true );

scene .updateRenderState();

}

protected void initSystem() {

// 保存屬性信息

width = settings .getWidth();

height = settings .getHeight();

depth = settings .getDepth();

freq = settings .getFrequency();

fullscreen = settings .isFullscreen();

try {

display = DisplaySystem. getDisplaySystem (

settings .getRenderer()

);

display .createWindow(

width , height , depth , freq , fullscreen

);

cam = display .getRenderer().createCamera( width , height );

} catch (JmeException e){

e.printStackTrace();

System. exit (-1);

}

// 設置背景為黑色

display .getRenderer().setBackgroundColor(ColorRGBA. black );

// 初始化攝像機

cam .setFrustumPerspective(

45.0f,

( float ) width /( float ) height ,

1f,

1000f

);

Vector3f loc = new Vector3f(0.0f,0.0f,25.0f);

Vector3f left = new Vector3f(-1.0f,0.0f,0.0f);

Vector3f up = new Vector3f(0.0f,1.0f,0.0f);

Vector3f dir = new Vector3f(0.0f,0.0f,-1.0f);

// 將攝像機移到正確位置和方向

cam .setFrame(loc, left, up, dir);

// 我們改變自己的攝像機位置和視錐的標志

cam .update();

// 獲取一個高分辨率用于 FPS 更新

timer = Timer. getTimer ();

display .getRenderer().setCamera( cam );

KeyBindingManager. getKeyBindingManager ().set(

"exit" ,

KeyInput. KEY_ESCAPE

);

}

/*

* 如果分辨率改變將被調用

*/

protected void reinit() {

display .recreateWindow( width , height , depth , freq , fullscreen );

}

/*

* 繪制場景圖

*/

protected void render( float interpolation) {

// 清除屏幕

display .getRenderer().clearBuffers();

display .getRenderer().draw( scene );

}

/*

* update 期間,我們只需尋找 Escape 按鈕

* 并更新 timer 去獲取幀率

*/

protected void update( float interpolation) {

// 更新 timer 去獲取幀率

timer .update();

interpolation = timer .getTimePerFrame();

// Escape 被按下時,我們退出游戲

if (KeyBindingManager. getKeyBindingManager ()

.isValidCommand( "exit" )

){

finished = true ;

}

}

}

jMonkeyEngine譯文 FlagRush2——從你的應用程序中移除SimpleGame


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 西昌市| 汉沽区| 曲周县| 湾仔区| 宜黄县| 房产| 淮南市| 莱西市| 屏南县| 闽清县| 福鼎市| 望江县| 五峰| 马山县| 邹平县| 洪江市| 晋州市| 鹿邑县| 科尔| 旌德县| 防城港市| 长武县| 昌图县| 姜堰市| 恩平市| 那曲县| 商南县| 体育| 固阳县| 温州市| 永定县| 襄垣县| 邯郸县| 永胜县| 华池县| 正安县| 柘城县| 盘山县| 宝兴县| 宁国市| 华池县|