I have been working on a 2d game that is similar to billiards/pool. I've got the basic game down and now I'm working on some visual effects. One of the things I would like to do is have have numbers pop up on the screen where a scoring event occurs and then have that number "swoosh up" to the main score at the top of the screen. To accomplish this I have been trying to overlay a Stage onto my main game area so that I can add score text and then let the LibGDX Scene2d take over. I am adding the text as an actor to the stage and then assigning some actions to it to achieve the desired effect. The problem I'm having is that when I add the object I need to convert from world to stage coordinates. This is because I want to place the score popup where two balls touch, which is in world coordinates. I have tried to use the "project" method of the stage's viewport (it is a FitViewport) but the coordinates never translate correctly.
Now that I've explained what I'm trying to do, I was hoping that someone would know how I could pull this off. I'm sure it isn't difficult and that I'm missing some small detail.
Here is the relevant code: This is the class that will be used to overlay a stage onto the main game screen.
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.utils.viewport.Viewport;
public class UIOverlay {
private Skin skin = new Skin( Gdx.files.internal("skins/gamePlaySkin.json"));
private Stage stage = new Stage();
public void init (Viewport viewport) {
stage.setViewport(viewport);
stage.getViewport().update(GameWorld.WIDTH, GameWorld.HEIGHT, true);
}
public void render () {
stage.act();
stage.draw();
}
public Stage getStage () {
return this.stage;
}
public void addScorePopup (int score, Vector2 worldPos) {
Viewport vp = stage.getViewport();
Vector2 screenPos = new Vector2(worldPos.x, worldPos.y);
vp.project(screenPos);
// Some sample vectors after projection:
// worldPos.x = 0.88585174, worldPos.y = 1.6051532
// screenPos.x = 0.885849, screenPos.y = 1022.39484
// Another Set:
// worldPos.x = 0.63776636, worldPos.y = 0.8991218
// screenPos.x = 0.63777924, screenPos.y = 1023.1009
Label popLabel = new Label(String.valueOf(score), skin, "popupScore");
stage.addActor(popLabel);
popLabel.setPosition(screenPos.x, screenPos.y);
float time = 0.5f;
popLabel.addAction(Actions.delay(1000, Actions.sequence(Actions.moveTo(0.0f, 0.0f, time, Interpolation.sineIn), Actions.alpha(0, 0.1f))));
}
}
This is where I set up the main game viewport:
public static void init(){
// GameWorld.WIDTH and HEIGHT are 1280 and 1024
m_camera = new OrthographicCamera();
m_camera.setToOrtho(true, GameWorld.WIDTH, GameWorld.HEIGHT);
m_viewport = new FitViewport(GameWorld.WIDTH, GameWorld.HEIGHT, m_camera);
}
When creating the UIOverlay I pass the game's m_viewport into UIOverlay.init(). I have also tried creating a new FitViewport in UIOverlay with the same dimensions as the game's viewport, but have the same behavior.