2016-08-24 11 views
0

私は蛇のゲームを作りました。そして、蛇と食べ物の間に衝突があるとき、それはスコアに1を加えることになっています。その代わりに、ヘビが食べ物を食べたら何が起こるか、複数のポイントが追加されます。リンゴには複数の器具が付いています(おそらく複数の衝突が検出されているためです)。スコアが1ポイントだけ上がることを確認する方法はありますか?いくつかのアイデアが参考になるでしょう。複数の衝突とスコアの維持

ブール値を使用して、食品の再配置が完了しても問題が解決されない限り、衝突が登録されていないことを確認しました。

コード:(関連性のないコードの中には人がいないので、オブジェクトのポリゴンシェイプの頂点のベクトル2のリストがあります)

Apple.java:

public class Apple { 

    private Sprite img; 
    private float width, x, y; 
    private Body body; 

    private Vector2[][] vertices; 
    public boolean isRelocating; 
    private Vector2 previousPosition; 

    //constructor 
    public Apple(float x, float y, float width, World world) { 
     this.x = x; 
     this.y = y; 
     this.width = width; 
     isRelocating = false; 
     //intialize previous number to a mechncially imposible number 
     previousPosition = new Vector2(-100, -100); 

     img = new Sprite(new Texture(Gdx.files.internal("Emoji/Red Apple.png"))); 
     img.setSize(width, width * 0.9416f); 
     img.setPosition(x, y); 

     //set up the physics body 
     BodyDef def = new BodyDef(); 
     def.type = BodyDef.BodyType.DynamicBody; //keep it dynamic so collisions can be collected 
     def.position.set(x, y); 
     body = world.createBody(def); 

     loadVertices(); 
     //scale vertices accroding to the width 
     for (int i = 0; i < vertices.length; i++) { 
      for (int j = 0; j < vertices[i].length; j++) { 
       vertices[i][j].scl(width); 
      } 
     } 

     //attach multiple fixtures to the body 
     FixtureDef fixtureDef = new FixtureDef(); 
     PolygonShape shape = new PolygonShape(); 
     fixtureDef.isSensor = true; 
     shape.set(vertices[0]); 

    } 

    public void update(float dt) { 
     img.setPosition(x, y); 
     body.setTransform(x, y, body.getAngle()); 
    } 

    public void draw(SpriteBatch batch) { 
     batch.begin(); 
     img.setAlpha(0.1f); 
     img.draw(batch); 
     batch.end(); 
    } 

    public void changePosition(float newX, float newY) { 
     x = newX; 
     y = newY; 
     body.setTransform(x,y,body.getAngle()); 
     isRelocating = false; 
    } 

    public float getWidth(){ 
     return img.getWidth(); 
    } 

    public float getHeight(){ 
     return img.getHeight(); 
    } 

    public Vector2 getPosition(){ 
     return new Vector2(x,y); 
    } 

    public Vector2 getPreviousPosition(){ 
     return previousPosition; 
    } 

    public void setPreviousPosition(Vector2 value){ 
     previousPosition = value; 
    } 

} 

Snake.java:

public class Snake { 

    private ArrayList<Segment> snake; 
    private float speed; 
    private World worldRef; 
    private float width; 

    public Snake(float x, float y, float width, float speed, World world) { 
     snake = new ArrayList<Segment>(); 

     this.speed = speed; 
     worldRef = world; 

     //add the head 
     snake.add(new Segment(width, x, y, true, Segment.Direction.UP, speed, world)); 

    } 

    public void draw(SpriteBatch batch){ 
     for (int i = 0; i < snake.size(); i ++){ 
      snake.get(i).draw(batch); 
     } 
    } 

    public void update(float dt){ 
     for (int i = 0; i < snake.size(); i ++){ 
      snake.get(i).update(dt); 
     } 
    } 


    public void changeDirection(Segment.Direction direction){ 
     //change the direction of the head, and the rest will follow 
     snake.get(0).setDirection(direction); 
    } 

    public Rectangle[] getTakeArea(){ 
     Rectangle[] rects = new Rectangle[snake.size()]; 
     for (int i = 0; i < rects.length; i ++){ 
      rects[i] = snake.get(i).getArea(); 
     } 
     return rects; 
    } 

    public float getWidth(){ 
     return width; 
    } 



} 

Segment.java:

public class Segment { 

    //direction enum 
    public enum Direction { 
     UP, 
     DOWN, 
     LEFT, 
     RIGHT; 
    } 

    private Sprite img; 
    private float width, x, y; 

    private Body body; 
    private float speed; 
    private Direction direction; 
    private boolean isHead; 

    private Vector2[] vertices1; 
    private Vector2[] vertices2; 
    private Vector2[] vertices3; 
    private Vector2[] vertices4; 

    //constructor 
    public Segment(float width, float x, float y, boolean isHead, Direction 
      direction, float speed, World world) { 
     this.width = width; 
     this.x = x; 
     this.y = y; 
     this.direction = direction; 
     this.speed = speed; 
     this.isHead = isHead; 

     if (isHead) 
      img = new Sprite(new Texture(Gdx.files.internal("Emoji/Tears of Joy.png"))); 
     else 
      img = new Sprite(new Texture(Gdx.files.internal("Emoji/Smiling Face with Mouth Open" + 
        ".png"))); 
     img.setSize(width, width); 
     img.setPosition(x, y); 

     //load up the physcis 
     BodyDef bodyDef = new BodyDef(); 
     bodyDef.position.set(x, y); 
     bodyDef.type = BodyDef.BodyType.DynamicBody; 
     body = world.createBody(bodyDef); 

     //load up fixtures 
     loadVertices(); 
     for (int i = 0; i < vertices1.length; i++) { 
      vertices1[i].scl(width); 
      vertices2[i].scl(width); 
      vertices3[i].scl(width); 
      vertices4[i].scl(width); 
     } 

     FixtureDef fixtureDef = new FixtureDef(); 
     fixtureDef.friction = 0; 
     fixtureDef.restitution = 1; 
     PolygonShape shape1 = new PolygonShape(); 

     shape1.set(vertices1); 
     fixtureDef.shape = shape1; 
     body.createFixture(fixtureDef); 


     shape1.dispose(); 

     //add userData to all the fixtures 
     for (int i = 0; i < body.getFixtureList().size; i++) { 
      body.getFixtureList().get(i).setUserData(new UserData("segment")); 
     } 
    } 


    public void update(float dt) { 
     //update the position based on the speed 
     switch (direction) { 
      case UP: 
       body.setLinearVelocity(0, speed); 
       break; 
      case DOWN: 
       body.setLinearVelocity(0, -speed); 
       break; 
      case RIGHT: 
       body.setLinearVelocity(speed, 0); 
       break; 
      case LEFT: 
       body.setLinearVelocity(-speed, 0); 
       break; 
     } 
     //make sure that the segment stays in side the camara 
     if (x > (Launcher.WIDTH/SnakeMain.PPM)) 
      body.setTransform(x - (Launcher.WIDTH/SnakeMain.PPM) - width,y, body.getAngle()); 


     x = body.getPosition().x; 
     y = body.getPosition().y; 
     //have to adjust the sprite if it is head 
     if (isHead) { 
      img.setPosition(x - (width * 0.03f), y - (width * 0.024f)); 
     } else { 
      img.setPosition(x, y); 
     } 
     img.setRotation((float) Math.toDegrees(body.getAngle())); 
    } 

    public void draw(SpriteBatch batch) { 
     batch.begin(); 
     img.setAlpha(0.1f); 
     img.draw(batch); 
     batch.end(); 
    } 

    public Direction getDirection() { 
     return direction; 
    } 

    public Rectangle getArea(){ 
     return new Rectangle(x,y,width,width); 
    } 


    public void setDirection(Direction newDirection) { 
     direction = newDirection; 
    } 
} 

SnakeMain.java:

public class SnakeMain implements Screen { 
    private Launcher mainRef; 

    private OrthographicCamera camera; 
    private FitViewport viewport; 

    private World world; 
    private Box2DDebugRenderer debugRenderer; 
    public static final float PPM = 100; 

    private Snake snake; 
    private Apple apple; 

    private Stage HUD; 
    private Table hubTable; 
    private Label lblScore; 

    private int score = 0; 

    //constructor 
    public SnakeMain(Launcher main) { 
     mainRef = main; 

     camera = new OrthographicCamera(); 
     viewport = new FitViewport(Launcher.WIDTH/PPM, Launcher.HEIGHT/PPM, camera); 
     viewport.apply(); 

     world = new World(new Vector2(0, 0), true); 
     debugRenderer = new Box2DDebugRenderer(); 

     snake = new Snake((Launcher.WIDTH/2)/PPM, (Launcher.HEIGHT/2)/PPM, 200/PPM, 400 
       /PPM, world); 
     apple = new Apple((Launcher.WIDTH/2)/PPM, (Launcher.HEIGHT/2 - 300)/PPM, 200/PPM, 
       world); 

     world.setContactListener(new CollisionDetector(this)); 
     Gdx.input.setInputProcessor(new GestureDetector(new TouchListener(snake))); 

     HUD = new Stage(); 
     HUD.setViewport(new FitViewport(Launcher.WIDTH /3, Launcher.HEIGHT/3, new OrthographicCamera 
       ())); 
     hubTable = new Table(); 
     String strScore = "Score: " + score; 
     lblScore = new Label(strScore, mainRef.getSkin(), "small38"); 
     hubTable.add(lblScore); 
     hubTable.top(); 
     hubTable.padTop(10); 
     hubTable.setFillParent(true); 
     HUD.addActor(hubTable); 


    } 

    @Override 
    public void show() { 

    } 

    public void update(float delta) { 
     world.step(1/30f, 6, 2); 
     snake.update(delta); 
     apple.update(delta); 
     lblScore.act(delta); 
     HUD.act(); 
    } 

    @Override 
    public void render(float delta) { 
     update(delta); 
     debugRenderer.render(world, camera.combined); 
     mainRef.batch.setProjectionMatrix(camera.combined); 
     snake.draw(mainRef.batch); 
     apple.draw(mainRef.batch); 
     HUD.draw(); 
    } 

    public Apple getApple(){ 
     return apple; 
    } 

    //handles things when the snake eats the food 
    public void foodEaten() { 
     score ++; 
     String strScore = "Score: " + score; 
     lblScore.setText(strScore); 

     //relocate the food to a new location 
     boolean isValid = false; 
     float newX = -1; 
     float newY = -1; 
     Rectangle rect = new Rectangle(); 
     while (!isValid) { 
      newX = (float) Math.random() * (Launcher.WIDTH - apple.getWidth() * PPM); 
      newY = (float) Math.random() * (Launcher.HEIGHT - apple.getHeight() * PPM); 
      rect.set(newX, newY, apple.getWidth(), apple.getHeight()); 

      isValid = true; 
      //check to make sure that the apple will not be in the same position as the snake 
      for (int i = 0; i < snake.getTakeArea().length; i++) { 
       if (rect.overlaps(snake.getTakeArea()[i])) { 
        isValid = false; 
       } 
      } 
     } 
     apple.changePosition(newX/PPM, newY/PPM); 
     Gdx.app.log("SnakeMain.java", "Done relocating the apple"); 

    } 

    @Override 
    public void resize(int width, int height) { 
     viewport.update(width, height, true); 
     HUD.getViewport().update(width,height,true); 
    } 

    @Override 
    public void pause() { 

    } 

    @Override 
    public void resume() { 

    } 

    @Override 
    public void hide() { 

    } 

    @Override 
    public void dispose() { 

    } 
} 

CollisionDetector.java:

public class CollisionDetector implements ContactListener { 

    private SnakeMain mainRef; 

    //constructor 
    public CollisionDetector(SnakeMain main) { 
     mainRef = main; 
    } 


    @Override 
    public void beginContact(Contact contact) { 
     try { 
      UserData userData1 = (UserData) contact.getFixtureA().getUserData(); 
      UserData userData2 = (UserData) contact.getFixtureB().getUserData(); 

      //if there is a collision between an apple and a segment 
      if ((userData1.getId() == "apple" && userData2.getId() == "segment") 
        || (userData1.getId() == "segment" && userData2.getId() == "apple")) { 
       if (!mainRef.getApple().isRelocating) { 
        Gdx.app.log("Apple eaten", "About to reset Apple"); 
        Gdx.app.log("Apple eaten", "State of apple: " + mainRef.getApple() 
          .isRelocating); 
        mainRef.getApple().isRelocating = true; 
        mainRef.foodEaten(); 
       } 



      } 
     } catch (Exception e) { 
      Gdx.app.log("Error!", e.getMessage()); 
     } 
    } 

    @Override 
    public void postSolve(Contact contact, ContactImpulse impulse) { 

    } 

    @Override 
    public void endContact(Contact contact) { 

    } 

    @Override 
    public void preSolve(Contact contact, Manifold oldManifold) { 

    } 
} 

答えて

0

は、すぐにリンゴを食べているよう設定されているアップルにhasBeenEatenブール値を追加することを検討してください。次に、衝突が検出されたとき(おそらくもう一度)、foodEaten()関数を呼び出す前にhasBeenEatenのステータスをチェックします。

public void beginContact(Contact contact) { 
    try { 
     UserData userData1 = (UserData) contact.getFixtureA().getUserData(); 
     UserData userData2 = (UserData) contact.getFixtureB().getUserData(); 

     //if there is a collision between an apple and a segment 
     if ((userData1.getId() == "apple" && userData2.getId() == "segment") 
       || (userData1.getId() == "segment" && userData2.getId() == "apple")) { 
      if (!mainRef.getApple().hasBeenEaten) { 
       mainRef.getApple().isRelocating = true; 
       mainRef.getApple().hasBeenEaten = true; 
       mainRef.foodEaten(); 
      } 
     } 
    } catch (Exception e) { 
     Gdx.app.log("Error!", e.getMessage()); 
    } 
}