1. 程式人生 > >Android及JavaSE遊戲引擎LGame-0 2 9釋出(新增物理引擎支援)

Android及JavaSE遊戲引擎LGame-0 2 9釋出(新增物理引擎支援)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

 

版本資訊:

 

釋出時間  版本號 
2010-12-11 0.2.9
2010-09-15 0.2.8
2010-08-19 0.2.7
2010-07-31 0.2.6
2009-12-29 0.2.5
2009-10-10 0.2.0
2009-09-13 0.1.5
2009-08-11 0.1.0

 

LGame-0.2.9下載地址(新增物理引擎,修正舊版BUG,內含jar、文件、原始碼及示例):

 

http://loon-simple.googlecode.com/files/LGame-0.2.9.7z

 

2010-12-11 LGame-0.2.9-Update:

1、為LGame新增Box2D物理引擎支援,並提供有針對物理遊戲的PhysicsScreen,此類為World封裝,預設世界大小即螢幕大小(可調),並能夠利用bindTo函式將任意圖片(自成物理邊界)、指定形狀或者精靈繫結到PhysicsObject當中(Body封裝,可選引數與Body及BodyDef高度一致,同時為精靈實現),也提供有一系列額外的Box2D封裝(此部分功能位於Android版的LGame-Android-Physics-0.2.9.jar及libjbox.so,JavaSE版LGame-JavaSE-Physics-0.2.9.jar及libjbox.dll中,皆非LGame執行必須,核心jar對此無依賴,選用)。即使不使用物理引擎,自該版開始LGame也可以直接將任意圖片轉化為Polygon。

2、為LGame新增重力感應支援,在遊戲初始化前呼叫setupGravity即可讓重力感應監聽成立,在任意Screen中過載onDirection函式即可獲得手機當前方向及具體的x,y,z數值。

3、為LGame新增了Triangle以及Polygon2D這兩個形狀類,具體作用在物理引擎部分可見。

4、修正原有LGameAndroid2DView、Screen、ThreadScreen、LGraphicsAndroid2D、Sprite、SpriteImage、Sprites等類中部分運算方法,並進行了相應擴充套件。

5、修正所有得到使用者反饋的BUG,包括長按鍵盤會造成FPS減速之類的細節問題。

6、暫時取消了JavaSE版的lua支援及Android版的http封裝,近期我會將相關部分作為獨立專案另行釋出(包括較早前在Android版本取消的ioc封裝、db封裝等)。

 

_______________________________________

 

下面所提供的,是以LGame開發物理遊戲的簡單示例:

 

[java] view plain copy print ?
  1. package org.loon.game.test.physics;  
  2. import org.loon.framework.android.game.core.graphics.device.LGraphics;  
  3. import org.loon.framework.android.game.core.timer.LTimerContext;  
  4. import org.loon.framework.android.game.physics.PhysicsObject;  
  5. import org.loon.framework.android.game.physics.PhysicsScreen;  
  6. import com.badlogic.gdx.math.Vector2;  
  7. import com.badlogic.gdx.physics.box2d.Body;  
  8. import com.badlogic.gdx.physics.box2d.BodyDef;  
  9. import com.badlogic.gdx.physics.box2d.FixtureDef;  
  10. import com.badlogic.gdx.physics.box2d.PolygonShape;  
  11. import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;  
  12. import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;  
  13. import android.view.MotionEvent;  
  14. public class Test1 extends PhysicsScreen {  
  15.     /** 
  16.      *  
  17.      */  
  18.     private static final long serialVersionUID = 1L;  
  19.     public Test1() {  
  20.         // x軸重力為0,y軸重力為0.2,重力自然衰弱(不迴圈)  
  21.         super(00.2f, false);  
  22.     }  
  23.     /** 
  24.      * 建立物理線橋 
  25.      *  
  26.      * @param imageName 
  27.      */  
  28.     private void createBridge(String fileName) {  
  29.         FixtureDef fixDef = new FixtureDef();  
  30.         PolygonShape poly = new PolygonShape();  
  31.         poly.setAsBox(6f, 2f);  
  32.         fixDef.density = 6f;  
  33.         fixDef.friction = 0.2f;  
  34.         fixDef.shape = poly;  
  35.         // 構建關節以聯動橋板  
  36.         RevoluteJointDef rjd = new RevoluteJointDef();  
  37.         int numPlanks = 22;  
  38.         Body prevBody = null;  
  39.         Body firstBody = null;  
  40.         for (int i = 0; i < numPlanks; i++) {  
  41.             BodyDef bd = new BodyDef();  
  42.             if (i == 0 || i == numPlanks - 1) {  
  43.                 bd.type = BodyType.StaticBody;  
  44.             }  
  45.             bd.position.set(3f + (15f * i), 320);  
  46.             Body body = world.createBody(bd);  
  47.             body.createFixture(fixDef);  
  48.             // 繫結指定路徑下圖片與Body  
  49.             PhysicsObject o = bindTo(fileName, body);  
  50.             // 不允許圖片旋轉  
  51.             o.lockRotate = true;  
  52.             o.make();  
  53.             if (prevBody == null) {  
  54.                 firstBody = body;  
  55.             } else {  
  56.                 Vector2 anchor = new Vector2(2.4f + (15f * i), 320);  
  57.                 rjd.initialize(prevBody, body, anchor);  
  58.                 world.createJoint(rjd);  
  59.             }  
  60.             prevBody = body;  
  61.         }  
  62.         Vector2 anchor = new Vector2(2.4f + (15f * numPlanks), 320);  
  63.         // 初始化關節  
  64.         rjd.initialize(prevBody, firstBody, anchor);  
  65.         world.createJoint(rjd);  
  66.     }  
  67.     public void onLoad() {  
  68.         // 初始化完畢後建立物理橋  
  69.         createBridge("res/bridge.png");  
  70.         // 匯入一張圖片為物理精靈(LGame可自動獲得精靈圖片的物理邊界)  
  71.         PhysicsObject o = bindTo("res/a4.png", BodyType.DynamicBody, 500);  
  72.         o.density = 2.0f;  
  73.         o.friction = 0.2f;  
  74.         o.make();  
  75.     }  
  76.     public void paint(LGraphics g) {  
  77.     }  
  78.     public void update(LTimerContext t) {  
  79.     }  
  80.     public void onDown(MotionEvent e) {  
  81.         // 獲得指定位置,且標記為"Ball"的物理精靈  
  82.         PhysicsObject ball = find(getTouchX(), getTouchY(), "Ball");  
  83.         if (ball != null) {  
  84.             // 存在則刪除  
  85.             removeObject(ball);  
  86.         } else {  
  87.             // 新增一個圓形的物理精靈,初始位置在觸控式螢幕點選區域,大小為64x64  
  88.             ball = bindTo(Circle, BodyType.DynamicBody, getTouchX(),  
  89.                     getTouchY(), 6464);  
  90.             // 標記為Ball(便於查詢)  
  91.             ball.setTag("Ball");  
  92.             // 設定圖片(請注意,當為固定形狀注入圖片時,圖片大小必須為設定大小,  
  93.             // 否則會發生圖片位置與物理位置不匹配的情況)  
  94.             ball.setDrawImage("res/ball.png");  
  95.             ball.setBitmapFilter(true);  
  96.             ball.density = 2.0f;  
  97.             ball.friction = 0.2f;  
  98.             ball.make();  
  99.         }  
  100.     }  
  101.     public void onMove(MotionEvent e) {  
  102.     }  
  103.     public void onUp(MotionEvent e) {  
  104.     }  
  105. }  
package org.loon.game.test.physics;import org.loon.framework.android.game.core.graphics.device.LGraphics;import org.loon.framework.android.game.core.timer.LTimerContext;import org.loon.framework.android.game.physics.PhysicsObject;import org.loon.framework.android.game.physics.PhysicsScreen;import com.badlogic.gdx.math.Vector2;import com.badlogic.gdx.physics.box2d.Body;import com.badlogic.gdx.physics.box2d.BodyDef;import com.badlogic.gdx.physics.box2d.FixtureDef;import com.badlogic.gdx.physics.box2d.PolygonShape;import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;import android.view.MotionEvent;public class Test1 extends PhysicsScreen { /**  *   */ private static final long serialVersionUID = 1L; public Test1() {  // x軸重力為0,y軸重力為0.2,重力自然衰弱(不迴圈)  super(0, 0.2f, false); } /**  * 建立物理線橋  *   * @param imageName  */ private void createBridge(String fileName) {  FixtureDef fixDef = new FixtureDef();  PolygonShape poly = new PolygonShape();  poly.setAsBox(6f, 2f);  fixDef.density = 6f;  fixDef.friction = 0.2f;  fixDef.shape = poly;  // 構建關節以聯動橋板  RevoluteJointDef rjd = new RevoluteJointDef();  int numPlanks = 22;  Body prevBody = null;  Body firstBody = null;  for (int i = 0; i < numPlanks; i++) {   BodyDef bd = new BodyDef();   if (i == 0 || i == numPlanks - 1) {    bd.type = BodyType.StaticBody;   }   bd.position.set(3f + (15f * i), 320);   Body body = world.createBody(bd);   body.createFixture(fixDef);   // 繫結指定路徑下圖片與Body   PhysicsObject o = bindTo(fileName, body);   // 不允許圖片旋轉   o.lockRotate = true;   o.make();   if (prevBody == null) {    firstBody = body;   } else {    Vector2 anchor = new Vector2(2.4f + (15f * i), 320);    rjd.initialize(prevBody, body, anchor);    world.createJoint(rjd);   }   prevBody = body;  }  Vector2 anchor = new Vector2(2.4f + (15f * numPlanks), 320);  // 初始化關節  rjd.initialize(prevBody, firstBody, anchor);  world.createJoint(rjd); } public void onLoad() {  // 初始化完畢後建立物理橋  createBridge("res/bridge.png");  // 匯入一張圖片為物理精靈(LGame可自動獲得精靈圖片的物理邊界)  PhysicsObject o = bindTo("res/a4.png", BodyType.DynamicBody, 50, 0);  o.density = 2.0f;  o.friction = 0.2f;  o.make(); } public void paint(LGraphics g) { } public void update(LTimerContext t) { } public void onDown(MotionEvent e) {  // 獲得指定位置,且標記為"Ball"的物理精靈  PhysicsObject ball = find(getTouchX(), getTouchY(), "Ball");  if (ball != null) {   // 存在則刪除   removeObject(ball);  } else {   // 新增一個圓形的物理精靈,初始位置在觸控式螢幕點選區域,大小為64x64   ball = bindTo(Circle, BodyType.DynamicBody, getTouchX(),     getTouchY(), 64, 64);   // 標記為Ball(便於查詢)   ball.setTag("Ball");   // 設定圖片(請注意,當為固定形狀注入圖片時,圖片大小必須為設定大小,   // 否則會發生圖片位置與物理位置不匹配的情況)   ball.setDrawImage("res/ball.png");   ball.setBitmapFilter(true);   ball.density = 2.0f;   ball.friction = 0.2f;   ball.make();  } } public void onMove(MotionEvent e) { } public void onUp(MotionEvent e) { }}

 

 

在上述演示程式碼裡,小弟主要使用到PhysicsScreen以及PhysicsObject這兩個新增類(其它部分歸Box2D範疇~)。

 

在LGame-0.2.9中,PhysicsScreen繼承自Screen,其本身可以認為是一個自動重新整理畫面結果的繪圖器,內部封裝有針對Box2D的World,世界大小預設即螢幕大小(可調),並提供了繫結任何事物到PhysicsObject的能力。其中涉及Box2D的部分(雖然libgdx的JNI封裝並不完整,但大體使用方式是一致的),請自行參閱Box2D文件,暫不贅述。另外,在除錯物理遊戲時,個人建議使用真機或者所執行環境硬體效能足夠高的虛擬機器。

 

而PhysicsObject繼承自ISprite,它本身也是一個精靈,但地位卻比較特殊,它的主要作用在於同PhysicsScreen聯動,其提供的大多數構造方法不能在PhysicsScreen以外的Screen中使用。PhysicsObject另一個比較特殊的地方在於,它能夠直接將影象轉化為形狀(我詛咒Box2D萬惡的凸多邊形限制,這個轉化過程是單獨寫的,沒有使用jbox2d中的BodyUtil,因為測高點的話有的圖形會轉換失敗)並參與碰撞,而無需手動設定。此外,BodyType與Body提供的引數皆可在PhysicsObject當中進行設定,但只在呼叫make函式後才會生效。

 

執行效果如下圖所示:

 

00

我們可以看到,即使使用了JNI封裝,Box2D跑在虛擬機器中的速度還是較慢,但是這僅僅是在虛擬環境中,如果釋出到真機裡,我相信大家就會看到差異了。順便發一張JavaSE版同程式碼的執行結果。

 

00

 

PS:當然,由於LGame目前以標準Android2D方式構建,其圖形渲染效能確實會受到一定的制約,即便構建方式完全一致,LGame-JavaSE版的物理引擎運算效率也要2、3倍於Android真機之上,而在Android虛擬機器執行時自然更低(基本上動態的物理精靈越多(上圖的線橋也是動態精靈,只是在模擬器上沒敢開線橋的圖片旋轉),執行速度就會越低,反之在全是靜態精靈的前提下,顯示速度會無限接近60FPS(預設最大值))。

 

LGame-0.2.9下載地址(新增物理引擎,修正舊版BUG,內含jar、文件、原始碼及示例):

 

http://loon-simple.googlecode.com/files/LGame-0.2.9.7z

 


——————————————————————————————

 

以下為較早前釋出過的一些程式示例畫面(請下載較早前LGame釋出版本獲得,此外JavaSE版與Android版程式碼可以基本通用):

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

使用模擬按鍵,可以輕鬆製作格鬥類或需要複雜操作的遊戲。

 

00

 

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述