5

タイルを使ったJavaゲームを作っています。衝突要素に問題があります。マップ上の各タイルに四角形を定義し、プレーヤーに別の四角形を定義しています。私が問題を抱えているのは、プレーヤーが長方形に当たったときにどちら側から来たのかを知り、プレーヤーが来た方向にプレーヤーを押しのけることです。文字が四角形の内側にどれだけ入っているかを確認するメソッドを既に作成しているので、押し出す量を知ることができますが、文字がどちら側から来ているかを知る方法がわかりません。

ここに私の現在の衝突方法があります-rect1がキャラクターで、rect2がタイルであることに注意してください

public void collision(Rectangle rect1, Rectangle rect2) {
    float xAdd;
    float xAdd2;
    float yAdd;
    float yAdd2;

    boolean hitRight = false;
    boolean hitLeft = false;
    boolean hitTop = false;
    boolean hitBot = false;

    Vector2f rect1Origin = new Vector2f(rect1.x, rect1.y);
    Vector2f rect2Origin = new Vector2f(rect2.x, rect2.y);
    Vector2f rect1Mid = new Vector2f((rect1.x + rect1.width) / 2,(rect1.y + rect1.height) / 2);
    Vector2f rect2Mid = new Vector2f((rect2.x + rect2.width) / 2,(rect2.y + rect2.height) / 2);

    Vector2f rect1A = new Vector2f(rect1Origin.x + rect1.width, rect1.y);
    Vector2f rect1B = new Vector2f(rect1Origin.x, rect1Origin.y+ rect1.height);
    Vector2f rect1C = new Vector2f(rect1Origin.x + rect1.width,rect1Origin.y + rect1.height);

    Vector2f rect2A = new Vector2f(rect2Origin.x + rect2.width, rect2.y);
    Vector2f rect2B = new Vector2f(rect2Origin.x, rect2Origin.y
            + rect2.height);
    Vector2f rect2C = new Vector2f(rect2Origin.x + rect2.width,
            rect2Origin.y + rect2.height);

    xAdd = rect2C.x - rect1B.x;
    xAdd2 = rect1C.x - rect2B.x;

    yAdd = rect2A.y - rect1B.y;
    yAdd2 = rect2C.y - rect1A.y;


    if (rect1Mid.y < rect2Mid.y) {
        if (rect1.intersects(rect2)) {
            y_pos += yAdd;
        }
    }
    if (rect1Mid.y > rect2Mid.y) {
        if (rect1.intersects(rect2)) {
            System.out.println(yAdd2);
            y_pos += yAdd2;
        }

    }
    if(rect1Mid.x > rect2Mid.x){
        if(rect1.intersects(rect2)){
            hitRight = true; x_pos += xAdd;
        }
    } 
    if(rect1Mid.x< rect2Mid.x){ 
          if(rect1.intersects(rect2)) {
              x_pos += -xAdd2;
          } 
    }
}

どんな助けでも大歓迎です

ありがとう

4

4 に答える 4

2

キャラクターの 2 つの位置を保持します - キャラクターの位置 (最後のフレーム、移動など) と、キャラクターを動かしたい場所です。次に、衝突を検出しない場合にのみ移動します。破損した状態を許可しない場合は、修正する必要はありません。

編集:collisionメソッドは次のようにする必要がありますboolean-実際にキャラクターを移動する前に実行する必要があります

if (!collision(character, tile))
{
    doMove(character);
}
else
{
    //custom handling if required
}

Edit2:前のものは小さなステップでしか機能しません。部分的な移動が必要な場合は、 と から方向を推測できる のようなキャラクターの元の位置を本当に知る必要がありmove(originalPosition, desiredPosition, tile)ます。originalPositiontile

重要なポイントは、有効な位置を取得する前に、実際にキャラクターを動かさないことです。

于 2012-04-29T15:27:21.403 に答える
1

まず、スプライト(ここではキャラクターとタイル) には、xPos、yPos、xVec、yVec の 4 つのメンバーが必要です。それを念頭に置いて、キャラクターがどこにいて、次のフレームにいるのかがわかります。

sprite.xPos += sprite.xVec;
sprite.yPos += sprite.yVec;

また、コードを見てください。命題を改善する必要があります (たとえば、4 つのifステートメントでif(rect1.intersects(rect2))をチェックします)。代わりに、intersects()を 1 回だけチェックし、考えられるケース (左、右、上、下のヒット) ごとに内部をチェックします。

最後に、衝突メソッドは 2 つのスプライト オブジェクト (たとえば、sprite1sprite2 ) を受け取り、両方のスプライトとそのベクトルの元の位置を考慮して、 intersects()メソッドをチェックする必要があります。スプライトが新しい位置で交差する場合は、それに応じてオブジェクトのベクトルを反転します。

于 2012-04-29T16:20:08.030 に答える
1

コードとの衝突を検出できると仮定します。長方形オブジェクトに対するキャラクターの位置を決定する方法を次に示します。

  1. 長方形の中点を見つけます。(Rx、Ry)。

  2. キャラクター スプライトの中間点を見つけます。(Sx、Sy)。

  3. これで、Rx、Ry、Sx、Sy を比較して、Rx と Ry のどちら側に Sx と Sy があるかを判断できます。

  4. 例:

    if Sx < Rx then
      Sx = left side of Rx
    
于 2012-05-03T09:42:55.783 に答える
1

私自身これに苦労していましたが、すべてのエンティティをリストに入れることでこのチェックを実行できると考えた後、私のコードでは、プレーヤーがブロックを移動するのをブロックする必要がありました。すべてのブロックはリストにあります。ここで、プレーヤーの位置を確認するときに、新しい Rectangle を作成し、次のフレームで更新が発生する方向にプレーヤーの位置を 1 フレーム進めます。長方形が交差する場合、その方向の更新は発生しません。これに対する私のコードは次のとおりです。

    if (isKeyPressed(KeyEvent.VK_LEFT)) {
        if(!collisionWithBlocks(1)){
            pl.x = pl.x - updatePlayerPosition;
        }
    }
    if (isKeyPressed(KeyEvent.VK_RIGHT)) {
        if(!collisionWithBlocks(0)){
            pl.x = pl.x + updatePlayerPosition;
        }
    }
    if (isKeyPressed(KeyEvent.VK_UP)) {
        if(!collisionWithBlocks(3)){
            pl.y = pl.y - updatePlayerPosition;
        }
    }
    if (isKeyPressed(KeyEvent.VK_DOWN)) {
        if(!collisionWithBlocks(2)){
            pl.y = pl.y + updatePlayerPosition;
        }
    }

コリジョンウィズブロック():

public boolean collisionWithBlocks(int side){
    for(Block b : main.blocks){
        Rectangle block = b.getBounds();
        Rectangle player = null;
        if(side == 0){
            player = new Rectangle(pl.x + updatePlayerPosition, pl.y, pl.getWidth(), pl.getHeight());
        } else if(side == 1){
            player = new Rectangle(pl.x - updatePlayerPosition, pl.y, pl.getWidth(), pl.getHeight());
        } else if(side == 2){
            player = new Rectangle(pl.x, pl.y + updatePlayerPosition, pl.getWidth(), pl.getHeight());
        } else if(side == 3){
            player = new Rectangle(pl.x, pl.y - updatePlayerPosition, pl.getWidth(), pl.getHeight());
        }

        if(player.intersects(block)){
            return true;
        }
    }

    return false;
}

updatePlayerPosition は 2 で、コードを変更しましたが、それで十分です。あなたの場合、エンティティをリストに入れてから、私がやったようにチェックすることをお勧めします。

于 2013-08-12T13:08:26.230 に答える