2014-05-15 48 views
1

我正在和一些朋友一起玩遊戲,我們有一個大的水平世界和一個只顯示1/3的OrthographicCamera。當攝像機的水平位置發生變化時,此攝像機會移動,因此攝像機只能向左和向右移動。在libGDX遊戲中實現視差效果

遊戲中顯示的一些物體靠近玩家視角,但其他物體距離較遠(例如島嶼)。考慮到這一點,我們無法爲元素設置固定位置並僅移動相機。考慮到元素的距離,我們需要實現視差效果。

下面是一個簡單的圖像來更好地解釋它: enter image description here 左側的視口顯示了遊戲的3個對象。綠色的在球員附近,紅色的橢圓很遠,黃色的在中間。在右側的視口中,攝像頭已移到右側,所有對象都消失在左側。問題在於綠色矩形的相對運動大於黃色的運動。同樣,黃色物體的移動大於紅色物體的移動。

我創建了所有我的資產,考慮到他們有多遠,但現在,我怎樣才能使用libGDX來模擬這個觀點?有沒有任何課程可以做到這一點?如果我必須在每次迭代中設置元素的位置,我如何計算正確的位置?

+0

我會爲每個圖層使用不同的OrthographicCamera。將每個圖層視爲具有其自己的座標系縮放比例。其中一層將成爲遊戲物理髮生的主要層。在每一幀上,在更新主圖層的相機後,抓住它的位置並將其縮放版本作爲其他圖層相機位置的位置(每層應具有相機位置縮放參數)。對於每個圖層,首先將其相機的組合矩陣應用到精靈批次的投影矩陣,然後添加該圖層的精靈。 – Tenfour04

+0

下面是一個例子。他們使用OrthographicCamera的一個子類的單個實例來完成它,但它是相同的基本概念。 – Tenfour04

回答

3

請注意,下面的示例沒有經過測試,因爲我只是回想起我是如何做到的。這個想法很簡單 - 爲每個圖層創建一個具有初始位置和速度的圖層並移動它們。如果一個圖層離開邊緣,則在另一邊放置另一個圖層(這就是爲什麼我們創建一個額外圖層的原因)。

假設有

public class Parallax extends DynamicGameObject { 

    public float width, height; // Use setter/getter if you prefer 

    public Parallax(float x, float y, float width, float height, float velocityX, float velocityY) { 

     super(x, y, width, height); 
     velocity.set(velocityX, velocityY); 
     this.width = width; 
     this.height = height; 

    } 

    public void update(float deltaTime) { 
     position.add(velocity.x * deltaTime, velocity.y * deltaTime); 
    } 

    public void setPosition(float x, float y) { 
     position.set(x, y); 
    } 
} 

DynamicGameObject從SuperJumper人口統計學

public class DynamicGameObject extends GameObject { 

    public final Vector2 velocity; 
    public final Vector2 accel; 

    public DynamicGameObject(float x, float y, float width, float height) { 
     super(x, y, width, height); 
     velocity = new Vector2(); 
     accel = new Vector2(); 
    } 
} 

遊戲物體作爲公

public class GameObject { 

    public final Vector2 position; 
    public final Rectangle bounds; 

    public GameObject(float x, float y, float width, float height) { 
     this.position = new Vector2(x,y); 
     this.bounds = new Rectangle(x - width/2f, y - height/2f, width, height); 
    } 
} 
視差對象,需要的初始位置,大小和網速度

假設我們有兩層 - 一個在前面,另一個在後面。我們每個都有一個紋理。每個紋理都填充整個屏幕。我們爲每個圖層創建兩個實例,以便當一個紋理開始離開屏幕時,另一個紋理出現在邊緣以填補空白。如果您的紋理較小,則需要先確定需要多少紋理填充屏幕,然後再創建一個圖層以填補間隙。

我們可以創建世界期間視差層creation-

Array<Parallax> parallaxList = new Array<Parallax>(4); 

我們可以創建所述層等這 -

// Back 
/* First parallax for back layer is at 0 x-axis. If you want to move the texture from right to left, the value of BACK_VELOCITY_X should be negative. You can experiment with velocity value for desire pace of movement. We do not want our layer to move on y-axis. Hence, it is set to 0. */ 

parallaxList.add(new Parallax(0, BACK_TEXTURE_HEIGHT, BACK_TEXTURE_WIDTH, BACK_TEXTURE_HEIGHT, BACK_VELOCITY_X, 0)); 

/* This one is also for back layer but it is positioned at the right edge of the layer above*/ 
parallaxList.add(new Parallax(BACK_TEXTURE_WIDTH, BACK_TEXTURE_HEIGHT, BACK_TEXTURE_WIDTH, BACK_TEXTURE_HEIGHT, SOME_VELOCITY_X, 0)); 

// Front 
parallaxList.add(new Parallax(0, 0, FRONT_TEXTURE_WIDTH, FRONT_TEXTURE_HEIGHT, FRONT_VELOCITY_X, 0)); 
parallaxList.add(new Parallax(FRONT_TEXTURE_WIDTH, 0, FRONT_TEXTURE_WIDTH, FRONT_TEXTURE_HEIGHT, FRONT_VELOCITY_X, 0)); 

我們在每個幀 - 的更新呼叫更新層的陣列

// In our example, TOTAL_LAYERS is 4 
for (int i = 0; i < TOTAL_LAYERS; i++) { 

    int tmpInt; 
    Parallax parallax = parallaxList.get(i); 

    parallax.update(deltaTime); 

    // If one layer is off the edge, put it at the right of the next one 
    // In this example, layers are moving from right to left 
    if (parallax.position.x <= -parallax.width) { 

     // We know that parallaxList's indexes 0 and 1 hold the back layers 
     // and indexes 2 and 3 have the front layers. You can add additional 
     // parameters in Parallax class to indicate a group so that you do not 
     // have to determine the group in dirty way like this 
     if(i == 0){ 
      tmpInt = 1; 
     } else if(i == 1) { 
      tmpInt = 0; 
     } else if(i == 2) { 
      tmpInt = 3; 
     } else { 
      tmpInt = 2; 
     } 

     parallax.setPosition(parallaxList.get(tmpInt).position.x + parallax.width, parallax.position.y);    
    }   
} 

您可以使用OrthographicCamera和SpriteBatch繪製視差圖層。你實際上可以使用你有的遊戲攝像頭,但我認爲使用單獨的攝像頭更清潔。無論如何,視差紋理通常足夠大,可以在單獨的通話中分批處理,因此使用遊戲攝像頭很可能不會爲您節省平局。