2013-08-06 37 views
8

Tôi muốn tạo bong bóng trợ giúp nổi để giới thiệu chức năng cơ bản của trò chơi của tôi. Bong bóng này nên trôi nổi phía trên diễn viên Tôi muốn nó giải thích, như thể hiện trong hình dưới đây.Nhận tọa độ của Diễn viên trong Bảng trong libGDX

Floating instruction bubble.

Để thực hiện điều này, tôi muốn các tọa độ của các diễn viên, trong trường hợp này nút trái, và sau đó tôi có thể thêm Actor bong bóng vào Stage trước mọi thứ khác. Phần cuối cùng là dễ dàng, nhưng tôi đang đấu tranh với việc lấy các tọa độ thực tế của nút, vì nó nằm trong một bảng.

Hai nút được thêm vào một bảng như thế này:

t.add(btnLab).expandX().center(); 
t.add(btnSea).expandX().center(); 

Tôi đã thử các cách tiếp cận rõ ràng nhất:

Vector2 loc = new Vector2(a.getX(), a.getY()); 
System.out.println("Loc: " + loc); 
a.localToStageCoordinates(loc); 
System.out.println("Loc: " + loc); 

này mang lại cho tôi (theo thứ tự của sysouts): [0.0, 0.0] và [40.0, 130.0]. Vị trí cuối cùng thực sự là vị trí của Bảng, lấp đầy vùng màu xanh của màn hình. Vì vậy, vị trí này rõ ràng là bỏ lỡ một cái gì đó Bảng không đặt diễn viên, và không thể được sử dụng (như tôi chỉ kết thúc với vị trí của Bảng).

(Tôi cũng đã cố gắng sử dụng t.localToStageCoordinates đây, t là Bảng kết quả tương tự..)

Một giải pháp tôi đã cố gắng là đệ quy tìm kiếm thông qua tất cả các bậc cha mẹ:

private static Vector2 getLoc(Actor a) { 
    return getLoc(new Vector2(a.getX(), a.getY()), a.getParent()); 
} 

private static Vector2 getLoc(Vector2 loc, Actor g) { 
    System.out.println("Location: " + loc + ", Actor: " + g); 
    loc.x += g.getX(); 
    loc.y += g.getY(); 
    if(g.getParent() == null) return loc; 
    return getLoc(loc, g.getParent()); 
} 

Thật không may, điều này mang lại cho tôi như vậy. Các sysouts cung cấp những điều sau đây:

Location: [0.0:0.0], Actor: Table 40.0,130.0 944.0x508.0 
Location: [40.0:130.0], Actor: Group 0.0,0.0 0.0x0.0 
Location: [40.0:130.0], Actor: Group 0.0,0.0 0.0x0.0 

Vì vậy, tôi dường như không thể có được vị trí thực tế của Nhóm/diễn viên trong bảng.

Tôi phải làm như thế nào?

+1

Ngoài câu trả lời của tôi, tôi tự hỏi nếu bạn đang cố gắng để có được vị trí của diễn viên trước khi diễn viên lần đầu tiên được kết xuất? Nếu bạn cố gắng để có được vị trí trước khi khuôn khổ đã có thời gian để làm một cách bố trí chính xác bạn sẽ nhận được các hợp âm sai. Trong ví dụ của tôi, tôi giảm bớt điều này bằng cách sử dụng trình xử lý sự kiện để có được vị trí chính xác sau khi bố cục đã được thực hiện. – Jyro117

+0

Tôi có một 'Bảng' bên trong một' VerticalGroup' bên trong một 'Bảng' khác trong 'Giai đoạn' của tôi. Tôi đã làm theo câu trả lời dưới đây, nhưng nó không hoạt động. Vấn đề kết thúc là các yếu tố không được đặt ra trước khi tôi chỉ định vị trí bảng bắt đầu. Không có bản dịch vị trí sân khấu nào trong câu trả lời đó là cần thiết. 'table.getX()' đã cho tôi vị trí trong giai đoạn mà tôi cần một khi tôi đã làm nó sau khi bố cục đã xảy ra. – bazola

+0

@ Jyro117 Cảm ơn lời khuyên đó. Tôi có những vấn đề giống nhau. Mất một thời gian dài để nhận ra rằng tôi có thể tính toán vị trí diễn viên quá sớm. – WeirdElfB0y

Trả lời

20

Tôi nghĩ rằng tôi hiểu nơi bạn bị nhầm lẫn. Nó thực sự là rất đơn giản để có được các tọa độ sân khấu của một diễn viên (giả định màn hình liên kết, không được bảo vệ, unscaled diễn viên).

Tất cả bạn cần làm là:

public static Vector2 getStageLocation(Actor actor) { 
    return actor.localToStageCoordinates(new Vector2(0, 0)); 
} 

gì bạn đang làm sai đang cố gắng để có được vị trí của các diễn viên tương đối so với bảng (bằng cách sử dụng actor.getX() và actor.getY ()), và sau đó chuyển đổi vị trí đó sang giai đoạn. Điều đó sẽ kết thúc cho bạn vị trí của bảng vì nó sẽ thêm vị trí của diễn viên. Những gì bạn thực sự là những gì để biết nơi điểm mới Vector2 (0, 0) bên trong diễn viên của bạn là. Điều này cho bạn biết góc dưới cùng bên trái của diễn viên là ở đâu. Nếu bạn muốn trên cùng bên trái, bạn sẽ sử dụng Vector2 mới (0, actor.getHeight()) và các góc khác theo cách tương tự.

Ngoài ra, nếu bạn đang làm việc với các sự kiện và muốn biết vị trí sân khấu của một sự kiện bạn chỉ đơn giản là sẽ làm như sau:

@Override public void touchUp(final InputEvent event, final float x, final float y, final int pointer, final int button) { 
    if (pointer == Buttons.LEFT) { 
     Gdx.app.log("Event", "x: " + event.getStageX() + " y: " + event.getStageY()); 
    } 
} 

Đối với một ví dụ hoàn chỉnh hơn nhìn vào đoạn mã sau:

import com.badlogic.gdx.ApplicationListener; 
import com.badlogic.gdx.Gdx; 
import com.badlogic.gdx.graphics.GL20; 
import com.badlogic.gdx.math.Vector2; 
import com.badlogic.gdx.scenes.scene2d.InputEvent; 
import com.badlogic.gdx.scenes.scene2d.Stage; 
import com.badlogic.gdx.scenes.scene2d.ui.*; 
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; 

public class ActorStage implements ApplicationListener { 
    private Stage stage; 
    private Skin skin; 

    @Override public void create() { 
     Gdx.app.log("CREATE", "App Opening"); 

     this.stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false); 
     Gdx.input.setInputProcessor(this.stage); 

     this.skin = new Skin(Gdx.files.internal("skin/uiskin.json")); 
     this.skin.hashCode(); 

     final Table table = new Table(); 
     table.setFillParent(true); 

     final Button btnLab = new TextButton("Lab", skin); 
     final Button btnSea = new TextButton("Sea", skin); 


     setupButton(table, btnLab); 
     setupButton(table, btnSea); 

     this.stage.addActor(table); 

     Gdx.gl20.glClearColor(0f, 0f, 0f, 1); 
     Gdx.gl20.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); 
    } 

    private void setupButton(Table table, final Button button) { 
     table.add(button).expandX().center(); 

     button.addListener(new ClickListener() { 
      @Override public void clicked(InputEvent event, float x, float y) { 
       Gdx.app.log("XY", "[" + x + ", " + y + "]"); 
       Gdx.app.log("Event", "[" + event.getStageX() + ", " + event.getStageY() + "]"); 
       Gdx.app.log("Actor", "[" + button.getX() + ", " + button.getY() + "]"); 

       Vector2 loc = new Vector2(button.getX(), button.getY()); 
       Vector2 stageLoc = button.localToStageCoordinates(loc); 
       Gdx.app.log("ActorStage", "[" + stageLoc.x + ", " + stageLoc.y + "]"); 

       Vector2 zeroLoc = button.localToStageCoordinates(new Vector2()); 
       Gdx.app.log("ZeroStage", "[" + zeroLoc.x + ", " + zeroLoc.y + "]"); 
      } 
     }); 
    } 

    @Override public void render() { 
     this.stage.act(); 

     Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT); 
     Gdx.gl20.glEnable(GL20.GL_BLEND); 

     this.stage.draw(); 
    } 

    @Override public void dispose() { 
     Gdx.app.log("DISPOSE", "App Closing"); 
    } 

    @Override public void resize(final int width, final int height) { 
     Gdx.app.log("RESIZE", width + "x" + height); 
     Gdx.gl20.glViewport(0, 0, width, height); 
     this.stage.setViewport(width, height, false); 
    } 

    @Override public void pause() {} 

    @Override public void resume() {} 
} 

Khi nhấp btnLab một lần, nhấp btnSea lần và sau đó đóng cửa sổ, kết quả đầu ra:

CREATE: App Opening 
RESIZE: 800x600 
XY: [18.0, 13.0] 
Event: [200.0, 296.0] 
Actor: [182.0, 283.0] 
ActorStage: [364.0, 566.0] 
ZeroStage: [182.0, 283.0] 
XY: [6.0, 23.0] 
Event: [588.0, 306.0] 
Actor: [582.0, 283.0] 
ActorStage: [1164.0, 566.0] 
ZeroStage: [582.0, 283.0] 
DISPOSE: App Closing 

Như bạn có thể thấy bạn muốn thông báo "ZeroStage" vì nó cung cấp cho bạn vị trí của diễn viên trên sân khấu.

+0

Câu hỏi cho thấy đầu ra của 'a.getX(), a.getY()' là '0,0', vậy điều đó có nghĩa là OP đã thực hiện chính xác những gì bạn đề nghị? – DannyMo

+0

Tôi đã cập nhật câu trả lời của tôi với một ví dụ đầy đủ cho thấy 0,0 không cho bạn các coords sân khấu. OP có thể làm điều gì đó khác biệt để làm cho kết quả của anh ta khác biệt. – Jyro117

+0

Haha, yeah, zeros đã làm các trick! Điều đó thật ngu ngốc. Cảm ơn bạn vì điều đó, và cho câu trả lời rất toàn diện. –