Kỹ thuật tốt nhất để vẽ gạch isometric


8

Tôi đang suy nghĩ về việc tạo một trò chơi isometric đơn giản với HTML5 Canvas và tự hỏi đâu là cách nhanh nhất để kết xuất các ô.

Vì gạch có hình kim cương, nhưng drawImage vẽ hình chữ nhật, tôi phải bỏ các góc (các phần màu đen sau đây):

mẫu kim cương

Tôi nghĩ rằng điều đó cho tôi ba lựa chọn:

  1. Sử dụng các đối tượng Image với các kênh alpha (.png). Tôi sợ điều này có thể giết chết hiệu suất.
  2. Sử dụng một đường cắt. Nếu trình kết xuất được tối ưu hóa, điều này có thể khá nhanh.
  3. Gạch vuông prerender, như thế này:

gạch vuông prerendered

Tôi có hình vuông màu đen như một ô thực tế trong bộ nhớ và tôi vẽ một ô như vậy cho trường màu xanh lá cây và tất cả các trường bên cạnh hoặc bên trên và bên dưới. Các trường chéo (màu xanh) sẽ được tạo thành từ các góc của gạch hình chữ nhật. Điều này sẽ tránh cắt các kênh alpha hoặc alpha, nhưng tôi sẽ phải trình bày trước tất cả các kết hợp có thể có của gạch và có vẻ như quá mức cần thiết.

Cách tốt nhất hoặc nhanh nhất để làm gạch isometric là gì? Những trò chơi khác, như FarmVille, sử dụng cái gì?


1
Tôi nghĩ rằng "kỹ thuật tốt nhất" là loại được tải, và sẽ phụ thuộc vào yêu cầu của trò chơi, công nghệ đang được sử dụng và nhà phát triển tạo ra trò chơi.
MichaelHouse

1
Vấn đề gì bạn thực sự gặp phải? Có vẻ như bạn đã cung cấp ba câu trả lời cho câu hỏi của riêng bạn trong văn bản câu hỏi?
Trevor Powell

1
Điều này không có đủ phiếu bầu: BESSSSSSST TỐT NHẤT! hả
Jimmy

1
Đoán bạn nên làm theo lời khuyên được tìm thấy ở đây: meta.gamedev.stackexchange.com/a/638/7191
MichaelHouse

1
Vì vậy, bạn không biết rằng đây thực sự là một vấn đề hiệu suất? Bạn chỉ đang cố gắng tối ưu hóa mã trước khi viết? Trong trường hợp đó, -1 và bỏ phiếu để đóng.
Trevor Powell

Câu trả lời:


11

Sử dụng tính minh bạch (kênh alpha) là cách để đi, tôi khuyên bạn nên.

Điều này có nghĩa là khi bạn muốn một đối tượng dọc trên ô như thế này:

ngói với cây

Sau đó, bạn có thể làm điều đó một cách dễ dàng nếu trình kết xuất của bạn vẽ các lát gạch trở lại mặt trước tức là thuật toán họa sĩ.

TÍN DỤNG HÌNH ẢNH: Gạch lát nền.


9

Mặc dù phương pháp được mô tả bởi sws và MarkR cũng là điều tôi thích, tôi muốn trình bày một cách tiếp cận khác.

Tùy chọn hackish để tạo giao diện đẳng cự với nỗ lực tối thiểu là thực sự sử dụng các khối trực giao và sử dụng bối cảnh.transform để đặt ma trận chiếu làm cho bản đồ trông giống hình học (hoặc kết hợp bối cảnh.rotate và bối cảnh.scale khi bạn không ' t biết ma trận chiếu hoạt động như thế nào).

Xem đặc điểm kỹ thuật cho các phương pháp chuyển đổi canvas để biết chi tiết.

Hình ảnh ngói:

hình ảnh gạch cơ sở

Vẽ mã:

    for (var x = 0; x < 5; x++) {
        for (var y = 0; y < 5; y++) {
            ctx.drawImage(img, x * img.width, y * img.height);
        }
    }

Kết quả trước khi áp dụng ma trận:

không áp dụng ma trận biến đổi

Cùng một mã với cùng một hình ảnh xếp sau khi áp dụng ma trận biến đổi này:

    ctx.transform(  1,   0.5,
                   -1,   0.5,
                  160,   0    );

với ma trận biến đổi

Với lưới nét đứt được loại bỏ khỏi hình ảnh gạch và thay đổi phần bù của ô trong mã bản vẽ thành img.width - 1img.height - 1để loại bỏ các khoảng trống gây ra bởi phép biến đổi. Đột nhiên, cái ngói trông xấu xí một nửa:

với ma trận và một số điều chỉnh

Hạn chế chính của phương pháp này là khi bạn thiết kế các ô của mình trong trình chỉnh sửa đồ họa, chúng sẽ không thực sự là những gì bạn thấy - là - những gì bạn nhận được. Bạn cũng sẽ gặp phải vấn đề khi bạn muốn vẽ bất kỳ vật nào không nằm trên sàn mà đứng thẳng. Đối với những điều này, bạn có thể tắt ma trận biến đổi trước khi vẽ chúng, nhưng sau đó bạn sẽ phải tự tính toán vị trí. Bạn có thể sử dụng các công thức này cho điều đó:

var xScreen = xWorld * 1   + yWorld * -1  + 160;
var yScreen = xWorld * 0.5 + yWorld * 0.5 + 0;  

(lưu ý cách các số từ ma trận biến đổi xuất hiện lại trong các công thức này - bạn đang tự thực hiện phép nhân ma trận ở đây).

Vậy tại sao tôi phải làm điều này?

Phương pháp này tốt khi bạn:

  1. không có kinh nghiệm với việc thiết kế gạch isometric, nhưng bạn có gạch trực giao
  2. không muốn dành nhiều thời gian để phát triển một công cụ đồ họa đẳng cự, điều này hơi khó hơn một công cụ trực giao.

Một tính năng thú vị khác là khi bạn biết cách tính toán ma trận, bạn có thể sửa đổi ma trận chiếu giữa các khung thành thu phóng, nghiêng và xoay bản đồ trong thời gian thực để có một số hiệu ứng giả-3d đẹp mắt (thử thực hiện THAT với các ô đẳng cự) .

Nhưng khi bạn biết cách xử lý gạch isometric, cả về mặt nghệ thuật và kỹ thuật, và bạn không cần bất kỳ mánh khóe giả mạo nào, tôi muốn khuyên bạn nên sử dụng gạch có hình kim cương với độ trong suốt.


Nó chắc chắn có thể làm điều này. Bằng cách này, bạn có thể có các ô "phẳng" hoặc "từ trên xuống". Tuy nhiên, điều đó có nghĩa là mọi phần tử "3d" trong ô không thể được thực hiện dễ dàng. Tôi thích làm sự chuyển đổi này trước thời hạn.
MarkR

+1 nếu không chỉ cho lời giải thích của chuyên gia! Làm tốt.
Luceos

@MarkR: Tôi đã mở rộng câu trả lời của mình rất nhiều sau khi bạn đưa ra nhận xét của mình, bạn có thể muốn xem nếu nó vẫn được áp dụng.
Phi

1
Cảm ơn đã viết chi tiết! Đó là một kỹ thuật rất thú vị, tôi đã không nghĩ về việc đó trước đây. Tuy nhiên, vì tôi đang bắt đầu từ đầu (và cũng tệ không kém khi vẽ các viên gạch đẳng cự và vuông ;-)), tôi sẽ chọn các gạch đẳng cự thực. Ngoài ra, điều này dường như không phải là rất nhanh. Tôi đã thực hiện một điểm chuẩn nhỏ và việc xóa các ô không có ma trận chuyển đổi sang các vị trí pixel nguyên nhanh hơn khoảng 3 lần so với chuyển đổi trên PC của tôi. Tôi vẫn có thể sử dụng điều này cho một số hiệu ứng đặc biệt.
jdm

Bất kỳ cách nào để thêm một số cấp độ z vào bản đồ này?
Tarion

3
  1. Bạn đang sử dụng context.drawImage để sao chép dữ liệu pixel từ một nguồn (hình ảnh hoặc khung vẽ ngoài màn hình) sang nguồn khác (khung ngoài màn hình hoặc trên màn hình), xử lý alpha ngoài luồng một cách duyên dáng. Canvas được tăng tốc phần cứng, do đó, kiểm tra sẽ cho phép bạn xác định xem có sự khác biệt rõ rệt nào về tốc độ kết xuất khi ghi alpha-vs opaque-pixel hay không.

  2. Việc cắt sẽ yêu cầu bạn đẩy / bật trạng thái bối cảnh khi xác định đường cắt một lần trên mỗi ô, đây có thể là một hoạt động tốn kém khi xem xét rút tiền của isometric.

  3. Các gạch được sắp xếp sẵn, như bạn nêu, yêu cầu một số lượng lớn các gạch 'đầu nối' được vẽ, có thể hoặc không thể khả thi. (Tôi đang nghiêng nhiều hơn về "có thể không".)

Một giải pháp thứ tư sẽ là sử dụng một "khối" (PRC) được kết xuất sẵn, được tạo một lần cho các khung vẽ ngoài màn hình, sau đó che màn hình bằng các PRC một lần trên mỗi khung. Vẫn sẽ bị rút tiền, nhưng xây dựng PRC một lần và hiển thị nó với phần bù được xác định bởi vị trí của nhân vật người chơi (hoặc xem camera) so với PRC nên là một thao tác tương đối đơn giản. Điều này sẽ cho phép bạn kết hợp kết xuất với tùy chọn # 1, đây là IMO tùy chọn tốt nhất nếu hiệu suất không được xem xét (vì đơn giản nhất để thực hiện).


3

Một kênh alpha nhỏ không gây hại nhiều, nhưng nếu bạn muốn tránh việc xem xét sử dụng hai phần tư gạch, điều này cũng mang lại cho bạn một số chỗ để thực hiện chuyển tiếp các ô đẹp mà không thực hiện nhiều hình ảnh khác nhau, đó có lẽ là lợi thế lớn nhất:

Mẫu gạch hình chữ nhật

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.