Trang này dành cho người muốn hiểu hoặc sửa engine. Nếu chỉ muốn làm game, bạn không cần đọc.
raylib bị giấu hoàn toàn: header trong api/ không include raylib. Các hàm to_raylib và from_raylib (file njin2rl và rl2njin) đổi qua lại giữa kiểu của njin (vec2, rgba...) và kiểu của raylib. Nhờ vậy game chỉ phụ thuộc vào njin::api, còn raylib là chi tiết cài đặt của njin::rt.
njin::context là một struct mờ với game: chỉ dùng qua các hàm. Định nghĩa thật nằm trong runtime/njin_ctx_impl.h:
| Thành viên | Vai trò |
|---|---|
| cfg | Cấu hình đã truyền vào create() |
| time | Thời gian, tốc độ, tạm dừng, bộ tích lũy fixed update |
| random | Bộ sinh số ngẫu nhiên dùng chung |
| window | Mở cửa sổ và thiết bị âm thanh khi tạo, đóng khi hủy |
| input | Trạng thái phím của frame trước và frame này, danh sách action |
| shader, texture, render_texture | Các store tài nguyên GPU |
| font | Store font |
| audio | Store âm thanh: sound và music |
| post | Ảnh ngoài màn hình của shader hậu kỳ (module camera) |
| sprites | Ảnh đã bake của các chunk tilemap (module sprite) |
| scene | Danh sách scene, scene hiện tại và yêu cầu chuyển |
| ecs | Registry, dispatcher và lịch chạy system, kèm thời gian từng system khi có inspector |
| view | Màn hình ảo: ảnh nhỏ cố định phóng ra cửa sổ (xem Màn hình ảo, hẹn giờ và tween) |
| timers | Hẹn giờ và tween đang chạy |
| dialog, i18n | Hộp thoại đang mở; bảng chuỗi các ngôn ngữ (xem Hộp thoại và đa ngôn ngữ) |
Thứ tự khai báo quan trọng: thành viên bị hủy theo thứ tự ngược, và window được khai báo trước các store, nên nó đóng sau cùng. Các store giải phóng tài nguyên GPU và bộ đệm âm thanh trong lúc OpenGL context và thiết bị âm thanh còn sống. Thiết bị âm thanh được mở cùng cửa sổ và đóng trong destructor của window.
shader_store, texture_store, render_texture_store và audio_store cùng một khuôn:
flowchart LR
A["ecs_register()"]:::api --> B[("pending[phase]<br/>system của module đang setup")]:::data
B --> C["sắp xếp theo after / before / order"]:::engine
C --> D[("schedule[phase]<br/>thứ tự chạy cuối cùng")]:::data
D --> E["ecs_run(phase)<br/>gọi lần lượt từng hàm"]:::update
ecs_store (file runtime/njin_ecs.h) giữ hai mảng theo phase:
Khi mod_register() được gọi:
Vì bước 3 nối vào cuối nên module đăng ký trước chạy trước.
Sắp xếp là sắp xếp topo: lấy các system chưa bị ràng buộc after/before chặn, chọn cái có order nhỏ nhất (bằng nhau thì theo thứ tự đăng ký), đặt nó vào kết quả, gỡ ràng buộc của nó, lặp lại. Nếu còn system mà không cái nào chọn được thì có vòng phụ thuộc: ghi lỗi và nối số còn lại theo thứ tự đăng ký.
ecs_run(phase) chỉ là một vòng for gọi từng hàm trong schedule[phase].
create() đăng ký sẵn các module lõi trước khi trả về, trong runtime/modules/, theo thứ tự:
| Module | Việc làm |
|---|---|
| njin.reload | Nạp lại texture, shader có file vừa đổi, khi hot reload bật (xem Vẽ ảnh và shader) |
| njin.debug | Khi bật cổng debug: nhận lệnh của njin_inspector ở đầu frame, gửi số liệu ở cuối (xem Công cụ debug: njin_inspector) |
| njin.dialog | Điều khiển hộp thoại đang mở: chữ chạy, chọn, sang câu (xem Hộp thoại và đa ngôn ngữ) |
| njin.ui | Đọc phím, chuột, tay cầm cho UI, chuyển lựa chọn, giữ phím điều hướng khi menu hiện, chặn widget phía sau popup; toast được vẽ ở cuối frame (xem UI: menu, nút, thanh trượt) |
| njin.camera | Bật camera (có rung) trước mọi lệnh vẽ; chạy post-processing (xem Camera, Hậu kỳ (post-processing)) |
| njin.audio | Cấp dữ liệu cho stream nhạc, phát lại sound lặp (xem Âm thanh) |
| njin.hierarchy | Tính transform của entity con từ cha (xem Prefab và transform cha–con) |
| njin.anim | Chạy njin::animator: chuyển trạng thái, đổi frame (xem Animation và máy trạng thái) |
| njin.particles | Sinh, di chuyển, xóa hạt (xem Particle và hiệu ứng) |
| njin.sprite | Chạy njin::sprite_anim, nháy sprite, bake chunk tilemap, vẽ sprite, tilemap và particle theo lớp (xem Sprite và animation, Tilemap) |
| njin.camera_follow | Đưa camera tới mục tiêu: trễ, vùng chết, nhìn trước, chặn trong khung level (xem Làm game platformer) |
| njin.collision | Tìm cặp collider chạm nhau, gửi event; vẽ khung khi bật dò lỗi (xem Va chạm) |
| njin.body | Điều khiển njin::platformer_body, njin::topdown_body và njin::path_mover trong phase_fixed_update (xem Làm game platformer, Làm game top-down) |
| njin.timer | Chạy hẹn giờ và tween theo entity ở phase_update (xem Màn hình ảo, hẹn giờ và tween) |
Vì chúng đăng ký trước module của game nên system của chúng chạy trước trong cùng phase. Module camera dựa vào điều này để bật camera trước mọi lệnh vẽ của game; hierarchy chạy trước anim, particle và sprite để chúng thấy vị trí mới của frame này.
CMake tự tìm mọi file .cpp dưới runtime/, không cần sửa danh sách file.