Tạo chuyển tiếp ánh sáng mượt mà bằng cách sử dụng các ô trong trò chơi HTML5 / JavaScript


7

Tôi đang cố gắng thực hiện hiệu ứng ánh sáng trong trò chơi HTML5 / JavaScript bằng cách sử dụng thay thế ô xếp. Những gì tôi có bây giờ là loại hoạt động, nhưng quá trình chuyển đổi trông không đủ mượt / tự nhiên khi nguồn sáng di chuyển xung quanh. Đây là nơi tôi đang ở:

  1. Ngay bây giờ tôi có một bản đồ nền có biểu đồ PNG phổ ánh sáng / bóng tối được áp dụng cho nó - đi từ ô tối nhất đến hoàn toàn trong suốt. Theo mặc định, ô tối nhất được vẽ trên toàn bộ cấp khi khởi chạy, bao gồm tất cả các lớp khác, v.v.
  2. Tôi đang sử dụng các kích thước ô được xác định trước (40 x 40px) để tính toán vị trí của từng ô và lưu trữ tọa độ x và y của nó trong một mảng.
  3. Sau đó tôi sẽ sinh ra một thực thể "khối lưới" 40 x 40px trong suốt tại mỗi vị trí trong mảng
  4. Công cụ tôi đang sử dụng (ImpactJS) sau đó cho phép tôi tính khoảng cách từ thực thể nguồn sáng của mình đến mọi phiên bản của thực thể khối lưới này.
  5. Sau đó tôi có thể thay thế gạch bên dưới mỗi gạch khối lưới đó bằng một lát có độ trong suốt thích hợp.

Hiện tại tôi đang thực hiện phép tính như thế này trong từng phiên bản của thực thể khối lưới được sinh ra trên bản đồ:

var dist = this.distanceTo( ig.game.player );
var percentage = 100 * dist / 960;

if (percentage < 2) {
    // Spawns tile 64 of the shadow spectrum tilesheet at the specified position
    ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, 64 ); 
}       
else if (percentage < 4) {
    ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, 63 );
}
else if (percentage < 6) {
    ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, 62 );
}       
// etc...

Vấn đề là như tôi đã nói, kiểu tính toán này không làm cho nguồn sáng trông rất tự nhiên. Chuyển đổi hình xếp trông quá sắc nét trong khi lý tưởng là chúng sẽ mờ dần trong và ngoài bằng cách sử dụng biểu đồ phổ (Tôi đã sao chép trang xếp hình từ một trò chơi khác quản lý để thực hiện việc này, vì vậy tôi biết đó không phải là vấn đề với các ô màu. Làm thế nào các trò chơi khác đang làm điều đó). Tôi nghĩ rằng có lẽ phương pháp sử dụng tỷ lệ phần trăm của tôi để chuyển đổi gạch có thể được thay thế bằng một diễn đàn lân cận tốt hơn / năng động hơn của một số loại cho phép chuyển đổi mượt mà hơn? Có ai có ý tưởng gì về những gì tôi có thể làm để cải thiện hình ảnh ở đây không, hay cách tính toán gần gũi hơn với thông tin tôi đang thu thập về mỗi ô?

(PS: Tôi đang đăng lại bài này từ Stack Overflow theo đề nghị của ai đó, xin lỗi về bản sao!)


1
Bạn có thể đăng ảnh chụp màn hình về những gì bạn có và những gì bạn muốn có?
MichaelHouse

Chắc chắn, tôi sẽ đăng một ảnh chụp màn hình tối nay.
Spectralbat

1
Bạn đã quên thêm ảnh chụp màn hình ...
MichaelHouse

Câu trả lời:


5

Trước hết, tôi xin lỗi vì tôi sẽ không thể giúp bạn với nền tảng cụ thể của bạn, vì tôi chưa bao giờ thực hiện loại công việc này trong HTML5. Vì vậy, tôi sẽ cố gắng giải quyết vấn đề này theo cách bất khả tri ngôn ngữ.

Tôi không nghĩ rằng bạn sẽ có thể có được sự chuyển tiếp suôn sẻ nếu bạn tính toán ánh sáng trên nền gạch trên mỗi ô . Điều này tương tự với sự khác biệt giữa việc sử dụng bóng phẳng, bóng gouraud hoặc bóng phong:

nhập mô tả hình ảnh ở đây

Những gì bạn đang làm tương tự như đổ bóng phẳng, tức là bạn đang gán một ánh sáng khác nhau cho mỗi ô , điều này dẫn đến sự chuyển đổi sắc nét giữa các ô như minh họa trên hình trên.

Để có được kết quả tốt hơn, bạn sẽ phải tính toán ánh sáng của mình trên cơ sở từng đỉnh (tức là gouraud). Tôi không biết khả năng của động cơ của bạn là gì, nhưng trường hợp lý tưởng sẽ là nếu mỗi ô của bạn là một hình tứ giác và bạn có quyền truy cập trực tiếp vào các đỉnh của nó. Sau đó, bạn sẽ có thể tính toán khoảng cách từ ánh sáng cho mỗi đỉnh và lưu trữ màu bóng của bạn ngay bên trong đỉnh. Cuối cùng, đường ống kết xuất sẽ tự động đảm nhiệm việc nội suy các sắc thái trên các bề mặt của gạch dẫn đến một cái nhìn mượt mà hơn (còn gọi là bóng gouraud ).

Để có kết quả tốt hơn, mặc dù đắt hơn một chút, bạn có thể tính toán ánh sáng trên cơ sở mỗi pixel (tức là phong) bên trong shader mảnh. Cách tiếp cận cơ bản hoạt động tốt nếu bạn chỉ có một vài đèn để lấy mẫu như dường như là trường hợp từ ví dụ của bạn.

Cuối cùng, một cách khác có thể hoạt động rất tốt là kết xuất tất cả các đèn của bạn (và chỉ đèn của bạn) vào một mục tiêu kết xuất riêng trước, tùy ý làm mờ kết quả và trộn nó với phần còn lại của cảnh ở cuối. Kiểm tra câu hỏi này cho một vài ý tưởng về điều này.


Sự thay thế cuối cùng có vẻ như phù hợp với HTML5 Canvas. Những cái khác của bạn không được tiếp xúc với Canvas, trừ khi ImpactJS đặc biệt thực hiện các shader và đỉnh, điều mà tôi rất nghi ngờ.
DMan

@DMan Bạn nói đúng, nếu nó dựa trên nền tảng thì có lẽ nó không hỗ trợ những thay đổi đó. Tôi đã nghĩ có lẽ nó có thể là một công cụ WebGL, trong trường hợp đó nó sẽ đơn giản.
David Gouveia

Cảm ơn rất nhiều cho phản ứng chi tiết của bạn. Tôi sẽ xem xét đề nghị cuối cùng của bạn tối nay cùng với một số ý tưởng khác mà tôi đang cố gắng.
Spectralbat

4

Bạn dường như được chiếu sáng với sự suy giảm tuyến tính (cường độ ánh sáng của bạn giảm xuống theo tuyến tính). Bạn có thể muốn thử sử dụng luật bình phương nghịch đảo . Hoặc một số mũ đơn giản rơi ra.

float maxLightDistance = 64;
float fallOff = 1.4f;
float intensity = Math.pow(distanceFromSource / maxLightDistance, fallOff);
int tileToUse = (int)intensity;
ig.game.backgroundMaps[2].setTile( this.pos.x, this.pos.y, tileToUse);

Các mã trên cũng giúp bạn thoát khỏi những if else ifđiều tàn bạo bạn đang đi.

Tôi chỉ sử dụng một số mũ theo cấp số nhân cơ bản và nhận được kết quả như thế này (tôi có thể đăng một hình ảnh tốt hơn sau một nguồn sáng, tôi chỉ không có một cái nào vào lúc này):

ánh sáng từ dung nham

Tôi cũng nên đề cập rằng một chương trình như Excel là tuyệt vời cho những thứ như thế này. Bạn có thể kiểm tra các thay đổi công thức khá nhanh và vẽ biểu đồ cho chúng hoặc sử dụng các quy tắc có điều kiện để thay đổi màu của một ô.


Tôi muốn lưu ý rằng việc thay đổi công thức suy giảm sẽ không làm cho ánh sáng được nội suy một cách trơn tru trên bề mặt của gạch. Mỗi ô sẽ vẫn có một màu duy nhất đột ngột thay đổi khi đến ô tiếp theo. Sử dụng các biến thể rất nhỏ trong độ sáng có thể giúp che giấu vấn đề và làm cho nó trông ổn, nhưng nó vẫn không phải là một sự chuyển đổi suôn sẻ. Ngoài ra, tôi cho rằng sự lựa chọn suy giảm có liên quan nhiều đến thẩm mỹ, vì tôi đã có các dự án mà tôi thích giao diện suy giảm tuyến tính (với bán kính hiệu ứng tối đa và tối thiểu) hơn là luật bình phương nghịch đảo.
David Gouveia

Đề nghị của tôi dựa trên những gì OP đã có. Đó có nghĩa là một giải pháp dễ dàng để thử mà không cần phải tạo lại hệ thống kết xuất. Và nó có thể tạo ra sự khác biệt nếu phương pháp OP đặt các ô có nhiều hơn một sắc thái khác nhau cạnh nhau.
MichaelHouse

@spectralbat Nhưng tôi chắc chắn đồng ý với việc thoát khỏi if else ifchuỗi đó . Tạo một phương thức ánh xạ tỷ lệ phần trăm vào chỉ mục ô vuông và thay thế tất cả các nhánh bằng một lệnh gọi setTilegiống như trong ví dụ của Byte56.
David Gouveia

Chắc chắn, đó là một điều tốt mà bạn đã chỉ ra, đặc biệt là xem xét sự thay đổi đơn giản như thế nào. Nó có thể trông tốt hơn những gì OP hiện có. :) Tôi chỉ chỉ ra rằng tôi không nghĩ nó có liên quan gì đến vấn đề thực tế của việc chuyển đổi suôn sẻ giữa các ô. Nhưng có lẽ đó chính xác là những gì OP yêu cầu và tôi là người hiểu lầm. ;-)
David Gouveia

Cảm ơn! Ngay cả khi điều này không giải quyết được vấn đề ban đầu của tôi, tôi sẽ cố gắng làm mọi thứ để nó trông đẹp hơn. Tôi sẽ đưa ra điều này và một số tùy chọn khác mà tôi đã xem xét thử tối nay.
Spectralbat
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.