Cách vẽ Space Invader
(muffinman.io)- Giới thiệu Space Invader Generator và giải thích nguyên lý tự động tạo ra nhiều invader pixel art đa dạng
- Cấu trúc này tận dụng việc tạo thân đa giác vector đơn giản cùng các quy tắc hình học như đối xứng, điểm ngẫu nhiên và phản chiếu
- Các chi tiết tay chân như cánh tay, xúc tu, sừng cũng được mở rộng bằng tính ngẫu nhiên và phương pháp hình học, mang lại khả năng biến thể dễ dàng và sáng tạo
- Hoàn thiện đồ họa game quen thuộc bằng cách chuyển đổi sang pixel từ dạng vector, áp dụng màu sắc và thêm mắt
- Công khai toàn bộ quy trình tạo ra cùng logic triển khai mã nguồn, để người học và lập trình viên có thể trực tiếp tùy biến hoặc thực hành
Tổng quan
Space Invader Generator là một công cụ giúp bất kỳ ai cũng có thể dễ dàng tạo ngẫu nhiên các invader phong cách pixel art. Bài viết này giải thích nguyên lý hoạt động của nó cùng quá trình tạo ngẫu nhiên đầy sáng tạo thông qua hoạt ảnh và ví dụ. Điểm nổi bật là cách tiếp cận kết hợp thiết kế và lập trình, bao gồm cấu trúc hình học của invader, chuyển đổi vector-pixel, áp dụng màu sắc, v.v.
Bối cảnh bắt đầu
- Trong khi phát triển công cụ dựng hình 3D tên là Rayven, tác giả nhận ra tầm quan trọng của việc tạo ra những sản phẩm sáng tạo thực sự
- Chọn Space Invader vì đây là đối tượng trực quan và dễ nhận biết với kết quả đơn giản nhưng thú vị
- Sau khi thử vẽ nhiều invader cổ điển bằng dựng hình 3D dựa trên vector, tác giả bắt đầu thực hiện ý tưởng mở rộng thành một bộ tạo ngẫu nhiên vì nghĩ rằng sẽ rất vui
- Trải nghiệm thực hiện này cũng được chia sẻ trong code challenge của Creative Coding Amsterdam
Code challenge
- Code challenge về Space Invaders đã thu hút sự quan tâm của nhiều nhà sáng tạo và lập trình viên
- Nhiều cách triển khai và kết quả khác nhau đang được tập hợp, đồng thời được chia sẻ sôi nổi trong cộng đồng phát triển
Từ phác thảo đến pixel
- Ban đầu, tác giả vẽ nguệch ngoạc và phác thảo bằng tay trên giấy để phân tích cấu trúc invader
- Dùng công cụ Aseprite để vẽ thử nhiều hình dạng invader trên lưới pixel 15x15
- Từ đó phát hiện các mẫu hình học chung như đối xứng qua trục giữa và thân đa giác đơn giản
- Bằng cách kết hợp ưu điểm của pixel art và đồ họa vector, tác giả đã thành công trong việc tạo tính năng tự động sinh ra phần lớn các thiết kế vốn trước đây phải tự vẽ
- Có thể tham khảo chi tiết triển khai tại kho GitHub
Quy trình tạo invader
Tìm tâm
- Thiết lập điểm trung tâm làm mốc cho mọi thao tác
- Xúc tu được tạo ở phía dưới, nên thân chính được đặt cao hơn một chút
- Tận dụng tính đối xứng tổng thể, chỉ cần vẽ một bên rồi phản chiếu trái-phải để hoàn thiện
Xác định phần trên và dưới
- Khi thiết kế cạnh bên của thân, chọn ngẫu nhiên điểm trên và điểm dưới
- Hình dạng hai bên được giữ giống nhau theo trục đối xứng
Vẽ cạnh bên trái
- Đặt ngẫu nhiên 1 đến 5 điểm ở phía trái của thân
- Tạo ra nhiều kết quả khác nhau bằng cách biến đổi tự do từ đa giác lồi đơn giản
- Hiện tượng chồng lấn đường nét sẽ được điều chỉnh tự nhiên trong quá trình pixel hóa
Phản chiếu sang bên phải
- Dùng dữ liệu đỉnh bên trái để tự động tạo phản chiếu sang bên phải
Nối thành đa giác thân
- Kết nối các điểm để hoàn thiện thân đa giác vector
- Khi thêm tay chân lên nền tảng này, hình dáng cốt lõi của invader sẽ được hình thành
Thêm tay chân
Cách tạo xúc tu và sừng
- Tạo xúc tu (tentacle) ở phía dưới và sừng (horn) ở phía trên, áp dụng cùng một phương pháp nhưng khác vị trí và góc
Tìm gốc xúc tu
- Dựa trên điểm thấp nhất của thân để tạo ngẫu nhiên xúc tu bên trái trước
Phác thảo đường trung tâm
- Dùng các điểm ngẫu nhiên để tạo polyline (đường trung tâm)
- Có thể biến đổi độ dài và hình dạng xúc tu theo nhiều hướng
Áp dụng độ dày (fat line)
- Chỉ có đường trung tâm thì quá mảnh, nên tạo các điểm ở hai bên để thể hiện hình dạng xúc tu dày hơn
- Càng gần thân thì càng dày, càng về đầu mút thì càng mảnh (hiệu ứng taper)
- Ở những chỗ góc gấp, độ rộng nét được giảm để thể hiện phần tiếp giáp tự nhiên
- Sử dụng tham số easing để điều chỉnh độ rộng
Hoàn thiện xúc tu
- Nối các điểm ở hai đầu để hoàn thành xúc tu dày
Mở rộng thành nhiều xúc tu và sừng
- Có thể mở rộng theo cùng cách để tạo đối xứng trái-phải, xúc tu trung tâm, sừng phía trên, v.v.
- Với xúc tu trung tâm, quá trình sẽ dừng sớm để tránh va chạm với các xúc tu bên đã được vẽ
- Với sừng, phạm vi góc được thu hẹp và bố trí sang hai bên để không chồng lấn không gian
Chuyển đổi từ vector sang pixel
Pixel hóa thân
- Xác định pixel của thân bằng cách kiểm tra xem tâm của mỗi pixel có nằm bên trong đa giác vector hay không
- Ưu tiên sự đơn giản và tốc độ thực thi hơn là độ chính xác tuyệt đối
Pixel hóa tay chân
- Xúc tu và sừng khá mảnh nên nhiều khi tâm pixel không nằm bên trong
- Gán pixel bằng cách kiểm tra khoảng cách từ điểm đến tâm các pixel lân cận
- Có thể cải thiện độ tự nhiên của xúc tu bằng cách chia nhỏ mid-line (line splitting)
Thêm mắt
- Chọn ngẫu nhiên từ nhiều bộ mắt được chuẩn bị sẵn
- Đặt chúng gần trung tâm thân và áp dụng padding bằng các pixel đệm ở phía ngoài
- Những pixel chồng lên nhau sẽ tự động bị bỏ trống để trông giống như lỗ
Áp dụng màu sắc
Logic tạo màu
- Sử dụng không gian màu OKLCH
- So với HSL, có thể giữ độ sáng (lightness) ổn định trong khi vẫn tạo ra nhiều phối màu sống động đa dạng
- Cố định một giá trị độ sáng, rồi chọn ngẫu nhiên hai tham số còn lại để tạo ra nhiều biến thể
- Mang lại ấn tượng invader liên tục và nhất quán về mặt thị giác
Tận dụng biến thể CSS
- Có thể điều chỉnh màu bằng biến CSS
- Có thể áp dụng thay đổi về độ sáng và độ bão hòa tùy từng tình huống như tương phản với UI hoặc chế độ debug
Triển khai hoạt ảnh
- Tạo chuyển động cho xúc tu, sừng và mắt bằng hoạt ảnh đơn giản 2 khung hình giống trò chơi gốc
- Sao chép mid-line của tay chân rồi dịch chuyển ngẫu nhiên để tạo khung hình biến thể
- Mắt cũng được dịch đi một pixel để tăng cảm giác sinh động
Điều chỉnh kích thước
- Khi tăng kích thước lưới, invader sẽ ngày càng tinh xảo và phức tạp hơn
- Nếu quá lớn, tính trừu tượng của vector sẽ nổi bật hơn và làm giảm cảm giác invader nguyên bản
- Giới hạn đến 31x31 pixel, và có tùy chọn ẩn để nâng tối đa lên 51x51
Kết luận
- Hoàn thiện một generator có thể tự động tạo ra vô số invader đầy màu sắc
- Quá trình thực hiện và viết bài mang lại việc học hỏi, niềm vui và sự tự do sáng tạo
- Cả mã nguồn lẫn nguyên lý đều được công khai nên rất thuận tiện cho thực hành, thử nghiệm và tùy biến
Cảm nghĩ sau khi thực hiện
- Mã JavaScript trong bài viết được lưu lại để tiện cho việc học tập và tham khảo
- Tận dụng Anime.js cùng nhiều phụ thuộc bên ngoài để thiết kế hoạt ảnh, và triển khai bằng TypeScript
- Có chế độ debug riêng cùng tùy chọn step để trực tiếp khám phá quá trình tạo sinh
Bonus - bài viết vẽ dây thừng
- Bài viết tương tác trước đó về cách vẽ hình dạng dây thừng (rope) bằng SVG và JavaScript cũng rất đáng tham khảo
1 bình luận
Ý kiến trên Hacker News
Tôi cũng đã thử làm một trình tạo space invader
Có bản chạy thử và cũng đã công khai mã nguồn
Lấy cảm hứng từ Jared Tarbell
Tôi nhận ra rằng kết quả đẹp hơn mong đợi một cách khá dễ dàng
Cốt lõi là đôi mắt, tính đối xứng hai bên, và các pixel ngẫu nhiên trong một hình vuông nhỏ
Có ý kiến nói là được truyền cảm hứng từ Jared Tarbell; với tôi cũng vậy, các tác phẩm của ông từng có ý nghĩa rất lớn vào thời tôi mới bắt đầu tiếp xúc với máy tính
levitated.net và sau này là complexification.net cũng là những viên ngọc của thời kỳ đầu Internet
Đáng tiếc là hỗ trợ cho Flash (Levitated) và Java (Complexification) đã bị ngừng, nên phần lớn ví dụ không còn chạy được
Dù vậy, bên Complexification thì vẫn có thể chạy nếu dán mã nguồn Processing
.pdevào trình biên tập ProcessingTôi thích cả UI lẫn bảng màu ngẫu nhiên
Kết quả thực sự rất tuyệt
Đây là một trong những trải nghiệm tuyệt nhất tôi từng có khi đọc một bài viết trên điện thoại
Tôi bất ngờ vì kết quả đẹp đến vậy
Có thể xem tại muffinman.io/invaders
Nó vượt xa kỳ vọng của tôi chỉ từ phần nội dung bài viết
Và hôm nay tôi cũng biết đến oklch
Sau khi tinh chỉnh và thêm UI, tôi thấy nó ổn hơn rất nhiều
OKLCH thực sự là một bước nâng cấp lớn
Việc xử lý màu sắc bằng code vốn khá khó, nhưng cái này rõ ràng giúp dễ hơn nhiều
Cá nhân tôi cũng thích HSLuv, nhưng tiếc là trình duyệt vẫn chưa hỗ trợ native
Rất vui
Trớ trêu thay, cảm giác như đang tạo ra invader để cứu hành tinh (Trái Đất), đúng kiểu hacker vui vẻ mà không cần brute force AI
Dự án này hoàn toàn đáng để giới thiệu
Phép màu của quá trình sáng tạo rốt cuộc nằm ngay trong chính công việc thủ công đó
Việc ghim hình ảnh ở phía trên để nó luôn cho thấy chúng ta đang nói về gì trong lúc cuộn thật sự rất hay
Bình thường tôi không thích những trang thay đổi lòe loẹt theo cuộn trang, nhưng bố cục này là ngoại lệ
Tuyệt lắm
Tôi đang sưu tầm space invader trên khắp thế giới
space-invaders.com/flashinvaders cũng đáng tham khảo
Một nội dung liên quan là levInvaderFractal (2003) từ huyền thoại web thập niên 2000 levitated.net
Tôi đã đọc rất thích thú
Có thể cảm nhận được sự chăm chút trong cách giải quyết vấn đề, trong bài viết, và cả phần trình bày
Tôi nghĩ một space invader đẹp phải trông đáng sợ và nguy hiểm
Nếu nó còn vung càng thì càng được cộng điểm
Rất thú vị
Đây là bài viết đặc biệt vui với những ai yêu thích cảm giác 8-bit và retro computing
Trong lúc đọc tôi chợt nghĩ rằng, rốt cuộc đây có phải là hiện thân kỹ thuật số của “ham muốn từ Mẹ Thiên Nhiên muốn tiến hóa mọi thứ thành cua” hay không
Vì tính đối xứng của space invader cùng các cấu trúc như chân và càng đa dạng, cuối cùng mọi invader đều trông giống cua
Tôi thậm chí còn tưởng tượng không biết liệu chúng ta có đang nhìn thấy một sự trùng hợp nào đó trong Matrix hay không