Sau đâu sẽ có nhiều từ ngữ mang tính chất chuyên ngành, nếu các bạn đọc không hiểu thì hãy xem chúng như những công cụ mà game developer sử dụng để tạo ra một sản phẩm. Giống như người thợ làm bánh, họ có lò nướng, chày giã bột, khay đựng, v.v.... Đối với game developer, thì nó là những framework, studio, hoặc cả một bộ development toolkit. Đừng hoang mang, hãy cùng tôi tham gia cuộc thám hiểm thế giới của game developer nào!
Tôi có một chút kiến thức về game cũng như về game framework cocos2d-x và cocos2d-js. Nhận thấy khả năng sử dụng javascript để tạo game của mình nhanh hơn hẳn c++ (2 ngày so với 2 tuần của cùng 1 project). Trước đây tôi cũng sử dụng Cocos Studio để layout game nhưng nó dường như thiêu hẳn các công cụ như là: kiểm thử trên nhiều device, scripting, fit screen. Tuy nhiên, với Cocos Creator, sau khoảng 30p tìm hiểu, tôi vẫn chưa thấy chỗ tích hợp sdkbox như Cocos studio, chắc có lẽ phiên bản sau mới có. Thôi, luyên thuyên chuyện tính năng đủ rồi, công cụ này hiện tại rất phù hợp với mục đích của tôi, tạo game trên nền web nhanh gọn lẹ. Chủ yếu là luyện tập khả năng sử dụng resources hiệu quả và tăng cường khả năng scripting. Để push lên một trang web, tôi có mua 1 tên miền và tạo trang web trên đó rồi, khi nào hoàn thành xong sản phẩm đầu tiên, tôi sẽ viết một bài hướng dẫn tạo một trang web trên cloud nhé.
Hừm, tôi vẫn đang lướt qua từng trang hướng dẫn của Cocos Creator, nếu bạn đang là game developer và đang đọc bài blog này thì cùng đọc với tôi cho vui nhé. Đọc xong tôi sẽ update vô bài blog này các khả năng và những gì giúp ích cho mục đích của tôi.
Cocos creator document:
http://cocos2d-x.org/docs/editors_and_tools/creator/index.html (nếu bạn không vô được link này thì có lẽ bên chủ site đã đổi đường dẫn, bạn có thể search google keyword: cocos creator documentation)
Đọc...lướt...lướt...lướt....
Đọc xong ví dụ Hello World, tôi có cảm tưởng đây như là một phiên bản Unity từ Cocos2d-x, nhưng cái họ đang có là engine chạy cực ổn đa nền. Nên việc phát triển thêm bộ Creator quả là tuyệt vời, tôi đang mong chờ từng ngày đây. Và bây giờ bắt đầu tiến đến phần hấp dẫn, tạo game đầu tiên trên Cocos Creator, tôi thật rảnh khi vừa đọc document vừa viết blog! Theo như hướng dẫn, thì họ chỉ tôi làm game "Pick Up The Stars". OK, let's go!
Đây là một thể loại game jumping (nhảy), bạn sẽ điều khiển một con quái vật ngố rừng để ăn các vì sao. Document có đưa ra một đường dẫn nhưng tôi không thể load nổi page đó, thôi vậy, đọc tiếp. Bước tiếp theo cần có của game developer là resources. Nên nhớ, bạn là developer chứ không phải artist, đừng đặt nặng vấn đề đồ hoạ khi đang phát triển game, nếu không bạn sẽ ngốn rất nhiều thời gian để làm một việc mà đa phần game developer không thể, đó chính là tạo resources đẹp. Theo kinh nghiệm non nớt của tôi, bạn nên thay các resources trong game bằng những hình khối đơn giản như hình vuông, hình tròn. Hãy chú tâm vào game play!
Tiếp tục việc mò mẫm Cocos creator, tôi phải download resources để có thể tiếp tục làm game hái sao này.
https://github.com/cocos-creator/tutorial-first-game/releases/download/0.7.0/start_project.zip
Sau khi download xong tôi giải nén và bỏ vô thư mục của project tạo bằng Cocos creator. Mọi thứ sẽ trông như thế này:
Hãy thử tưởng tượng bạn sẽ phải tạo 1 số thứ resources thế này xem, tốn thời gian lắm. Tập trung vào việc của mình thôi. Khi đã có resources như bên trên, tiếp theo tôi tạo scene đầu tiên của game này. Tôi đặt tên cho nó là "game". Đây là khoảnh khắc mà bất cứ developer nào cũng từng trải qua, không biết phải đặt tên thế nào cho đẹp, sử dụng cho lâu dài và đọc cho dễ hiểu. Tôi cứ bất chấp hết đặt bừa là "game".
Tiếp tục là thiết lập Canvas, chỉnh cho nó Fit Height màn hình, mặc xác Width. Thật ra cũng có một bài viết cho vấn đề này tôi đã từng đọc qua. Nhưng thôi, ban đầu thì biết là Fit Height hiện tại nó tiện hơn là Fit Width hay Fit cả hai.
Trong phần Assets/textures, kéo thả background vào Canvas trong Hierachy. Sau đó chỉnh lại size cho background thành (1360, 960). Điều này đảm bảo cho background có thể phủ được tất cả device.
Tiếp đến tôi kéo thả ground vào Canvas, canh chỉnh vị trí cũng như kích cỡ để được như bên dưới
Tiếp theo, thả quái vật màu tím (PurpleMonster) vào Canvas (đảm bảo nằm dưới ground). Sau đó chỉnh Anchor Point x=0.5, y=0. Thế là việc kéo thả cơ bản đã xong, lúc này tôi cảm thấy chưa bao giờ làm game nó dễ dàng đến thế này. Nhớ đến những ngày tháng ngồi code chay để chạy được một game đơn giản như Pong cũng phải mất đến cả mấy ngày trời, có khi là cả mấy tuần!
Bây giờ tôi sẽ tới phần mà tôi khá yêu thích chính là scripting <3 Không hiểu sao khi nghe tới scripting là lại hưng phấn hẳn lên! Tạo thư mục scripts trong thư mục assets, sau đó tạo 1 file JavaScript tên là Player
Sau đó Add Component cho Player Node
Tiếp theo tôi sửa file script cho Player, viết 1 hàm tạo jump action. Jump Action tượng trưng cho hành vi nhảy múa của con quái vật tím tái! Khi nhảy sẽ có 2 bước, nhảy lên và nhảy xuống, đây là lẽ đương nhiên. Vì nếu chỉ nhảy lên mà không nhảy xuống thì "ếu" phải nhảy mà nó là bay "cmnr"!
Sử dụng hàm onLoad để thiết lập thông tin cho quái vật tím tái khi người chơi load màn hình (scene) của họ. Hiện tại là màn hình game. Nói thêm là trong game sẽ có nhiều màn hình như màn hình chính, màn hình chơi, màn hình tinh chỉnh, màn hình shop mua item, màn hình giới thiệu, hướng dẫn,... Mỗi khi chuyển sang màn hình mới thì hàm onLoad sẽ được gọi, do đó tôi sử dụng nó để thiết lập thông tin ban đầu cho đối tượng nhắm tới, hiện tại là Player.
Thiết lập input từ bán phím, nút a để lách qua trái, nút d để lách qua phải.
Rồi, nhét vào hàm onLoad thôi, đơn giản ghê ^^
Nếu bạn từng, đang và sẽ làm game developer thì bạn không thể nào không biết một hàm huyền thoại, đó là hàm update(). Hàm này sẽ được call trên từng frame, hầu hết tất cả game framework, engine đều hỗ trợ hàm update này. Một giây thông thường được chia 60 frames, mỗi frame thời gian thực thi tối đa 0.016s (16ms). Ngoài ra, tôi cần ôn lại kiến thức vật lí một tí.
Vận tốc = gia tốc * thời gian.
Quãng đường = vận tốc * thời gian.
Sau đây là mapping cho thông tin vật lí của các biến
xSpeed : vận tốc
accel : gia tốc
maxMoveSpeed: vận tốc tối đa cho phép
dt: thời gian
Ta sẽ có:
xSpeed = accel * dt
Quãng đường di chuyển = xSpeed * dt
Hàm update sẽ như sau
Khoan hãy vội làm tiếp, mấy bữa nay tôi gặp rất nhiều người, cũ có mới có. Cuộc sống đa sắc màu là vậy. Hồi chiều có gặp lại một chị đồng nghiệp cũ. Lúc trước chị ấy làm lead QA, hiện tại đang làm PM cho project của công ty cũ của mình. 2 chị em lâu ngày không gặp nói huyên thuyên đủ chuyện trên trời dưới đất. Một phần liên quan tới game, chị í mô tả tầm nhìn cũng như cái nghiệp của nghề làm game. Tôi cũng chú ý tiếp thu và góp nhặt những ý kiến phụ trợ cho mình sau này. Mục đích làm game của tôi cần có tâm hơn, cái tâm ở đây không phải là tâm huyết, mà là tâm cảm, tâm cam. Tôi không nên làm game chỉ vì sở thích hay chỉ vì đam mê vật chất. Trò chơi mà tôi tạo ra cần có tầm nhìn dài hạn, không phải là vòng đời của game, mà là vòng đời của người chơi game. Có thể bạn nghĩ nó rất lạ, nhưng sau khi nói chuyện với chị ấy về thiền cũng như về game. Tôi đã nghiệm ra khá nhiều điều hay, và điều này càng mài dũa cái tâm của tôi về nghề làm game hơn nữa. Và bây giờ, tôi cần cải thiện cái tầm của mình, đó chính là rèn luyện các sản phẩm game đầu tay của mình.
Tiếp tục với Cocos creator, con quái vật xấu xí tím lịm đã biết nhảy và di chuyển rồi. Trông cũng không đến nỗi nào! Nhưng với những thiết lập này, con quỷ này nó thay đổi vận tốc chậm quá. Bấm nút a hoặc d một hồi lâu nó mới chạy. Tôi cần phải thay đổi gia tốc của nó ngay!
accel=1000
Có vẻ ổn hơn rồi, cảm giác tương tác người dùng đã có. Không còn sự delay như vừa rồi nữa. Tiếp tục, tôi sẽ làm những vì sao. Theo như trong hướng dẫn, các vì sao xuất hiện và biến mất thường xuyên, nên phải sử dụng đến "Prefab". Nghe giống như một thứ gì đó làm sẵn trước hết, rồi sau đó chỉ cần xài thôi mà không cần phải làm lại nhỉ. Việc này sẽ giúp ích khá nhiều để sử dụng lại content trong game cũng như chia sẻ với game khác! Wao, khá giống Unity.
Tiếp theo, tôi tạo thêm một component JavaScript nữa, đặt tên là Star
Thêm 1 property cho script Star
Kéo texture Star lên Hierarchy, rồi Add Component Star vô.
Kéo ngược node này từ Hierarchy xuống Assets để tạo Prefab và xoá node star khỏi Hierarchy.
Lúc này, tôi tạo một file JavaScript tên là Game để phục vụ logic cho trò chơi. Và thêm 1 số properties như sau
Nếu bạn có để ý thì những gì trong properties đều được show trong Inspector. Có thể nói properties như là cách để script của bạn giao tiếp với các Node trong Canvas vậy. Tiếp tục, tạo một empty node tên là game, rồi kéo thả file Game JavaScript vô trong bảng Inspector hoặc bấm nút Add Component trong bảng Inspector (tương tự như Star vậy đó).
Bây giờ, tôi kéo thả Prefab Star trong assets vô trong property Star Prefab ở Inspector. Còn ground và Player thì kéo từ Hierarchy. Tôi có kết quả như sau
Thêm 1 đoạn script để sinh vị trí Star random trong Game JavaScript. Phải đảm bảo là vì sao này nên nằm trong tầm "đụng chạm" của quái vật tím.
groundY: vị trí sát phía trên của nền đất
newStar: một instance được tạo ra từ Prefab Star
randY: random vị trí từ sát phái trên nền đất cho tới vị trí nhảy của người chơi
randX: nằm trong vị trí độ rộng của node game (nên chỉnh lại width cho node game thành 960)
Hiện tại, game chạy đơn giản như sau, ngôi sao sẽ random vị trí "ăn được" của quái vật tím đáng thương.
Bây giờ, tôi sẽ thêm logic để cho quái vật tím của mình có thể ngoạm được những ngôi sao lung linh kia. Phần này sẽ phát huy hết tinh của của scripting cũng như điểm yếu của scripting so với ngôn ngữ lập trình truyền thống.
Trong Game JavaScript file:
Trong Star JavaScript file:
Tôi để ý thấy, khi game bắt đầu chạy, thì ngôi sao vẫn chưa sinh ra. Mỗi khi sinh ra một ngôi sao, tôi lại gán thêm một biến game cho Star Component (tức Star JavaScript file). Trong khi đó, biến game này chưa từng được khởi tạo trong Star JavaScript file. Đây là một đặc tính khá quan trọng của JavaScript để scripting game. Tuy nhiên, điều này sẽ gây khó khăn khi muốn truy ngược lại nếu như các biến kiểu này được tạo quá nhiều và các mối liên hệ quá vong vo. Nên, tôi không lạm dụng đặc điểm này. Thường thì tôi cần phải quy ước một số luật trong dự án của mình, hiện tại là biến game sẽ được gán vô Star JavaScript file mỗi khi có ngôi sao mới được tạo.
Sau đó, Star JavaScript file sẽ sử dụng biến game để truy xuất thông tin về người chơi, tính khoảng cách. Nếu nằm trong tầm "ngoạm" được, thì ngôi sao sẽ biến mất và một ngôi sao khác sẽ được sinh ra, tại một địa điểm bất kì. Đó là logic mà 2 đoạn script phía trên thể hiện.
Tôi tiếp tục làm thêm phần score để thể hiện điểm số. Trước tiên là add 1 label vô scene, và chỉnh các thông số như bên dưới
Kéo thả file font (bf mikado...) vô trong phần File của Label, chỉnh lại size, line height các thứ
Kết quả là
Tạo 1 label slot scoreDisplay trong Game Javascript và tạo 1 biến score với giá trị ban đầu là 0
Thêm hàm update score trong Game JavaScript
Trong Star JavaScript. sử dụng hàm update score mỗi khi quái vật tím xực được ngôi sao
Kéo thả score node trong Canvas vô property scoreDisplay của Game Component
Dừng lại một chút và nhìn lại những gì tôi đã làm được. Layout background, ground, Player, star. Tạo script cho Player di chuyển và nhảy nhót, Star có khả năng bị ăn(hơi hài, đáng lẽ Player ăn star chứ nhỉ !o_0). Star sau khi bị ăn sẽ tự động hồi sinh tại vị trí bất kì mà Player có thể chạm tới. Sau khi Player ăn được Star, score sẽ thay đổi.
Tiếp theo tôi nên làm gì đây nhỉ. Thông thường một game đơn giản sẽ thêm yếu tố nào nữa nhỉ, mải mê scripting một hồi tôi lại quên mất cái cơ bản của một game cần là gì rồi! Đây là một điều mà game developer nên cực kì lưu ý. Chúng ta cần có một cái nhìn tổng quan, một đặc tả về game mà mình muốn tạo ra. Vì tôi đang học làm game, nên các ý tưởng sẽ hình thành từ từ trong lúc làm. Nhưng khi tôi làm game thật sự, tôi mong muốn mình sẽ biết tất cả các yếu tố cần có trong game trước khi bắt tay vào làm. Trong giới phần mềm, yếu tố này thường được gọi là đặc tả yêu cầu. Điều này vô cùng, cực kì quan trọng. Nó như xương sống của cả quá trình làm game. Nếu bị lệch từ khúc xương sống thì khó mà ngồi thẳng và đi đứng ngay ngắn được. Tôi mong muốn game của mình sẽ là một "soái ca" chứ không phải là "chàng gù" lay lất nơi "phố chợ".
Cuối cùng chính là vòng đời của game. Khi nhìn lại kĩ những gì mình đã làm được, tôi thấy có gì đó sai sai. Tự nhiên đùng 1 cái vô là có con gì nó nhảy nhảy, mà nó nhảy hoài không biết khi nào xong. Đó chính là vấn đề. Nếu là game, thì nó sẽ có khởi đầu và kết thúc, giống như một bộ phim vậy. Tôi không dự định hướng tới các thể loại game online hay game không hồi kết lúc này, những gì tôi muốn hướng tới là game có cốt truyện và có điểm kết. Tôi rất thích những câu truyện, những bộ phim. Nhất là những bộ phim khoa học viễn tưởng, phiêu lưu mạo hiểm. Điều này đóng góp khá nhiều cho việc lựa chọn con đường phát triển game của tôi. Tôi gọi nó là "niệm" của tôi khi làm game.
Trong Game JavaScript, thêm 1 số đoạn scripting để gia hạn thời gian người chơi cần phải ăn sao. Nếu trong thời gian quy định mà không ăn thêm được sao thì sẽ thua cuộc (gameover).
Và câu hỏi được đặt ra lúc này là, thời gian giới hạn để ăn sao được hiển thị thế nào để người chơi biết hoặc chí ít cảm nhận được "à, thì ra tại mình không ăn sớm nên mới thua". Về mặt trải nghiệm người dùng, có nhiều cách để thể hiện việc này. Dùng đồng hồ đếm, hiện màn hình hướng dẫn,... Nhưng trong ví dụ này, tôi làm cho ngôi sao mờ dần. Và đến khi biến mất, thì cũng là lúc trò chơi kết thúc (gameover). Trong Star JavaScript file
Trong Player JavaScript, thềm 1 phần xử lí âm thanh nữa. Mỗi khi con tím lịm nhảy chạm đất thì kêu lên 1 tiếng "búm"! Nhớ kéo thả file âm thanh jump vô Inspector của Player nhé mọi người.
Roài, thêm tiếng khi nhai sao xong ghi điểm nữa. Tương tự như trên, nhưng làm cho Game Javascript khi gainScore
Property mới
Play sound
Và không quên kéo thả score sound vô Game trong Inspector.
Waaaa, xong roài, làm game thật đơn giản. Suy nghĩ trong tôi lúc này là vậy! Tôi sẽ tiếp tục cuộc hành trình tìm kiếm chân lí trong việc phát triển game, cũng như phát triển bản thân tôi. Còn các bạn thì sao?
Next topic:
http://saigongamestory.blogspot.com/2016/03/3-phu-chuong-tao-lap-website-e-host-game.html