sukaraki
Donkey Kong
- 12/5/08
- 356
- 9
Kiến thức lập trình căn bản
( cho jassuser , nếu bạn dùng GUI, cũng nên xem qua 1 ít
Bạn muốn hỏi các bro trên forum , muốn nhờ fix dùm bug, hoặc đơn giản hơn , bạn muốn làm quen với lập trình jass ? Tất cả những điều bạn muốn ở trên, đạt được hay không, thường phụ thuộc vào 1 thứ mà bạn ít nghĩ đến nhất . Đó là sự rõ ràng trong lập trình.
Tại sao nó lại quan trọng như vậy ?
Nếu bạn không tuân thủ việc lập trình minh bạch, hậu quả bạn nhận được sẽ là số bug vô bờ bến , số memory leak thừa mứa , và spell của bạn, nếu phải sửa , thì sẽ mất thời gian gấp nhiều lần bình thường. Bài viết này mục tiêu mang lại cho bạn 1 phong cách nhất quán, minh bạch trong lập trình jass cơ bản - giúp bạn làm map khoa học hơn.
Các bro nếu có freetime, sẵn sàng giúp bạn fix bug, test map thôi. Nhưng các bro mà nhìn vào mớ code tùm lum tè le ko trật tự ko quy cách ko tiêu chuẩn gì của bạn, ko chắc họ sẽ tiếp tục, hay lại fang 1 câu : "tớ bận quá, để sau nhé".

Đối với những bạn mới làm quen với lập trình , thường mắc những lỗi căn bản sau :
0) Lập quá nhiều trigger , gây rối mắt.

1) Code liền 1 mạch ko xuống dòng. Lỗi này làm mớ code của bạn trở thành 1 cái thùng rác.mà chẳng ai có hứng thú lục thùng rác dùm bạn cả.

2) Code liền 1 mạch ko ghi chú.Lỗi này làm mớ code của bạn dù đơn giản nhưng trông phức tạp hơn khoảng 70%. Người đọc phải đọc thật kỹ, vì biến của bạn đặt ra thật vô phương hiểu được vì nó là những từ được lai giống giữa 3 cái sau : tiếng anh+tiếng việt+viết tắt.

Tôi bỏ làm map mấy tháng rồi, giờ giở lại code của chính mình còn ko hiểu 1 số chỗ, nên phải ngồi bỏ 1 buổi tối ghi chú lại cho tất cả các hàm cái library ( cái library này tự tôi tạo ).
3)Xóa 1 biến đi mất tiêu rồi còn dùng , hoặc chưa khai báo mà đã dùng , hoặc ko thèm xóa biến sau khi dùng. Lỗi này là lỗi dẫn tới map bạn bị memory leak ( yên tâm bác nào chơi thanh ram 16 GB thì khỏi lo vụ này
). Hãy tập cho mình thói quen lập trình thật rõ ràng , sau đây là giải pháp :
Giả pháp 0) Lập quá nhiều trigger, gây rối mắt. Giải pháp : cho tất cả trigger của bạn vào một library. Phân loại ra library spell, library system .v.v..
Cú pháp :
Mã:
library MasterHandy
//================================================
// masterco's library
//================================================
//Dung de bat 1 unit stop
function stop takes unit u returns nothing
call IssueImmediateOrder( u, "stop" )
endfunction
//================================================
endlibrary
Trong đó : MasterHandy là tên library , 3 dòng tiếp theo là chú thích cho dễ nhìn, bên trong là các hàm (function ) của bạn, ví dụ là bắt 1 unit stop, bạn phải type : call IssueImmediateOrder( u, "stop" ) , thì nay, với hàm stop này, bạn chỉ cần ghi stop(u) thì nó sẽ stop.
Giữa các hàm , bạn phải có ghi chú công dụng của hàm theo cách dễ hiểu nhất, và phải có đường biên phân cách như
//================================================
Thông tin ngoài lề :Trước khi 1 unit bắt đầu làm 1 animation nào đó , thì bạn nên bắt nó stop trước, thì hành động của nó mới chính xác thời gian.
Nhờ lập library, sau này bạn rất được lợi về thời gian làm spell.
Ví dụ : spell meteor strike cần làm 1 quả meteor bay dần dần xuống và lăn đi 1 đoạn, vừa lăn vừa gây dam / Spell Spear di chuyển nhân vật cầm cây giáo chọc thẳng tới phía trước và gây dam ...v..v... 2 spell này đều có điểm chung là cần di chuyển 1 vật đi 1 distance, trong 1 time , và gây dam trên đường đi.
Bạn chỉ cần tạo 1 hàm dash( u , ang ,dis, time )
Trong đó : u : unit cần di chuyển / ang : góc mà nó sẽ di chuyển / dis : khoảng cách mà nó sẽ di chuyển / time : thời gian nó đến đích là bao lâu.
Sau đó bạn tạo 1 hàm dmgarea( u , dmg , loc ,rad )
Trong đó : u : unit gây dmg / dmg : số dmg / loc : vị trí mà nó gây dmg / rad : diện tích mà nó gây dmg.
Có 2 hàm này, sau này làm spell bạn ko cần lập trình lại nữa, mà chỉ việc gọi hàm dash , và dmgarea , và đưa đủ thông số yêu cầu là ok.
Giải pháp 1và 2 ) Code liền 1 mạch ko xuống dòng, ko ghi chú . Trước khi nêu giải pháp, bạn hãy nhìn function dưới đây :
---------- Post added at 16:27 ---------- Previous post was at 16:26 ----------
Hàm được chia ra làm 3 vùng : vùng khởi tạo để khai báo các biến, vùng xử lý , và cuối cùng là vùng hủy biến. Nếu bạn thích rõ ràng hơn , thì phân cách mỗi vùng bằng
//-------------câu chú thích---------------------
Nhìn vào hàm, ta thấy ngay 3 vùng , và nếu bắt tay sửa lỗi sẽ rất dễ dàng. Ngòai việc xuống dòng, bạn còn phải vô lề như code dưới, if nằm trong loop. Nếu như nhiều if nằm trùng nhau mà ko vào lề, thì khi bạn sửa sẽ chẳng biết code nào thuộc if nào.

loop
exitwhen( i > gnum-1)
if( i != chose ) then
set u = null
endif
set i = i+1
endloop
Thông tin ngoài lề : Khi khai báo biến , nên thống nhất cho tất cả các biến theo 1 quy cách nào đó, để dù nhìn vào code nào, ta cũng nhận ra công dụng của nó ngay. Theo kinh nghiệm của tôi, khi bạn tuân thủ theo quy cách khai báo biến , thì bạn ko cần nhiều chú thích mà vẫn hiểu rõ ràng code.

Mã:
Ví dụ :
unit chính : u
unit dummy : dum
unit trong group : e
effect : eff
string : s
group : g
timer : t
location : loc
Nếu có 2 dum thì dum1 , dum2.
Còn về tên hàm :
nên thống nhất 1 kiểu đặt tên : ví dụ cho hàm tạo 1 unit :
Mã:
type1 : createunit
type2 : create_unit
type3 : Create_Unit
type4 : create_u
)---------- Post added at 16:29 ---------- Previous post was at 16:27 ----------
Giải pháp 3)Xóa 1 biến đi mất tiêu rồi còn dùng , hoặc chưa khai báo mà đã dùng , hoặc ko thèm xóa biến sau khi dùng
Điển hình như sau :
Mã:
call DestroyEffect(eff)
set eff =null
Tại sao Destroy rồi còn phải set null ?
Khi destroy effect vụ nổ, bạn chỉ hủy cái hình ảnh vụ nổ trong bộ nhớ, còn cái biến eff để trỏ tới nó thì vẫn còn đó, dù ko dùng nữa , nhưng vùng nhớ đó ko được giải phóng để sử dụng. Nếu bạn làm spell có tầm 300 cái effect trên giây, thì sẽ đứng máy sớm thôi.

Để biết khi nào thì spell có memory =leak, bạn cứ tạo 1 bầy đàn unit có spell đó ( tầm 25 con ), sau đó tạo 1 trigger có event là khi player bấm ESC , trong trigger đó là group 25 thằng cu đó lại, sau đó bắt nó cast spell ( phải đúng order string trong spell đó nó mới cast nhé ). Nên để spell manacost là 0 , cooldown là 0 ,và loại spell là Unit để tránh rắc rối.
1 spell MUI đầy effect 25 unit cùng cast mà ko giật máy , nếu bạn ko tin cứ pm tôi sẽ send 1 example cho
. Map có 10 người chơi mà dùng ultimate liên tục cứ gọi là thoải mái đi, nếu bạn master cái vụ này
.Xem code mẫu :
Mã:
local unit u
set u = createunit(....)
call dash(u...)
set u = null
Trong đó , hàm dash là dash liên tục trong 1 thời gian, ví dụ 1 giây đi. Thì khi mình set u = null mất rồi, thì nó có dash tiếp ko ?
Câu trả lời là có !
Vì unit u là biến local, nó chỉ là trong khu vực hàm đó thôi, khi bạn gọi dash(u...) thì u được bay tới hàm dash rồi, và cuối hàm này bạn có set nó null chăng nữa, chỉ là giải phóng cái biến local này thôi, unit u đã được trỏ tới hàm dash rồi.

Vậy nếu bạn Removeunit u , thì nó còn dash ko ?
Câu trả lời là không!
Vì hàm remove ( với unit, destroy với effect... ) thì nó ko phải giải phóng vùng nhớ, mà là hủy cái con unit của bạn đi!

Để khắc phục những memory leak hiệu quả nhất, đầu tiên bạn nên set null tất cả các biến ở khu vực cuối hàm. Yên tâm set null ở hàm này , nhưng nó vẫn chạy ổn ở hàm khác, vì biến ta dùng là biến local
.Tiếp theo : bạn nên tạo 2 hàm sau trong library :
destroyunit( u, time) : sau 1 khoảng thời gian thì Remove unit u, và set u = null
destroyeffect(eff,time) : sau 1 khoảng thời gian thì Destroy effect eff và set eff = null
Ví dụ trong 1 spell bạn tạo 1 dummy có mang 1 quả cầu lửa trên đầu, spell có animation trong 2 giây. thì bạn :
Mã:
local unit dum = createunit(.....) // tạo unit dummy
local effect eff = createeff(dum...) //gắn effect lên người nó
call destroyunit(dum,2) // destroy và set null dummy sau 2 giây
call destroyeffect(eff,time) // destroy và set null effect sau 2 giây
set dum = null
set eff = null
Chỉ có thế thôi, là bạn hoàn toàn yên tâm sau 2 giây , effect và unit dummy sẽ bốc hơi như chưa bao giờ hiện hữu , ko để lại 1 memory leak nào, mà bạn ko cần phải đi lần mò remove với cả set null nó nữa.

Còn location thì thường là dùng xong hủy ngay, nên ko cần tạo hàm time.
Còn gì nữa nhỉ, thôi hôm nay thế thôi, có gì tôi edit sau.
Have fun programming !

.