scene2d
scene2d package是一個2D場景圖結構,用來管理場景中的actors組。它能處理用戶輸入,並在相對於父actor的座標系統中進行旋轉和縮放。它還提供一個刷新actors的框架。scene2d.ui package對建立GUI很有用。
Important classes
Stage類有一個名爲"root"的group(組),可以向其中添加actors。Stage有一個camera和一個SpriteBatch。camera的viewport尺寸與屏幕相同。當需要繪製Stage時,SpriteBatch就作爲參數傳遞給root組。
Group類派生自Actor類,其實就是一個包含其他actors的Actor。對Group的旋轉和縮放操作同時影響它的chidren。Group負責把繪製操作和用戶輸入分配給合適的children。
Actor類提供場景結點(node)所需的全部基本函數,包含position, size, scale, rotation, origin, color這些屬性,有一個可選的name,可以在debug模式下顯示整個actor樹形結構。
Stage setup
Stage類有一個viewport size的屬性,該屬性可以在構造函數裏初始化,但最好還是在程序的resized事件中設置該屬性。構造函數中還有一個名爲"stretch"的參數,如果它爲true,就算Stage的viewportsize和屏幕分辨率不同,stage也會被拉伸到屏幕分辨率。如果爲false,stage的viewportsize中較大的那個維度會放大到和屏幕分辨率一樣。如果在resized事件中把viewport size設置成和屏幕一樣,則stretch值就無關緊要了。
Stage有一個"act"函數,輸入參數包括兩幀的間隔時間,可以使場景中所有actor都調用各自的act()函數。
private Stage stage;
public void create () {
stage = new Stage(0, 0, true);
}
public void resize (int width, int height) {
stage.setViewport(width, height, true);
}
public void render () {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
public void dispose() {
stage.dispose();
}
Actor
請創建Actor的派生類來實現繪製、碰撞檢測、處理用戶輸入等工作。
Drawing
當Stage::draw()函數被調用時,它會調用root group,然後root再調用它的所有children。要繪製actor,需要實現它的draw函數:
TextureRegion region;
public void draw (SpriteBatch batch, float parentAlpha) {
batch.setColor(1, 1, 1, parentAlpha);
batch.draw(region, x, y, width, height);
}
actor::draw函數裏收到的SpriteBatch已經被轉換過了,所以actor的position, size, rotation, scale屬性都是相對於父group的左下角的。這使繪製操作變得很簡單。在上面的代碼中,x,y,width,height都是Actor類的public屬性。
如果actor的visible屬性被設置爲false,Group就不會調用該actor的draw()函數。
draw()函數裏的parentAlpha參數是該actor的parent的alpha值。如果draw函數使用了透明度,那麼整個group和它的所有children都會變得透明。
SpriteBatch::begin()在actor::draw()函數被調用前就已經調用過了。如果一個actor需要用其他方式來繪製,比如使用ShapeRenderer,好麼batch應該先end()並在繪製結束後再begin()。當然,這樣會使得batch被重置,所以應該謹慎使用,具體使用方法如下:
private ShapeRenderer renderer;
public void draw (SpriteBatch batch, float parentAlpha) {
batch.end();
renderer.setProjectionMatrix(batch.getProjectionMatrix());
renderer.setTransformMatrix(batch.getTransformMatrix());
renderer.translate(x, y, 0);
renderer.begin(ShapeType.Rectangle);
renderer.rect(0, 0, width, height);
renderer.end();
batch.begin();
}
Hit detection
當Stage::hit()被調用時,它會調用root group,然後root再調用所有children。第一個返回非null值的actor將被stage返回。要進行碰撞檢測,需要實現下面的函數:
public Actor hit (float x, float y) {
return x > 0 && x < width && y > 0 && y < height ? this : null;
}
函數中用到的座標都是actor的局部座標系的。Input handling
要想觸發手機屏幕的用戶輸入,需要實現touchDown, touchDragged, touchUp函數。
public boolean touchDown (float x, float y, int pointer) {
return true;
}
public void touchDragged (float x, float y, int pointer) {
}
public void touchUp (float x, float y, int pointer) {
}
當stage::touchDown被觸發時,它調用root group。root group會先調用所有children的hit()函數,然後由第一個被hit()函數返回的actor調用touchDown函數。如果touchDown返回false,表示該actor忽略touch down事件,所以group會繼續調用hit(),並由被hit到的actor調用touchDown。如果touchDown()返回true,則該actor成爲group的focused actor(焦點),這意味着該actor可以接收到touchDragged和touchUp事件,即使它們並沒有在該actor上發生(它們會接收到事件,但如果不在它們身上發生,就可以選擇忽略)。如果touchUp被調用(一旦touchDown已經觸發,touchUp就一定會觸發),該actor就失去焦點。
如果actor的touchable屬性設置爲false,則Group不會觸發它的touch事件。
Actions
當前的action系統馬上就會進行重構,到時候再寫。