2015-02-08 15 views
8

Tôi đang cố gắng làm việc với lớp học SKMutableTexture của SpriteKit nhưng tôi không biết cách làm việc với UnsafeMutablePointer<Void>. Tôi có một ý tưởng mơ hồ rằng nó là một con trỏ đến một loạt các dữ liệu byte trong bộ nhớ. Nhưng làm thế nào tôi có thể cập nhật nó? Điều này thực sự trông như thế nào trong mã?UnsafeMutablePointer <Void> là gì? Làm thế nào để sửa đổi bộ nhớ cơ bản?

Sửa

Đây là một mẫu mã cơ bản để làm việc với. Làm thế nào tôi có thể làm điều này đơn giản như tạo một hình vuông màu đỏ trên màn hình?

let tex = SKMutableTexture(size: CGSize(width: 10, height: 10)) 
    tex.modifyPixelDataWithBlock { (ptr:UnsafeMutablePointer<Void>, n:UInt) -> Void in 

     /* ??? */ 

    } 

Trả lời

12

Từ các tài liệu cho SKMutableTexture.modifyPixelDataWithBlock:

Các kết cấu byte được giả định được lưu trữ như đóng gói chặt chẽ 32 bpp, 8bpc (unsigned integer) dữ liệu RGBA pixel. Các thành phần màu bạn cung cấp nên đã được nhân với giá trị alpha.

Vì vậy, trong khi bạn được cung cấp void*, dữ liệu cơ bản ở dạng luồng 4x8 bit.

Bạn có thể thao tác một cấu trúc như vậy như vậy:

// struct of 4 bytes 
struct RGBA { 
    var r: UInt8 
    var g: UInt8 
    var b: UInt8 
    var a: UInt8 
} 

let tex = SKMutableTexture(size: CGSize(width: 10, height: 10)) 
tex.modifyPixelDataWithBlock { voidptr, len in 
    // convert the void pointer into a pointer to your struct 
    let rgbaptr = UnsafeMutablePointer<RGBA>(voidptr) 

    // next, create a collection-like structure from that pointer 
    // (this second part isn’t necessary but can be nicer to work with) 
    // note the length you supply to create the buffer is the number of 
    // RGBA structs, so you need to convert the supplied length accordingly... 
    let pixels = UnsafeMutableBufferPointer(start: rgbaptr, count: Int(len/sizeof(RGBA)) 

    // now, you can manipulate the pixels buffer like any other mutable collection type 
    for i in indices(pixels) { 
     pixels[i].r = 0x00 
     pixels[i].g = 0xff 
     pixels[i].b = 0x00 
     pixels[i].a = 0x20 
    } 
} 
+0

Chỉ cần thử với dự án SpriteKit mẫu trong Xcode và dường như làm điều đúng - nhưng tôi biết _nothing_ về SpriteKit nên không thể đảm bảo đây là "cách" để làm điều đó. –

+0

Cảm ơn bạn điều này đang hoạt động. Bây giờ tôi nhìn thấy một hình vuông trên màn hình tuy nhiên, tôi đã mong đợi phương thức modifyPixelDataWithBlock được gọi một lần trên mỗi khung hình - giống như một loại thay thế cho trình đổ bóng phân đoạn nhưng khối chỉ được gọi một lần. Tìm hiểu thêm ... – Bret

+0

Lưu ý rằng bạn cần chuyển các giá trị alpha trước khi nhân với phần RGB. Từ [tài liệu] (https://developer.apple.com/library/ios/documentation/SpriteKit/Tham khảo/SKMutableTexture_Ref/# // apple_ref/occ/instm/SKMutableTexture/modifyPixelDataWithBlock :) 'Các byte kết cấu được giả định được lưu trữ dưới dạng đóng gói chặt chẽ 32 bpp, 8bpc (số nguyên không dấu) RGBA pixel dữ liệu. Các thành phần màu bạn cung cấp nên đã được nhân với giá trị alpha.' – Benzi

7

UnsafeMutablePointer<Void> là Swift tương đương với void* - một con trỏ đến bất cứ điều gì cả. Bạn có thể truy cập bộ nhớ cơ bản dưới dạng thuộc tính memory của nó. Thông thường, nếu bạn biết loại cơ bản là gì, bạn sẽ ép buộc một con trỏ đến loại đó trước tiên. Sau đó, bạn có thể sử dụng chỉ số con để đạt được "vị trí" cụ thể trong bộ nhớ.

Ví dụ, nếu các dữ liệu thực sự là một chuỗi các giá trị uint8, bạn có thể nói:

let buffer = UnsafeMutablePointer<UInt8>(ptr) 

Bây giờ bạn có thể truy cập các giá trị UIInt8 cá nhân như buffer[0], buffer[1], và vân vân.

+0

Và xem hướng dẫn Swift tôi để biết thêm: http://www.apeth.com/swiftBook/apa.html#_c_pointers – matt

+0

Đánh giá bởi phương pháp này chữ ký của [modifyPixelDataWithBlock] (https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SKMutableTexture_Ref/index.html#//apple_ref/occ/instm/SKMutableTexture/modifyPixelDataWithBlock :), tôi nghĩ rằng loại là số nguyên 8 bit. Điều gì sẽ diễn viên thực sự trông giống như trong mã? Tôi thực sự hy vọng cho một số mẫu mã về làm thế nào để làm điều này – Bret

+0

Nếu nó là một số nguyên 8 bit, đó sẽ là một Int8 hoặc UInt8. Vì vậy, nếu bạn truyền đến một UnsafeMutablePointer hoặc UnsafeMutablePointer , tùy theo điều kiện nào, bạn có thể sử dụng chỉ số con để nhận được từng byte riêng lẻ theo số. – matt

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