Làm thế nào để tạo một trò chơi mà không có OOP? [đóng cửa]


10

Tôi hiện đang nghiên cứu phát triển trò chơi và thực hành làm game.

Tôi sử dụng rất nhiều OOP trong các trò chơi của mình. Ví dụ, mỗi tên lửa được bắn là một thể hiện của một Missileđối tượng và được thêm vào danh sách các Missileđối tượng. Mỗi chiếc xe tăng trong trò chơi là một Tankđối tượng. Vân vân.

Toàn bộ thiết kế của chương trình dựa trên điều này. Chẳng hạn, việc có một danh sách các Missileđối tượng cho phép tôi mọi khung hình để di chuyển tên lửa, vẽ chúng Tank, v.v.

Thật khó cho tôi để tưởng tượng làm thế nào một trò chơi (phức tạp hơn Pac-Man) có thể được lập trình bằng ngôn ngữ không phải OO. (Tất nhiên không có sự thiếu tôn trọng đối với các lập trình viên không thuộc OO). Không chỉ về thời gian sẽ mất bao lâu, mà chủ yếu là về cách một trò chơi có thể được thiết kế theo cách này.

Tôi không thể tưởng tượng việc thiết kế một trò chơi mà không sử dụng lập trình hướng đối tượng, bởi vì toàn bộ sự hiểu biết của tôi về cách thiết kế một chương trình trò chơi dựa trên OOP.

Tôi muốn hỏi: Hôm nay, có trò chơi nào không được lập trình bằng OOP, theo cách tương tự với những gì tôi mô tả ở trên không? Có trò chơi 'chuyên nghiệp' nào không sử dụng OOP làm nhân tố chính trong quá trình phát triển không?

Nếu vậy, bạn có thể cho tôi ý tưởng về cách phát hiện va chạm giữa xe tăng và N số tên lửa có thể được thực hiện mà không cần OOP không?


6
Đây có phải là một câu hỏi triết học? Ngay cả khi bạn không gọi xe tăng của mình là "đối tượng", có lẽ bạn sẽ muốn "thực thể", "diễn viên", "tác nhân", "cấu trúc" hoặc chỉ một số tên khác cho cùng một ý tưởng, đó là một bộ sưu tập các thuộc tính và hành vi tạo nên một vật thể hình khối xoay với một tháp pháo có thể bắn mọi thứ, được gọi là xe tăng. Ngôn ngữ lập trình sẽ có nhiều cách khác nhau để chính thức hóa ý tưởng tương tự, nhưng cuối cùng, nó sẽ là một chiếc xe tăng.
Anko

Nhiều trò chơi sử dụng hệ thống dựa trên Thành phần như câu trả lời này mô tả: gamedev.stackexchange.com/a/31491/9366
John McDonald

Điều này vừa quá rộng (mà bạn có thể khắc phục bằng cách thu hẹp phạm vi) và không thực sự cụ thể để phát triển trò chơi (vì xây dựng phần mềm không có kỹ thuật OO không phải là thứ mà nhà phát triển trò chơi sẽ cho bạn câu trả lời tốt hơn bất kỳ nhà phát triển phần mềm nào khác), Điều này làm cho nó lạc đề ở đây, tôi sợ.

Nó có thể phù hợp với StackOverflow hoặc bạn có thể kiểm tra trung tâm trợ giúp để tìm một lựa chọn các trang web dành riêng cho phát triển trò chơi (như GDNet) sẽ cho phép loại chủ đề hướng thảo luận rộng này. Chúc may mắn!

Câu trả lời:


16

Tôi không thể tưởng tượng việc thiết kế một trò chơi mà không sử dụng lập trình hướng đối tượng, bởi vì toàn bộ sự hiểu biết của tôi về cách thiết kế một chương trình trò chơi dựa trên OOP.

Sau đó, có lẽ sẽ tốt cho bạn để thử viết một số chương trình theo phong cách không phải OO. Ngay cả khi bạn phát hiện ra rằng điều này không thực dụng với bạn, có lẽ bạn sẽ học được rất nhiều điều sẽ giúp bạn trong tương lai.

Phong cách OO khá phù hợp cho các trò chơi vì các trò chơi hầu như luôn luôn là về thao túng các đối tượng trạng thái. Một tia laser chiếu vào robot và trạng thái của robot thay đổi trong khi danh tính của nó vẫn giữ nguyên.

Tuy nhiên, có thể lập trình trò chơi theo phong cách chức năng . Trong một phong cách chức năng, trạng thái không thay đổi mỗi se. Đối tượng là bất biến. Thay vì thay đổi vật thể, bạn đặt câu hỏi vũ trụ sẽ khác như thế nào nếu tôi thay đổi điều này? và sau đó sản xuất toàn bộ vũ trụ mới có tính chất thay đổi. Tất nhiên, bạn có thể sử dụng lại rất nhiều vũ trụ đã tồn tại trước đó bởi vì nó là bất biến .

Trong lập trình chức năng, mọi hàm phải tính giá trị trả về của nó chỉ từ thông tin được truyền vào; không có đọc từ "nhà nước toàn cầu".

Nếu bạn làm điều này, vấn đề cơ bản bạn sẽ phải vượt qua trong đầu là mọi cập nhật đều không phá hủy . Khi tia laser chạm vào robot, bạn không thay đổi trạng thái của robot. Cuối cùng, bạn tính toán một vũ trụ hoàn toàn mới giống hệt với vũ trụ cũ ngoại trừ việc robot có trạng thái khác; nếu bạn cần vũ trụ cũ, nó vẫn ở đó, không thay đổi.

Loạt bài viết trên blog này có nhiều suy nghĩ hơn về việc viết các trò chơi theo phong cách chức năng:

http://prog21.dadgum.com/23.html

Bài viết này đề cập cụ thể đến câu hỏi "shell hit a tank" của bạn:

http://prog21.dadgum.com/189.html

Trong thực tế, chỉ cần đọc toàn bộ blog. Có những thứ tốt ở đó và các bài viết ngắn.


12

Bất kỳ chương trình hướng đối tượng nào cũng có thể được tái cấu trúc thành chương trình thủ tục bằng cách thay thế tất cả các lớp bằng các cấu trúc và chuyển đổi tất cả các hàm thành viên thành hàm độc lập, lấy đối tượng thislàm đối số.

Vì thế

 missile.setVelocity(100);

trở thành

 setMissileVelocity(missile, 100);

hoặc khi chức năng đó là tầm thường, bạn chỉ cần làm

 missile.velocity = 100;

Sự khác biệt chính giữa lập trình hướng đối tượng và lập trình thủ tục là cách bạn xử lý dữ liệu của mình. Trong OOP, dữ liệu là thông minh . Nó quản lý và thao túng chính nó. Nhưng trong lập trình thủ tục, dữ liệu thật ngu ngốc . Nó không tự làm bất cứ điều gì và cần phải được thao túng từ bên ngoài.

Khi bạn thậm chí xem xét các cấu trúc quá hướng đối tượng, bạn có thể thay thế một mảng cấu trúc bằng nhiều mảng, một mảng cho mọi thứ sẽ là một biến của tên lửa. Vì thế

struct Missile {
     int x;
     int y;
     int velocity;
}

Missile missiles[256];

trở thành

int missileX[256];
int missileY[256];
int missileVelocities[256];

Trong thiết kế này, một chức năng thực hiện một hoạt động liên quan đến nhiều thuộc tính trên cùng một tên lửa giờ đây sẽ lấy một chỉ số mảng thay vì tham chiếu đến một cấu trúc. Việc thực hiện của nó sẽ như thế này:

function updateMissilePosition(int index) {
     missileX[index] += missileVelocity[index];
}

1
Nhưng missilelà một ví dụ của một đối tượng. Trong phi OOP, không có trường hợp nào, tôi có đúng không? Nếu vậy, làm thế nào bạn có thể làm setMissileVelocity (tên lửa, 100)?
dùng3150201

1
@ user3150201 Bạn không hoàn toàn chính xác. Hầu hết các ngôn ngữ không phải OOP (và tôi sẽ tranh luận về bất kỳ ngôn ngữ nào phù hợp để phát triển trò chơi nghiêm túc) đều hỗ trợ các cấu trúc. Một cấu trúc giống như một lớp, chỉ là nó không chứa gì ngoại trừ các biến công khai. Vì vậy, nó sẽ cho phép bạn tạo ra một loại Missile, mà là một cấu trúc với một số lĩnh vực, như x, y, anglevelocity.
Philipp

@ user3150201 Câu trả lời được cập nhật với phần về cách thực hiện mà không cần cấu trúc.
Philipp

Mặc dù vậy, câu trả lời rất hay của Philipp, tôi không hiểu tại sao người ta không muốn lập trình Hướng đối tượng. Thật sự rất khó để đọc các ngôn ngữ không phải OOP và có thể gây khó chịu. Mã có thể trở thành một mớ hỗn độn trong thời gian không.
Zhafur

2
@Zhafur Bạn có biết rằng tuyên bố của bạn là một flamebait lớn, phải không?
Philipp

6

Tôi làm như sau:

  • Tất cả các lớp / phương thức OOP có quyền truy cập vào this. Để sử dụng thistheo cách tiếp cận không OO, chỉ cần vượt qua bất kỳ trường hợp nào (xem điểm tiếp theo) thisphải là tham số đầu tiên.
  • Bây giờ, như đối với các trường hợp, bạn có thể chuyển structs vào các hàm của mình this, nhưng tôi thấy cách tốt nhất để đạt được hiệu năng bộ đệm tốt cho các đối tượng là phổ biến, chẳng hạn như các thực thể hoặc các hạt, chỉ đơn giản là chuyển một chỉ mục duy nhất vào một số mảng nguyên thủy hoặc structs nhỏ . Vì vậy, chỉ mục này được sử dụng cho từng thành viên dữ liệu riêng lẻ của lớp ban đầu. Vì vậy, ví dụ nếu bạn có

...

class Entity //let's say you had 100 instances of this
{
   int a;
   char b;
   function foo() 
   {
      .../*can access 'this' herein*/
   }
}

Bạn sẽ thay thế nó bằng

int a[100];
char b[100];
function foo(int index);

Vì vậy, bây giờ bạn đang chuyển một chỉ mục vào hàm để có được những gì thường có this.

Hãy nhớ rằng bạn có thể muốn sử dụng một trong các mảng nguyên thủy như trên hoặc mảng của structs, tùy thuộc vào cách tốt nhất để xen kẽ dữ liệu của bạn cho địa phương bộ đệm tốt (địa phương tham chiếu). Tất nhiên, hiệu năng bộ đệm tốt phụ thuộc nhiều vào điều này - đặc biệt, ngôn ngữ / nền tảng mà bạn đang viết mã của mình - nhưng ngay cả trong các ngôn ngữ được phân bổ động, dựa trên VM như Java, các mảng nguyên thủy tuyến tính lớn có xu hướng hiển thị các đặc tính hiệu suất tốt hơn so với các đối tượng. Lý do chính cho điều này là các đối tượng được truy cập bằng tham chiếu và điều này có nghĩa là bạn đang nhảy khắp bộ nhớ để truy cập dữ liệu - không hiệu quả so với việc truy cập nguyên thủy liên tục từ một mảng lớn.

Để biết thêm thông tin về việc xây dựng các thực thể, v.v. như một loạt các cấu trúc hoặc nguyên thủy, hãy xem Mick West's Evolve your HVELy .


0

Ngoài các câu trả lời hiện có, bạn có thể muốn biết cách thực hiện đa hình bằng ngôn ngữ thủ tục.

Có hai cách tiếp cận:

Lưu trữ các loại

Trong trường hợp này, struct có một trường cho định danh kiểu, có thể là enum, được kiểm tra bằng cách sử dụng một switchcâu lệnh khi cần thực hiện hành động cụ thể của loại.

Một cách khác là:

Lưu trữ con trỏ hàm

Bạn đã không đề cập đến ngôn ngữ lập trình nào bạn có kinh nghiệm, nhưng trong các ngôn ngữ khác nhau, chúng còn được gọi là ngôn ngữ gọi lại, đại biểu, sự kiện hoặc hàm bậc cao hoặc đơn giản là các đối tượng hàm.

Trong trường hợp này, bạn sẽ không lưu trữ một loại, nhưng lưu trữ một con trỏ / tham chiếu đến một chức năng thực hiện hành động cụ thể. Khi cần thực hiện hành động cụ thể, bạn chỉ cần gọi hàm này. Cái này trông giống như các phương thức ảo thông thường.

Bằng cách cho phép thiết lập từng chức năng một cách độc lập, bạn sẽ có được mẫu chiến lược miễn phí.


Về đoạn cuối cùng của bạn với việc phát hiện va chạm. Tôi nghĩ rằng bạn có thể có nhiều loại xe tăng và bạn có nhiều loại tên lửa, và mỗi sự kết hợp có thể có kết quả khác nhau khi chúng va chạm. Nếu đây là những gì bạn tìm kiếm, bạn có một vấn đề chưa được giải quyết bằng các ngôn ngữ OOP: nhiều công văn và nhiều phương thức có thể có nhiều thistham số thuộc các loại khác nhau. Đối với vấn đề này lại có hai lựa chọn thay thế:

  • Công tắc lồng nhau cho mỗi sự kết hợp của xe tăng và tên lửa.
  • Mảng công văn hai chiều, chứa con trỏ tới các chức năng cho mỗi tổ hợp xe tăng và tên lửa.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.