Xem Sprite Sheet

Thả vào một sprite sheet — hoặc nhiều ảnh khung hình cùng lúc — rồi xem nó chạy. Chọn tốc độ khung hình, xem từng khung một, và lấy lại các khung hình khi xong việc.

Thả một sprite sheet, hoặc một bộ ảnh khung hình, hoặc bấm để chọn file

PNGWEBPGIFBMPJPEG

Thả nhiều ảnh cùng lúc thì mỗi ảnh là một khung hình, xếp theo tên file: walk1, walk2, walk10.

Công Cụ Này Làm Gì

Thả một sprite sheet vào và xem nó chạy. Tốc độ khung hình, chế độ lặp và mức phóng to đều đổi được ngay tức thì, bạn có thể xem từng khung một, và có hai lớp phủ dành cho câu hỏi mà người xem thường thật sự muốn hỏi — khung nào đang sai. Xong việc thì lấy lại các khung hình: trang này mở sẵn phần xuất file ở thẻ Khung PNG (ZIP), với mọi khung hình đã được xếp vào khung chứa chung.

Vẫn là bộ công cụ mà trang cắt sheet, trang xuất GIF và trang tạo sprite sheet cùng dùng. Cả bốn kiểu xuất — khung PNG, ảnh GIF động, sheet đã đóng gói và file atlas JSON của nó — đều có mặt ở đây; chỉ khác nhau ở thẻ được mở sẵn và ở cách các khung hình trong thẻ đó được định kích thước.

Một Sheet, Hay Một Đống Khung Hình

Cả hai kiểu đầu vào đều được chấp nhận, và chúng đi hai đường khác nhau.

Một ảnh được coi là một sheet. Nó được đo đạc: một lưới đều đọc được từ chính các khe hở của sheet sẽ thắng tuyệt đối, còn nếu không có thì các sprite được dò riêng từng cái khi tìm được nhiều hơn một sprite và chiều rộng hoặc chiều cao của chúng chênh nhau quá 10 phần trăm so với sprite lớn nhất. Nếu cả hai điều trên đều không xảy ra, bộ cắt theo lưới vẫn được giữ với các con số do bạn nhập. Dòng trạng thái luôn nói rõ điều gì đã xảy ra và vì sao, và chỉ một nút bấm là đổi sang kiểu còn lại.

Nhiều ảnh được coi là các khung hình — mỗi ảnh một khung, xếp theo tên file, rồi ghép thành một sprite sheet duy nhất. Không có gì được dò tìm trên sheet ghép đó: hình học của nó do chính công cụ dựng nên, nên không có lưới nào để đo và không có sprite nào để dò, và dòng trạng thái nói đúng như vậy thay vì báo một kết quả đo chưa từng diễn ra.

Hãy thả chính các file ảnh chứ đừng thả thư mục chứa chúng: một thư mục tới dưới dạng một mục duy nhất mang tên thư mục chứ không phải nội dung bên trong, và mục đó không phải là ảnh. Công cụ nhận PNG, WEBP, GIF, BMP và JPEG, và dán ảnh từ bộ nhớ tạm cũng được như thả file.

Thứ Tự Theo Tên File

Tên file được so sánh từng ký tự một, và ở chỗ cả hai tên cùng là chữ số thì cả cụm chữ số được so sánh theo giá trị chứ không phải theo mặt chữ. Chính điều đó đưa walk2 lên trước walk10 mà không ai phải đổi tên gì cả. Các chữ cái được so sánh bỏ qua hoa thường và dấu, còn nếu hai tên còn lại giống hệt nhau thì tên ngắn hơn đứng trước, nên frame7 đứng trước frame07 thay vì hai file rơi vào đúng thứ tự mà trình duyệt tình cờ đưa sang.

Dù vậy, thứ tự theo tên file chỉ là phỏng đoán ban đầu, và dải khung hình là chỗ để bạn sửa lại.

Xem Thật Kỹ

Thanh phát bắt đầu hoạt ảnh ở 12 khung hình mỗi giây và cho chọn từ 1 tới 60. Ba chế độ lặp là Xuôi, Ngược và Qua lại; chế độ Qua lại quay đầu ở mỗi đầu mút mà không giữ khung đầu mút thêm một nhịp. Mức phóng to có 1×, 2×, 4× và 8×. Các nút điều khiển nhảy tới khung đầu hoặc khung cuối và bước từng khung một, thanh tua đưa bạn tới bất kỳ đâu, và thao tác tua sẽ tạm dừng trước — một thanh tua phải giằng co với hoạt ảnh đang chạy sẽ bật ngược lại và trông như một điều khiển bị hỏng. Kéo thanh tốc độ khung hình thì khung đang hiển thị được giữ nguyên chứ không chạy lại từ đầu.

Có hai lớp phủ trả lời câu hỏi "khung nào đang sai", và cả hai đều tắt cho tới khi bạn bật lên:

Lớp phủNó vẽ gì
Bóng mờ khung kềKhung liền trước, hoặc cả hai khung hai bên, mờ phía sau khung hiện tại
Viền khung chứaKhung chứa vẽ bằng nét đứt, kèm một đường liền trên hàng neo

Bóng mờ luôn là các khung kề trong dải chứ không phải theo chiều phát, nên chúng ở nguyên bên của mình khi lặp Ngược và không lật sang bên kia giữa chừng nhịp Qua lại. Đường neo mới là thứ đáng đọc: cạnh neo của mọi khung hình đều được ghim vào đúng hàng đó, nên sprite nào có cạnh nằm lệch khỏi hàng ấy chính là sprite bị nhấp nhô.

Đổi Thứ Tự Và Chọn Khung Để Phát

Mỗi khung hình là một ảnh thu nhỏ trong dải. Bấm vào một ảnh — hoặc bấm vào ô của nó trên sheet phía trên — để loại nó khỏi hoạt ảnh và khỏi mọi bản xuất. Khoảng Từ/Đến thu hẹp phần phát về một đoạn khung hình, các nút hàng chọn một hàng của sheet đã đo được, và một nút riêng tắt hết những khung không có điểm ảnh đục nào — đó là thứ giữ cho hoạt ảnh không bị đứng lại ở mấy ô trống mà hàng cuối cùng thường được chèn thêm.

Các khung hình chỉ kéo đổi thứ tự được ở trường hợp nhiều ảnh rời, và giới hạn đó là có chủ ý chứ không phải làm dở. Thứ tự của một sheet lưới chính là cái lưới của nó, còn thứ tự của một sheet dò riêng là thứ tự đọc; cả hai đều được dựng lại từ sheet mỗi khi có thiết lập thay đổi, nên một thứ tự làm bằng tay ở đó sẽ âm thầm bị bỏ đi ngay ở lần kéo thanh trượt kế tiếp. Một bộ file được thả vào là đầu vào duy nhất mà thứ tự thật sự do bạn quyết định.

Ở chỗ có kéo đổi thứ tự, mỗi ảnh thu nhỏ đều in số khung của nó, và toàn bộ thao tác làm được bằng bàn phím: nhấn tab tới tay cầm của một khung, nhấn phím cách để nhấc lên, dùng các phím mũi tên để di chuyển, nhấn phím cách lần nữa để thả, hoặc nhấn escape để huỷ. Mỗi bước đều được đọc lên. Lưu ý rằng khoảng Từ/Đến vẫn gọi khung hình theo số gốc của chúng chứ không theo vị trí trên màn hình — và đó chính là lý do các con số được in ra.

Khung Chứa

Mọi khung hình đều được xếp vào cùng một khung chứa, và kể từ lần cập nhật này, bản xem trước, sheet đã đóng gói, file atlas, ảnh GIF và cả ZIP theo khung chứa đều đọc chung một tập vị trí. Cái gì chạy trên màn hình là cái đó tải về.

Chế độ tự động lấy khung đang được chọn lớn nhất theo từng trục một cách độc lập, cộng thêm phần đệm ở cả hai phía, rồi làm tròn lên số chẵn kế tiếp — hoặc lên luỹ thừa của hai kế tiếp nếu bạn bật tuỳ chọn đó. Chế độ tự đặt nhận chiều rộng và chiều cao bạn gõ, hoặc một trong các mức dựng sẵn: 32, 64, 128, 256 và 512. Phần đệm ăn vào cả bốn cạnh, còn điểm neo quyết định sprite nằm ở đâu trong khoảng còn lại. Mặc định là giữa cạnh dưới để bàn chân đứng yên; cả chín điểm neo đều chỉ cách một cú bấm.

Việc cắt bỏ viền trong suốt trước là thứ làm cho điểm neo có ý nghĩa trên một sheet mà các khung đều được chèn cho vừa một khổ cố định — và bật nó lên bây giờ cũng làm đổi cả bản xem trước, vì bản xem trước vẽ theo các vị trí đã cắt gọn chứ không theo ô thô như trước. Một ô mà cắt xong không còn gì thì sẽ hiện ra trống trơn. Công cụ chỉ mở nút này ở chỗ nó thật sự làm được việc: khung của một sprite dò riêng vốn đã bám sát các điểm ảnh của chính nó, còn sheet không có vùng trong suốt thì không có viền trong suốt nào để tìm, nên ở cả hai trường hợp công cụ nói rõ lý do thay vì lặng lẽ làm mờ nút đi.

Sprite lớn hơn khung chứa thì được báo chứ không bị âm thầm đổi kích thước. Nhãn đỏ nêu tên những khung có vấn đề, liệt kê rõ sáu khung đầu và đếm số còn lại. Ở bản xem trước và ở ảnh GIF, vùng vẽ được nới rộng ra để giữ trọn phần tràn cho bạn thấy; còn trên sheet đã đóng gói thì sprite được vẽ từ một vị trí lệch âm bên trong ô của nó, nên nó tràn sang ô bên cạnh hoặc ra ngoài mép file PNG, và một khung trong ZIP theo khung chứa thì đúng bằng kích thước khung nên phần tràn bị cắt ngay ở mép. Tăng kích thước khung chứa, bỏ chọn khung đó, hoặc chuyển sang chế độ thu nhỏ cho vừa đều giải quyết được; chế độ thu nhỏ giảm theo cùng một tỉ lệ trên cả hai trục nên tỉ lệ hình không bị méo.

Lấy Lại Các Khung Hình

Bốn kiểu xuất. Ảnh GIF, sheet đã đóng gói và file atlas đều dựng từ cùng một tập vị trí, và file ZIP cũng vậy — trừ khi bạn chuyển nó sang Kích thước gốc, khi đó nó lấy đúng ô của từng khung hình:

Kiểu xuấtBạn nhận được gì
Khung PNG (ZIP)Một file PNG cho mỗi khung đang chọn — theo khung chứa, hoặc theo kích thước gốc như lúc được cắt ra
GIF độngKích thước khung chứa nhân 1×, 2×, 4× hoặc 8×, ở tốc độ bạn đặt
Sprite sheet (PNG)Các khung đang chọn đóng thành lưới đều, một dải ngang, hoặc số cột cố định
Atlas (JSON)Định dạng TexturePacker, lấy tên file làm khoá hoặc dạng mảng

Các file khung hình được đánh số theo thứ tự phát và thêm số 0 phía trước cho khớp tổng số khung, để trình quản lý file liệt kê chúng đúng thứ tự chạy chứ không đặt frame_10 lên trước frame_2. Khi các khung hình đến từ những ảnh rời chứ không phải từ một sheet được cắt ra, mỗi file còn mang thêm tên của ảnh gốc sinh ra nó — frame_03_walk_idle.png — đặt sau con số chứ không phải trước, để thứ tự sắp xếp vẫn bám theo thứ tự phát ngay cả khi bạn đã kéo các khung hình sang một thứ tự khác. Ảnh GIF chỉ phát xuôi được, nên chế độ Ngược và Qua lại được thực hiện bằng cách ghi thẳng thứ tự đó vào chính các khung mà file chứa — nghĩa là một file GIF Qua lại chứa 2n − 2 khung cho n khung đang chọn. Bản xuất ZIP thì không làm vậy; nó xuất đúng một file PNG cho mỗi khung đang chọn, bất kể chế độ lặp là gì. Thời gian của GIF được lưu theo đơn vị một phần trăm giây, nên phần lớn tốc độ khung hình không thể qua được định dạng này một cách chính xác, và bảng xuất file sẽ nói file thật sự phát ở tốc độ nào mỗi khi con số đó khác với con số bạn đặt.

Còn một nút nữa gói sheet, file atlas và ảnh GIF vào chung một file ZIP dùng cùng một tên gốc, và cả ba được tạo ra bằng đúng những lệnh mà các nút tải riêng lẻ gọi — nên gói đó không thể chứa một sheet lệch với chính file atlas của nó.

Giới Hạn

Một sheet đơn lẻ bị từ chối nếu vượt quá 16384 điểm ảnh mỗi cạnh, vì đến mức đó thì chính việc cấp phát canvas đã đủ làm sập tab; khi vượt quá 8192 và chưa quá giới hạn ấy, công cụ báo trước rằng việc dò tìm và xuất file sẽ mất vài giây thay vì để bạn tưởng nó bị treo. Một lô ảnh rời bị từ chối ngay khi sheet ghép từ chúng vượt quá cùng mốc 16384 điểm ảnh đó — và mốc này được kiểm tra ngay trong lúc đọc từng ảnh, nên lô ảnh dừng sớm chứ không phải sau khi đã giải mã hết, và không có gì được nạp vào cả.

Câu hỏi thường gặp

Sprite sheet của tôi có bị upload lên đâu không?
Không. Ảnh được giải mã, vẽ ra và mã hoá lại bằng JavaScript chạy ngay trong tab trình duyệt đó — những bước nặng chạy trong một Web Worker do chính trang này phục vụ — và không có gì được gửi qua mạng. Đó cũng là lý do công cụ vẫn chạy được khi mất mạng, miễn là trang đã tải xong.
Tôi thả nguyên một thư mục ảnh khung hình được không?
Hãy thả chính các file ảnh chứ đừng thả thư mục chứa chúng. Một thư mục được thả vào sẽ tới dưới dạng một mục duy nhất mang tên thư mục chứ không phải nội dung bên trong, mà mục đó không phải là ảnh, nên công cụ báo là không đọc được; còn chọn hoặc kéo nhiều file ảnh cùng lúc thì chạy tốt. Khi có nhiều hơn một file, mỗi ảnh là một khung hình, chúng được xếp theo tên file rồi được ghép thành một sprite sheet duy nhất ở phía sau — nên dải khung hình, bản xem trước và mọi bản xuất đều hoạt động y như với một sheet thật. Không có bước dò tìm nào chạy trên sheet ghép đó, vì hình học của nó do chính công cụ dựng nên và đã biết chính xác.
Vì sao các khung hình của tôi chạy sai thứ tự — walk10 trước walk2?
Thực ra là không sai. Tên file được duyệt từng ký tự một, và ở chỗ cả hai tên đều là chữ số thì cả cụm chữ số được so sánh theo GIÁ TRỊ chứ không phải theo mặt chữ, nên walk2 đứng trước walk10 mà không cần thêm số 0 nào. Các chữ cái được so sánh bỏ qua hoa thường và dấu. Khi hai tên còn lại giống hệt nhau thì tên ngắn hơn đứng trước, nên frame7 đứng trước frame07 thay vì phụ thuộc vào việc trình duyệt đưa file nào sang trước. Còn nếu thứ tự tên file vốn không phải thứ tự bạn muốn, hãy kéo các khung hình trong dải bên dưới.
Bóng mờ khung kề dùng để làm gì?
Để đối chiếu một khung hình với các khung nằm hai bên nó, và đó là cách một khung bị giật tự lộ ra. Chế độ Khung trước tạo bóng mờ của khung liền trước; chế độ Cả hai tạo bóng mờ của cả hai khung hai bên. Bóng mờ được vẽ phía sau khung hiện tại ở một phần tư độ đục, và chúng luôn là các khung kề trong dải chứ không phải theo chiều phát — chúng không đổi bên khi bạn đặt chế độ lặp Ngược, và cũng không lật sang bên kia giữa chừng một nhịp Qua lại. Dưới hai khung hình thì không có bóng mờ nào, và đúng hai khung hình thì khung kề duy nhất được vẽ một lần chứ không chồng hai lần lên chính nó.
Viền khung chứa và đường neo cho biết điều gì?
Hình chữ nhật nét đứt chính là khung chứa mà mọi khung hình được xếp vào — đúng cái khung mà sheet đã đóng gói, file atlas JSON và ảnh GIF đều dựng theo. Đường liền nằm ngang cắt qua nó là hàng neo: hàng mà cạnh neo của từng khung hình được ghim vào, và với điểm neo mặc định giữa cạnh dưới thì đó chính là đường mặt đất nhân vật đứng lên. Một sprite mà cạnh neo của chính nó không nằm trên đường đó là sprite bị lệch so với các khung bên cạnh, và chính độ lệch ấy làm nhân vật trông như nhấp nhô khi hoạt ảnh chạy. Đường neo có tính cả phần đệm trong, nên nó dịch theo vùng dùng được chứ không nằm cách mép khung một khoảng cố định.
Những gì tôi thấy ở bản xem trước có đúng với file tải về không?
Có, và đó chính là thay đổi của lần cập nhật này. Bản xem trước, file PNG sheet đã đóng gói, file atlas JSON, ảnh GIF động và — khi chọn Theo khung chứa — cả file ZIP đều đọc chung một mảng vị trí, nên một khung hình nằm ở đúng một chỗ trong cả năm. Có một điểm cần lưu ý. Khi một sprite lớn hơn khung chứa mà bạn chọn chế độ cảnh báo thay vì thu nhỏ cho vừa, bản xem trước và ảnh GIF sẽ nới rộng vùng vẽ để giữ trọn phần tràn ra cho bạn nhìn thấy, còn sheet đã đóng gói vẫn vẽ sprite đó từ một vị trí lệch âm bên trong ô của nó — nên trên sheet nó tràn sang ô bên cạnh hoặc ra ngoài mép, và một khung trong ZIP theo khung chứa thì bị cắt phần tràn ngay ở mép file. Nhãn đỏ dưới phần khung chứa chỉ đích danh những khung nào bị như vậy.
Vì sao ảnh GIF tôi xuất ra có kích thước khác trước?
Vì giờ ảnh GIF lấy đúng kích thước khung chứa, thay vì một khung bao mà riêng đường xuất GIF tự tính lấy như trước. Một lưới 63 điểm ảnh giờ xuất ra ở 64 điểm ảnh, do kích thước khung tự động làm tròn lên số chẵn kế tiếp, và phần đệm trong bạn đặt cũng được tính vào. Đó là cái giá để ảnh GIF và sheet đã đóng gói cuối cùng cũng thống nhất với nhau về vị trí của một khung hình. Các nút tỉ lệ nhân kích thước đó lên 1, 2, 4 hoặc 8 lần, và kích thước ảnh xuất ra chính xác được in ngay trên bảng xuất file để bạn thấy trước khi bấm.
Tôi lấy lại khung hình theo kích thước gốc của chúng thay vì theo khung chứa được không?
Được — thẻ Khung PNG (ZIP) có nút chuyển Kích thước gốc / Theo khung chứa. Trang này mở sẵn ở Theo khung chứa, vì đầu vào mà nó được xây quanh là một bộ ảnh rời có kích thước thật sự khác nhau; còn Kích thước gốc thì xuất mỗi file PNG theo đúng kích thước của chính khung hình đó, như lúc nó được cắt ra — lưu ý rằng Kích thước gốc lấy đúng ô khung hình, nên khi bật cắt bỏ viền trong suốt thì nó vẫn xuất nguyên phần chưa cắt chứ không bám sát điểm ảnh. Dù chọn kiểu nào thì cũng đúng một file PNG cho mỗi khung hình đang chọn, đánh số theo thứ tự phát và thêm số 0 phía trước cho khớp tổng số khung, để trình quản lý file liệt kê chúng đúng theo thứ tự chạy.