2012-04-29 33 views
5

Tôi đang tạo trò chơi java bằng cách sử dụng các ô xếp kề. Tôi đang gặp rắc rối với yếu tố va chạm. Tôi đang xác định hình chữ nhật cho mỗi ô trên bản đồ và một hình chữ nhật khác cho trình phát. Những gì tôi gặp khó khăn là biết bên nào người chơi đến từ khi nó chạm vào hình chữ nhật, và sau đó đẩy người chơi ra theo hướng người chơi đến. Tôi đã thực hiện một phương pháp kiểm tra xem ký tự có bao nhiêu bên trong hình chữ nhật, vì vậy nó có thể biết bao nhiêu để đẩy nó ra, nhưng tôi không thể tìm ra cách để biết bên nào nhân vật đến từ đó.Trò chơi xếp hình Java - Phát hiện va chạm

đây là hiện va chạm methoe tôi - lưu ý rect1 là nhân vật và rect2 là ngói

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; 
      } 
    } 
} 

Bất kỳ trợ giúp sẽ được đánh giá cao

Cảm ơn

Trả lời

2

Giữ hai vị trí cho nhân vật của bạn - nơi nó là (như khung cuối cùng, di chuyển, vv), và nơi bạn muốn di chuyển nó. Sau đó, chỉ di chuyển nó nếu bạn không phát hiện va chạm - nếu bạn không cho phép trạng thái bị hỏng, bạn không phải sửa chữa nó.

Edit: Phương pháp collision nên boolean - nó nên được thực hiện trước thực sự di chuyển nhân vật, như

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

Edit2: Các trước sẽ chỉ làm việc cho một bước nhỏ, nếu bạn cần di chuyển một phần, bạn thực sự cần biết vị trí ban đầu của nhân vật, như move(originalPosition, desiredPosition, tile), tại đó bạn có thể suy ra hướng từ originalPositiontile.

Điểm chính là, bạn không thực sự di chuyển nhân vật, trước khi bạn có vị trí hợp lệ cho nó.

+0

Điều này sẽ dẫn đến tình huống lạ, tùy thuộc vào khoảng thời gian bước. – Matzi

+0

@Matzi Không thực sự, điều xác thực trước khi thực hiện một số lệnh người dùng - nếu nó không xác nhận, bạn có thể thực hiện xử lý tùy chỉnh. – jmruc

+0

@KirilRaychev Tôi không thực sự hiểu những gì bạn đang cố gắng để nói – grimrader22

1

Trước hết, bất kỳ Sprite (ký tự và ô ở đây) phải có bốn thành viên: xPos, yPos, xVec, yVec. Với ý nghĩ đó, bạn biết nhân vật ở đâu và sẽ ở trong khung tiếp theo.

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

Ngoài ra hãy xem xét mã của bạn, bạn nên nâng cao mệnh đề (ví dụ, bạn kiểm tra if (rect1.intersects (rect2)) trong bốn nếu báo cáo). Thay vào đó, chỉ kiểm tra một lần cho các giao lộ () và kiểm tra bên trong từng trường hợp có thể (trái, phải, trên cùng, dưới cùng).

Cuối cùng, phương pháp va chạm sẽ nhận được 2 sprites đối tượng (ví dụ, sprite1sprite2), và sau đó kiểm tra cho giao cắt() phương pháp, có tính đến vị trí ban đầu của cả hai mảng đồ họa, nó vectơ. Nếu các sprites giao nhau ở vị trí mới, thì bạn đảo ngược vector của đối tượng cho phù hợp.

+0

Các biến xVec và yVec đại diện cho những gì? – grimrader22

+0

Tôi xin lỗi tôi đã không rõ ràng, đó là những vectơ định hướng của sprite (bạn cũng có thể sử dụng Vector2f hoặc Point2D). Giá trị có thể được hiểu là tốc độ của ma sát theo mỗi hướng. Vì vậy, nếu nhân vật chạm vào gạch chính xác từ bên trái, xVec là một giá trị dương, và yVec là 0; và sau lần truy cập, xVec phải có cùng giá trị, nhưng bây giờ âm. Hãy cho tôi biết nếu bạn cần thêm sự giúp đỡ. –

+0

Tôi không hoàn toàn hiểu những gì bạn đang nói, xin lỗi nếu tôi câm. Liệu các vand y Vecs có phải là vận tốc không? – grimrader22

1

Giả sử bạn có thể phát hiện xung đột với mã của bạn. Đây là một cách để xác định vị trí của nhân vật của bạn đối với đối tượng hình chữ nhật.

  1. Tìm điểm giữa của hình chữ nhật. (Rx, Ry).

  2. Tìm điểm giữa của ký tự nhân vật của bạn. (Sx, Sy).

  3. Bây giờ bạn có thể so sánh Rx, Ry, Sx, Sy để xác định, trong đó bên là Sx và Sỹ của Rx và Ry

  4. cho ví dụ:

    if Sx < Rx then 
        Sx = left side of Rx 
    
1

Được đấu tranh với điều này bản thân mình, nhưng sau khi một số suy nghĩ kiểm tra này có thể được thực hiện bằng cách có tất cả các thực thể của bạn trong một danh sách, trong mã của tôi, tôi đã phải ngăn chặn người chơi di chuyển qua các khối. Tất cả các khối đều nằm trong Danh sách. Bây giờ, khi kiểm tra vị trí người chơi tôi tạo ra một hình chữ nhật mới và đặt các vị trí người chơi một khung về phía trước theo hướng cập nhật sẽ xảy ra khung tiếp theo, nếu hình chữ nhật cắt ngang cập nhật cho hướng đó sẽ không xảy ra. Heres mã của tôi cho điều này:

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; 
     } 
    } 

collisionWithBlocks():

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 là 2, và những thay đổi trong mã của tôi, nhưng đủ về điều đó. Trong trường hợp của bạn, tôi khuyên bạn nên đặt các thực thể trong Danh sách và sau đó kiểm tra như tôi đã làm.