简体   繁体   English

矩形libgdx之间的碰撞检测

[英]Collision detection between rectangles libgdx

In my top down game how can I make my player collide when he pass through the baby crib? 在我的自上而下的游戏中,当我的玩家穿过婴儿床时,我该如何使其发生碰撞? I'm using intersectRectangles . 我正在使用intersectRectangles。

Here is my code 这是我的代码

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);

Update Method 更新方式

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

In render method 在渲染方法中

// 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);

Here is the full code 这是完整的代码

 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
}
}

Can anyone till me what is the correct implementation of rectangle collision detection there's no overlap happen , I'm new to this framework. 任何人都可以直到我知道矩形冲突检测的正确实现是什么,而不会发生重叠,我是这个框架的新手。 Thank's and advance :) 谢谢和提前:)

You can use player.contains(babycrib) for regular collision detection. 您可以使用player.contains(babycrib)进行常规碰撞检测。 You could also use Intersector for this but this also calculates the area of overlap occurring. 您也可以为此使用Intersector ,但这也可以计算发生重叠的区域。

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

Your code is somehow messy, may be because you're new for this Framework so I can't say exactly what's going wrong. 您的代码有些混乱,可能是因为您是此框架的新手,所以我无法确切地说出问题所在。

But at the point of collision detection , It's seems that you're only updating position of player rectangle that having zero width and height. 但是在碰撞检测时 ,似乎您只是在更新宽度和高度为零的player矩形的位置。 Also not changing position of babycrib rectangle that having zero size too. 同样也没有改变大小为零的babycrib矩形的位置。


You're using : 您正在使用:

babycrib Rectangle <-----FOR-------> sprite_baby Sprite babycrib Rectangle <----- FOR -------> sprite_baby Sprite
player Rectangle <-----FOR-----> catsprite Sprite player Rectangle <----- FOR -----> catsprite Sprite

Don't create new Rectangle for Sprite , Sprite having own bounds data member of type Rectangle so use bounds instead of new Rectangle. 不要为Sprite创建新的RectangleSprite具有自己的Rectangle类型的bounds数据成员,因此请使用bounds而不是new Rectangle。

Whenever you want to access sprite_baby rectangle use sprite_baby.getBoundingRectangle() and when you want to catsprite 's rectangle use catsprite.getBoundingRectangle() . 每当您要访问sprite_baby矩形时,请使用sprite_baby.getBoundingRectangle()而当您要获取catsprite的矩形时,请使用catsprite.getBoundingRectangle()

If you don't want to change more in your code, Keep reference of Sprite 's rectangle to your Rectangle variable like, 如果您不想在代码中进行更多更改,请保留Sprite矩形对Rectangle变量的引用,例如,

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

And

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

Set width and height of your rectangles, for example: 设置矩形的宽度和高度,例如:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM