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;
}
};
ả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)
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(); }
+1 cho luận án xuất sắc. Hình ảnh sẽ làm cho nó tốt hơn. ;-) –
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
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. –