2010-05-20 25 views
5

Tôi đang viết chương trình chỉnh sửa bản đồ cho trò chơi 2D bằng XNA. Để tạo một Texture2D cho tất cả các ô mà bản đồ yêu cầu mất quá nhiều thời gian.Có cách nào thay thế nhanh hơn khi sử dụng kết cấu trong XNA?

Có cách nào khác để sử dụng kết cấu để vẽ bằng XNA không?

Tôi cố gắng tạo một kết cấu cho mỗi khối hình thay vì kết cấu cho mỗi ô trong bộ ô, nhưng có giới hạn về kích thước của họa tiết và tôi không thể vừa với tất cả các lát của ô được đặt thành một kết cấu.

Hiện tại, chương trình chứa tất cả các kết cấu sẽ là bộ nhớ trong các đối tượng Bitmap. Có cách nào để vẽ một đối tượng Bitmap vào màn hình trong XNA không? Tôi đã tìm kiếm nhưng tôi không thể tìm thấy bất kỳ thông tin nào về điều này. Cách tiếp cận này sẽ tránh phải tạo ra kết cấu hoàn toàn, tuy nhiên bất kỳ màu hoặc hiệu ứng nào tôi sẽ phải thực hiện trực tiếp với bitmap.

Trả lời

0

Thật không may, theo như tôi biết, không có cách nào để trực tiếp vẽ một bitmap vào màn hình trong XNA; nó yêu cầu mọi thứ được ánh xạ tới các đối tượng Texture, được mặc định đệm vào card đồ họa. Nghe có vẻ như bạn đang nói về rất nhiều gạch, mặc dù, nếu họ sẽ không tất cả phù hợp với kết cấu tối đa cho phép (tôi không thể nhớ cho dù đó là 1024 hoặc 4096 vuông ...) - có bạn đã cố gắng có một kết cấu không bị căng thẳng cho mục đích tốc độ? Một lựa chọn khác là để lười biếng tải các tileets của bạn vào textures để người dùng không phải chờ cho tất cả chúng tải - đối với một trình soạn thảo, sử dụng màu dự phòng màu hồng tươi sáng thường được chấp nhận trong khi nó tải.

Ngoài ra, có bất kỳ điều gì vốn cần thiết để viết công cụ của bạn trong XNA không? Vì có vẻ như bạn đang viết công cụ riêng biệt với bản thân trò chơi, bạn có thể tìm thấy một số giải pháp có thể chấp nhận được trong WPF, bao gồm vẽ trực tiếp từ BitmapSources và một số tiện ích cho giao diện người dùng của bạn.

+0

Cảm ơn bạn đã phản hồi, không có gì yêu cầu tôi sử dụng XNA, không. Ngay bây giờ tôi đã quay trở lại để làm việc trên một phiên bản C++ và DirectX của công cụ. Vấn đề của tôi là kết cấu trong XNA dường như cực kỳ chậm. Những gì mất hơn 100 giây bằng cách sử dụng XNA Texture2Ds mất 0,3 giây bằng cách sử dụng kết cấu DirectX. Cảm ơn sự thẳng thắn - chủ yếu là những gì tôi muốn biết là không có cách nào để trực tiếp vẽ một bitmap vào màn hình. –

0

Giả sử tất cả các ô mà bản đồ yêu cầu hình ảnh hiện tại chỉ đơn giản là đặt trên màn hình để bố trí bản đồ lát gạch? Hay bạn đang tạo hình ảnh trong trình chỉnh sửa bản đồ này và muốn lưu chúng ra?

Tôi đọc điều này và bài đăng khác của bạn về họa tiết - Nếu chúng là tất cả hình ảnh đã sẵn sàng mà bạn muốn sử dụng trong trò chơi, bạn chỉ cần đưa chúng vào thư mục nội dung và tham chiếu chúng ở đó? Điều này cho phép XNA biên dịch các kết cấu theo định dạng xnb và bạn không nên có các vấn đề mà bạn đang giải thích.

Tuy nhiên nếu chúng ta đang nói hoàn toàn năng động - hoặc bạn đang tạo một hình ảnh lớn từ bố cục của ô xếp (thay vì làm một cái gì đó giống như bản đồ ô) thì tôi không biết cách tiếp cận vấn đề.

+0

Xin chào, cảm ơn phản hồi của bạn. Vấn đề chỉ đơn giản là thêm các tập tin hình ảnh vào thư mục nội dung là chúng là hình ảnh định dạng tùy chỉnh - trình chỉnh sửa bản đồ của tôi dành cho trò chơi hiện có sử dụng những hình ảnh này.Tôi đã hy vọng có thể viết mã cho trình soạn thảo bằng C# và XNA, tuy nhiên bây giờ tôi có thể sẽ bắt đầu lại và sử dụng C++ và DirectX để thực hiện nó, vì tôi biết rằng các kết cấu từ bitmap rất nhanh trong DirectX. Lý do chính tôi sử dụng C# là vì tôi muốn dễ dàng thiết kế giao diện người dùng, tuy nhiên nếu tôi không thể sử dụng C# thì tôi sẽ xem xét sử dụng một cái gì đó như Qt. –

+0

đó là lý do tôi do dự lúc đầu, tôi nghĩ rằng phải có một lý do bạn không thể sử dụng chúng trong thư mục nội dung của trò chơi và trình soạn thảo của bạn - xin lỗi tôi không có câu trả lời tốt hơn cho ya! –

0

Nếu nhiều ô sử dụng cùng một kết cấu, nó sẽ đủ để tải nó chỉ một lần.

Nếu người dùng bao gồm kết cấu ở một số định dạng tệp, bạn có thể tự động chuyển đổi nó thành định dạng kết cấu/hình ảnh nhanh hơn cho nhu cầu của bạn.

+0

Cảm ơn bạn đã trả lời. Thật không may tôi chỉ tải mỗi kết cấu yêu cầu một lần. Tôi phát hiện ra rằng chỉ cần thêm Texture2D tx = new Texture2D (thiết bị, chiều rộng, chiều cao); để mã của tôi cho mỗi kết cấu yêu cầu tăng thời gian tải cho một bản đồ từ 2,7 giây đến 74 giây! Lưu ý rằng 2,7 giây bao gồm việc tạo bitmap giữ các họa tiết cần thiết. Texture2D dường như quá chậm để tạo họa tiết liên tục. –

1

Vì bạn cần sử dụng định dạng hình ảnh tùy chỉnh, nếu bạn muốn (cho tốc độ), bạn có thể cố gắng viết các bộ nhập và bộ xử lý nội dung tùy chỉnh cho XNA (http://msdn.microsoft.com/en-us/library/bb447754.aspx), nhưng điều này có thể quá mức cần thiết.

Tôi thấy bạn muốn thiết kế GUI dễ dàng nhất có thể, ngay cả khi những vấn đề này buộc bạn phải sử dụng ngôn ngữ như C++ để bạn có thể sử dụng DirectX. Trong Visual C++ bạn vẫn có thể tận dụng lợi thế của visual Windows Forms layout nếu bạn đang sử dụng Visual Studio.

0

Bạn đang cố gắng vẽ tất cả bằng cách sử dụng một chuỗi thực thi duy nhất?

Thử đa luồng trò chơi của bạn. Luồng trong C# khá dễ dàng và được hỗ trợ bởi XNA.

Thay vì xem toàn bộ màn hình của bạn, hãy thử chia thành hai (hoặc nhiều) phần. Bạn có thể cần phải viết lại hàm bạn đang sử dụng để vẽ (tôi chắc chắn rằng bạn không chỉ đổ tất cả mọi thứ trực tiếp trong phương thức Draw() của bạn !!) để đưa vào tọa độ thiết lập ranh giới của vùng vẽ của bạn.

+0

Chương trình của tôi đã được đa luồng. Một luồng sẽ xử lý các thông báo cửa sổ trong khi một chuỗi con cố gắng tải các ô và tạo ra các kết cấu từ chúng. Tại thời điểm viết câu hỏi này, tôi chưa thêm phương thức vẽ nào vì lần đầu tiên tôi cần có phương thức tải họa tiết trong một khung thời gian hợp lý. –

1

Có lý do nào bạn không cân nhắc tải hình ảnh một lần và sau đó chuyển các tọa độ bù x và y vào trình đổ bóng pixel?

Bạn về cơ bản sẽ đặt C# lên như thế này:

myGraphicsDevice.Textures[0] = whateverYourGiantMapTextureIs; 

foreach(MapChunk chunk in mapChunks) { 
    myShader.Effect.Parameters["xOffset"] = chunk.XOffset; 
    myShader.Effect.Parameters["yOffset"] = chunk.YOffset; 

    myGraphicsDevice.DrawIndexedPrimitives(your chunk drawing code here); 
} 

Và sau đó mã đổ bóng như thế này:

float4x4 World; 
float4x4 View; 
float4x4 Projection; 

float xOffset; 
float yOffset; 

sampler TextureSampler; 

struct VS_INPUT { 
    float4 Position : POSITION0; 
    float4 Color : COLOR0; 
}; 

VS_INPUT Transform(VS_INPUT Input) { 
    VS_INPUT Output; 

    float4 worldPosition = mul(Input.Position, World); 
    float4 viewPosition = mul(worldPosition, View); 
    Output.Position = mul(viewPosition, Projection); 
    Output.Color = Input.Color; 

    return Output; 
} 

float4 ColorTexture(VS_INPUT Input) : COLOR0{ 
    return Input.Color.rgba * tex2D(TextureSampler, float2(xOffset, yOffset)); 
} 

technique TransformColorTexture { 
    pass P0 { 
     VertexShader = compile vs_2_0 Transform(); 
     PixelShader = compile ps_2_0 ColorTexture(); 
    } 
} 

Mã shader thể cần một số phù hợp vào mã hiện tại của bạn nhưng nếu không nó nên làm các trick.

1

Sử dụng một kết cấu cho mỗi ô không phải là rất hiệu quả. Đặc biệt là vì nó có nghĩa là bạn không thể thực hiện batch (theo bất kỳ ý nghĩa thực sự nào).

Nếu bạn CẦN có chúng dưới dạng kết cấu riêng biệt trong dự án nội dung của bạn vì một số lý do (dễ dàng chỉnh sửa một lát, v.v.), bạn có thể dễ dàng biên dịch chúng thành tilemaps sau khi tải. Làm thế nào bạn làm điều này là cơ bản:

1: Load một số gạch (cho phép nói 40 32 * 32 gạch cho bây giờ)

2: Chỉ ra một kết cấu có kích thước đẹp cho tilemap: căn bậc hai của 40 là 6. một cái gì đó, vì vậy chúng tôi tròn lên đến 7. 7 * 32 là 224, đó là tốt đẹp, nhưng 256 là đẹp hơn, do đó, cho phép làm cho kết cấu 256x256. (bạn có thể tạo mã để tìm ra điều này một cách nhanh chóng)

3: Tạo một Rendertarget2D là kích thước mong muốn.

4: Kích hoạt mục tiêu hiển thị.

5: Render gạch trên rendertarget:

int x, y = 0; 
foreach (var tile in allTiles) 
{ 
    RenderTile(tile, x*32, y*32); 
    x++; 

    if (x >= 8) 
    { 
     x = 0; 
     y++; 
    } 
} 

Để betch-làm cho bạn có một đỉnh-đệm với 4 * 40 đỉnh. mỗi bộ 4 có một giá trị chỉ ra chỉ số của quad nó thuộc về (0,1,2, vv ...). Trong trình đổ bóng của bạn, bạn có một mảng ma trận [40] cho vị trí của các ô, cũng như một mảng tileIndex (int [40]) để biết gạch nào sẽ hiển thị từ tilemap.

Tôi xin lỗi, nhưng tôi không có thời gian để viết tất cả các shader-code ngay bây giờ: s

Một mẹo khác mà tôi đã sử dụng trong các trò chơi của chúng tôi là kết xuất trước mức vào gạch lớn (640x360), làm giảm số lượng cuộc gọi vẽ rất nhiều, đặc biệt là khi giao dịch với hơn 5 lớp gạch từ các ô khác nhau. Chỉ có điều là nó không hoạt động với gạch động (gạch hoạt hình, vv), nhưng bạn có thể đánh dấu chúng và làm cho chúng bình thường nếu bạn muốn ...

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