【问题标题】:Collision detection between rectangles libgdx矩形 libgdx 之间的碰撞检测
【发布时间】:2017-10-30 09:11:33
【问题描述】:

在我的自上而下的游戏中,我怎样才能让我的玩家在通过婴儿床时发生碰撞? 我正在使用 intersectRectangles 。

这是我的代码

Rectangle player = new Rectangle();
Rectangle babycrib = new Rectangle();
Rectangle intersection = new Rectangle(); 


// Load the sprite sheet as a texture
    cat = new Texture(Gdx.files.internal("spriteCatsheet.png"));
    catsprite = new Sprite(cat);
    player = new Rectangle();
    player.x = Gdx.graphics.getWidth() - player.width - 350; 

    baby = new Texture(Gdx.files.internal("baby.png"));
    sprite_baby = new Sprite(baby);
    babycrib = new Rectangle();
    sprite_baby.setPosition(180,4000);

更新方法

   public void update(){
    deltaTime = Gdx.graphics.getDeltaTime();
    camera.update();   
}

在渲染方法中

// check collision
    Intersector.intersectRectangles(player, babycrib, intersection);
     if(intersection.x > player.x)
        //Intersects with right side
     if(intersection.y > player.y)
            //Intersects with top side
     if(intersection.x + intersection.width < player.x + player.width)
                //Intersects with left side
     if(intersection.y + intersection.height < player.y + player.height)
                    //Intersects with bottom side
     Intersector.overlaps(player,babycrib);

这是完整的代码

 public class GameScreen implements Screen ,InputProcessor {

final MyGdxGame game;
// Constant rows and columns of the sprite sheet
private static final int FRAME_COLS = 8, FRAME_ROWS = 4;
private boolean peripheralAvailable;
// Objects used
Animation<TextureRegion> walkAnimation; // Must declare frame type (TextureRegion)
Texture left_paw,right_paw;

Texture baby,cat;
SpriteBatch spriteBatch;
Sprite catsprite,sprite_baby;
ImageButton moveBackward,moveForward;
Viewport viewport;
private Stage stage;
private static float fade;
// A variable for tracking elapsed time for the animation
float stateTime;
private TextureRegion myTextureRegion;
TextureRegion textureRegion;
private TextureRegionDrawable myTexRegionDrawable;

OrthographicCamera camera;
Rectangle player = new Rectangle();
Rectangle babycrib = new Rectangle();
Rectangle intersection = new Rectangle();


float deltaTime;
int progressKnobX = 18;
Float fadeTime = 1f;

public GameScreen(final MyGdxGame game) {
    this.game = game;
    stage = new Stage(new StretchViewport( 720, 1280));
    camera = new OrthographicCamera(1280 ,720);
    Gdx.input.setCatchBackKey(true);
    camera.update();
    Gdx.graphics.setContinuousRendering(true);
    Gdx.graphics.requestRendering();
    camera.setToOrtho(false, 720, 1280);
    Gdx.input.setInputProcessor(stage);
    spriteBatch = new SpriteBatch();
    Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    Gdx.input.setInputProcessor( this);
    peripheralAvailable = Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer);
    viewport = new ScreenViewport();

    baby = new Texture(Gdx.files.internal("equip/baby.png"));
    sprite_baby = new Sprite(baby);
    babycrib = new Rectangle();
    sprite_baby.setPosition(180,4000);


    // Load the sprite sheet as a texture
    cat = new Texture(Gdx.files.internal("spriteCatsheet.png"));
    catsprite = new Sprite(cat);
    player = new Rectangle();
    player.x = Gdx.graphics.getWidth() - player.width - 350; //250;  //550 // 410
    // Use the split utility method to create a 2D array of TextureRegions. This is
    // possible because this sprite sheet contains frames of equal size and they are
    // all aligned.
    TextureRegion[][] tmp = TextureRegion.split(cat, cat.getWidth() /   FRAME_COLS , cat.getHeight()/ FRAME_ROWS);
    // Place the regions into a 1D array in the correct order, starting from the top
    // left, going across first. The Animation constructor requires a 1D array.
    TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
    int index = 0;
    for (int i = 0; i < FRAME_ROWS; i++) {
        for (int j = 0; j < FRAME_COLS; j++) {
            walkFrames[index++] = tmp[i][j];
        }
    }
    // Initialize the Animation with the frame interval and array of frames
    walkAnimation = new Animation<TextureRegion>(0.099f, walkFrames);
    // Instantiate a SpriteBatch for drawing and reset the elapsed animation
    // time to 0
    spriteBatch = new SpriteBatch();
    stateTime = 0f;
    //left_control
    left_paw = new Texture(Gdx.files.internal("left_paw.png"));
    myTextureRegion = new TextureRegion(left_paw);
    myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
    moveBackward = new ImageButton(myTexRegionDrawable); //Set the button up
    moveBackward.getStyle().imageUp = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("left_paw.png"))));
    //the hover
    moveBackward.getStyle().imageDown = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("left_paw_hover.png"))));
    moveBackward.setPosition(10,25);
    stage.addActor(moveBackward); //Add the button to the stage to perform rendering and take input.
    Gdx.input.setInputProcessor(stage);
    moveBackward.addListener(new InputListener(){
        @Override
        public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
            System.out.println("Left Button Pressed");
            //Start Animation
            progressKnobX = progressKnobX - 4;
            Gdx.graphics.setContinuousRendering(true);
            motionState=MotionState.NONE;
        }
        @Override
        public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
            System.out.print("Released");
            Gdx.graphics.setContinuousRendering(false);
            motionState=MotionState.DOWN;
            return true;
        }
    });
    stage.addActor(moveBackward);
    //right_control
    right_paw = new Texture(Gdx.files.internal("right_paw.png"));
    myTextureRegion = new TextureRegion(right_paw);
    myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
    moveForward = new ImageButton(myTexRegionDrawable); //Set the button up
    moveForward.getStyle().imageUp = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("right_paw.png"))));
    //the hover
    moveForward.getStyle().imageDown = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("right_paw-hover.png"))));
    moveForward.setPosition(517,25);
    stage.addActor(moveForward); //Add the button to the stage to perform rendering and take input.
    Gdx.input.setInputProcessor(stage);
    moveForward.addListener(new InputListener(){
        @Override
        public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
            System.out.println("Right Button Pressed");
            progressKnobX = progressKnobX + 4;

            motionState=MotionState.NONE;
        }
        @Override
        public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
            motionState=MotionState.UP;
            return true;
        }
    });
    stage.addActor(moveForward);
}
public enum State
{
    PAUSE,
    RUN,
    RESUME,
    STOPPED
}
private State state = State.RUN;

MotionState motionState=MotionState.NONE;
enum MotionState {
    NONE {
        @Override
        public boolean update(Rectangle player) {
            return true;
        }
    },

    UP {
        @Override
        public boolean update(Rectangle player) {
            player.y += 300 * Gdx.graphics.getDeltaTime();
            return false;
        }
    },
    DOWN{
        @Override
        public boolean update(Rectangle player) {
            player.y -= 300 * Gdx.graphics.getDeltaTime();
            return false;
        }
    },
    LEFT{
        @Override
        public boolean update(Rectangle player)  {
            player.x -= 100 * Gdx.graphics.getDeltaTime();
            return false;
        }
    },
    RIGHT{
        @Override
        public boolean update(Rectangle player) {
            player.x  += 100 * Gdx.graphics.getDeltaTime();
            return false;
        }
    };
    public abstract boolean update(Rectangle player);
}

@Override
public void show() {
}
public void update(){
deltaTime = Gdx.graphics.getDeltaTime();
camera.position.x += 10;
camera.position.y += 10;
camera.update();
}
@Override
public void render(float delta) {
    // clear previous frame
    Gdx.gl.glClearColor(0.294f, 0.294f, 0.294f, 1f);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear screen
    stateTime += Gdx.graphics.getDeltaTime(); // Accumulate elapsed animation time
    camera.update();
    update();
    spriteBatch.begin();
    stateTime += Gdx.graphics.getDeltaTime();
    TextureRegion currentFrame = walkAnimation.getKeyFrame(stateTime, true);
    camera.position.x = player.getX() + 100; //190
    camera.position.y = player.getY() + 180;
    camera.position.x = 350;
    update();
    spriteBatch.setProjectionMatrix(camera.combined);
    spriteBatch.draw(currentFrame,player.x, player.y);
    sprite_baby.draw(spriteBatch);


    if(Gdx.input.isKeyPressed(Input.Keys.DOWN)) motionState = MotionState.DOWN;
    if(Gdx.input.isKeyPressed(Input.Keys.UP)) motionState=MotionState.UP;
    if(Gdx.input.isKeyPressed(Input.Keys.LEFT)) motionState=MotionState.LEFT;
    if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)) motionState=MotionState.RIGHT;

    if(motionState.update(player)) motionState=MotionState.NONE;


    // check collision
    Intersector.intersectRectangles(player, babycrib, intersection);
    if(intersection.x > player.x)
        //Intersects with right side
        if(intersection.y > player.y)
            //Intersects with top side
            if(intersection.x + intersection.width < player.x + player.width)
                //Intersects with left side
                if(intersection.y + intersection.height < player.y + player.height)
                    //Intersects with bottom side
                    Intersector.overlaps(player,babycrib);
    //Intersects with bottom side


    if(!player.overlaps(babycrib)){
        Gdx.app.log("babycrib overlaps", "yes");
    }

    //Mobile acceleration
    if (Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer)) {
        player.x -= Gdx.input.getAccelerometerX();
    }
    if (player.x < 0) {
        player.x = 0;
        player.x += Gdx.graphics.getDeltaTime() *20 *delta;
    }
    if (player.x > Gdx.graphics.getWidth()-player.getWidth() -150) {
        player.x = Gdx.graphics.getWidth()-player.getWidth() -150;
    }
    if(this.state==State.RESUME) {
        switch (state) {
            case RUN:
                //do suff here
                break;
            case PAUSE:
                break;
            case RESUME:
                break;
            default:
                break;
        }
    }
    spriteBatch.end();
    stage.act(); //acting a stage to calculate positions of actors etc
    stage.draw(); //drawing it to render all
}


@Override
public void resize(int width, int height) {
    viewport.update(width, height);
    camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
    camera.update();
}
@Override
public void pause() {

}
@Override
public void resume() {

}

@Override
public boolean keyDown(int keycode) {
    return false;
}

@Override
public boolean keyUp(int keycode) {
    return false;
}
@Override
public boolean keyTyped(char character) {
    return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
    return false;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
    return false;
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
    return false;
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
    return false;
}
@Override
public boolean scrolled(int amount) {
    return false;
}
@Override
public void hide() {
}
@Override
public void dispose() { // SpriteBatches and Textures must always be disposed
}
}

谁能告诉我什么是矩形碰撞检测的正确实现没有重叠发生,我是这个框架的新手。谢谢并提前:)

【问题讨论】:

  • 更新player和babycrib的位置并检查if(!player.overlaps(babycrib)){ }时这两者之间没有碰撞
  • 我已经做了@AbhishekAryan 先生,但仍然不能与婴儿床相撞。
  • 如何更新player和babycrib的位置,请添加该代码
  • 在我的更新方法player.setPosition(getX(), getY());,babycrib.setPosition(getX(), getY());
  • getX() 和 getY() 是什么?

标签: java android libgdx collision-detection


【解决方案1】:

您可以使用player.contains(babycrib) 进行常规碰撞检测。您也可以为此使用Intersector,但这也会计算重叠区域。

if (Intersector.intersectRectangles(player, babycrib, intersection))
{
  //player and babycrib are intersecting...
  if (intersection.contains(babyRoom))
  {
    //Collision happened in baby room.
  }
}

【讨论】:

  • 我会试试这个 @Madmenyo 先生 :)
  • 早上好 @Madmenyo 先生,我试试你的代码,但我怎样才能使矩形的两侧相交?婴儿床的左右两边。
  • 你的意思是它在哪里碰撞?这是一个答案:gamedev.stackexchange.com/a/29796/20075
  • 是的,玩家在婴儿床中相交我的应用程序日志消息只有在他到达婴儿床顶部时才会出现..使用此代码我的玩家在到达婴儿床顶部时停止..if (babycrib.contains(player)) { Gdx.app.log("Collision happened in baby crib ", "yes"); , ` if (player.y > 4000) player.y = 4000; } `
【解决方案2】:

你的代码有点乱,可能是因为你是这个框架的新手,所以我不能确切地说出了什么问题。

但在碰撞检测时,您似乎只是在更新宽度和高度为零的player 矩形的位置。也不会改变大小为零的babycrib 矩形的位置。


你正在使用:

babycrib Rectangle sprite_baby Sprite
player Rectangle catspriteSprite

不要为 Sprite 创建新的 Rectangle,Sprite 拥有自己的 bounds 类型为 Rectangle 的数据成员,因此请使用边界而不是新的 Rectangle。

当你想访问sprite_baby矩形时使用sprite_baby.getBoundingRectangle(),当你想访问catsprite的矩形时使用catsprite.getBoundingRectangle()。

如果您不想在代码中进行更多更改,请将Sprite 的矩形引用到您的Rectangle 变量中,例如,

sprite_baby = new Sprite(baby);
babycrib = sprite_baby.getBoundingRectangle();

和

catsprite = new Sprite(cat);
player = catsprite.getBoundingRectangle();

【讨论】:

  • 谢谢先生,当我尝试catsprite = new Sprite(cat); player = catsprite.getBoundingRectangle(); 我的播放器没有显示在我的屏幕上。
  • 在控制台打印播放器的位置,检查是否在屏幕上。您还在更改相机的位置,因此请确保玩家在相机视口中。
【解决方案3】:

设置矩形的宽度和高度,例如:

player = new Rectangle();
player.setWidth( catsprite.getWidth() );    
player.setHeight( catsprite.getHeight() );

babycrib = new Rectangle();
babycrib.setWidth( babysprite.getWidth() );
babycrib.setHeight( babysprite.getHeight() );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-26
    • 2014-02-07
    • 1970-01-01
    • 2014-05-05
    相关资源
    最近更新 更多