2D平台中的NullPointerException - Libgdx - Eclipse Neon

时间:2017-03-11 03:49:38

标签: eclipse libgdx box2d

运行我的游戏时,我收到一个空指针异常。在我创建攻击类之前,我没有遇到过这个问题。有时我可以发送攻击按钮,直到所有敌人都被摧毁,其他时候几乎立即抛出异常(大部分时间是在与墙壁或敌人发生碰撞时发生)。攻击涉及三个主要类别:Level1State,Champion和Attack。请帮我找错,我一直在搜索/测试几天。

为什么会这样?它有时如何变为空,而其他时候它工作正常?另外,如何解决这个问题?

就这是一个重复的问题而言,每种情况似乎都不同。我已经回顾了其他帖子,但还没有找到解决我问题的方法。

Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.badlogic.gdx.graphics.g2d.SpriteBatch.switchTexture(SpriteBatch.java:1056)
at com.badlogic.gdx.graphics.g2d.SpriteBatch.draw(SpriteBatch.java:565)
at com.badlogic.gdx.graphics.g2d.Sprite.draw(Sprite.java:515)
at com.foxdonut.eiu.sprites.Champion.draw(Champion.java:225)
at com.foxdonut.eiu.states.Level1State.render(Level1State.java:172)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.foxdonut.eiu.EIUGame.render(EIUGame.java:43)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:225)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:126)

Champion.Java(第225行是此文件中的最后一行)

public class Champion extends Sprite{
public enum champState {STANDING, RUNNING, JUMPING, FALLING, ATTACK, RUN_ATTACK}
public champState currentState;
public champState previousState;
public World world;
public Body b2body;
private TextureAtlas atlas;
private Level1State screen;
private Array<Attack> attacks;

// Champion States
private TextureRegion champStand;
private TextureRegion champAttack;
private Animation<TextureRegion> champRun;
private Animation<TextureRegion> champJump;
private Animation<TextureRegion> champRunAttack;

private boolean runningRight;
private float champStateTimer;   // how long in state

private Config config = Config.getInstance();

public Champion(Level1State screen){            
    atlas = new TextureAtlas("champion.pack");
    this.screen = screen;
    this.world = screen.getWorld();

    // Initialize states
    currentState = champState.JUMPING;
    previousState = champState.JUMPING;
    champStateTimer = 0;
    runningRight = true;

    // Create an array of texture regions to pass the constructor for the animation
    Array<TextureRegion> frames = new Array<TextureRegion>();

    // Run right animation
    // start x, start y, dimensions(x,y)
    for(int i = 1; i < 4; i++)
        frames.add(new TextureRegion(atlas.findRegion("champ"), i * 27, 5, 27, 25));
    champRun = new Animation<TextureRegion>(0.1f, frames);
    frames.clear();

    // Jump Animation
    for(int i = 4; i < 5; i++)
        frames.add(new TextureRegion(atlas.findRegion("champ"), 108, 0, 27, 30));
    champJump = new Animation<TextureRegion>(0.1f, frames);
    frames.clear();

    // Standing still
    champStand = new TextureRegion(atlas.findRegion("champ"), 0, 5, 27, 25);
    setBounds(0, 0, 27 / EIUGame.PPM, 25 / EIUGame.PPM);
    setRegion(champStand);

    // Standing still and attacking
    champAttack = new TextureRegion(atlas.findRegion("champ"), 0, 31, 27, 25);
    setBounds(0, 0, 27 / EIUGame.PPM, 25 / EIUGame.PPM);
    setRegion(champAttack);

    // Running and attacking
    for(int i = 1; i < 4; i++)
        frames.add(new TextureRegion(atlas.findRegion("champ"), i * 27, 31, 27, 25));
    champRunAttack = new Animation<TextureRegion>(0.1f, frames);
    frames.clear();

    defineChampion();

    setBounds(0, 0, 27 / EIUGame.PPM, 25 / EIUGame.PPM);
    setRegion(champStand);

    attacks = new Array<Attack>();
}

public void update(float dt){
    setPosition(b2body.getPosition().x -getWidth() / 2, b2body.getPosition().y - getHeight() / 2);
    setRegion(getFrame(dt));

    for(Attack atk : attacks){
        atk.update(dt);
        if(atk.isDestroyed())
            attacks.removeValue(atk, true);
    }
}

public TextureRegion getFrame(float dt){
    currentState = getState();

    TextureRegion region;
    switch(currentState){
        case STANDING:
            region = champStand;
            break;
        case JUMPING:
            region = (TextureRegion) champJump.getKeyFrame(champStateTimer, true);
            break;
        case RUNNING:
            region = (TextureRegion) champRun.getKeyFrame(champStateTimer, true);
            break;
        case FALLING:
            region = champStand;
            break;
        case ATTACK:
            region = champAttack;
            break;
        case RUN_ATTACK:
            region = (TextureRegion) champRunAttack.getKeyFrame(champStateTimer, true);
            break;
        default:
            region = champStand;
            break;
    }
    // Given that the sprite initially is facing right
    // If there is no x-axis velocity, or is running left, and region is not flipped (facing right)
    if((b2body.getLinearVelocity().x < 0 || !runningRight) && !region.isFlipX()){
        region.flip(true,  false);
        runningRight = false;
    }
    // If moving on x-axis or is running right, and region is flipped (facing left)
    else if((b2body.getLinearVelocity().x > 0 || runningRight) && region.isFlipX()){
        region.flip(true,  false);
        runningRight = true;
    }

    champStateTimer = currentState == previousState ? champStateTimer + dt : 0;
    previousState = currentState;
    return region;
}

// Returns the state of the character
public champState getState(){

    if(b2body.getLinearVelocity().y > 0 || (b2body.getLinearVelocity().y < 0 && previousState == champState.JUMPING))
        return champState.JUMPING;

    else if(b2body.getLinearVelocity().y < 0)
        return champState.FALLING;

    else if(Gdx.input.isKeyPressed(config.getAttackInt()) && (b2body.getLinearVelocity().x != 0))
        return champState.RUN_ATTACK;

    else if(b2body.getLinearVelocity().x != 0)
        return champState.RUNNING;

    else if(Gdx.input.isKeyJustPressed(config.getAttackInt()) && (b2body.getLinearVelocity().x == 0))
        return champState.ATTACK;

    else
        return champState.STANDING;
}

public void defineChampion(){
    BodyDef bdef = new BodyDef();                         // Define body

    bdef.position.set(196 / EIUGame.PPM, 128 / EIUGame.PPM); 
    bdef.type = BodyDef.BodyType.DynamicBody;             // Make character movable
    b2body = world.createBody(bdef);                      // Create the body

    FixtureDef fdef = new FixtureDef();                   // Define Fixture
    PolygonShape pShape = new PolygonShape(); 

    // Create a rectangle using an array of 4 vertices
    Vector2[] vertex = new Vector2[4];
    vertex[0] = new Vector2( 7,  9).scl(1 / EIUGame.PPM);
    vertex[1] = new Vector2( 7, -9).scl(1 / EIUGame.PPM);
    vertex[2] = new Vector2(-7, -9).scl(1 / EIUGame.PPM);
    vertex[3] = new Vector2(-7,  9).scl(1 / EIUGame.PPM); 

    pShape.set(vertex);

    fdef.filter.categoryBits = EIUGame.CHAMP_BIT;         // What we are
    fdef.filter.maskBits = EIUGame.GROUND_BIT         |   // What we can collide with
                           EIUGame.MEM_CHIP_BLUE_BIT  |
                           EIUGame.MEM_CHIP_GREEN_BIT |
                           EIUGame.MEM_CHIP_RED_BIT   |
                           EIUGame.ENEMY_BIT          |
                           EIUGame.ENEMY_HEAD_BIT     |
                           EIUGame.DEATH_BIT;

    fdef.shape = pShape;                                  // Define shape of fixture as polygon
    b2body.createFixture(fdef).setUserData(this);         // Create Fixture in body

    EdgeShape head = new EdgeShape();                     // Line between 2 different points
                                                          // A contact "sensor"
    // Relative to Box2D body Center
    // A point offset by -1 and 10 above head
    // A point offset by  1 and 10 above head
    head.set(new Vector2(-1 / EIUGame.PPM, 10 / EIUGame.PPM),
             new Vector2( 1 / EIUGame.PPM, 10 / EIUGame.PPM));

    fdef.shape = head;                                    // Set shape
    fdef.isSensor = true;                                 // Doesn't allow collision
                                                          //   Allows for query of data

    b2body.createFixture(fdef).setUserData("head");       // Uniquely sets fixture as "head"
}

public void attack(){
    attacks.add(new Attack(screen, b2body.getPosition().x, b2body.getPosition().y, runningRight ? true : false));
}

public void draw(Batch batch){
    super.draw(batch);
    for(Attack atk : attacks)
        atk.draw(batch);
}

}

Attack.Java

public class Attack extends Sprite{

Level1State screen;
World world;
TextureAtlas attackRightAtlas;
TextureAtlas attackLeftAtlas;
Array<TextureRegion> frames;
Animation <TextureRegion> attackRightAnimation;
Animation <TextureRegion> attackLeftAnimation;
TextureRegion region;
float stateTime;
boolean destroyed;
boolean setToDestroy;
boolean attackRight;

Body b2body;

public Attack(Level1State screen, float x, float y, boolean attackRight){

    this.attackRight = attackRight;
    this.screen = screen;
    this.world = screen.getWorld();

    if (attackRight){
        frames = new Array<TextureRegion>();
        attackRightAtlas = new TextureAtlas("attack/attackRight.pack");

        for (int i = 0; i < 3; i++)
            frames.add(new TextureRegion(attackRightAtlas.findRegion("attackRight"), i * 24, 0, 24, 25));

        attackRightAnimation = new Animation<TextureRegion>(0.1f, frames);
        //setRegion(attackRightAnimation.getKeyFrame(0));

        frames.clear();

        stateTime = 0;
        region = (TextureRegion) attackRightAnimation.getKeyFrame(stateTime, true);
    }
    else{
        frames = new Array<TextureRegion>();
        attackLeftAtlas = new TextureAtlas("attack/attackLeft.pack");

        for (int i = 0; i < 3; i++)
            frames.add(new TextureRegion(attackLeftAtlas.findRegion("attackLeft"), i * 24, 0, 24, 25));

        attackLeftAnimation = new Animation<TextureRegion>(0.1f, frames);
        //setRegion(attackLeftAnimation.getKeyFrame(0));

        frames.clear();

        stateTime = 0;
        region = (TextureRegion) attackLeftAnimation.getKeyFrame(stateTime, true);
    }

    setBounds(x, y, 24 / EIUGame.PPM, 25 / EIUGame.PPM);

    setToDestroy = false;
    destroyed = false;

    defineAttack();
}

public void defineAttack(){
    BodyDef bdef = new BodyDef();
    // Offset the attack so it appears to the side of the character
    bdef.position.set(attackRight ? getX() + 13.5f / EIUGame.PPM : getX() - 13.5f / EIUGame.PPM, getY());
    bdef.type = BodyDef.BodyType.DynamicBody;

    bdef.gravityScale = 0;

    if(!world.isLocked())
        b2body = world.createBody(bdef);

    FixtureDef fdef = new FixtureDef();                   // Define Fixture

    CircleShape shape = new CircleShape();
    shape.setRadius(5 / EIUGame.PPM);

    fdef.filter.categoryBits = EIUGame.ATTACK_BIT;        // What fixture is
    fdef.filter.maskBits = EIUGame.GROUND_BIT         |   // What fixture can collide with
                           EIUGame.MEM_CHIP_BLUE_BIT  |
                           EIUGame.MEM_CHIP_GREEN_BIT |
                           EIUGame.MEM_CHIP_RED_BIT   |
                           EIUGame.ENEMY_BIT;

    fdef.shape = shape;
    fdef.restitution = 1;
    fdef.friction = 0;

    b2body.createFixture(fdef).setUserData(this);
    b2body.setLinearVelocity(new Vector2(attackRight ? 3 : -3, 0));
}

public void update(float dt){
    stateTime += dt;

    if(setToDestroy && !destroyed){
        world.destroyBody(b2body);
        destroyed = true;
        stateTime = 0; 
    }
    else if (!destroyed){
        if (attackRight)
            setRegion(attackRightAnimation.getKeyFrame(stateTime, true));
        else
            setRegion(attackLeftAnimation.getKeyFrame(stateTime, true));

        setPosition(b2body.getPosition().x - getWidth() / 2, b2body.getPosition().y - getHeight() / 2);

        if((stateTime > 2  || setToDestroy) && !destroyed) {
            world.destroyBody(b2body);
            destroyed = true;
        }
        if(b2body.getLinearVelocity().y > 2f)
            b2body.setLinearVelocity(b2body.getLinearVelocity().x, 2f);
        if((attackRight && b2body.getLinearVelocity().x < 0) || (!attackRight && b2body.getLinearVelocity().x > 0))
            setToDestroy();
    }

}

public void setToDestroy(){
    setToDestroy = true;
}

public boolean isDestroyed(){
    return destroyed;
}

}

Level1State.Java(第172行的错误在render方法中) ----第172行:champ.draw(mapRenderer.getBatch());

public class Level1State implements Screen {

private MusicAndSoundManager msm = MusicAndSoundManager.getInstance();
private Config config = Config.getInstance();   
private TextureAtlas atlas;
private OrthographicCamera gameCam, parallaxCam;
private Viewport gamePort;


private GamePad gamepad;

private Hud hud;    
private PauseState pause;

private TmxMapLoader maploader;                     // Loads a tilemap
private TiledMap map;                               // Reference to map itself
private OrthogonalTiledMapRenderer mapRenderer;     // Renders our map to screen
private Champion champ;

// Box2D variables
private World world;
private Box2DDebugRenderer b2dr;   // Shows outlines of fixtures and bodies in box2D world
private B2DWorldCreator creator;

private int backgroundLayer = 0;
private int foregroundLayer = 1;

private TiledMapImageLayer imgLayer;
private TiledMapTileLayer tileLayer;

public Level1State(EIUGame game) {
    gamepad = new GamePad();
    atlas = new TextureAtlas("champion.pack");

    gameCam = new OrthographicCamera();         // Centered on and follows the player
    parallaxCam = new OrthographicCamera();     // Follows the player at a slower rate and moves the background

    // Create a FitViewport to maintain virtual aspect ratio for the gameport and the parallax camera
    gamePort = new FitViewport(EIUGame.V_WIDTH / EIUGame.PPM, EIUGame.V_HEIGHT / EIUGame.PPM, gameCam);
    parallaxCam.setToOrtho(false, EIUGame.V_WIDTH / EIUGame.PPM, EIUGame.V_HEIGHT / EIUGame.PPM);

    // Center the camera at the gamePort
    gameCam.position.set(gamePort.getWorldWidth() / 2 +32f, gamePort.getWorldHeight() / 2, 0);

    // Map loading and layer definitions to specify what we are drawing for the map //
    maploader = new TmxMapLoader();
    map = maploader.load("TestLevel.tmx");

    imgLayer = (TiledMapImageLayer)map.getLayers().get(backgroundLayer);
    tileLayer = (TiledMapTileLayer)map.getLayers().get(foregroundLayer);

    // Pass our tile map to a MapRenderer so that we can manipulate the batch for drawing and update purposes
    mapRenderer = new OrthogonalTiledMapRenderer(map, 1 / EIUGame.PPM); 

    hud = new Hud(game.batch);                  // Add an instance of the game HUD      

    // Box2D initialization
    // Gravity set to -10, set bodies to "rest" that don't need physics calculations
    world = new World(new Vector2(0,-10), true);
    b2dr = new Box2DDebugRenderer(); 

    creator = new B2DWorldCreator(this);            // Create Box2D map

    // Create Champion in game world
    champ = new Champion(this); 

    // Contact listener for hitting head on objects
    world.setContactListener(new WorldContactListener());

    pause = new PauseState(game);
    pause.addPauseToStage(hud.stage);

    // Since we have multiple input processors to work with it'll be best to use a multiplexer
    InputMultiplexer multiplexer = new InputMultiplexer();
    multiplexer.addProcessor(hud.getStage());
    multiplexer.addProcessor(gamepad.getStage());
    Gdx.input.setInputProcessor(multiplexer);
}

// Simple method to return atlas
public TextureAtlas getAtlas(){
    return atlas;
}

@Override
public void show() {}

// Updating of Game World
public void update(float dt){


    // Clear the game screen with black            // Move to render
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    for (Enemy enemy : creator.getCogs()){
        enemy.update(dt);

        if(!enemy.isDestroyed() && enemy.getX() < champ.getX() + 224 / EIUGame.PPM)
            enemy.b2body.setActive(true);
    }

    config.animateChamp(champ);
    gamepad.animateChamp(champ, pause);

    // Run at 60fps, velocity of 6, position 2
    world.step(1/60f, 6, 2);

    // Update the champion
    champ.update(dt);

    hud.update(dt);

    // Move camera with champion
    parallaxCam.position.x = champ.b2body.getPosition().x/2.00f + 1.1f;     
    parallaxCam.update();       
    mapRenderer.setView(parallaxCam);
    mapRenderer.renderImageLayer(imgLayer);     

    gameCam.position.x = champ.b2body.getPosition().x;      
    gameCam.update();       
    mapRenderer.setView(gameCam);
    mapRenderer.renderTileLayer(tileLayer);

}

@Override
public void render(float delta) {

    if(Gdx.input.isKeyJustPressed(Input.Keys.ESCAPE)) {
        pause.togglePause();                        
    }

    // If the game is paused prevent character movement and HUD updates
    if(!pause.getPauseState()) {

        // Get the batch to begin updating the screen
        mapRenderer.getBatch().begin(); 

        // Handles player movement
        update(delta);

        champ.draw(mapRenderer.getBatch()); 
        for (Enemy enemy : creator.getCogs())
            enemy.draw(mapRenderer.getBatch());

        mapRenderer.getBatch().end();

        //b2dr.render(world, gameCam.combined);
    }
    hud.stage.draw();   
    gamepad.draw();
} 

@Override
public void resize(int width, int height) {
    gamePort.update(width, height);
    gamepad.resize(width, height);
}

public TiledMap getMap(){
    return map;
}

public World getWorld(){
    return world;
}

@Override
public void pause() {}

@Override
public void resume() {}

@Override
public void hide() {}

@Override
public void dispose() {
    map.dispose();
    mapRenderer.dispose();
    world.dispose();
    b2dr.dispose();
    hud.dispose();
    gamepad.dispose();
}

}

我知道这要经历很多事情。但是,我自己花了很多时间在这上面,似乎无法弄明白。是时候问专家了。

0 个答案:

没有答案