2009-12-09 66 views
7

Tôi xây dựng một trò chơi với QT. Mỗi đối tượng trên GraphicsScene của tôi kế thừa từ GraphicsPixmapItem (Player, Obstacles, bomb ...). Tôi muốn cấy các hiệu ứng va chạm. Ví dụ như khi người chơi được di chuột thưởng, anh ta có thể chọn nó. Với khung QT, tôi có thể nhận được các mục va chạm nhưng tôi không biết chúng thuộc loại nào vì không có hàm instanceof. Có lời khuyên nào không?Làm thế nào để thực hiện các hiệu ứng va chạm trong một trò chơi?

chỉnh sửa: Tôi nhận được sự cố "sự kiện" mà điều tôi muốn làm là xử lý các xung đột khác nhau. Tôi đã thực hiện một số khác question với từ ngữ tốt hơn.

Trả lời

9

Cân nhắc thiết kế:

Tôi không thể khuyên bạn nên kế thừa các đối tượng trò chơi từ biểu diễn đồ họa của chúng. Tại sao? Bạn có thể muốn có nhiều biểu diễn đồ họa của một đối tượng trò chơi (như một đối tượng trong chế độ xem trò chơi hoặc một đối tượng khác trong minimap hoặc bất kỳ thứ gì). Mối quan hệ là "Player" có một "đại diện đồ họa" và không phải "Player" là một "đại diện đồ họa". Giải pháp tốt hơn là sử dụng bố cục và không phải thừa kế. Hiệu ứng tốt đẹp khác là có thể đóng gói các phát hiện va chạm khác nếu bạn không hài lòng với một được cung cấp bởi Qt, tách, ... Sự thật cũng là, cho trò chơi đơn giản nó có thể là đủ mặc dù.

Đối với logic trò chơi đơn giản, kế thừa, nơi các đối tượng khác phản ứng với đối tượng đang hoạt động. Có lẽ quá đơn giản cho bất kỳ cơ chế trò chơi phức tạp hơn.

class Asteroid { 
public: 
    virtual void CollideWithPlayer(Player&) { p.loseHealth(100); } 
}; 

class ExplodingAsteroid: Asteroid { 
public: 
    virtual void CollideWithPlayer(Player&) { explode(); p.loseHealth(1000); } 
}; 

Nếu sự tương tác trở nên phức tạp (nhiều đối tượng hoạt động hành xử của riêng mình), bạn có thể cần phải xác định đối tượng của bạn:

  • Có là RTTI, nhưng erm thật khó để giới thiệu Xem: How expensive is RTTI? Trong ngắn: tốn kém, khó duy trì.

  • Bạn có thể sử dụng công văn kép. Xác định các đối tượng bằng cách sử dụng hai cuộc gọi ảo. Vấn đề: Khá một chút cú pháp, đôi khi khó duy trì (đặc biệt khi bạn thêm đối tượng mới), vấn đề quyền sở hữu (xem thêm). game ví dụ từ Wikipedia:


class SpaceShip {}; 
class GiantSpaceShip : public SpaceShip {}; 

class Asteroid { 
public: 
    virtual void CollideWith(SpaceShip&) { 
    cout << "Asteroid hit a SpaceShip" << endl; 
    } 
    virtual void CollideWith(GiantSpaceShip&) { 
    cout << "Asteroid hit a GiantSpaceShip" << endl; 
    } 
}; 

class ExplodingAsteroid : public Asteroid { 
public: 
    virtual void CollideWith(SpaceShip&) { 
    cout << "ExplodingAsteroid hit a SpaceShip" << endl; 
    } 
    virtual void CollideWith(GiantSpaceShip&) { 
    cout << "ExplodingAsteroid hit a GiantSpaceShip" << endl; 
    } 
}; 

  • "liệt kê"

ảo chức năng id

class GameObject() { 
    virtual getId() { return GAME_OBJECT; } 
}; 

class Asteroid() { 
    virtual getId() { return ASTEROID; } 
}; 

hoặc như một thành viên

class GameObject() { 
    ID getId() { return id; } 
protected: 
    GameObject(ID id):id(id) {} 
private: 
    ID id; 
}; 

hoặc sử dụng mẫu với tính năng tự khởi của id (một chút cú pháp tâm-boggling, chúng ta hãy bỏ qua nó: o)

  • và những người khác

Bây giờ cho vòng lặp trò chơi như thế này:

for each object 
    update by (fixed) time step 
    detect collisions and resolve them 

bạn sẽ gặp phải:

vấn đề Quyền sở hữu:

chơi thua sức khỏe khi bị trúng thiên thạch và tiểu hành tinh đang bị phá hủy sau đó ..

Asteorid::collideWithPlayer(Player& p) { p.loseHealth(100); this->explode(); } 

bây giờ xem xét cũng

Player::collideWithAsteroid(Asteroid& a) { this->loseHealth(100); a.explode(); } 

kết quả: mã trùng lặp hoặc cơ chế trò chơi không rõ ràng

nghèo của con người giải pháp: gọi người khác để giúp bạn: o)

Asteorid::collideWithPlayer(Player& p) { resolveCollision(p, *this); } 
Player::collideWithAsteroid(Asteroid& a) { resolveCollision(*this, a); } 
resolveCollision(Player, Asteroid) { p.loseHealth(100); a.explode(); } 
+0

+1 cho luận án xuất sắc. Hình ảnh sẽ làm cho nó tốt hơn. ;-) –

+0

cảm ơn rất nhiều vì lời giải thích của bạn. Có đúng là C++ không phải là lựa chọn tốt cho game dev? – amirouche

+2

C++ là một trong những lựa chọn TỐT NHẤT cho trò chơi IM IMO. Bạn có nhiều quyền kiểm soát hơn đối với bộ nhớ và quyền truy cập vào các cuộc gọi cấp thấp khi cần. Nhưng tôi thiên vị vì tôi không bao giờ cố gắng tạo ra một trò chơi nào ngoại trừ C++ và java. –

4

một ý tưởng:
Inheritance: Mỗi đối tượng một cầu thủ có thể va chạm với có một phương pháp CollideWithPlayer mà không bất cứ đối tượng cần

C++ như mã giả ví dụ

class Item : GameObject { 
public: 
    CollideWithPlayer(Player p); 
} 

class PointBag : Item { 
public: 
    CollideWithPlayer(Player p) { p.points += 5000; } 
} 
1

Bạn có thể sử dụng một thư viện bên ngoài như Nvidia PhysX hoặc Bullet, nó sẽ cho phép bạn thiết lập các callback khi xảy ra xung đột. Bằng cách sử dụng các thư viện như vậy, những người sẽ không sử dụng hệ thống va chạm của Qt, thay vào đó, mỗi khung hình bạn sẽ mô phỏng vật lý và sau đó cập nhật các thuộc tính của GraphicsPixmapItem để phản ánh trạng thái của chúng trong mô phỏng vật lý.

0

Bạn có thể xem ví dụ Qt sau đây: Ví dụ về ghép hình.

Nó khá dễ dàng và nó sẽ cung cấp cho bạn một giới thiệu khá tốt đẹp để xử lý va chạm cơ bản với Qt.

Nhanh chóng tóm tắt, từng đối tượng sẽ có một hộp bounding rằng sẽ cung cấp cho bạn không gian nó sử dụng ... Sau đó bạn sẽ sử dụng các hộp bounding biết liệu mục được chạm vào nhau hay không ...

Hi vọng điêu nay co ich !

+1

http://doc.trolltech.com/4.6/graphicsview-collidingmice.html –

+0

http://web.archive.org/web /20100409105849/http://doc.trolltech.com/4.6/graphicsview-collidingmice.html – Fuhrmanator

Các vấn đề liên quan