Ý tưởng của các bạn về Sprites ?

Black FaceBlack Face Posts: 424Registered
Ở đây hầu như các bạn đã biết rồi, để một vật chuyển động trong game 2D chúng ta gọi là sprite và công việc của nó là làm game thật sống động, mình viết topic này để tìm hiểu xem cách lựa chọn và suy nghĩ của các bạn khi làm sprite là thế nào, dưới đây mình đưa ra 2 cách cơ bản để cử động 1 nhân vật chẳng hạn, như sau, mình sẽ nói đơn giản dễ hiểu:
Cách 1:
Gộp những hình ảnh chuyển động của nhân vật đó vào 1 hình lớn rồi cho chạy từng khung hình để thành một chuyển động.

Cách 2:
Mỗi file hình rời nhau là 1 khung hình và lập trình cho chạy nhiều hình ảnh, cũng sẽ thành chuyển động.

Xem hình sẽ rõ
16ocZU.jpg

Vậy theo bạn thì bạn sẽ chọn cách nào, và vì sao ? Bình chọn và cmt nhé.

Comments

  • rosenetrosenet Posts: 175Registered
    Theo mình cách 1 là tối ưu vì:
    - Nếu làm cách 2: Load từng ảnh sẽ rất sẽ bị lỗi khi có quá nhiều tên. (1 file ảnh là 1 tên, 1 chuyển động gồm 8 ảnh thì chuyển động đó cần phải có 1 mảng chứa 8 cái tên)
    - Việc load từng ảnh sẽ chậm hơn là load 1 ảnh (mặc dù kích thước cả 2 đều như nhau).
  • CryingWOLFCryingWOLF Posts: 1,766Registered
    Cách 1. Load = cách 2 mất thời gian hơn
  • slucis7593slucis7593 Posts: 544Registered
    Mình nghĩ là tùy trường hợp nên sử dụng khác nhau:
    Cách 1: Các Sprite trong Sprite sheet sắp xếp theo thứ tự tăng dần từ trái sang phải, trên xuống dưới, tối ưu hiệu năng vì phép tính toán ít, đơn giản, không cần lưu nhiều dữ liệu tránh việc set/get dữ liệu gây giảm hiệu năng. Phù hợp cho việc tạo animation skill hoặc hình ảnh nhân vật chuyển động trong platform.

    Cách 2: Chưa thử nhưng có vẻ giống cách 3 dưới đây.

    Cách 3: Các Sprite nằm trên 1 file nhưng không theo thứ tự tăng dần như cách 1 mà xếp lộn xộn hoặc 1 quy luật khác.
    Ngược lại cách 1, cách này sử dụng nhiều dữ liệu, cần set/get nhiều lần có thể gây giảm hiệu năng.
    Nhưng nó rất linh động. Ví dụ như sprite sheet của RPG Maker các phiên bản, hình ảnh không phải theo thứ tự tăng dần như cách 1 mà nó chạy 2 3 2 1 2, dao động như con lắc qua điểm chính giữa.
    Thực ra cái này cũng có quy luật nên vẫn có thể làm 1 vài thủ thuật để chạy như cách 1, nhưng 1 số trường hợp khác lại không được như vậy, giống như tạo animation trong RPG Maker vậy, bạn có thể kéo từng sprite trong sprite sheet animation 1 cách rất linh động, không nhất thiết là chạy 1 mạch từ đầu xuống cuối.

    Ngoài ra cách 3 này các sprite không cần phải có cùng kích thước, cách 1 thường là sẽ phải cùng kích thước.

    Tóm lại:
    2 cách trên khá là ngược nhau:
    Cách 1: Được hiệu năng, kém linh động.
    Cách 2: Kém hiệu năng, được cái linh động.
  • Black FaceBlack Face Posts: 424Registered
    Cách 3 mà bạn nói không khác gì cách 2 cả, chỉ khác là phải set toạ độ cho nó, nói ngắn ngọn là những hình ảnh đó unpack ra đc nhưng không có thông tin về toạ độ của nó cho nên khá khó khăn trong việc sử dụng, nhớ lúc trước Ngọa Hổ có viết 1 đoạn code rgss xử lý vấn đề này và đưa nó trở thành 1 sprite sheet nhưng chưa dc tối ưu lắm. Còn về phần hiệu năng thì tuỳ cách sử dụng chương trình của các bạn, không phải trường hợp nào cũng tối ưu. Những effect hiện tại các bạn đang sử dụng hầu như là từ extra game ra cả, vậy tại sao không unpack ra dc những hình lớn mà tại sao toàn các frame riêng lẻ. Cách làm thế nào thì mình không rõ nhưng trong quá trình code mình nhận ra thế này. Cách 2 mình nêu ở trên đối với việc sử dụng ngay lập tức thì rất chậm. Nhất là đối với những game nhiều chi tiết, vì các frame sử dụng chưa dc load vào ram, chạy đến đâu thì những hình ảnh mới dc đưa vào ram và hiển thị đến đó, ram sẽ tăng lên liên tục, nên cần có máy cấu hình tốt mới xử lý dc nhanh gọn. Không như sprite sheet, load 1 hình lớn rồi xử lý chia ảnh ra để hiển thị. Cho nên như các bạn thấy, các game lớn thường có module load game trước khi vào màn chơi hay khởi động game. Đó là việc đưa dữ liệu vào ram để game chạy mượt mà. Còn các bạn không dùng nhiều tài nguyên và không có hàm load nên nếu dùng theo cách 2 sẽ thấy sprite dc load khá chậm, giật hoặc lag nhưng khi load xong toàn bộ frame rồi thì mượt mà chả khác gì sprite sheet
  • DeathDeath Posts: 732Registered, Moderators
    Mình thấy RM có 1 cái script load trước tài nguyên nhưng ngốn rất nhiều ram mặc dù game chẳng có mấy :benhnang:
    Có lẽ RM không phù hợp với cách 2, 3 cho lắm.
  • slucis7593slucis7593 Posts: 544Registered
    Black Face wrote:
    Cách 3 mà bạn nói không khác gì cách 2 cả, chỉ khác là phải set toạ độ cho nó, nói ngắn ngọn là những hình ảnh đó unpack ra đc nhưng không có thông tin về toạ độ của nó cho nên khá khó khăn trong việc sử dụng, nhớ lúc trước Ngọa Hổ có viết 1 đoạn code rgss xử lý vấn đề này và đưa nó trở thành 1 sprite sheet nhưng chưa dc tối ưu lắm. Còn về phần hiệu năng thì tuỳ cách sử dụng chương trình của các bạn, không phải trường hợp nào cũng tối ưu. Những effect hiện tại các bạn đang sử dụng hầu như là từ extra game ra cả, vậy tại sao không unpack ra dc những hình lớn mà tại sao toàn các frame riêng lẻ. Cách làm thế nào thì mình không rõ nhưng trong quá trình code mình nhận ra thế này. Cách 2 mình nêu ở trên đối với việc sử dụng ngay lập tức thì rất chậm. Nhất là đối với những game nhiều chi tiết, vì các frame sử dụng chưa dc load vào ram, chạy đến đâu thì những hình ảnh mới dc đưa vào ram và hiển thị đến đó, ram sẽ tăng lên liên tục, nên cần có máy cấu hình tốt mới xử lý dc nhanh gọn. Không như sprite sheet, load 1 hình lớn rồi xử lý chia ảnh ra để hiển thị. Cho nên như các bạn thấy, các game lớn thường có module load game trước khi vào màn chơi hay khởi động game. Đó là việc đưa dữ liệu vào ram để game chạy mượt mà. Còn các bạn không dùng nhiều tài nguyên và không có hàm load nên nếu dùng theo cách 2 sẽ thấy sprite dc load khá chậm, giật hoặc lag nhưng khi load xong toàn bộ frame rồi thì mượt mà chả khác gì sprite sheet

    :D quả đúng như bạn nói, nếu như theo cách 2 của bạn thì game sẽ load nhiều file ảnh riêng lẻ và việc chuyển đổi giữa các file ảnh sẽ khến hiệu năng chương trình giảm đi. Giống như trong RPG Maker, ở phiên bản XP thì các file bị chia nhỏ rất nhiều, nhưng sang VX và VX Ace thì các file đã được gộp lại, việc này chính là giúp tăng hiệu năng.

    Vậy giải pháp đặt ra làm sao mà nó vẫn riêng lẻ, nhưng lại chỉ cần 1 file mà thôi.
    Việc đó dẫn tới Cách 3 của mình.
    Và vấn đề nảy sinh như bạn nói là quản lý tọa độ và kích thước của từng file.

    Vấn đề này trong RPG Maker mình ko rõ có tool hỗ trợ nào không, nhưng trong lập trình game java thì có đó, công việc hoàn toàn tự động, sử dụng rất dễ dàng, không hề cần quan tâm tới tọa độ, kích thước nào cả.

    Ví dụ đây nè:
    Các file riêng lẻ:
    1.png

    Gộp các file vào 1 file:
    canyonbunny.png

    kèm theo 1 file ghi chép tọa độ, kích thước, nếu muốn lấy ảnh nào chỉ cần dùng tên của file ảnh để lấy.
  • Focker_cFocker_c Posts: 1,577Registered
    Các engine ngày nay hay hầu như các phương pháp dev game hiện nay đều dùng cách 1.
  • Dang_KhoaDang_Khoa Posts: 3,861Administrators
    Cách 3 là cách tối ưu nhất, gọi là Texture Atlas, đây là cách thông dụng và thường được dùng trong lập trinh mobile vì yêu cầu đặt ra là hiệu suất cao trên môi trường máy móc cấu hình thấp.

    Texture Atlas thường gồm 1 file .atlas dùng để lưu tọa độ và một file ảnh .png. Nó tối ưu vì trong bộ nhớ chỉ chứa duy nhất một file ảnh, và khi cần hình gì chỉ cần truy xuất file ảnh đó, lấy khúc hình mình cần tại tọa độ (x, y) trong ảnh. Load một lần thì bao giờ cũng nhanh hơn load nhiều lần.

    Cách 1 gọi là Sprite Sheet, cách này cũng khá tối ưu, nhưng không bằng Texture Atlas. Giả sử mình có 10 hero, mỗi hero sẽ có 1 file Sprite Sheet riêng, tức là phải load 10 lần, còn với Texture Atlas thì chỉ cần load 1 lần duy nhất dc cả 10 hero.

    Chưa kể trường hợp SpriteSheet không sử dụng hết không gian trống trong hình, ví dụ tư thế 1 có 3 hình, tư thế 2 có 4 hình, thì file hình phải để đủ 4 chỗ chứa. còn khi dùng TextureAtlas thì nó sẽ tự động gói lại sao cho kích thước file là nhỏ nhất, làm tối ưu dung lượng.

    Cách 2 là cách tệ nhất, vì phải load quá nhiều hình, quá nhiều file khó quản lý.

    Tóm lại theo thứ tự 3 > 1 > 2.

    Để đóng gói file theo kiểu Texture Atlas, ta dùng phần mềm TexturePacker, chỉ cần kéo thư mục vào nó sẽ tự động đóng gói lại cho mình một cách tự động.
  • Focker_cFocker_c Posts: 1,577Registered
    Texture Atlas :) Giờ e mới nghe đến đấy.
    Nếu dùng các ngôn ngữ lập trình thì gọi nó ra như nào đấy a ?
  • Black FaceBlack Face Posts: 424Registered
    Cách thức đó không có gì mới, nói đơn giản là cắt 1 khoảng nhỏ trong 1 hình lớn và hiển thị theo tọa độ, mỗi frame hiển thị 1 khoảng nhỏ khác nhau, sẽ thành sprite, rộng cao tương ứng với khoảng đó, còn viết thế nào thì tùy ngôn ngữ sử dụng và suy nghĩ của người viết đến đâu, chỉ là ở đây ít người làm tới thôi, x, y, height, width, point... có thể lưu = file txt rồi dịch ra cũng được, thấy đa số đều save = xml, nếu công cụ lập trình có hỗ trợ thì tốt, còn không thì phải tự viết module thôi. Mệt người dev nhưng bù lại được cái hiệu năng làm việc khá OK, còn để đỡ mệt hơn nhiều thì làm đơn giản và dựa vào vài hàm hỗ trợ trong công cụ lập trình, VD như là DXT compress..., còn không thì giảm thiểu chất lượng hình ảnh, với 1 vài công cụ thì giảm chất lượng hình ảnh cũng như 0 :(
  • Dang_KhoaDang_Khoa Posts: 3,861Administrators
    Focker_c wrote:
    Texture Atlas :) Giờ e mới nghe đến đấy.
    Nếu dùng các ngôn ngữ lập trình thì gọi nó ra như nào đấy a ?

    @Focker_c nếu em dùng Engine để làm game thì nó có cách load hình riêng của nó, mình không lựa chọn được, có thể nó dùng Atlas hoặc không, còn nếu em dùng Framework để làm game (ví dụ libgdx, haxe-flixel, cocos2D-x) thì framework sẽ hỗ trợ em cách đọc file Atlas chỉ với vài dòng code ^^

    @Black Face Thường thì người ta code sẵn cho mình rồi, anh dùng qua một số framework thì cái nào cũng có làm sẵn hết, bỏ vào rồi xài thôi. Với giờ người ta ưa dùng json hơn xml đó em :3
  • Focker_cFocker_c Posts: 1,577Registered
    Thấy cách 3 tính bảo mật khá tốt, nhưng với GME thì chỉ có thể là dùng cách 2 thôi.
    Mà thấy cũng ổn rồi, sang GMS nó bảo mật tốt hơn. :)
Sign In or Register to comment.