如何在 LibGDX 中正确绘制碰撞边界?
How to properly draw collision bounds in LibGDX?
我正在尝试制作一款基本的角色扮演游戏,口袋妖怪看起来很像。我的问题是我无法弄清楚如何正确绘制游戏的碰撞。我不知道如何或为什么,但似乎它们没有按预期缩放。这里我举个例子:
它应该是这样的:
这是代码,第一部分是父级 class。
public class BaseScreen implements Screen {
protected Juego game;
protected World world;
protected Actores stage;
protected Stage pantalla;
protected TiledMap map;
protected static int WIDTH; //Aquí almacenaremos la anchura en tiles
protected static int HEIGHT; //Aquí almacenaremos la altura en tiles
protected MapProperties properties;
protected AssetManager manager;
protected int tileWidth, tileHeight,
mapWidthInTiles, mapHeightInTiles,
mapWidthInPixels, mapHeightInPixels;
protected OrthographicCamera camera;
protected Jugador jugador;
public static final float unitScale = 1 / 32f;//Nos servirá para establecer que la pantalla se divide en tiles de 32 pixeles
public static final float pixelsPorCuadro=32f;
protected OrthogonalTiledMapRenderer renderer;
protected ShapeRenderer shapeRenderer;
protected TiledMapTileLayer terrainLayer,terrainLayer2,terrainLayer3;
protected Colisiones colisiones;
public BaseScreen(Juego g){
game=g;
}
@Override
public void show() {
}
@Override
public void render(float delta) {
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
}
@Override
public void dispose() {
manager.dispose();
jugador.dispose();
renderer.dispose();
pantalla.dispose();
}
}
第二个是扩展:
public class Mapa1 extends BaseScreen {
private Juego juego;
public Mapa1(Juego g){
super(g);
this.juego=g;
shapeRenderer=new ShapeRenderer();
TiledMap map = new TmxMapLoader().load("Mapas/InteriorCasaInicialFinal.tmx");
renderer = new OrthogonalTiledMapRenderer(map,unitScale);
camera = new OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
camera.translate(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
camera.update();
MapProperties properties = map.getProperties();
tileWidth = properties.get("tilewidth", Integer.class);
tileHeight = properties.get("tileheight", Integer.class);
mapWidthInTiles = properties.get("width", Integer.class);
mapHeightInTiles = properties.get("height", Integer.class);
mapWidthInPixels = mapWidthInTiles * tileWidth;
mapHeightInPixels = mapHeightInTiles * tileHeight;
jugador=new Jugador(map,camera,280,40,mapWidthInPixels/20 ,mapHeightInPixels/20 );
System.out.println(mapWidthInTiles);//El sout de mapWidthInTiles y Heigh da la altura y anchura del mapa, el de Gdx da el viewportWidth y Heigth
System.out.println(mapHeightInTiles);
//
//Establecemos el zoom de la cámara. 0.1 es más cercano que 1.
WIDTH = ((TiledMapTileLayer) map.getLayers().get(0)).getWidth(); //Obtenemos desde el mapa el número de tiles de ancho de la 1º Capa
HEIGHT = ((TiledMapTileLayer) map.getLayers().get(0)).getHeight(); //Obtenemos desde el mapa el número de tiles de alto de la 1º Capa
System.out.println(WIDTH);
System.out.println(HEIGHT);
camera.setToOrtho(false, WIDTH,HEIGHT); //Establecemos la cámara, y le decimos cuanto tiene que ocupar. Doc:
camera.position.x=WIDTH/2;
camera.position.y=HEIGHT/2;
camera.position.set(WIDTH/2,HEIGHT/2,1);
MapLayers mapLayers = map.getLayers();
terrainLayer = (TiledMapTileLayer) mapLayers.get("Suelo");
terrainLayer2 = (TiledMapTileLayer) mapLayers.get("Cosas");
colisiones=new Colisiones();
colisiones.checkCollision(map,jugador);
InputMultiplexer multiplexer = new InputMultiplexer();
multiplexer.addProcessor(new TecladoJugador(jugador));
Gdx.input.setInputProcessor(multiplexer);
pantalla=new Stage();
pantalla.setDebugAll(true);
pantalla.addActor(jugador);
for(int b=0;b<colisiones.getActores().length-1;b++){
pantalla.addActor(colisiones.getActores()[b]);
}
System.out.println(colisiones.getActores().length);
}
public OrthographicCamera getCamera() {
return camera;
}
public int getMapWidthInPixels() {
return mapWidthInPixels;
}
public int getMapHeightInPixels() {
return mapHeightInPixels;
}
@Override
public void show() {
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
super.render(delta);
renderer.getBatch().begin();
renderer.renderTileLayer(terrainLayer);
renderer.getBatch().end();
jugador.dibujarConHitbox();
renderer.getBatch().begin();
renderer.renderTileLayer(terrainLayer2);
renderer.getBatch().end();
renderer.setView(camera);
camera.update();
pantalla.act(Gdx.graphics.getDeltaTime());
pantalla.draw();
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
}
public void dispose() {
manager.dispose();
jugador.dispose();
renderer.dispose();
pantalla.dispose();
}
public TiledMap getMap() {
return map;
}
}
可能是我忘记上传了,欢迎在评论中告诉我,不胜感激!
实际上,我没有使用任何ShapeRenderer,我曾经使用过它,但我不再需要它了。以下是可能需要的代码部分:
public class Jugador extends Actor {
private int x,y;
private Sprite sprite;
private Boolean colliding;
private Texture texture;
private Animation animation;
private TextureRegion textureRegion;
private TextureRegion[][] tmp;
private String jugadorVista;
private float tiempo;
private TextureRegion[] regions;
private OrthographicCamera camara; //La necesito para que me siga
private Vector3 posicionTiles;
private Batch batch;// La uso para dibujar en este batch al jugador. Podría pasarlo por constructor. Es decisión nuestra como programadoeres.
private Boolean colision;
//Variables para poder redimensionar al jugador según el zoom
private TiledMap mapa; //Necesito el mapa para poder redimensionar al jugador
private int anchuraMapaPixels; //Anchura del mapa donde nos movemos en pixels
private int alturaMapaPixels; //Altura del mapa donde nos movemos en pixels
private int anchuraMapaTiles; //Anchura del mapa donde nos movemos en tiles
private int alturaMapaTiles; //Anchura del mapa donde nos movemos en tiles
private Rectangle rectangle;
private Rectangle[]rectangles;
private Colisiones colisiones;
float anchoJugador, largoJugador;
public Jugador(TiledMap mapa, OrthographicCamera c,int posicionPersonajeX, int posicionPersonajeY, float anchoJugador, float largoJugador) {
this.x=posicionPersonajeX;
this.y=posicionPersonajeY;
this.anchoJugador=anchoJugador;
this.largoJugador=largoJugador;
texture=new Texture(Gdx.files.internal("Sprites/gfx/character.png"));
this.sprite = new Sprite(texture);
colliding=new Boolean(false);
this.camara = c;
colisiones=new Colisiones();
colisiones.checkCollision(mapa,this);
rectangles=colisiones.getRect();
rectangle=new Rectangle(posicionPersonajeX,posicionPersonajeY,texture.getWidth(),texture.getHeight());
posicionTiles=new Vector3();
batch=new SpriteBatch();
anchuraMapaTiles = ((TiledMapTileLayer) mapa.getLayers().get(0)).getWidth(); //Obtenemos desde el mapa el número de tiles de ancho de la 1º Capa
alturaMapaTiles = ((TiledMapTileLayer) mapa.getLayers().get(0)).getHeight(); //Obtenemos desde el mapa el número de tiles de alto de la 1º Capa
System.out.println(sprite.getX());
System.out.println(sprite.getY());
anchuraMapaPixels=anchuraMapaTiles*(int)mapa.getProperties().get("width");
alturaMapaPixels=alturaMapaTiles*(int)mapa.getProperties().get("height");
//sprite.setPosition(250,250);
sprite.setBounds(posicionPersonajeX,posicionPersonajeY,anchoJugador,largoJugador);
//x e y es donde aparece el personaje, width y height altura y anchura
jugadorVista="";
tmp = TextureRegion.split(texture, texture.getWidth() / 17, texture.getHeight() / 8);
regions = new TextureRegion[4];
for (int b = 0; b < regions.length; b++) {
regions[b] = tmp[0][0];
animation = new Animation((float) 0.2, regions);
tiempo = 0f;
}
}
/**
* Esta función redimensiona el sprite del jugador según el tamaño del mapa,
* el tamaño de la propia textura del jugador, y el zoom actual. Debería llamarse
* en dibujar.
*/
public Rectangle getHitBox(){
return sprite.getBoundingRectangle();
}
public void dibujarConHitbox( SpriteBatch batch){
tiempo += Gdx.graphics.getDeltaTime();
textureRegion = (TextureRegion) animation.getKeyFrame(tiempo, true);
setBounds(x,y,anchoJugador-1,largoJugador-5);
batch.draw(textureRegion, x, y,anchoJugador,largoJugador);
}
此外,这是绘制对象碰撞的代码:
public class Colisiones {
private Actor[]actores;
private Rectangle[]rect;
private Rectangle jugador;
public void checkCollision(TiledMap map, Jugador personaje) {
jugador=new Rectangle();
jugador.set(personaje.getX(),personaje.getY(),personaje.getWidth(),personaje.getHeight());
MapObjects mons = map.getLayers().get("Colisionables").getObjects();
// MapObjects mons2 = map.getLayers().get("Entrada").getObjects();
actores=new Actor[mons.getCount()];
rect=new Rectangle[mons.getCount()];
for (int i = 0;i < mons.getCount(); i++) {
RectangleMapObject obj1 = (RectangleMapObject) mons.get(i);
Rectangle rect1 = obj1.getRectangle();
rect[i]=rect1;
rect[i].set(rect1.x,rect1.y,rect1.width,rect1.height);
actores[i]=new Actor();
actores[i].setBounds(rect1.x,rect1.y,rect1.width,rect1.height);
}
}
public Actor[] getActores() {
return actores;
}
public Rectangle[] getRect() {
return rect;
}
}
尝试将您的 Stage
与 Viewport
结合使用:
OrthographicCamera camera = new OrthographicCamera();
camera.setToOrtho(false, x, y);
FitViewport viewport = new FitViewport(x, y, camera); // change this to your needed viewport
SpriteBatch batch = new SpriteBatch();
Stage s = new Stage(viewport, batch);
我正在尝试制作一款基本的角色扮演游戏,口袋妖怪看起来很像。我的问题是我无法弄清楚如何正确绘制游戏的碰撞。我不知道如何或为什么,但似乎它们没有按预期缩放。这里我举个例子:
public class BaseScreen implements Screen {
protected Juego game;
protected World world;
protected Actores stage;
protected Stage pantalla;
protected TiledMap map;
protected static int WIDTH; //Aquí almacenaremos la anchura en tiles
protected static int HEIGHT; //Aquí almacenaremos la altura en tiles
protected MapProperties properties;
protected AssetManager manager;
protected int tileWidth, tileHeight,
mapWidthInTiles, mapHeightInTiles,
mapWidthInPixels, mapHeightInPixels;
protected OrthographicCamera camera;
protected Jugador jugador;
public static final float unitScale = 1 / 32f;//Nos servirá para establecer que la pantalla se divide en tiles de 32 pixeles
public static final float pixelsPorCuadro=32f;
protected OrthogonalTiledMapRenderer renderer;
protected ShapeRenderer shapeRenderer;
protected TiledMapTileLayer terrainLayer,terrainLayer2,terrainLayer3;
protected Colisiones colisiones;
public BaseScreen(Juego g){
game=g;
}
@Override
public void show() {
}
@Override
public void render(float delta) {
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
}
@Override
public void dispose() {
manager.dispose();
jugador.dispose();
renderer.dispose();
pantalla.dispose();
}
}
第二个是扩展:
public class Mapa1 extends BaseScreen {
private Juego juego;
public Mapa1(Juego g){
super(g);
this.juego=g;
shapeRenderer=new ShapeRenderer();
TiledMap map = new TmxMapLoader().load("Mapas/InteriorCasaInicialFinal.tmx");
renderer = new OrthogonalTiledMapRenderer(map,unitScale);
camera = new OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
camera.translate(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
camera.update();
MapProperties properties = map.getProperties();
tileWidth = properties.get("tilewidth", Integer.class);
tileHeight = properties.get("tileheight", Integer.class);
mapWidthInTiles = properties.get("width", Integer.class);
mapHeightInTiles = properties.get("height", Integer.class);
mapWidthInPixels = mapWidthInTiles * tileWidth;
mapHeightInPixels = mapHeightInTiles * tileHeight;
jugador=new Jugador(map,camera,280,40,mapWidthInPixels/20 ,mapHeightInPixels/20 );
System.out.println(mapWidthInTiles);//El sout de mapWidthInTiles y Heigh da la altura y anchura del mapa, el de Gdx da el viewportWidth y Heigth
System.out.println(mapHeightInTiles);
//
//Establecemos el zoom de la cámara. 0.1 es más cercano que 1.
WIDTH = ((TiledMapTileLayer) map.getLayers().get(0)).getWidth(); //Obtenemos desde el mapa el número de tiles de ancho de la 1º Capa
HEIGHT = ((TiledMapTileLayer) map.getLayers().get(0)).getHeight(); //Obtenemos desde el mapa el número de tiles de alto de la 1º Capa
System.out.println(WIDTH);
System.out.println(HEIGHT);
camera.setToOrtho(false, WIDTH,HEIGHT); //Establecemos la cámara, y le decimos cuanto tiene que ocupar. Doc:
camera.position.x=WIDTH/2;
camera.position.y=HEIGHT/2;
camera.position.set(WIDTH/2,HEIGHT/2,1);
MapLayers mapLayers = map.getLayers();
terrainLayer = (TiledMapTileLayer) mapLayers.get("Suelo");
terrainLayer2 = (TiledMapTileLayer) mapLayers.get("Cosas");
colisiones=new Colisiones();
colisiones.checkCollision(map,jugador);
InputMultiplexer multiplexer = new InputMultiplexer();
multiplexer.addProcessor(new TecladoJugador(jugador));
Gdx.input.setInputProcessor(multiplexer);
pantalla=new Stage();
pantalla.setDebugAll(true);
pantalla.addActor(jugador);
for(int b=0;b<colisiones.getActores().length-1;b++){
pantalla.addActor(colisiones.getActores()[b]);
}
System.out.println(colisiones.getActores().length);
}
public OrthographicCamera getCamera() {
return camera;
}
public int getMapWidthInPixels() {
return mapWidthInPixels;
}
public int getMapHeightInPixels() {
return mapHeightInPixels;
}
@Override
public void show() {
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
super.render(delta);
renderer.getBatch().begin();
renderer.renderTileLayer(terrainLayer);
renderer.getBatch().end();
jugador.dibujarConHitbox();
renderer.getBatch().begin();
renderer.renderTileLayer(terrainLayer2);
renderer.getBatch().end();
renderer.setView(camera);
camera.update();
pantalla.act(Gdx.graphics.getDeltaTime());
pantalla.draw();
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
}
public void dispose() {
manager.dispose();
jugador.dispose();
renderer.dispose();
pantalla.dispose();
}
public TiledMap getMap() {
return map;
}
}
可能是我忘记上传了,欢迎在评论中告诉我,不胜感激!
实际上,我没有使用任何ShapeRenderer,我曾经使用过它,但我不再需要它了。以下是可能需要的代码部分:
public class Jugador extends Actor {
private int x,y;
private Sprite sprite;
private Boolean colliding;
private Texture texture;
private Animation animation;
private TextureRegion textureRegion;
private TextureRegion[][] tmp;
private String jugadorVista;
private float tiempo;
private TextureRegion[] regions;
private OrthographicCamera camara; //La necesito para que me siga
private Vector3 posicionTiles;
private Batch batch;// La uso para dibujar en este batch al jugador. Podría pasarlo por constructor. Es decisión nuestra como programadoeres.
private Boolean colision;
//Variables para poder redimensionar al jugador según el zoom
private TiledMap mapa; //Necesito el mapa para poder redimensionar al jugador
private int anchuraMapaPixels; //Anchura del mapa donde nos movemos en pixels
private int alturaMapaPixels; //Altura del mapa donde nos movemos en pixels
private int anchuraMapaTiles; //Anchura del mapa donde nos movemos en tiles
private int alturaMapaTiles; //Anchura del mapa donde nos movemos en tiles
private Rectangle rectangle;
private Rectangle[]rectangles;
private Colisiones colisiones;
float anchoJugador, largoJugador;
public Jugador(TiledMap mapa, OrthographicCamera c,int posicionPersonajeX, int posicionPersonajeY, float anchoJugador, float largoJugador) {
this.x=posicionPersonajeX;
this.y=posicionPersonajeY;
this.anchoJugador=anchoJugador;
this.largoJugador=largoJugador;
texture=new Texture(Gdx.files.internal("Sprites/gfx/character.png"));
this.sprite = new Sprite(texture);
colliding=new Boolean(false);
this.camara = c;
colisiones=new Colisiones();
colisiones.checkCollision(mapa,this);
rectangles=colisiones.getRect();
rectangle=new Rectangle(posicionPersonajeX,posicionPersonajeY,texture.getWidth(),texture.getHeight());
posicionTiles=new Vector3();
batch=new SpriteBatch();
anchuraMapaTiles = ((TiledMapTileLayer) mapa.getLayers().get(0)).getWidth(); //Obtenemos desde el mapa el número de tiles de ancho de la 1º Capa
alturaMapaTiles = ((TiledMapTileLayer) mapa.getLayers().get(0)).getHeight(); //Obtenemos desde el mapa el número de tiles de alto de la 1º Capa
System.out.println(sprite.getX());
System.out.println(sprite.getY());
anchuraMapaPixels=anchuraMapaTiles*(int)mapa.getProperties().get("width");
alturaMapaPixels=alturaMapaTiles*(int)mapa.getProperties().get("height");
//sprite.setPosition(250,250);
sprite.setBounds(posicionPersonajeX,posicionPersonajeY,anchoJugador,largoJugador);
//x e y es donde aparece el personaje, width y height altura y anchura
jugadorVista="";
tmp = TextureRegion.split(texture, texture.getWidth() / 17, texture.getHeight() / 8);
regions = new TextureRegion[4];
for (int b = 0; b < regions.length; b++) {
regions[b] = tmp[0][0];
animation = new Animation((float) 0.2, regions);
tiempo = 0f;
}
}
/**
* Esta función redimensiona el sprite del jugador según el tamaño del mapa,
* el tamaño de la propia textura del jugador, y el zoom actual. Debería llamarse
* en dibujar.
*/
public Rectangle getHitBox(){
return sprite.getBoundingRectangle();
}
public void dibujarConHitbox( SpriteBatch batch){
tiempo += Gdx.graphics.getDeltaTime();
textureRegion = (TextureRegion) animation.getKeyFrame(tiempo, true);
setBounds(x,y,anchoJugador-1,largoJugador-5);
batch.draw(textureRegion, x, y,anchoJugador,largoJugador);
}
此外,这是绘制对象碰撞的代码:
public class Colisiones {
private Actor[]actores;
private Rectangle[]rect;
private Rectangle jugador;
public void checkCollision(TiledMap map, Jugador personaje) {
jugador=new Rectangle();
jugador.set(personaje.getX(),personaje.getY(),personaje.getWidth(),personaje.getHeight());
MapObjects mons = map.getLayers().get("Colisionables").getObjects();
// MapObjects mons2 = map.getLayers().get("Entrada").getObjects();
actores=new Actor[mons.getCount()];
rect=new Rectangle[mons.getCount()];
for (int i = 0;i < mons.getCount(); i++) {
RectangleMapObject obj1 = (RectangleMapObject) mons.get(i);
Rectangle rect1 = obj1.getRectangle();
rect[i]=rect1;
rect[i].set(rect1.x,rect1.y,rect1.width,rect1.height);
actores[i]=new Actor();
actores[i].setBounds(rect1.x,rect1.y,rect1.width,rect1.height);
}
}
public Actor[] getActores() {
return actores;
}
public Rectangle[] getRect() {
return rect;
}
}
尝试将您的 Stage
与 Viewport
结合使用:
OrthographicCamera camera = new OrthographicCamera();
camera.setToOrtho(false, x, y);
FitViewport viewport = new FitViewport(x, y, camera); // change this to your needed viewport
SpriteBatch batch = new SpriteBatch();
Stage s = new Stage(viewport, batch);