Làm thế nào để bạn di chuyển một sprite trong gia số pixel phụ?


11

Điểm ảnh là bật hoặc tắt. Số lượng tối thiểu bạn có thể di chuyển một sprite là một pixel. Vậy làm thế nào để bạn làm cho sprite di chuyển chậm hơn 1 pixel mỗi khung hình?

Cách tôi đã làm là thêm tốc độ vào một biến và kiểm tra xem nó có đạt 1 (hoặc -1) không. Nếu vậy, tôi sẽ di chuyển sprite và đặt lại biến thành 0, như vậy:

update(dt):
    temp_dx += speed * dt
    temp_dy += speed * dt

    if (temp_dx > 1)
        move sprite
        reset temp_dx to 0
    if (tempy_dy > 1)
        move sprite
        reset temp_dy to 0

Tôi không thích cách tiếp cận này vì nó cảm thấy ngớ ngẩn và chuyển động của sprite trông rất giật. Vậy theo cách nào bạn sẽ thực hiện chuyển động pixel phụ?


Điều duy nhất bạn có thể làm là lọc song tuyến.
AturSams

Nếu bạn di chuyển dưới 1 px mỗi khung hình, làm thế nào nó có thể bị giật?

Câu trả lời:


17

Có một số tùy chọn:

  1. Làm như bạn làm. Bạn đã nói nó không được trơn tru. Có một số sai sót với phương pháp hiện tại của bạn mặc dù. Đối với x, bạn có thể sử dụng như sau:

    tempx += speed * dt
    
    while (tempx > 0.5)
      move sprite to x+1
      tempx -= 1
    while (tempx < -0.5)
      move sprite to x-1
      tempx += 1
    

    điều này nên tốt hơn Tôi đã chuyển các thống kê if sang 0,5, khi bạn vượt qua 0,5, bạn gần với giá trị tiếp theo hơn so với trước đó. Tôi đã sử dụng các vòng lặp trong khi cho phép di chuyển hơn 1 pixel mỗi bước thời gian (đó không phải là cách tốt nhất để làm điều đó, nhưng nó tạo ra mã nhỏ gọn và dễ đọc). Đối với các đối tượng chuyển động chậm, nó vẫn sẽ rất khó khăn, vì chúng ta chưa giải quyết được vấn đề cơ bản của căn chỉnh pixel.

  2. Có nhiều đồ họa cho sprite của bạn và sử dụng một đồ họa khác nhau tùy thuộc vào độ bù pixel phụ. Ví dụ, để làm mịn pixel con trong x, bạn có thể tạo một đồ họa cho sprite của mình x+0.5và nếu vị trí nằm giữa x+0.25x+0.75, hãy sử dụng sprite này thay vì bản gốc của bạn. Nếu bạn muốn định vị tốt hơn, chỉ cần tạo thêm đồ họa subpixel. Nếu bạn thực hiện điều này xysố lần kết xuất của bạn có thể nhanh chóng xuất hiện, vì số lượng tỷ lệ với bình phương của số khoảng: một khoảng cách 0.5sẽ yêu cầu 4 kết xuất, 0.25sẽ cần 16 kết xuất.

  3. Siêu mẫu. Đây là một cách lười biếng (và có khả năng rất tốn kém) để tạo một hình ảnh với độ phân giải subpixel. Về cơ bản, nhân đôi (hoặc nhiều hơn) độ phân giải mà bạn kết xuất cảnh của mình, sau đó thu nhỏ nó xuống khi chạy. Tôi muốn giới thiệu ở đây, vì hiệu suất có thể giảm nhanh chóng. Một cách ít gây khó chịu hơn để làm điều này sẽ chỉ là thay thế sprite của bạn và hạ thấp nó khi chạy.

  4. Theo đề xuất của Zehelvion , có thể nền tảng bạn đang sử dụng đã hỗ trợ điều này. Nếu bạn được phép chỉ định tọa độ x và y không nguyên, có thể có các tùy chọn để thay đổi bộ lọc kết cấu. Hàng xóm gần nhất thường là mặc định và điều này sẽ gây ra chuyển động "giật". Lọc khác (tuyến tính / khối) sẽ mang lại hiệu ứng mượt mà hơn nhiều.

Sự lựa chọn giữa 2. 3. và 4. phụ thuộc vào cách thức đồ họa của bạn được thực hiện. Một kiểu đồ họa bitmap phù hợp với kết xuất trước tốt hơn nhiều, trong khi một kiểu vectơ có thể phù hợp với siêu mẫu sprite. Nếu hệ thống của bạn hỗ trợ nó, 4. cũng có thể là cách để đi.


Tại sao thay thế ngưỡng 0,5 trong opt 1? Tôi cũng không hiểu lý do tại sao bạn chuyển các câu lệnh thành một vòng lặp while. Các chức năng cập nhật được gọi một lần mỗi lần đánh dấu.
bzzr

1
Câu hỏi hay - Tôi đã làm rõ câu trả lời dựa trên nhận xét của bạn.
Jez

Siêu mẫu có thể là "lười biếng", nhưng trong nhiều trường hợp, chi phí hiệu năng của quá mức gấp đôi hoặc thậm chí gấp 4 lần sẽ không phải là một vấn đề cụ thể, đặc biệt nếu nó cho phép các khía cạnh khác của kết xuất được đơn giản hóa.
supercat

Trong các trò chơi có ngân sách lớn, tôi thường thấy 3 là một tùy chọn được liệt kê trong cài đặt đồ họa là khử răng cưa.
Kevin

1
@Kevin: Bạn thực sự có thể không. Hầu hết các trò chơi sử dụng multisampling , có phần khác nhau. Các biến thể khác cũng thường được sử dụng, ví dụ như độ bao phủ khác nhau cũng như các mẫu độ sâu. Supersampling gần như không bao giờ được thực hiện do chi phí thực hiện shader mảnh.
imallett

14

Một cách mà nhiều trò chơi skool cũ đã giải quyết (hoặc che giấu) vấn đề này là làm động các sprite.

Đó là, nếu sprite của bạn sẽ di chuyển ít hơn một pixel trên mỗi khung hình (hoặc, đặc biệt, nếu tỷ lệ pixel / khung hình sẽ là một thứ gì đó kỳ lạ như 2 pixel trong 3 khung hình), bạn có thể che giấu sự giật cục bằng cách tạo một n vòng lặp hoạt hình khung hình, trên n khung hình đó, cuối cùng đã di chuyển sprite bởi một số k < n pixel.

Vấn đề là, miễn là sprite luôn di chuyển theo một cách nào đó trên mỗi khung hình, sẽ không bao giờ có bất kỳ khung hình nào mà toàn bộ sprite sẽ đột nhiên "giật" về phía trước.


Tôi không thể tìm thấy một sprite thực tế từ một trò chơi video cũ để minh họa điều này (mặc dù tôi nghĩ ví dụ như một số hoạt hình đào từ Lemmings là như thế), nhưng hóa ra mô hình "tàu lượn" từ Trò chơi Cuộc sống của Conway tạo ra minh họa rất hay:

nhập mô tả hình ảnh ở đây
Hoạt hình của Kieff / Wikimedia Commons , được sử dụng theo giấy phép CC-By-SA 3.0 .

Ở đây, các khối nhỏ của các pixel đen đang bò xuống và bên phải là các tàu lượn. Nếu bạn nhìn kỹ, bạn sẽ nhận thấy rằng họ lấy bốn khung hình động để thu thập thông tin một pixel theo đường chéo, nhưng vì chúng di chuyển theo một cách nào đó trên mỗi khung hình đó, nên chuyển động trông không bị giật (ít nhất là không còn nữa giật hơn bất cứ thứ gì nhìn vào tốc độ khung hình đó, dù sao).


2
Đây là một cách tiếp cận tuyệt vời nếu vận tốc được cố định hoặc nếu nó nhỏ hơn 1/2 pixel trên mỗi khung hình hoặc nếu hình ảnh động "đủ lớn" và đủ nhanh để che khuất các biến thể trong chuyển động.
supercat

Đây là một cách tiếp cận tốt, mặc dù nếu một máy ảnh phải tuân theo sprite, bạn vẫn sẽ gặp sự cố vì nó sẽ không di chuyển khá trơn tru.
Abob

6

Vị trí của sprite phải được giữ như một đại lượng điểm nổi và được làm tròn thành một số nguyên ngay trước khi hiển thị.

Bạn cũng có thể duy trì sprite ở độ phân giải siêu cao và lấy mẫu sprite trước khi hiển thị. Nếu bạn duy trì sprite ở độ phân giải màn hình 3x, bạn sẽ có 9 sprite thực tế khác nhau tùy thuộc vào vị trí subpixel của sprite.


3

Giải pháp thực sự duy nhất ở đây là sử dụng bộ lọc song tuyến. Ý tưởng là để GPU tính toán giá trị của từng pixel dựa trên bốn pixel sprite chồng chéo với nó. Đó là một kỹ thuật phổ biến và hiệu quả. Bạn chỉ cần đặt sprite trên 2d-plain (bảng quảng cáo) làm kết cấu; sau đó sử dụng GPU để hiển thị các đồng bằng này. Điều này hoạt động tốt nhưng hy vọng sẽ nhận được kết quả hơi mờ và mất giao diện 8 bit hoặc 16 bit nếu bạn đang nhắm đến nó.

ưu:

Đã thực hiện, rất nhanh, giải pháp dựa trên phần cứng.

Nhược điểm:

Mất độ trung thực 8 bit / 16 bit.


1

Điểm nổi là cách thông thường để thực hiện việc này, đặc biệt là nếu cuối cùng bạn kết xuất với mục tiêu GL nơi phần cứng khá hài lòng với đa giác được tô bóng với tọa độ nổi.

Tuy nhiên, có một cách khác để làm những gì bạn đang làm nhưng hơi giật hơn: điểm cố định. Giá trị vị trí 32 bit có thể biểu thị các giá trị 0 đến 4.294.967.295 mặc dù màn hình của bạn gần như chắc chắn có ít hơn 4k pixel dọc theo một trong hai trục. Vì vậy, đặt một "điểm nhị phân" cố định (bằng cách tương tự với dấu thập phân) ở giữa và bạn có thể biểu thị các vị trí pixel từ 0-65536 với độ phân giải 16 bit khác. Sau đó, bạn có thể thêm số như bình thường, bạn chỉ cần nhớ chuyển đổi bằng cách dịch chuyển đúng 16 bit bất cứ khi nào chuyển đổi sang không gian màn hình hoặc khi bạn nhân hai số với nhau.

.


1

Ngoài các câu trả lời khác ở đây, bạn có thể sử dụng phối màu ở một mức độ nào đó. Phối màu là nơi các pixel của đối tượng có màu sáng hơn / tối hơn để phù hợp với nền tạo ra cạnh mềm hơn. Ví dụ: giả sử bạn có hình vuông 4 pixel tôi sẽ ước tính với:

OO
OO

Nếu bạn di chuyển 1/2 pixel này sang bên phải, sẽ không có gì thực sự di chuyển. Nhưng với một số phối màu, bạn có thể tạo ra ảo ảnh về chuyển động một chút. Coi O là đen và o là xám, vì vậy bạn có thể làm:

oOo
oOo

Trong một khung và

 OO
 OO

Ở phần tiếp theo. "Hình vuông" thực tế với các cạnh màu xám sẽ thực sự có chiều ngang 3 pixel, nhưng vì chúng có màu xám nhạt hơn màu đen nên chúng trông nhỏ hơn. Điều này có thể khó mã hóa, tuy nhiên, và tôi không thực sự biết bất cứ điều gì làm điều này ngay bây giờ. Về thời gian họ bắt đầu sử dụng phối màu cho mọi thứ, độ phân giải nhanh chóng trở nên tốt hơn và không có nhiều nhu cầu ngoại trừ những thứ như thao tác hình ảnh.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.