Thanh cooldown là một thành phần đồ họa không chỉ có ở trong game mà còn ở trong rất nhiều các phần mềm đang thịnh hành hiện nay. Nó dùng để diễn tả khoảng thời gian mà người chơi hoặc người dùng phải chờ để có thể thực hiện một hành động nào đó.
Trong những game nhập vai hoăc chiến thuật như DOTA ,LOL hoặc StarCraft thì đây là một trong nhưng thành phần quan trọng nhất ảnh hưởng đến cục diện trận đấu của game.
Trong bài hướng dẫn này, chúng ta sẽ tìm hiểu cách làm sao để tạo được một thanh cooldown bất kể ngôn ngữ bạn dùng là gì, tất cả sẽ chỉ là code dựng (psuedo-code) và cơ chế hoạt động của thanh cooldown. Bạn có thể lấy demo ở phần cuối của bài viết.
Thanh cooldown thực tế là một hình ảnh đồ họa cho việc cooldown và việc cooldown có thể gọi ngắn gọn là việc hẹn giờ cho thứ gì đó. Ví dụ : Khi một hoạt động nào đó được xảy ra, quá trình đếm thời gian bắt đầu, khi quá trình này kết thúc, hành động đó lại có thể được xảy ra lần nữa. Đó là cooldown.
Nếu đứng từ góc độ lập trình, để ngăn chặn một hành động trong quá trình cooldown, ta đặt một biến bool và gán giá trị cho nó bằng “true” khi hành động được thực hiện. Khi chúng ta có gắng thực thi hành động này thì đoạn code sẽ kiểm tra xem biến bool ta đặt ra có phải bằng “false” không và theo như ta gán ở phía trên thì hành động này sẽ không được xảy ra.Khi quá trình đếm thời gian đã kết thúc, ta gán giá trị cho biến bool đó bằng “false” và hành động sẽ được thực hiện.
Khi nút Action được kích hoạt, quá trình đếm được bắt đầu và nút Action bị tắt đi. Trong quá trình đếm ngược , khoảng thời gian được hiển thị và đến cho đến khi nó kết thúc. Nút Action sẽ lại được kích hoạt lại.
Ta hãy xem đoạn code sau :
01. //An object Character has a boolean variable “Cooldown”, a numeric variable “cTimer” and another numeric variable “cEndTime” 02. 03. On clicked Button 04. txtHistory.text = txtHistory.text & newline & “The character performs an action” 05. Character.cTimer = 0 06. Character.cEndTime = txtTimer.text //The text object “Cooldown duration” 07. Character.Cooldown = True 08. Button.Enabled = False 09. 10. If Character.Cooldown = True 11. Character.cTimer = Character.cTimer + dt 12. If Character.cTimer >= Character.cEndTime 13. txtHistory.text = txtHistory.text & newline & “The character is ready to perform an action” 14. Character.cTimer = -1 15. Character.Cooldown = False 16. Button.Enabled = True 17. Else & Every 0.5 seconds 18. txtHistory.text = txtHistory.text & newline & “The action is on cooldown. ” & Character.cEndTime – Character.cTimer & ” seconds of cooldown remaining.”
Hàm “On clicked Button” chỉ được thực thi khi nút bấm được kích hoạt và phần code bên dưới sẽ chỉ được thực thi khi sau cú click. Đó là hành động người dùng bắt đầu đếm thời gian và đặt “Cooldown” là “true”.
Khi nút bấm được kích hoạt, biến “Character.cEndTime” là thời điểm cho khoảng cooldown kết thúc. Giá trị này được đặt vào đối tượng text “txtTimer” ngay bên cạnh nút Action.
Đồng thời tại thời điểm này, giá trị của “cTimer” được đặt về 0 vì nó được coi là một vòng thời gian đếm ngược mới. “Cooldown” đặt về “true” để cho phép phần thứ 2 của đoạn code được kích hoạt. Cuối cùng, chúng ta vô hiệu hóa nút đi.
Dòng thứ 10 của đoạn code trên được thực thi vào mỗi giây, nó kiểm tra giá trị của “Character.Cooldown” là “true” và nếu thỏa mãn điều kiện nó sẽ thêm giá trị của “dt” vào giá trị hiện tại của “Character.Timer”.
“dt” là viết tắt cho delta time, là một biến hệ thống đại diện cho khoảng thời gian cần thiết để vẽ từ khung hình trước cho đến khung hình hiện tại. Điều này có nghĩa là, cho dù máy tính có mạnh mẽ đến đâu, thì chúng ta đều có thể đảm bảo rằng khoangt hời gian đếm ngược cũng sẽ chạy từng đó thời gian.
Nếu như vẫn còn thời gian đếm ngược, chúng ta sẽ kiểm tra giá trị của “cTimer” xem có lớn hơn “cEndTime” không, nếu có, chúng ta phải đi đến cái kết thúc của việc đếm ngược. Chúng ta đặt “Character.Cooldown” là “false” để cho đoạn code này không được thực thi tiếp cho dến khi người dùng ấn nút Action lại.
Đó là tất cả giải thích về cơ chế đếm ngược hay còn gọi là cooldown, sau đây chúng ta sẽ tập trung vào việc làm sao tạo được thanh cooldown.
Một thanh cooldown là một thành phần đồ họa mà nó thay đổi kích thước và hiển thị liên tục . Nó là cơ chế cho người chơi biết có thể tiếp tục thực hiện một hành động.
Thanh bar chuyển từ màu xanh sang màu đỏ thể hiện việc cooldown, nó mở rộng từ 0 cho đến độ rộng ban đầu.
Trong ví dụ trên, thanh bar chỉ đơn thuần là một hình ảnh có độ rộng bằng 100 pixel. Khi hành đông được thực thi, độ rộng giảm về 0 pixel. Sau đó, mỗi giây khi biến “Cooldown” là “true”, độ rộng được trả về với giá trị cũ dựa vào giá trị của “cTimer”.
Hãy xem đoạn code sau:
01 //Using the same “Character” object as in the basic example, this time the object is visible on screen 02 03 On any mouse click & Character.Cooldown = False 04 Character.cTimer = 0 05 Character.cEndTime = txtEndTimer.text 06 Character.Cooldown = True 07 CooldownBar.Width = 0 08 CooldownBar.AnimationFrame = 1 09 10 If Character.Cooldown = True 11 Character.cTimer = Character.cTimer + dt 12 CooldownBar.Width = (CooldownBar.MaxWidth / Character.cEndTime) *Character.cTimer 13 14 If Character.cTimer >= Character.cEndTime 15 Character.cTimer = -1 16 Character.Cooldown = False 17 CooldownBar.Width = CooldownBar.MaxWidth 18 CooldownBar.AnimationFrame = 0
Cơ chế đếm ngược khá giống với ví dụ bên trên nên chúng ta sẽ tập trung vào “CooldownBar”. Đối tượng này có hai khung hình là hình vuông màu xanh 32x32px và màu đỏ 32x32px. Nó còn có thuộc tính “MaxWidth” được đặt là 100 , là chiều rộng lớn nhất của thanh bar.
Mỗi giây, nếu “Cooldown” là “true”, “CooldownBar.width” được đặt là một phần của “CooldownBar.MaxWidth”. Chúng ta xác định phần này bằng giá trị của việc chia độ rộng lớn nhất với thời gian kết thúc của việc đếm ngược vào sau đó nhân kết quả với giá trị “cTimer”.
Ở thời điểm bắt đầu và kết thúc của việc đếm ngược, chúng ta cần phải đảm bảo chuyển khung hình sang đỏ khi quá trình bắt đầu và sang xanh khi quá trình kết thúc.
Chúng ta có thể thay đổi điểm bắt đầu của thanh bar nhiều cách khác nhau:
Trong một số game, nút kĩ năng còn thể hiện luôn việc đếm ngược thời gian tái kích hoạt cho kĩ năng. Như ví dụ dưới đây :
Như bạn đã thấy, mỗi kĩ năng có một thanh bar màu đen và một bộ đếm giờ thể hiện việc cooldown. Thanh bar màu đen thực chất là một hình ảnh được đặt trên nút kĩ năng có độ mờ bằng 45%, và bộ đếm thời gian là một đối tượng text. Mỗi nút kĩ năng đều có thực thể của nó là “SkillCover” và “txtSkillTimer”.
Lần này, các biến “Cooldown” , “sTime” và “sEndTime” được gắn vào mỗi thực thể “SkillButton” . Và điểm gốc cho “SkillCover” là cạnh đáy của nó.
Xem đoạn code sau :
01 //Object “SkillButton” with variables “Cooldown” (boolean), “sTime” (numeric), “sEndTime” (numeric), and a specific animation frame to know which instance is being clicked/selected. 02 //Object “SkillCover” with a variable “Skill” set accordingly to the animation frame of the SkillButton they are related to. 03 //Object “txtSkillTimer” with a variable “Skill” for the same purpose as above. 04 On SkillButton clicked & SkillButton.Cooldown = False 05 SkillButton.sTime = 0 06 SkillButton.Cooldown = True 07 Create Proj & ProjImage objects 08 ProjImage.AnimationFrame = SkillButton.AnimationFrame //To either throw a dagger or a ninja star 09 10 txtSkillTimer.Skill = SkillButton.AnimationFrame 11 & 12 SkillCover.Skill = SkillButton.AnimationFrame 13 Set txtSkillTimer’s position to the bottom of SkillButton 14 Set SkillCover’s position to the bottom of SkillButton 15 Set txtSkillTimer in Front of SkillButton 16 Set SkillCover behind txtSkillTimer //Still in front of SkillButton 17 txtSkillTimer.Visible = True 18 SkillCover.Visible = True 19 SkillCover.Height = SkillButton.Height 20 21 For each SkillButton & SkillButton.Cooldown = True 22 SkillButton.sTime = SkillButton.sTime + dt 23 24 txtSkillTimer.Skill = SkillButton.AnimationFrame 25 & 26 SkillCover.Skill = SkillButton.AnimationFrame 27 txtSkillTimer.text = SkillButton.sEndTime – SkillButton.sTime 28 SkillCover.height = SkillButton.Height – ((SkillButton.Height / SkillButton.sEndTime) * SkillButton.sTime) 29 30 If SkillButton.sTime >= SkillButton.sEndTime 31 SkillButton.sTime = -1 32 SkillButton.Cooldown = False 33 34 txtSkillTimer.Skill = SkillButton.AnimationFrame 35 & 36 SkillCover.Skill = SkillButton.AnimationFrame 37 txtSkillTimer.Visible = False 38 SkillCover.Visible = False
Ở đây, chúng ta chọn đúng thực thể của “txtSkillTimer” và “SkillCover”. Không giống như thanh cooldown trước, “Skillcover” bắt đầu từ đầy cho đến vơi, che toàn bộ chiều cao của “SkillButton”, và sau đó trong quá trình đếm ngược sẽ bắt đầu giảm chiều cao để hở ra hình ảnh của nút.
Để làm được việc này, chúng ta cho “SkillCover” chiều cao bằng với “SkillButton” để bắt đầu, và sau mỗi khung hình, sẽ trừ đi (“SkillButton.Height” / “SkillButton.sEndTime”) * “SkillButton.sTime” từ chiều cao đủ của nó.
Bạn có thể làm nhiều hơn với “SkillCover”, tất cả đều dựa vào trí tưởng tượng và kĩ năng mĩ thuật của bạn.
Bạn có thể dùng rất nhiều cách để tạo một thanh cooldown bar .Không có một khuôn mẫu nào có định cho nó. Tất cả đều phụ thuộc vào kĩ năng của bạn. Bạn có thể lấy hướng dẫn ở đây :
Cảm ơn bạn đã đọc bài hướng dẫn và mong được nghe những phản hồi từ phía bạn.
Tôi là Nguyễn Văn Sỹ có 15 năm kinh nghiệm trong lĩnh vực thiết kế, thi công đồ nội thất; với niềm đam mê và yêu nghề tôi đã tạo ra những thiết kếtuyệt vời trong phòng khách, phòng bếp, phòng ngủ, sân vườn… Ngoài ra với khả năng nghiên cứu, tìm tòi học hỏi các kiến thức đời sống xã hội và sự kiện, tôi đã đưa ra những kiến thức bổ ích tại website nhaxinhplaza.vn. Hy vọng những kiến thức mà tôi chia sẻ này sẽ giúp ích cho bạn!