2011-09-02 25 views
7

Hãy tưởng tượng một công cụ hiển thị bắt buộc sẽ trích xuất các sprites tới một bitmap mà sau này sẽ được hiển thị. Điều này phụ thuộc rất nhiều vào khả năng biến đổi hiệu quả các pixel riêng lẻ trong bitmap đã nói. Làm thế nào tôi sẽ làm một điều như vậy một ngôn ngữ mà không có tác dụng phụ? Tôi đoán một cấu trúc dữ liệu hoàn toàn khác được gọi là gì?Làm cách nào tôi có thể tưởng tượng hiển thị dựa trên pixel trong Haskell?

Trả lời

5

Bạn có thể chuyển đổi bất kỳ thuật toán nào sử dụng trạng thái có thể thay đổi thành thuật toán "chuỗi" trạng thái cùng với nó. Haskell cung cấp một cách để làm điều này như vậy mà nó vẫn cảm thấy như lập trình bắt buộc với Monad nhà nước.

Mặc dù, có vẻ như với tôi rằng thao tác blit cơ bản có thể được thực hiện theo phong cách chức năng hơn. Về cơ bản, bạn kết hợp hai bitmap để tạo ra một bitmap mới thông qua thao tác pixel bằng pixel. Điều đó nghe có vẻ rất chức năng đối với tôi.

chất lượng cao mã bắt buộc thường là nhanh hơn so với mã chức năng tốt, nhưng nếu bạn sẵn sàng từ bỏ một chút tốc độ bạn thường có thể tạo kiến ​​trúc rất đẹp trong một phong cách chức năng thuần túy

4

Haskell có tác dụng phụ, và bạn nên sử dụng chúng bất cứ khi nào chúng thích hợp. Một thói quen blit tốc độ cao sẽ có trong vòng lặp bên trong của bạn (và do đó là hiệu suất quan trọng) chắc chắn là một nơi mà đột biến là thích hợp, do đó, sử dụng nó! Bạn có một vài tùy chọn:

  • Cuộn của riêng bạn trong Haskell, sử dụng Mảng ST (U) hoặc Mảng IO (U). Không được khuyến khích.
  • Cuộn của riêng bạn trong C và gọi nó bằng FFI. Không được khuyến khích.
  • Sử dụng một trong nhiều bộ công cụ đồ họa cung cấp loại hoạt động này và đã có hàng trăm giờ lập trình dành cho việc tạo giao diện tốt với hiệu suất cao, chẳng hạn như Gtk hoặc OpenGL. Rat khuyen khich.

Tận hưởng!

1

Một cách chức năng tự nhiên của đại diện cho một hình ảnh là bằng cách sử dụng các chức năng chỉ số:

Image :: (Int,Int) -> Color 

Với đại diện này, blitting diện tích từ một hình ảnh khác có thể đạt được với

blit area a b = \(x,y) -> if (x,y) `isInsideOf` area then a (x,y) else b (x,y) 

Nếu cần phải dịch hoặc chuyển đổi khác, nó có thể được áp dụng trực tiếp cho tọa độ:

translate (dx,dy) image = \(x,y) -> b (x+dx,y+dy) 

Biểu diễn này mang đến cho bạn cách làm việc tự nhiên với các điểm ảnh. Bạn có thể, ví dụ, dễ dàng làm việc với khu vực phi hình chữ nhật, và làm thủ thuật như làm suy hình ảnh như chức năng riêng biệt thay vì là một phần của thuật toán hình ảnh rộng thông thường của bạn:

quadraticInterpolation :: ((Int,Int) -> Color) -> ((Double,Double) -> Color) 

Việc thực hiện có thể bị ảnh hưởng trong một số trường hợp, chẳng hạn như khi bạn blit nhiều hình ảnh thành một và sau đó thực hiện các phép tính với kết quả. Điều này dẫn đến một chuỗi các thử nghiệm cho mỗi điểm ảnh cho mỗi phép tính liên tiếp. Tuy nhiên, bằng cách áp dụng ghi nhớ, chúng tôi có thể tạm thời hiển thị biểu diễn chức năng thành một mảng và chuyển đổi trở lại hàm chỉ mục của nó, do đó loại bỏ hiệu suất nhấn cho các hoạt động liên tiếp.

Lưu ý rằng việc ghi nhớ cũng có thể được sử dụng để giới thiệu song song với quy trình.

Các vấn đề liên quan