处理中的多个类

时间:2014-10-23 16:57:11

标签: java collision-detection

我正在制作一个游戏,你正在控制一个正方形,物体将在随机的地方产生,你必须拿起来获得积分,同时还必须躲避从一边到另一边的大方块。现在我有2个类(一个用于敌人 - 大方块 - 和一个用于英雄),我还没有使用产卵对象完成点系统,但这不是我现在要做的。

所以我现在的问题是,当你用英雄触碰“敌人”时,我真的不知道如何让这个人输掉游戏/生命。我会知道如何在没有课程的情况下这样做,但我想知道如何在不同的课程中这样做。

如果有人可以解释代码和评论如何做到这一点,它会帮助我很多:)(我读了一些关于类的'扩展',但我不确定这是否是我应该使用的或不是)。

这是我的游戏目前的样子截图,只是为了更好地说明它:

http://i.gyazo.com/d87f4353064da39ec7a91a28febcc1ca.png

这是主要代码页:

Hero myHero = new Hero(400,480,5);
Enemies myEnemies = new Enemies(50,50,10);
Enemies myEnemies2 = new Enemies(50,350,15);
Enemies myEnemies3 = new Enemies(50,650,12);

void setup() {
    size(900,800);
    frameRate(30);
    smooth();
}

void draw() {
    background(0);
    myHero.keyPressed();
    myEnemies.enemyDisplay();
    myEnemies.enemyMove();
    myEnemies2.enemyDisplay();
    myEnemies2.enemyMove();
    myEnemies3.enemyDisplay();
    myEnemies3.enemyMove();
}

第1课:

class Enemies {
    float xpos, ypos, speed;

    Enemies(float x, float y, float s) {
        xpos = x;
        ypos = y;
        speed = s;
    } 

    void enemyDisplay() {
        rect(xpos, ypos, 100, 100); 
    }

    void enemyMove() {
        xpos += speed;
        if((xpos > width - 100) || (xpos < 0)) {
            speed *= -1;
        }
    }
}

第2课:

class Hero {
    float xpos_, ypos_, speed_;

    Hero(float x, float y, float s) {
        xpos_ = x;
        ypos_ = y;
        speed_ = s;
    }     

    void keyPressed() {
        if (key == CODED) {
            if (keyCode == UP) {
                ypos_ -= speed_;
            }
            if (keyCode == DOWN) {
                ypos_ += speed_;
            }
            if (keyCode == LEFT) {
                xpos_ -= speed_;
            }
            if (keyCode == RIGHT) {
                xpos_ += speed_;
            }     
        }
        rect(xpos_,ypos_,30,30);
    }
}

5 个答案:

答案 0 :(得分:1)

我相信你提出的问题涉及基本的碰撞检测和对象交互。

我会先Enemies一个List并在setup()来电期间创建/添加元素:

List<Enemies> enemies = new List<Enemies>();
enemies.add(new Enemies(50,50,10));

这允许您将所有Enemies存储在一个对象下。因此,您的draw()方法看起来像:

void draw(){
    background(0);
    myHero.keyPressed();

    for(Enemies enemy : enemies)
    {
        enemy.enemyDisplay();
        enemy.enemyMove();

        if (hero.isCollidingWith(enemy)) // collision method defined in the hero object, but you could define it in the Enemies class as well, it doesn't really matter
        {
            hero.removeHealth(); // method defined in hero that removes health
        }
    }
}

此方法将在您的某个类中:

public boolean isColliding(Enemies enemy)
{
  // check the x and y coordinates of each object

}

我希望这有助于指出你正确的方向。

答案 1 :(得分:0)

你需要弄清楚碰撞检测以及当你的物体相互碰撞时,基本的东西如:

class Enemy 
{
//...
public boolean isColliding(Hero hero)
{
  //figure out the distance between two objects, if its less than their size, they are colliding..
  //...
}
//...
}

然后你需要游戏循环的一部分来检查是否有任何东西与你的英雄,皮卡,墙壁等相撞......

答案 2 :(得分:0)

看来你需要帮助的第一部分是碰撞检测。我给出的简短回答几乎无疑会引导你更多的问题是看看Area类(特别是Area.intersect)。您可能还想查看我为了显示而放置的类。管理区域in this project here

答案 3 :(得分:0)

这里有几个问题涉及应用程序设计和约定。在尝试解决碰撞检测问题之前,应首先解决这些问题。

Enemies类只代表一个敌人,因此该类的名称应该反映出来。另外,在方法名称前加上&#34;敌人&#34;是多余的,可以删除。其他更改已在下面的修订版中进行了评论。

public class Enemy {
  // Instead of hard-coding in the width and height of an enemy, allow the 
  // instantiating code to specify the enemy's size.  This will allow you 
  // to have different size enemies and prevents you from having "magic numbers" 
  // in your code.
  private float xpos, ypos, width, height, speed;

  public Enemy(float x, float y, float s, float w, float h) {
    xpos = x;
    ypos = y;
    width = w;
    height = h;
    speed = s;
  }

  /* These getters will be used for collision detection later */

  public float getX() {
    return xpos;
  }

  public float getY() {
    return ypos;
  }

  public float getWidth() {
    return width;
  }

  public float getHeight() {
    return height;
  }

  // I've changed `display` to `draw` to be consistent with the method name in 
  // your main `draw` method.
  public void draw() {
    rect(xpos, ypos, width, height); 
  }

  // This method now accepts a screenWidth parameter so that the enemy can know
  // when they've collided with the left or right wall of the screen without 
  // having to rely on an global variable.
  public void move(int screenWidth) {
    xpos += speed;

    if ((xpos > screenWidth - width) || (xpos < 0)) {
      speed *= -1;
    }
  }
}

我提到了#34;魔术数字&#34;在上面的一条评论中。有关详情,请参阅此wikipedia article

Hero类包含具有下划线后缀的属性名称。其范围从非常规到与其他类中的所有其他属性名称不一致。原始的keyPressed()方法混合了绘图和移动的逻辑。这两件事已经分开,并且方法的名称与Enemy类的名称相同。

public class Hero {
  private float xpos, ypos, width, height, speed;

  public Hero(float x, float y, float s, float w, float h) {
    xpos = x;
    ypos = y;
    width = w;
    height = h;
    speed = s;
  }

  // Change this method name to draw for consistency with the Enemy class
  public void draw() {
    // Key press functionality has been moved to the `move` method for consistency 
    // with the Enemy class.
    rect(xpos, ypos, WIDTH, HEIGHT);
  }

  // This method uses the variables key, keyCoded, UP, DOWN, LEFT, and RIGHT.  You 
  // did not include any import statements with your code, so they may be coming 
  // from there; however, if they are globals, you should pass them to this method 
  // as arguments whenever you call it.
  public void move() {
    // If this condition isn't satisfied, return immediately.  This prevents 
    // unnecessary nesting and work below.
    if (key != CODED) {
      return;
    }

    if (keyCode == UP) {
      ypos -= speed;
    }
    // Use `else if` here and below to prevent multiple unnecessary 
    // comparisons of keyCode.
    else if (keyCode == DOWN) {
      ypos += speed;
    }
    else if (keyCode == LEFT) {
      xpos -= speed;
    }
    else if (keyCode == RIGHT) {
      xpos += speed;
    }
  }

  public boolean isColliding(Enemy enemy) {
     // Collision detection is easy since all of your game entities (the hero and 
     // the enemies) are all rectangles and axis-aligned (not rotated). You can 
     // use a method known as "bounding box intersection."

     return (Math.abs(enemy.getX() - xpos) * 2 < (enemy.getWidth() + width))
       && (Math.abs(enemy.getY() - ypos) * 2 < (enemy.getHeight() + height));
  }
}

有关边界框交叉点的更多信息,请参阅此gamedev stackexchange question

现在您的课程已经完成,是时候解决您的主要代码了。我们需要更新方法名称,正如@James T建议的那样,你应该制作一个敌人列表,而不是为每个敌人创建一个新的独立对象。这将使您更容易在将来添加或移除敌人,并且能够使用一个代码块处理所有敌人而无需重复自己。

// Use constants to remove magic numbers.
private static final int SCREEN_WIDTH = 900;
private static final int SCREEN_HEIGHT = 800;

private Hero myHero = new Hero(400, 480, 30, 30, 5);
private List<Enemy> enemies = new ArrayList<Enemy>();

void setup() {
  size(SCREEN_WIDTH, SCREEN_HEIGHT);
  frameRate(30);
  smooth();

  enemies.add(new Enemy(50, 50, 100, 100, 10));
  enemies.add(new Enemy(50, 350, 100, 100, 15));
  enemies.add(new Enemy(50, 650, 100, 100, 12));
}

void draw() {
  hasCollision = false;

  background(0);

  // I've changed the order of draw->move to move->draw.  If you draw first, then 
  // move, then detect collisions, it will appear to your user that your hero has 
  // not yet collided with an enemy even though you act as they have (e.g.: they 
  // will not see the collision until the next time you draw the scene).
  myHero.move();
  myHero.draw();

  for (Enemy enemy : enemies) {
    enemy.move();
    enemy.draw(SCREEN_WIDTH);

    if (!hasCollision &&  myHero.isColliding(enemy)) {
      hasCollision = true;
    }
  }

  if (hasCollision) {
    // Handle enemy collision here
  }
}

您会注意到我还为所有内容添加了辅助功能修饰符。虽然在技术上有效地排除它们并使用默认值,但它使您的代码更易于包含它们,因为它更明显。当你第一次出发时,越明显越好。

答案 4 :(得分:0)

感谢你们所有乐于助人的人们,让它工作!

我这样做了:

public boolean isColliding(Enemies h){
   float distance = dist(x,y,h.x,h.y);
    if(distance<100){
      return true;
    }else{
      return false;
    }
  }

在我的画中(){我有

 if(myHero.isColliding(myEnemies)){
    println("You lost!");
  }

我有一个非常相似的解决方案&#39;早些时候,但我之所以出现错误的原因是因为我有“Hero h”而不是“Enemies h”中的“如果&#39;功能,所以我忽略了一个非常愚蠢的错误:P