Port engine game JavaScript sang C mà chẳng vì lý do gì
(phoboslab.org)- high_impact tái hiện cấu trúc của engine JavaScript Impact từ năm 2010, là một engine C cho game hành động 2D, hỗ trợ Windows, Mac, Linux và WASM cho web
- Impact là engine được tạo ra trong bối cảnh iOS loại bỏ Flash, nhằm chứng minh rằng game web vẫn có thể làm bằng Canvas2D, và sau khi bán hơn 3.000 giấy phép với giá $99, nó đã được phát hành miễn phí dưới dạng mã nguồn mở
- Engine mới là một framework nhỏ gộp tilemap, entity, vật lý·va chạm, hoạt ảnh sprite, văn bản và âm thanh lại với nhau, sử dụng backend SDL hoặc Sokol
- Phần hiện thực giữ sự đơn giản bằng kho lưu trữ entity kích thước cố định, asset QOI/QOA, bộ nhớ hunk đơn, renderer OpenGL·phần mềm, và trình biên tập level Weltmeister dựa trên JavaScript
- Có thể chuyển và chạy Biolab Disaster cùng Drop khá sát với mã nguồn JS gốc, và có thể mở rộng sang nhiều hệ thống thông qua việc bổ sung nền tảng·renderer
Tổng quan về high_impact
- high_impact là một engine game nhỏ dành cho game hành động 2D
- Được viết bằng C và có thể biên dịch cho Windows, Mac, Linux và WASM trên web
- Lấy cảm hứng từ engine game JavaScript Impact năm 2010, và cái tên ám chỉ thời kỳ C được xem là ngôn ngữ cấp cao
- Được phát hành theo giấy phép MIT và mã nguồn có trên GitHub
Bối cảnh ra đời của Impact
- Tháng 4 năm 2010, Steve Jobs công bố bức thư ngỏ “Thoughts on Flash”, tuyên bố iOS sẽ không hỗ trợ Flash
- Khi đó Flash là trung tâm của văn hóa game web và hoạt hình dựa trên plugin trình duyệt, và các trang như Newgrounds hay Kongregate phụ thuộc rất nhiều vào nội dung Flash
- Hỗ trợ Flash trên Android có nhiều vấn đề, và Adobe cũng bị đánh giá là không nỗ lực cải thiện các nhược điểm trên di động
- Khi ấy có nhận thức rằng “không có Flash thì không có game trình duyệt”, nhưng Canvas2D API vẫn có thể vẽ hình ảnh và hình dạng lên
<canvas> - Canvas2D do Apple/Safari tạo ra để render widget desktop, sau đó được Google và Mozilla hỗ trợ, trong khi Internet Explorer của Microsoft bị bỏ lại phía sau
- Trong dòng chảy đó, Biolab Disaster được tạo ra, đồng thời engine game và trình biên tập level cũng được phát triển để phục vụ nó
Việc bán Impact và các trường hợp sử dụng
- Sau khi dọn dẹp mã nguồn và viết tài liệu, Impact được bán với giá $99; dù có phản ứng trước quyết định bán trả phí, nó vẫn đạt hơn 3.000 giấy phép được bán ra
- Nhiều game web đã được tạo bằng Impact, và nó cũng được dùng trong các tựa game thương mại đa nền tảng
- Ở cuối vòng đời của mình, Impact được phát hành miễn phí dưới dạng mã nguồn mở
- high_impact là dự án xây lại Impact từ đầu, nhưng viết bằng C thay vì JavaScript
Tại sao lại là C
- C là một ngôn ngữ đơn giản nhưng có chiều sâu, được xem là giống với đặc tính của game: “dễ học nhưng khó tinh thông”
- Qua nhiều dự án, sự quan tâm với C lại tăng lên
- Bản thân Impact ban đầu không cùng quy mô với các engine như Godot, Unreal hay Unity, nhưng vẫn là nền tảng vững chắc cho nhiều game
- Việc viết lại Impact bằng C bắt đầu như một bài tập vui vẻ
Cấu trúc engine và asset
- high_impact được hiện thực theo hướng đơn giản nhất có thể, với mục tiêu gồm ít mã nhất có thể
- Các chức năng cơ bản giống như engine JavaScript gốc
- Tải tilemap
- Tạo·cập nhật·vẽ entity là các đối tượng trong game
- Xử lý vật lý và va chạm giữa các entity
- Xử lý va chạm với collision map
- Hoạt ảnh sprite sheet
- Hiển thị văn bản
- Phát hiệu ứng âm thanh và nhạc
- Nó gần với một framework hơn là một thư viện, và logic game được viết bên trong framework
- Ở tầng dưới có backend
platform, hiện có thể biên dịch với SDL hoặc Sokol - Mã game nằm trong một hoặc nhiều “scene”, trong đó scene là một struct có các con trỏ hàm
- Sau khi gọi
engine_set_scene(&scene_game), engine sẽ thiết lập scene mới scene_game.init()chỉ được gọi một lầnscene_game.update()vàscene_game.draw()được gọi mỗi frame
- Sau khi gọi
- Tilemap và các entity ban đầu có thể được tải từ file
.jsonhoặc tạo động - Lý do chọn JSON làm định dạng level là để giữ tương thích ngược với Impact gốc
- high_impact dùng QOI cho ảnh và QOA cho âm thanh, nhạc
- Makefile của game demo tự động chuyển PNG sang QOI và WAV sang QOA
- Không cần kèm thêm thư viện giải mã ảnh·âm thanh riêng
- Trong tương lai có thể hỗ trợ các định dạng asset khác, nhưng sự đơn giản của QOI/QOA rất hợp với định hướng dự án
Hệ thống entity
- Tất cả entity đều dùng chung
entity_t struct, chứa các thuộc tính mà high_impact cần như vị trí, vận tốc, kích thước - Mọi entity có cùng kích thước byte, nên việc lưu trữ và quản lý trở nên đơn giản
- Khi muốn di chuyển entity, chỉ cần đặt vận tốc hoặc gia tốc, phần còn lại do engine xử lý
- Có thể dùng macro để thêm thuộc tính riêng của game vào struct entity cơ bản
- Biolab Disaster dùng
unionvới struct riêng theo từng loại entity - Drop không cần định nghĩa thêm thuộc tính
- Biolab Disaster dùng
- Mỗi loại entity phải có một
entity_vtab_tcung cấp các con trỏ hàmupdateđược gọi mỗi frametouchđược gọi khi chồng lấn với entity khác thỏa điều kiện- Tất cả các mục đều là tùy chọn
- Kho lưu trữ entity có kích thước cố định
- Số entity hoạt động mặc định là 1.024
- Có thể cấu hình bằng định nghĩa
ENTITIES_MAX - Engine có thể xử lý dễ dàng tối đa 64k entity
- Nếu cần giữ tham chiếu entity lâu hơn một frame thì dùng
entity_ref_tentity_ref_tlà struct cóuint16_t idvàindex- Có thể ánh xạ lại thành con trỏ bằng
entity_by_ref() - Giúp phân biệt trường hợp một entity khác đi vào cùng địa chỉ lưu trữ
- Do dùng chỉ số
uint16_t, số entity hoạt động tối đa bị giới hạn ở 64k
- Việc hiện thực các cấu trúc như OOP đơn giản, class hay kế thừa đơn trong C có phần gượng gạo, nhưng high_impact cố gắng làm cho nó thoải mái nhất có thể
- Cách tiếp cận OOP “ngây thơ” là gom logic entity theo từng loại vào một chỗ đã tỏ ra dễ hiểu và hoạt động tốt trong các game được làm cho tới nay
Phát hiện và phản hồi va chạm
- Xử lý va chạm đơn giản chỉ kiểm tra xem có thể di chuyển đến vị trí mới hay không rồi dừng lại nếu không thể, nhưng với vật thể nhanh thì có thể sinh ra hành vi kỳ lạ
- Trong platformer 2D, nếu người chơi đang ở cách mặt đất 16px và bước di chuyển tiếp theo khiến nhân vật chui xuống đất, nó có thể trông như một pha tiếp đất mượt khi nhân vật dừng giữa không trung rồi rơi tiếp ở frame sau
- high_impact truy vết hộp entity lên tilemap để tính chính xác điểm va chạm
- Cách này phức tạp hơn việc kiểm tra có/không đơn giản, nhưng cho kết quả tốt hơn và còn xử lý được cả tile dốc
- Sau khi va vào tile, có thể cần truy vết lần hai với phần vận tốc còn lại
- Ví dụ nếu chạm đất theo góc chéo thì
vel.ysẽ thành0, cònvel.xđược giữ lại để trượt dọc mặt đất
- Ví dụ nếu chạm đất theo góc chéo thì
- Va chạm giữa các entity được xử lý riêng
- Particle có thể va với tilemap nhưng không va với entity khác
- Nền tảng di chuyển có thể va với entity khác nhưng không nên tự di chuyển vì phản hồi va chạm
- Phát hiện va chạm broad phase sắp xếp entity theo
pos.x- Vì từ frame trước phần lớn đã được sắp xếp sẵn nên chi phí insertion sort thấp
- Sau khi sắp xếp, hệ thống quét từ trái sang phải và chỉ kiểm tra các entity trong khoảng từ
pos.xđếnpos.x + size.x
- Cách sweep and prune này chạy nhanh miễn là không có quá nhiều entity chồng lấn ở các vị trí x tương tự nhau
- Nếu nhiều entity dồn vào cùng vị trí x như một chồng hộp, đó sẽ là trường hợp xấu nhất
- Với game như bắn súng màn hình dọc nơi trục khác phù hợp hơn, có thể đổi trục sweep bằng
#define ENTITY_SWEEP_AXIS y
Kết xuất
- high_impact hiện có renderer OpenGL và một renderer phần mềm còn chưa hoàn thiện
- Toàn bộ việc render đi qua một API rất mỏng và các lệnh vẽ thực tế được thực hiện trong một hàm duy nhất, nên việc hiện thực backend khác tương đối đơn giản
- Các hàm cốt lõi mà backend render bổ sung cần hỗ trợ là khởi tạo, dọn dẹp, đặt kích thước màn hình, chuẩn bị·kết thúc frame, và vẽ quad
- Để xử lý texture cũng cần các hàm mark, reset, create
- Tính năng khá đơn giản: chỉ vẽ được quad và không dùng được hiệu ứng shader, nhưng như vậy là đủ cho mục tiêu của engine này
- Renderer phần mềm chỉ có 140 dòng mã và chỉ hỗ trợ quad căn theo trục
- Renderer OpenGL cố gắng đưa toàn bộ render của một frame vào một OpenGL draw call
- Gom mọi quad vào một buffer lớn rồi gửi một lần bằng
glDrawElements() - Gộp mọi texture vào một texture atlas duy nhất để tránh rebinding texture
- Gom mọi quad vào một buffer lớn rồi gửi một lần bằng
- Texture atlas là cách làm cũ và cũng có nhược điểm, nhưng vẫn được dùng vì bindless texture không được hỗ trợ ở mọi nơi
- high_impact chỉ hỗ trợ một texture atlas duy nhất, nhưng kích thước có thể cấu hình bằng
#define- GPU di động thường hỗ trợ texture 8k×8k
- GPU desktop hiện đại có vẻ hỗ trợ tới 32k×32k
- Biolab Disaster và Drop dùng atlas 512×512
Âm thanh
- Đầu ra âm thanh do SDL2 hoặc Sokol xử lý, còn engine phụ trách tải·giải mã·trộn nhiều âm thanh
- Hệ thống âm thanh được chia thành
sound_source_tchứa sample vàsound_tbiểu diễn âm thanh đang phát - Hệ thống này dựa trên hệ thống được tạo khi viết lại wipEout, và có thể giải nén QOA khi cần
- Mọi thứ đều được cấp phát tĩnh
- Số source có thể nạp là cố định
- Số sound có thể phát đồng thời là cố định
- Sound phát xong sẽ tự động bị loại bỏ để tái sử dụng
- Có thể thay đổi âm lượng, pan trái·phải và pitch của âm thanh
- Nếu đặt pitch âm thì âm thanh sẽ phát ngược
- Việc resample cần thiết cho pitch biến thiên dùng phương pháp chất lượng thấp với nội suy nearest-neighbor
Quản lý bộ nhớ
- high_impact cho rằng nếu game không có asset do người dùng tạo ra thì có thể biết chính xác lượng bộ nhớ cần thiết
- Engine cấp phát tĩnh một mảng byte duy nhất gọi là “hunk”, và đây là toàn bộ bộ nhớ mà high_impact sử dụng
- Kích thước hunk có thể cấu hình bằng
#define ALLOC_SIZE - Có hai cách cấp phát bộ nhớ trong hunk
- Một bump allocator, hay arena, tăng dần từ đầu dùng cho asset game·entity·dữ liệu scene hiện tại
- Một temporary allocator tăng ngược từ cuối hoạt động như
malloc()vàfree(), dùng cho lưu trữ tạm như sau khi giải nén ảnh trước khi chuyển lên GPU
- Bump allocator có nhiều “high water mark” và tự động quay lui về một mốc nhất định
- Bộ nhớ cấp phát theo bump không cần
free()tường minh - Vòng đời theo khái niệm được chia thành
game,scene,frame- Những gì cấp phát trước khi scene đầu tiên được thiết lập chỉ được giải phóng khi chương trình kết thúc
- Những gì cấp phát trong
scene.load()được giải phóng khi scene kết thúc - Những gì cấp phát trong lúc scene đang chạy được giải phóng ở cuối frame
load()theo từng loại entity được gọi ở giai đoạn 1 vì không thể biết trước entity nào sẽ được dùng trong scene- Có thể bọc thêm ngữ cảnh cấp phát bằng
alloc_pool(), thực chất là dạng viết tắt củabump_mark()vàbump_reset(mark)
Trình biên tập level Weltmeister
- Impact gốc có trình biên tập level tên là Weltmeister, và high_impact cũng bao gồm nó
- Nó vẫn được viết bằng JavaScript và dùng nhiều mã nguồn gốc, nhưng đã được cập nhật để phù hợp với các tính năng trình duyệt hiện đại
- Weltmeister hoạt động hoàn toàn độc lập
- Có thể nhấp đúp
weltmeister.htmlđể bắt đầu tạo level - Trước đây cần API backend PHP hoặc NodeJS để tải·lưu file
- Giờ đây có thể dùng FileSystemAPI để xin quyền truy cập vào một thư mục cụ thể
- Có thể nhấp đúp
- Safari và Firefox, đặc biệt là với showDirectoryPicker(), vẫn chưa hỗ trợ đầy đủ nên cần trình duyệt họ Chrome
- Weltmeister đọc file mã nguồn C và thu thập các loại entity
- high_impact cung cấp các macro mà editor hiểu nhưng mã C thì không làm gì với chúng
EDITOR_SIZE(X, Y): kích thước trong editor, mặc định là(8, 8)EDITOR_RESIZE(RESIZE): có cho phép đổi kích thước trong editor hay khôngEDITOR_COLOR(R, G, B): màu hộp trong editor, mặc định là(128, 255, 128)EDITOR_IGNORE(IGNORE): có thể tạo trong editor hay không
Game demo
- Để kiểm tra high_impact có thực sự hoạt động như một engine game hay không, 2 game Impact gốc đã được port sang C
- Việc port gần giống như “phiên âm” mã nguồn JS có sẵn và tái sử dụng các asset hiện có
- Việc không gặp nhiều thử thách có thể xem là bằng chứng rằng high_impact đã hoạt động đúng như mong muốn
-
Biolab Disaster
- Là tựa game phát hành cùng Impact gốc
- Là game Jump'n'Gun cuộn ngang
- Mã nguồn có tại github.com/phoboslab/high_biolab
- Bản JS gốc có tại playbiolab.com
-
Drop
- Là một game arcade rất đơn giản
- Mã nguồn có tại github.com/phoboslab/high_drop
- Bản JS gốc có tại impactjs.com/drop/
- Điểm cao nhất hiện được nêu là 26789 Points
Khả năng mở rộng
- high_impact có cấu trúc viết mã theo game kiểu bổ sung thêm giống các engine game truyền thống
- Không cần sửa mã nguồn engine, nhưng nó cũng đủ đơn giản để nếu cần có thể chỉnh thẳng vào mã nguồn engine
- Nền tảng và renderer được thiết kế để có thể mở rộng mà không cần thay đổi phần còn lại của mã
- Nếu quan tâm, tác giả hoan nghênh pull request hỗ trợ renderer Vulkan, DirectX, Metal và backend nền tảng như PSX, N64, Dreamcast
- Vì được viết bằng C, định hướng là nó phải có thể chạy ở mọi nơi
1 bình luận
Ý kiến trên Hacker News
Phần lớn những công việc lập trình mà tôi học được nhiều nhất đều là nhờ Impact
Impact thực sự đi trước thời đại, và tôi rất tự hào vì mình là một trong 3000 người sở hữu giấy phép. Đó là một trong những món mua đáng giá nhất tôi từng thực hiện, và cũng là trò chơi duy nhất tôi thực sự hoàn thành đến cùng bằng Impact
Tôi thích việc giấy phép đi kèm mã nguồn, và tôi đã tự chỉnh sửa cả engine lẫn trình biên tập cho phù hợp với nhu cầu của mình. Ảnh hưởng từ đó khiến tôi dành vài năm để tự làm engine game JS của riêng mình, dù rốt cuộc lại trì hoãn việc hoàn thành game, nhưng tôi vẫn học được rất nhiều trong quá trình đó và cũng làm ra không ít game cho game jam
Tôi cũng được truyền cảm hứng từ Ejecta, phần hỗ trợ iOS native của Impact, nhưng hồi đó bực ở chỗ nó không chạy trên Android, nên tôi đã tạo JVM binding cho V8 và triển khai một phần WebGL để chạy engine của mình trên Android mà không cần webview. Kho lưu trữ V8 binding tôi công khai sau đó lại bất ngờ được dùng trong phần mềm thương mại: https://github.com/namuol/jv8
Tôi thậm chí còn thử làm một startup tự lực, lấy cảm hứng từ mô hình kinh doanh của Impact, bán quyền truy cập vào kho GitHub riêng tư, nhưng kể chuyện đó thì sẽ dài. Dù sao đi nữa, thấy Impact được cập nhật cho web “hiện đại” bằng bản port sang C khiến tôi thấy ấm lòng và vui vẻ. Tôi muốn nói web đang ở một giai đoạn kỳ quặc, nhưng thật ra tôi không nhớ nổi thời nào web lại không kỳ quặc
CrossCode là một trò chơi tuyệt vời. Tôi biết nó dùng công nghệ web, và vẫn luôn ngạc nhiên vì hiệu năng của nó lại tốt đến vậy trên phần cứng Nintendo Switch
Có lẽ engine này cũng góp một phần công sức vào đó
Điều này lại càng ngầu hơn. Thật tốt khi nhà phát triển có thể thay đổi engine cho phù hợp với game của mình, và tương tự, high_impact cũng nên được xem là một điểm khởi đầu tiện lợi hơn là một game engine “đủ tính năng” hoàn chỉnh
Một giai thoại thú vị là ai cũng muốn có bản Switch, nhưng vì giới hạn kỹ thuật nên đội ngũ từng trả lời rằng “CrossCode sẽ lên Switch khi Hedgehags học được cách bay”: https://www.radicalfishgames.com/?p=6581
Khi việc port cuối cùng thành công, họ đã thêm nhiệm vụ phụ “A switch in attitude”, và đúng như dự đoán, có cả những hedgehags bay lượn xuất hiện: https://www.radicalfishgames.com/?p=6668
“Thoughts on Flash” có lẽ đã cứu web đúng vào thời điểm nền tảng này cần nhất, tức là khi sự thống trị của một phần mềm duy nhất đang dần lớn lên
Có vẻ trong đó cũng có sự bực bội với Adobe, khi hãng dường như bỏ bê hỗ trợ MacOS để ưu tiên cơ sở người dùng Windows lớn hơn nhiều. Ví dụ, bản Mac luôn bị tụt lại phía sau bản Windows
Có thể Jobs cảm thấy rằng Apple đã giúp Adobe thành công, nên Adobe cũng nên có đóng góp tương xứng cho Apple, nhưng điều đó gần như chỉ là suy đoán. Bản thân trò chơi trông thực sự rất mượt
Dù vậy cũng chưa đến mức gần như assembly, chỉ là đang thử cắt giảm đủ thứ theo hướng khiến mình muốn đào sâu hơn nữa
Với tư cách là người muốn rời công việc ở công ty và một ngày nào đó thực sự dấn thân vào side project, tôi muốn nghe thêm về phần tự nuôi sống bằng hình thức thu phí
Ý nghĩ thu tiền cho thứ vốn ban đầu chỉ làm vì vui khiến tôi thấy áp lực một cách kỳ lạ, nhưng tôi cũng biết điều đó có thể giúp mình được làm toàn thời gian thứ mình yêu thích
Vì vậy điều quan trọng là phải hiểu vì sao suy nghĩ ấy lại khiến bạn thấy áp lực. Những lý do thường gặp là người xung quanh hay can ngăn, bạn chưa có đủ kỹ năng để thực hiện tốt điều mình muốn làm, bạn ngại nhờ giúp đỡ hoặc sợ làm phiền người khác, bạn sợ công việc của mình bị đánh giá, hoặc sợ mất đi cảm giác “an toàn” từ thu nhập hiện tại, nhất là khi còn phải nuôi gia đình
Trong phần lớn trường hợp, những lý do đó không hẳn là lý do thật sự tốt, mà gần giống những điều cần được điều chỉnh lại phần nào, nhưng vì chúng tạo cảm giác như “rủi ro” nên rất khó rời khỏi vùng an toàn. Với kiểu tâm thế như vậy, mọi cơ hội đều trông như rủi ro, nên sẽ rất khó tìm được thời điểm thích hợp để bắt đầu điều bạn thực sự muốn làm
Liên quan đến chuyện này, việc đơn giản là làm điều bạn thấy vui và cho cả thế giới thấy nó là quan trọng, nhưng biến nó thành thứ nuôi sống bản thân lại là một thử thách hoàn toàn khác. Phần lớn mọi người không thể biến điều mình yêu thích thành nghề mưu sinh, và ngay cả khi làm được thì kỳ vọng của khách hàng trả tiền cùng áp lực phải duy trì doanh thu có thể lấy đi tình yêu đó. Không phải tôi bảo đừng làm, chỉ là đây là điều nên biết trước khi lao vào
Tôi hiếm khi dùng tài khoản HN của mình đến mức phải đăng nhập lại chỉ để nói rằng, vài năm trước tôi đã chơi đi chơi lại Biolab Disaster mà quên mất tên của nó
Việc tình cờ tìm lại được nó khiến tôi thấy khá kỳ lạ
Bình thường tôi diễn đạt chuyện này theo hướng tiêu cực hơn nhiều. Với tôi, “framework” đơn giản là một thư viện không chơi cùng tốt với những thứ khác
Dù vậy, nghe được cách diễn đạt tích cực và thuyết phục như thế này cũng thật hay
Dùng một framework phong phú, được thiết kế tốt và xử lý cực ổn 99% những gì cần thiết là một trải nghiệm rất thích. Việc thêm mã của riêng tôi vào đó cũng thuộc hàng dễ nhất trong số các kiểu phát triển tôi từng làm, và nó đơn giản là hoạt động tốt. Cảm giác như phép màu, và đến giờ tôi vẫn còn nhớ nó
Framework lý tưởng trong suy nghĩ của tôi là bên trong nó thực chất là một thư viện hoặc một nhóm thư viện phối hợp với nhau, còn tính chất framework thì càng ít càng tốt
Ví dụ, Qt là một framework và Qt “gọi tôi”, nhưng bạn vẫn có thể chạy mã QPainter mà không cần khởi động vòng lặp sự kiện của Qt hay suy nghĩ quá nhiều về QObject. Lý tưởng nhất là bạn cũng nên dùng được vòng lặp sự kiện mà không cần chấp nhận toàn bộ signals và slots, chỉ là trải nghiệm sử dụng có thể kém tiện hơn
Điều đó không phải lúc nào cũng khả thi và cũng không phải lúc nào cũng đáng làm, nhưng nếu các điều kiện khác như nhau thì tôi vẫn thích phía không có framework hơn
Tôi hiểu vì sao trong game engine lại cần một chút tính chất framework. Khi biên dịch sang những nền tảng đặc thù như điện thoại hay console, engine phải can dự vào quy trình build, đôi khi cả những phần liên quan đến libc, nên không thể chỉ tạo một tệp thực thi Win32 rồi gọi đó là game PlayStation được
Kết hợp định dạng tệp không mất dữ liệu QOI với 7Zip cho kết quả tốt hơn PNG không mất dữ liệu. Công việc thật ấn tượng
“for No Reason” có lẽ là để tôn trọng thời lượng pin của người chơi
Tôi thích phần quản lý bộ nhớ. Arena allocation thực sự rất đơn giản
Cả web server đồ chơi tôi đang dùng lúc đầu cũng bắt đầu bằng arena, nhưng chẳng bao lâu tôi nhận ra là mình hoàn toàn không cần phải tăng rồi giảm bộ nhớ
Giờ thì tôi cấp phát toàn bộ lượng bộ nhớ cần thiết ngay từ đầu, rồi chia nó thành từng phần cho mỗi mô-đun dùng. Khi lập trình, chúng ta thường mặc định rằng có thể sẽ cần một lượng bộ nhớ tùy ý, nhưng không hẳn vậy
Nhiều thứ thực ra có giới hạn rõ ràng, và với phần còn lại thì thường cũng có thể định nghĩa giới hạn. Liệt kê chúng ra là bạn sẽ biết cần bao nhiêu bộ nhớ. Nghĩ trước và định nghĩa các giới hạn như vậy vừa thú vị, vừa tạo sự tự tin, lại còn rèn được thói quen tiết kiệm lành mạnh
Nếu bắt đầu từ một vector rỗng rồi thêm hàng nghìn phần tử mà không reserve bộ nhớ trước thì dĩ nhiên có thể như vậy. Nhưng trong thực tế có rất nhiều trường hợp bạn có thể tìm được mức tối đa thật sự cần và cấp phát trước, khi đó mọi thứ đều ổn
Tôi thực sự thích cách họ dùng union để tạo cấu trúc dữ liệu ENTITY kiểu đa hình. Thiết kế rất tốt
Tôi vẫn thích nghịch với C. Đó là ngôn ngữ đầu tiên tôi học, và tôi đã vật lộn với nó trong nhiều năm. Như bài gốc cũng nói, C là một ngôn ngữ cô đọng nên rất ngầu, và nếu muốn thì bạn có thể đào rất sâu vào nó
Trò chơi cũng hay vì nó gợi không khí kiểu Commander Keen ngày xưa, và tôi từng khá thích thương hiệu mà Carmack làm trong thời kỳ trước 3D đó