How to make player get destroyed through camera?

2020-04-21 00:17发布

问题:

I've been having some trouble making the player get destroyed through the camera. In my application, I made the camera follow the player(the ball). But the camera can only follow the ball upward. So what I want to accomplish is, when the player(the ball) reaches the bottom of the interface(the screen) it gets destroyed. After it gets destroyed it would be good, if a new activity(new screen) pops up, that says "Game over". Thanks a lot for the great support. the interface of the application

package com.luca.tuninga;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.*;



public class MyGdxGame extends ApplicationAdapter {


public static float APP_FPS = 60f;
public static int V_WIDTH = 480;
public static int V_HEIGHT = 640;


Box2DDebugRenderer b2dr;
World world;
Body ballBody;

OrthographicCamera camera;

float cameraMaxY;

@Override
public void create() {
    world = new World(new Vector2(0, -9.8f), false);
    b2dr = new Box2DDebugRenderer();


    camera = new OrthographicCamera();
    camera.setToOrtho(false, V_WIDTH, V_HEIGHT);
    cameraMaxY = camera.position.y;


    ballBody = createBall();
    createWalls();
}

private void update() {
    world.step(1f / APP_FPS, 6, 2);

    if (Gdx.input.isTouched()) {
        ballBody.setLinearVelocity(0, MathUtils.clamp(ballBody.getLinearVelocity().y, 0, 3));
        ballBody.applyForceToCenter(new Vector2(0, 650f), false);
    }

    if (ballBody.getPosition().y * 32 > cameraMaxY) {
        camera.translate(0, (ballBody.getPosition().y * 32) - cameraMaxY);
        camera.update();

        cameraMaxY = camera.position.y;
    }
}

@Override
public void render() {
    Gdx.gl.glClearColor(.25f, .25f, .25f, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    update();

    b2dr.render(world, camera.combined.cpy().scl(32f));
}

@Override
public void dispose() {
    super.dispose();
    world.dispose();
}

private Body createBall() {
    Body body;
    BodyDef def = new BodyDef();
    def.type = BodyDef.BodyType.DynamicBody;
    def.fixedRotation = true;
    def.position.set(camera.position.x/ 32 + .5f, camera.position.y/ 32);
    def.gravityScale = 3;
    CircleShape shape = new CircleShape();
    shape.setRadius(.5f);

    body = world.createBody(def);
    body.createFixture(shape, 1.0f);
    return body;

}

private void createWalls() {
    Body body;
    BodyDef def = new BodyDef();
    def.type = BodyDef.BodyType.StaticBody;
    def.fixedRotation = true;

    PolygonShape shape = new PolygonShape();
    shape.setAsBox(1, 200 / 32);
    for(int i = 0; i < 20 ; i++) {
        def.position.set(1.01f, i * (200 / 32));
        body = world.createBody(def);
        body.createFixture(shape, 1.0f);

        def.position.set(V_WIDTH / 32 - 1, i * (200 / 32));
        body = world.createBody(def);
        body.createFixture(shape, 1.0f);
    }
 }

}

回答1:

From what I understand, the camera will follow upwards only. Thus when the ball transitions into upwards position, camera will update and follow through, camera won't go down again.

So you can check when the ball is outside of the sight of camera; specifically the bottom of camera.

You can do something like this putting it at the end of update() function

if ((ballBody.getPosition().y + 0.5f) * 32 < ballBody.getPosition().y -
    camera.getViewportHeight()/2) {
    // destroy body
    world.destroyBody(ballBody);

    // TODO: switch to another screen (thus next frame update & draw loop of this screen won't be called anymore)
}

above is to check if when ball is completely out of camera's sight (thus I do + 0.5f which is its radius as you used to create the shape for such body) against camera's viewport height.

Then switch to another screen. This means the current screen won't be update or draw its content anymore, thus no need to have a flag to check. But if you need to do something else again in next frame, you better have a flag checking for the current screen to know that the game is now over, and thus you can check whether to do certain operations.