python - Python + sdl2:列表或字节数组到 c_void_p
问题描述
我目前正在用 Python 编写 Gameboy 模拟器。我想使用 pysdl2 进行图形输出。
我有一个 RGB 值列表(每个像素 3 个值,所以列表是 256x256x3)。这是背景,而不是实际屏幕将显示的内容。
直接像素操作太慢了,所以我想用sdl2.SDL_UpdateTexture
一次更新整个纹理。但我无法将我的列表转换为必要的c_void_p
类型。是否有捷径可寻?或者有没有更好的方法来获得足够的 FPS?我没想到每秒更新 60 次图像会这么难。
一个简短的例子:
import sdl2
pic = [0xff] * 256*256*3
window = sdl2.SDL_CreateWindow(b"Gameboy Emulator", 256, 256, 256, 256, sdl2.SDL_WINDOW_SHOWN)
renderer = sdl2.SDL_CreateRenderer(window, -1, 0)
texture = sdl2.SDL_CreateTexture(renderer, sdl2.SDL_PIXELFORMAT_RGB888, sdl2.SDL_TEXTUREACCESS_STATIC, 256, 256)
我尝试了以下方法:
pic_as_string = "".join(map(chr, pic))
pointer = cast(c_char_p(pic_as_string), c_void_p)
sdl2.SDL_UpdateTexture(texture, None, pointer, 3*256)
我目前正在使用pypy3
,如果相关的话。
解决方案
最好将帧缓冲区存储在 bytearray() 中而不是列表中的整数中,因为这样它就会自动成为可写的字节数组。您读取/修改它的方式与列表相同(即 pic[0] = 255)。
pic = bytearray([0xff]*256*256*3)
然后,您可以使用相同的缓冲区创建一个 ctypes char 数组:
pointer = (c_char*len(pic)).from_buffer(pic)
sdl2.SDL_UpdateTexture(texture, None, pointer, 3*256)
此外,您可能希望在创建纹理时使用 sdl2.SDL_TEXTUREACCESS_STREAMING(表示您打算更新它的 SDL)。
推荐阅读
- python - 如何更有效地触发类内函数?
- python - graphql.error.located_error.GraphQLLocatedError:connection_resolver() 缺少 1 个必需的位置参数:“信息”
- c++ - 在 GUI 中集成 Boost.Asio
- go - 正确关闭运行无限循环的 Go 例程
- javascript - 在 DOM 加载后立即自动运行给定 url 的 onclick 函数
- pyspark - 居中和缩放 Pyspark 数据框
- java - 如何使用 PowerMock 模拟非静态记录器?
- javascript - 从 Three.js 中的 .js 文件加载模型
- redirect - S3 WebsiteRedirectionLocation 元似乎积极浏览器缓存
- c# - Outlook 加载项始终运行