1. Giao diện sử dụng
Đây là giao diện sử dụng của C-Script:
Ở bên trái chúng ta có thể thấy danh sách các biến, danh sách môi trường. Dĩ nhiên, chúng ta có thể di chuyển cửa sổ này và đặt nó ở phía bên phải nếu muốn.
Ở phía bên dưới, chúng ta có cửa sổ chú thích các lệnh, cung cấp tất cả các hướng dẫn nằm trong tập tin help liên quan đến lệnh mà bạn đang viết. Nó cũng hiển thị kết quả kiểm tra cấu trúc mà nó kiểm tra trong lần biên dịch gần nhất. Nếu muốn debug, có cửa sổ xem biến hoặc thực thể trong tab Watch. Nếu
đặt con trỏ chuột nằm trên toolbar, sẽ hiện lên một lời chỉ dẫn để mô tả những gì chúng ta sẽ thực hiện.
Chương 3: Game Engine – Cách sử dụng SED
2. Soạn thảo
Đây là phần quan trọng nhất của hướng dẫn sử dụng SED, nó sẽ giới thiệu về cách soạn thảo nhanh với những phím tắt.
2.1. Lệnh Insert
Nếu muốn thêm một lệnh chỉ cần ấn phím [CTRL+SPACE]. Nó đưa ra một danh sách các lệnh từ dữ liệu các lệnh và cả các hàm hoặc hành động từ tập tin wdl. Đánh kí tự đầu tiên của lệnh muốn thêm vào và danh sách sẽ cuộn đến lệnh đó, cũng có thể đi lên hoặc xuống danh sách bằng ấn phím mũi tên [UP/DOWN] hoặc phím [PAGE UP / PAGE DOWN].
Chúng ta cũng có thểấn [CTRL+SPACE] ngay khi mới bắt đầu viết lệnh. Danh sách sẽđược cuộn đến một lệnh trước con trỏ và khi đó ấn [ENTER]
được chèn lệnh vào.
2.2. Dòng chú thích
Dòng chú thích rất cần thiết khi người biên soạn muốn bỏ qua một vài đoạn mã trong engine.
Để có một dòng chú thích, chọn nó và ấn nút “//” xanh trên toolbar. Hoặc có thểấn lệnh [CTRL+ALT+C]. Lệnh này sẽ chèn thêm dấu “//” trước dòng được chọn.
Để bỏ một dòng chú thích, chọn nó và ấn nút “//” đỏ trên toolbar. Hoặc có thể ấn lệnh [CTRL+SHIFT+C]. Lệnh này sẽ xóa dấu “//” trước dòng được chọn.
Chương 3: Game Engine – Cách sử dụng SED
Nhảy đến một đoạn mã sẽ tiết kiệm được rất nhiều thời gian, nếu chúng ta viết một hàm có tên là “myfunction”. Rồi khi mã nguồn nhiều lên và chúng ta muốn quay trở lại và thay đổi nó, lúc này chúng ta sẽ nhảy đến đoạn mã đó.
Mặc định, nó nằm phía bên phải, và chứa tất cả các hàm, hành vi, chuỗi … Chỉ cần mở phần function trong cửa sổ code jumber và nhấp vào
myfunction. Con trỏ sẽ nhảy tới hàm myfunction.
2.4. Sử dụng danh sách các thành phần
Chúng ta biết rằng danh sách môi trường chứa tất cả các nhân tố trong mã nguồn, như tập tin wdl, pcx được đưa vào. Để mở những tập tin này, vào
element list và nhấp vào mục cần thiết. Nếu nó là một tập tin wdl nó sẽ được mở trong SED, còn không nó sẽđược mở trong một ứng dụng thích hợp.
2.5. Kiểm tra cú pháp
Đây là cách để kiểm tra xem có lỗi trong mã nguồn hay không. Để có thể
phát hiện ra đúng các lỗi trong lúc viết mã, nên chạy Test Run trước khi kiểm tra cú pháp. Tuy nhiên, hàm Test Run sẽ tự động kiểm tra cú pháp sau khi engine được thực thi.
Để kiểm tra cú pháp nhanh chóng, chúng ta có thể ấn phím F5 để chạy
engine và ấn F6 để kiểm tra cú pháp.
2.6. Soạn thảo thông minh
Trong khi đang viết mã chúng ta nên chú ý hàm tự động thụt đầu dòng, nó sẽ tự động thuộc đầu dòng khi ấn phím [ENTER], cũng khi ấn phím [ENTER] và nếu một biểu tượng “{” được đặc trên một dòng thì biểu tượng “}” sẽ được
được thêm tự động. Một tab sẽđược thêm vào để thụt lềđoạn mã giữa các dấu ngoặc. Cũng giống như vậy, khi một biểu tượng “(” được thêm vào, thì một biểu tượng “)” sẽ tựđộng thêm vào.
Chương 3: Game Engine – Cách sử dụng SED
Tất cả các cửa sổ trong SED là lưu động, có nghĩa là chúng nó có thểđược di chuyển và được lưu trữ lại. Sử dụng khả năng này và điều chỉnh màu sắc để
có được một giao diện tốt. Một số phím tắt nên nhớ:
[Alt+Left] để nhảy đến vị trí cuối cùng trong cửa sổ soạn thảo. [Ctrl+F6] chuyển đổi giữa các tập tin mã nguồn đang mở.
[F1] mở tập tin giúp đỡ và chuyển đến lệnh hiện thời mà con trỏ đang chi vào. 3. Cấu hình Đây là hộp thoại cấu hình, nó nằm ở vị trí Options->Configuration. Paths Thư mục 3D GameStudio – thư mục chứa tập tin acknex.exe. Environment
Tabsize: kích thướt của tab trong mã nguồn, mặc định là 3.
Show hints while writing: Mặc định, hiển thị lời chỉ dẫn trong khi viết hàm.
Load included files: Mở các tập tin được bao gồm trong tập tin wdl khi mở
tập tin này, mặc định là tắt.
Start with a blank script: Mặc định bắt đầu với một tập tin trống rỗng.
Auto Indent: Giống như trong thực đơn Options, tựđộng thụt lề khi ấn phím
Chương 3: Game Engine – Cách sử dụng SED
Only use these extensions with the element list: đánh “wdl,pcx” để chỉ có các tập tin wdl và pcx trong danh sách thành phần.
Update watches every X ms: Cập nhật cửa sổ sau X giây, nếu giá trị này thấp, nó sẽđược cập nhật nhanh hơn nhưng nó có thể làm cho quá trình gỡ lỗi chậm xuống. Nếu xem các giá trị không thay đổi thường xuyên, hãy chọn giá trị này càng lớn càng tốt.
Back up:
Enable backup when opening files: Nếu tùy chọn này được chọn, một bản sao sẽđược tạo ra mỗi khi một đoạn mã được mở. Nó sẽđược lưu trữ trong thư
mục backup, hãy nhìn vào thư mục này, dung lượng của nó sẽ ngày càng tăng lên nhưng tùy chọn này nên được chọn.
4. Thực đơn 4.1. Thực đơn File
Đây là thực đơn File, hầu hết mọi lệnh ởđây đều chuẩn ngoại trừ lệnh Commands Database.
Chương 3: Game Engine – Cách sử dụng SED
4.2. Thực đơn Edit
Đây là thực đơn edit, chứa các lệnh chuẩn và các lệnh:
Find In Files: Tìm đoạn văn bản trong các tập tin wdl trong một thư mục.
Indent All: Thụt lề trong tất cả các tập tin wdl,
để cho đoạn mã được dễ nhìn hơn.
Comment Line : Tất cả các dòng được chọn đều trở
thành các dòng chú thích, hoặc chỉ chuyển dòng hiện tại thành dòng chú thích nếu không chọn dòng nào.
Uncomment Line : Xóa các dấu “//” trước các dòng
được chọn, hoặc xóa dấu “//” trước dòng hiện tại nếu không chọn dòng nào.
Insert Date: Chèn ngày hiện thời vào mã nguồn,
Bookmarks: Đánh dấu một dòng để sau này có thể di chuyển đến dòng đó
được dễ dàng hơn.
4.3. Thực đơn Options
Đây là thực đơn Options, dưới đây là phần diễn giải các tùy chọn:
Auto Indent: Tựđộng thụt lề khi nhấn phím enter.
Show Line Numbers: Hiển thị số dòng ở phía bên trái, chúng ta có thể tìm thấy số dòng hiển thị ở phía dưới của SED.
Highlight Selected Line: Làm nổi bật dòng được chọn bằng màu được chọn trong hộp thoại Customize Colors.
Chương 3: Game Engine – Cách sử dụng SED
Show Toolbar: Hiển thị toolbar nếu nó đã bị tắt.
Show Command Help: Hiển thị Command Help nếu nó đã bị tắt.
Show Variable List: Hiển thị danh sách biến nếu nó đã bị tắt.
Configuration: Hiển thị hộp thoại cấu hình.
Font: Thay đổi Font.
4.4. Thực đơn Tools
Đây là thực đơn tools, chứa các lệnh sau:
Add Comment: Để cho người dùng có thể nhập dòng chú thích.
To-Do List: Mang đến một danh sách có ghi tất cả những công việc bạn sẽ thực hiện.
Color Picker: Để chọn một màu và giá trị RGB sẽđược đưa vào đoạn mã.
Insert Image: Để chọn một ảnh và thêm nó và mã nguồn.
4.5. Thực đơn Debug
Đây là thực đơn debug, nó chứa các lệnh sau:
Syntax Check: Kiểm tra lỗi cú pháp trong lần chạy cuối cùng.
Test Run: Khởi động engine sử dụng đường dẫn đã
được cấu hình. Hãy chắc chắn những thiết lập này
đều chính xác. Nếu engine được khởi động, nó sẽ tiếp túc chạy tập tin wdl.
Step over: Bỏ qua các dòng tiếp theo và tiến tới vị trí gỡ lỗi hiện tại.
Chương 3: Game Engine – Cách sử dụng SED
Goto current debugposition: Nhảy tới vị trí gỡ lỗi hiện tại.
Ignore further breakpoints: Tiếp tục engine và bỏ qua các điểm dừng tiếp theo.
Add watch: Thêm biến vào cửa sổwatch.
Edit watch: Thay đổi giá trị được chọn trong cửa sổwatch trong lúc run-time.
Chương 3: Game Engine – Cách viết một DLL
IV. Giao tiếp với các DLL
DLL là một thư viện ngoài chứa các hàm có sẵn hoặc do người dùng viết. DLL A6 có thể được sử dụng như phần mở rộng đến engine và ngôn ngữ C-Script. Để tạo ra một plugin A6, SDK (hệ thống phát triển mã nguồn) và ngôn ngữ lập trình như Visual C++ cần phải có. Plugin DLL được dùng để thêm nhiều tác động mới, như tạo ra trí thông minh cho một thực thế, chỉ lệnh C-Script mới, cũng như có thể viết toàn bộ chương trình bằng C++ hoặc Delphi thay vì viết bằng C-Script. Theo lý thuyết, mọi thứ: engine vật lý, một engine 3D khác hoặc ngay cả một ngôn ngữ viết kịch bản có thể được thêm vào engine theo cách này. Bởi vì plugin DLL làm việc với tất cả các phiên bản.
1. Bắt đầu với SDK
Khi tạo một dự án mới (chọn File->New Project), VC++ sẽ đề nghị chọn một dự án mẫu. Hãy chọn Win32 Dynamic-Link Library, khi ứng dụng Win32 được hiển thị, chọn Simple DLL. VC++ sẽ tạo ra một dự án DLL. Tập tin main.cpp chứa mã nguồn như sau:
//plugin.cpp : Defines the entry point for the DLL application.
#include "stdafx.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; }
Chép tất cả các tập tin SDK vào thư mục được tạo ra bởi VC++. Bây giờ, đê biên dịch một plugin DLL A6, chúng ta phải liên kết thư viện a5dll.lib (một tập tin trong SDK) đến dự án (Project Properties -> Linker Input -> Additional Dependencies) và include tập tin a5dll.h và a5funcs.hđến tập tin main.cpp. 3
Chương 3: Game Engine – Cách viết một DLL
Thư viện a5dll.lib chứa đựng một vài hàm cần thiết cho một DLL, như các hàm: a5dll_getwdlobj, a5dll_getwdlfunc, vả a5dll_getscript. Chúng ta sẽ xem những hàm này sau. Tuy nhiên DLL phải gọi ít nhất một trong những hàm này để chắc chắn rằng thư viện được liên kết đúng. Để làm điều này, thêm hàm theo sau: // để chắc chắn rằng thư viện được liên kết đúng void force_library(void) { a5dll_getwdlobj(""); }
Bây giờ, chúng ta có thể thêm một hàm nào đó đến DLL, mà nó có thể được gọi trong một script, hoặc bởi hàm main của game. Đểđược engine chấp nhận, tất cả các hàm phải có loại là DLLFUNC fixed function(...), như thế này:
// trả về giá trị x * 2n
DLLFUNC fixed ldexpc(fixed x,fixed n) {
return (FLOAT2FIX(FIX2FLOAT(x)*pow(2.0,FIX2FLOAT(n)))); }
Hàm này trả về một biểu thức số học với các đối số của nó. DLLFUNC không phải là một phần của C++ - đây chỉ quy ước để định nghĩa một hàm DLL xuất.
fixed là loại biến số của A6 và C-Script. Cả hai đều được định nghĩa trong
a5dll.h với các hàm chuyển đổi sau:
#define DLLFUNC extern "C" __declspec(dllexport)
typedef long fixed; // fixed point 22.10 number format used by C-Script
inline fixed INT2FIX(int i) { return i<<10; } inline int FIX2INT(fixed x) { return x>>10; }
inline double FIX2FLOAT(fixed x) { return ((double)x)/(1<<10); }
inline fixed FLOAT2FIX(double f) { return (fixed)(f*(1<<10)); }
Engine sẽđưa qua và nhận lấy tất cảđều là số - tọa độ, biến … đều được biểu diễn theo loại fixed. Vì thế, hãy chuyển đổi bất kì số nào thành fixed trước khi đưa nó trở lại engine, giống như trong ví dụ trên.
Chương 3: Game Engine – Cách viết một DLL
Hãy dịch DLL - giả định rằng tên nó là plugin.dll - và chép nó thư mục
work. Để gọi hàm ldexpc, chúng ta phải làm 2 việc: khai báo hàm và mở DLL. Việc đầu tiên được thực hiện bằng tuyên bốdllfunction trong script:
dllfunction ldexpc(x,n); // khai báo một hàm dll
Với khai báo này, hàm ldexpc sẽ được biết trong script. Trước khi gọi nó, chúng ta phải mở DLL. Hãy đặt nó trong hàm main của script:
function main() { ...
dll_open("plugin.dll");
và đừng quên đóng DLL trước khi thoát khỏi game: ...
dll_close(dll_handle); exit;
Sau hoàn thành, chúng ta có thể gọi chỉ lệnh thêm vào trong C-Script: ...
x = ldexp(y,n); // tính x = y * 2n
...
Để có thể debug DLL trong VC++, thiết lập lệnh trong Project Properties - > Debug đến đường dẫn của tập tin exe của engine ( ví dụ như "C:\program files\gstudio\bin\acknex.exe), đối số lệnh chỉnh đến tập tin script và tham số dòng lệnh (như “mygame.wdl -wnd") và thư mục làm việc đến thư mục game (như "C:\program files\gstudio\mygame"). Trong Project Properties -> General, thiết lập thư mục output và immediate là “.” (dấu chấm, có nghĩa là thư mục đang làm việc) để engine có thể tìm thấy tập tin ngay lập tức. Như vậy, chúng ta có thể biên dịch và debug bằng cách đặt các điểm dừng như thông thường.
Đây chỉ là những kiến thức cơ bản để viết một plugin DLL. Vẫn còn nhiều thứđể học. Còn các phương pháp để trao đổi dữ liệu với engine sẽ được mô tả trong phần tiếp theo. Tất cả các hàm DLL có thể được khai báo và gọi đến trong script giống như những hàm trong C-Script, sau khi kích hoạt DLL bằng hàm dll_open và dll_closeđược mô tả trong phần hướng dẫn script.
Chương 3: Game Engine – Cách viết một DLL
2. Sử dụng đối tượng C-Script trong một DLL
Chúng ta đã biết được cách thêm một chỉ lệnh C-Script mới, còn bên trong DLL chúng ta có thể truy cập biến, đối tượng và hàm như thế nào? Chúng ta có một vài hàm thư viện để làm điều này. Tất cả các hàm thư viện được cung cấp bởi SDK đều bắt đầu bằng a5dll_. Trong đó, hàm thường sử dụng nhất là:
long a5dll_getwdlobj(char *name);
Hàm này trả vềđịa chỉ của một đối tượng hoặc biến có tên được đưa. Nó có thể sử dụng để đọc hoặc ghi bất kì một đối tượng C-Script bên trong một DLL. Nếu đối tượng không tồn tại, nó sẽ trả về NULL và sẽ xuất hiện một lỗi. Thí dụ một hàm DLL mà truy cập đối tượng trong C-Script.
// thêm giá trị được đưa vào một vector trong C- Script
fixed AddToVector(fixed value) {
// lấy địa chỉ của một biến
static fixed *myvector = (fixed *)a5dll_getwdlobj("myvector");
// thêm cùng giá trị đến 3 thành phần của vector
myvector[0] += value; myvector[1] += value; myvector[2] += value; return value; } Vì thế, chúng ta có thể sử dụng hàm này để lấy một con trỏ chỉ đến một đối tượng bất kì trong C-Script, không kể nó được định nghĩa trước bởi engine hoặc do chúng ta định nghĩa. Trong trường hợp, nó là một vector được định nghĩa trong C-Script như sau:
Chương 3: Game Engine – Cách viết một DLL
và hàm a5dll_getwdlobj sẽ trả về một con trỏ đến vector này, cũng chính là một mảng các sốfixed. Tại sao chúng ta lại không chuyển sang số kiểu fixed?. Bởi vì value có kiểu là fixed và chúng ta có thể cộng hai số kiểu fixed giống như 2 số nguyên. Nhưng chúng ta không thể chia hoặc nhân 2 số này.
Như vậy, bây giờ chúng ta đã biết cách đọc và thay đổi các biến trong C- Script, nhưng với những đối tượng phức tạp như panel, view, entity thì sao? Hãy nhìn vào tập tin a5dll.h – chúng ta sẽ tìm thấy tất cả các cấu trúc được định nghĩa trong C-Script, nhưA4_STRING, A4_ENTITY, A4_PARTICLE,
A4_BMAP, A4_TEX … Tất cả những cấu trúc này bắt đầu với A4_ ( ngay cả trong phiên bản A6). Chúng ta sẽ nhận được một con trỏ chỉ đến cấu trúc như với các biến.
// phóng to, thu nhỏ camera view
fixed ZoomIn(fixed value) {
static A4_VIEW *camera = (A4_VIEW *)a5dll_getwdlobj("camera");
return (camera->arc -= value); }
camera là một khung nhìn (view) đã được định nghĩa trước. Bởi vì