gpt4 book ai didi

java - libgdx 中多个摄像机和视口(viewport)的问题

转载 作者:行者123 更新时间:2023-11-29 19:11:28 25 4
gpt4 key购买 nike

所以我正在做的应该是一款简单的游戏,但我认为我可能会使事情复杂化。我有一个用于 GameScreen 的摄像头和一个跟随玩家位置的视口(viewport),当它到达侧面的点时,摄像头停止跟随玩家并停留在一个点上。

这本身工作正常,但后来我想在游戏中添加暂停菜单和其他一些功能,创建一个具有自己的相机和视口(viewport)以及舞台和 shapeRenderer 的 hud 类。

当我在我的 gameScreen 中创建这个 hud 的实例时,问题就来了,我在玩游戏时正在看的相机看起来像是 hudCam,它不跟随玩家并且基本上不让我看到玩家它到达屏幕的边缘。

这是我的 GameScreen 类:

public class GameScreen implements Screen {

WowInvasion game;
ScrollingBackground background;
private OrthographicCamera gameCam;
private Viewport gameViewPort;

/*
Basically I wanna keep the same sprites running while in the menu, playing and till dead

therefore, I'll have a switch statement with cases on where the games at, inside the functions needed. That way I'll keep
the game has a background for the menu and there's no need for running a second screen.
*/
public static final int MAIN_MENU = 0;
public static final int GAME = 1;
private static int state = 1; //current state. starts with MAIN_MENU //DEBUGGING GAME SCREEN

//STAGES
private GameStage gameStage; //game ui
private menuStage mainMenu; //Main menu of the game
private Hud hud;

//Resources
private TextureAtlas atlas; //for the textures most
private Skin skin; //for the styles and fonts

//Sprites
private Player player;

//Shapes
private float progressPower; //for the power to build up
private final float POWER_CHARGED = 1000; //limit to get power
private final float DECREASING_POWER = 20; //limit to get power

public GameScreen(WowInvasion game){
this.game = game;
gameCam = new OrthographicCamera();
gameCam.setToOrtho(false, WowInvasion.WIDTH, WowInvasion.HEIGHT);
gameViewPort = new StretchViewport(WowInvasion.WIDTH, WowInvasion.HEIGHT, gameCam);
progressPower = 0f;
game.wowAssetManager.loadTexturesGameScreen(); // tells our asset manger that we want to load the images set in loadImages method
game.wowAssetManager.loadSkins(); //load the needed skins
game.wowAssetManager.manager.finishLoading(); // tells the asset manager to load the images and wait until finsihed loading.
skin = game.wowAssetManager.manager.get("ui/menuSkin.json");
}

@Override
public void show() {
game.batch.setProjectionMatrix(gameCam.combined);
background = new ScrollingBackground();
atlas = game.wowAssetManager.manager.get(WowAssetManager.GAME_ATLAS); //declaring atlas
mainMenu = new menuStage(gameViewPort, game.batch, skin, game); //pass it so that we only use one batch and one same viewport
gameStage = new GameStage(gameViewPort, game.batch, skin, game);
hud = new Hud(game.batch, skin);
player = new Player(atlas.findRegion("player"), (int) gameCam.viewportWidth / 2, (int) gameCam.viewportHeight / 2);

switch(state){
case MAIN_MENU:
Gdx.input.setInputProcessor(mainMenu);
break;
case GAME:
background.setFixedSpeed(false); //does not work in here
}
}

@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

if(state == GAME) {
background.setFixedSpeed(false);
player.update(delta, gameCam.viewportWidth, gameCam.viewportHeight); //updating player for movement
//really cheap way to charge power with velocity
if(progressPower != POWER_CHARGED) {
progressPower += Math.abs(player.getVelocity().x) + Math.abs(player.getVelocity().y);
progressPower -= DECREASING_POWER;
}
else
progressPower = POWER_CHARGED / 4;
}


mainMenu.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f)); //updating while making sure delta won't be more than 1/30f.
gameStage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
game.batch.begin();
background.updateAndRender(delta, game.batch); //updating scrolling background
player.draw(game.batch);
game.batch.end();
mainMenu.draw(); //draw the menu stage
gameStage.draw(); //draw the ui stage for the game
hud.getStage().draw();
hud.renderRotateMeter();

updateCamera(0, WowInvasion.WIDTH);
System.out.println(player.getPosition().x);
}

public void updateCamera(float startX, float endX){
Vector3 position = gameCam.position;
//linear interpolation : a + (b - a) * lerp
//b = player position
//a = current camera position
//lerp = interpolation factor
position.x = gameCam.position.x + (player.getPosition().x - gameCam.position.x) * .1f;

//making the camera stay when the player gets to close to the sides
if(position.x < startX) {
position.x = startX;
}

if(position.x > endX){
position.x = endX;
}

gameCam.position.set(position);
gameCam.update();
}

@Override
public void resize(int width, int height) {
gameViewPort.update(width, height);
//hud.getViewport().update(width, height);
}

@Override
public void pause() {

}

@Override
public void resume() {

}

@Override
public void hide() {
dispose();
}

@Override
public void dispose() {
mainMenu.dispose();
gameStage.dispose();
game.dispose();
hud.dispose();
}

public static void setState(int state) {
GameScreen.state = state;
}

}

这是我的 HUD:

public class Hud implements Disposable{

private Stage stage;
private Viewport viewport;
Button buttonPause, buttonResume;
private OrthographicCamera hudCam;
private ShapeRenderer sp; //like a batch for shapes

public Hud(SpriteBatch sb, Skin skin){
hudCam = new OrthographicCamera();
hudCam.setToOrtho(false, WowInvasion.WIDTH, WowInvasion.HEIGHT);
viewport = new StretchViewport(WowInvasion.WIDTH, WowInvasion.HEIGHT, hudCam);
stage = new Stage(viewport, sb);
sp = new ShapeRenderer();

Table table = new Table();
table.top();
//this makes the table the size of the stage
table.setFillParent(true);

buttonPause = new Button(skin, "pause");
buttonPause.setTransform(true);
buttonPause.addListener(new ClickListener(){ //listener to handle event
@Override
public void clicked(InputEvent event, float x, float y) {

}
});

buttonResume = new Button(skin, "resume");
buttonResume.setTransform(true);
buttonResume.setScale(0.5f);
buttonResume.addListener(new ClickListener(){
@Override
public void clicked(InputEvent event, float x, float y) {
buttonResume.setVisible(false);

}
});

table.add(buttonPause);
table.row();
table.add(buttonResume);

stage.addActor(table);
}

public void renderRotateMeter(){
sp.setProjectionMatrix(hudCam.combined);
sp.begin(ShapeRenderer.ShapeType.Filled);
sp.setColor(Color.YELLOW);
sp.rect(hudCam.position.x,hudCam.position.y, WowInvasion.WIDTH / 2, 20);
sp.end();
}

public Viewport getViewport() {
return viewport;
}

public Stage getStage() {
return stage;
}

@Override
public void dispose() {
stage.dispose();
sp.dispose();
}
}

提前致谢!

编辑

所以我尝试将 gameCam 有一个参数传递给 hud,而不是制作一个新的 OrthographicCamera 我使用那个也有 hudCamara 的玩家的运动是完美的,除了现在来自 Hud 的薄片不完全移动..

最佳答案

看起来您只将 projectionMatrix 设置为仅 HUD 相机,如中所示

sp.setProjectionMatrix(hudCam.combined);

在绘制调用之前尝试将其设置为与 HUD 类之外的其他内容相同。

另一件要记住的事情是,当你涉及在游戏中使用多个 ViewportCamera 时,大多数情况下它将是 1 个 Viewport 与 1 个 Camera 匹配,并与您的情况一样使用另一组。在draw call中,你也需要调用Viewport类的apply()apply(true)来告诉系统你将基于因此,在哪个视口(viewport)上,它将遵循由视口(viewport)的附加相机设置的屏幕坐标。

因此假设您有 2 个对象需要在不同的视口(viewport)中连续调用,请按照以下代码进行操作。根据 libgdx API,方法调用是正确的,但变量名称是虚构的。

// draw objA adhering to viewportA (thus cameraA) <-- assume it's player cam
sb.setProjectionMatrix(cameraA.combined);
viewportA.apply();
objA.draw();

// draw objB adhering to viewportB (thus cameraB) <-- assume it's HUD cam
sb.setProjectionMatrix(cameraB.combined);
viewportB.apply(true); // send in true as for HUD, we always want to center the screen
objB.draw();

总而言之,在连续绘制调用中绘制使用多个相机和视口(viewport)的对象时要记住两件事。

  1. 将投影矩阵设置为 SpriteBatchShapeRenderer
  2. 调用 Viewport 类的 apply()apply(true) 以让它知道您正在使用此视口(viewport)。

关于java - libgdx 中多个摄像机和视口(viewport)的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45155576/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com