Pygame索引表面无法显示求助:移植旧代码后黑屏排查
问题描述
我正在将一份古老的Pygame等离子效果代码移植到Python 3。已经为表面应用了多种调色板,plasma_buffer矩阵的值也有变化,但调用pygame.display.flip()后始终显示黑屏,虽然表面像素确实已经更新。请问我遗漏了什么?

完整移植代码
"""Plasma.py -- Korruptor Jan 2001, test code for Seal Basher (v1.0) This little doobry is based on the fast flame example by Pete Shinners and is another novel neat hack on the surfarray module. The plasma algo itself is pretty simple, just a sum of four cosine values from a pre-calculated look-up table inserted into a surf buff. It's all pretty easy really. The comments explain my thinking... This is my first hack, and not really optimised apart from what I've learnt from Pete's example and whilst lurking on #Pygame. If you've got suggestions for speed increases let me know...""" from math import cos from numpy import array, mod, zeros, uint8 from pygame import Surface, display import pygame.transform from pygame.surfarray import blit_array # pylint: disable=no-name-in-module from pygame.locals import KEYDOWN, MOUSEBUTTONDOWN, QUIT RES = (320, 256) SMALL_X = int(RES[0] // 8) SMALL_Y = int(RES[1] // 8) PI = 3.14159 # Linear array of cosine values to be indexed and summed, initialised to zero prior to pre-calc... cos_tab = [0] * 256 # Array of indexes to be used on our cos_tab. Could be variables I suppose. Just easier to cut_n_paste! ;-) pnt_tab = array((0, 0, 0, 0)) def main(): "Inisalises display, precalculates the cosine values, and controls the update loop" display.init() # Turn SDL_PIXELFORMAT_RGB888 to SDL_PIXELFORMAT_INDEX8 screen_surface: Surface = display.set_mode(RES, 0, 8).convert(8) info = display.Info() print(info) # Numeric array (working) for the display. Do all our fun stuff here... plasma_buffer: list = [[0] * SMALL_Y] * SMALL_X # Pygame Surface object which will take the surfarray data and be translated into a screen blit... plasma_surface = Surface((SMALL_X, SMALL_Y), 0, 8).convert(8) set_palette(screen_surface) plasma_surface.set_palette(screen_surface.get_palette()) screen_surface.fill(100) make_cosine() # Fruity loops... while 1: for e in pygame.event.get(): if e.type in (QUIT, KEYDOWN, MOUSEBUTTONDOWN): return add_cosine(plasma_buffer) # print(plasma_buffer[0]) blit_scaled_surface(screen_surface, plasma_buffer, plasma_surface) pygame.display.flip() def add_cosine(plasma_buffer): "An Y by X loop of screen co-ords, summing the values of four cosine values to produce a color value that'll map to the previously set surface palette." # Use working indices for the cosine table, save the real ones for later... t1 = pnt_tab[0] t2 = pnt_tab[1] for y in range(0, SMALL_Y): # Save the horizontal indices for later use... t3 = pnt_tab[2] t4 = pnt_tab[3] for x in range(0, SMALL_X): # Our color value will equal the sum of four cos_table offsets. # The preset surface palette comes in handy here! We just need to output the value... # We mod by 256 to prevent our index going out of range. (C would rely on 8bit byte ints and with no mod?) color = ( cos_tab[mod(t1, 256)] + cos_tab[mod(t2, 256)] + cos_tab[mod(t3, 256)] + cos_tab[mod(t4, 256)] ) # Arbitrary values, changing these will allow for zooming etc... t3 += 3 t4 += 2 # Insert the calculated color value into our working surfarray... plasma_buffer[x][y] = color # Arbitrary values again... t1 += 2 t2 += 1 # Arbitrary values to move along the cos_tab. Play around for something nice... # Don't think I need these boundary checkings, but just in case someone decides to run this code for a couple of weeks non-stop... # if pnt_tab[0] < 256: pnt_tab[0] += 1 else: pnt_tab[0] = 1 if pnt_tab[1] < 256: pnt_tab[1] += 2 else: pnt_tab[1] = 2 if pnt_tab[2] < 256: pnt_tab[2] += 3 else: pnt_tab[2] = 3 if pnt_tab[3] < 256: pnt_tab[3] += 4 else: pnt_tab[3] = 4 def make_cosine(): "Knock up a little pre-calculated cosine lookup table..." i = 0 for i in range(0, 256): # Play with the values here for interesting results... I just made them up! :-) cos_tab[i] = 60 * (cos(i * PI / 32)) def set_palette(screen_surface): "Create something trippy... Based on Pete's cmap creator, and without doubt the thing that took the longest... Aaaargh! Decent palettes are hard to find..." colors = zeros((256, 3), uint8) i = 0 for i in range(0, 64): colors[i][0] = 255 colors[i][1] = i * 4 colors[i][2] = 255 - (i * 4) colors[i + 64][0] = 255 - (i * 4) colors[i + 64][1] = 255 colors[i + 64][2] = i * 4 colors[i + 128][0] = 0 colors[i + 128][1] = 255 - (i * 4) colors[i + 128][2] = 255 colors[i + 192][0] = i * 4 colors[i + 192][1] = 0 colors[i + 192][2] = 255 screen_surface.set_palette(colors) def blit_scaled_surface(screen, flame, miniflame): "double the size of the data, and blit to screen -- Nicked from Shread's Fast Flame" f = array(flame, uint8) print(f[0]) blit_array(miniflame, f) s2 = pygame.transform.scale(miniflame, screen.get_size()) print(s2.get_at((0,0))) screen.blit(s2, (0, 0)) if __name__ == "__main__": main()
简化测试示例
import pygame as pg from pygame import QUIT, KEYDOWN, MOUSEBUTTONDOWN RES = (320, 256) pg.display.init() # Turn SDL_PIXELFORMAT_RGB888 to SDL_PIXELFORMAT_INDEX8 screen_surface: pg.Surface = pg.display.set_mode(RES).convert(8) info = pg.display.Info() print(info) PAL = [(251, 252, 253)] * 256 screen_surface.set_palette(PAL) screen_surface.fill(220) print(screen_surface.get_at((0, 0))) # (251, 252, 253, 255) pg.display.flip() # 按预期应该显示颜色 running: bool = True while running: for e in pg.event.get(): if e.type in (QUIT, KEYDOWN, MOUSEBUTTONDOWN): running = False
注:在Windows 11、Pygame 2.5.2(SDL 2.28.3)、Python 3.10.6环境下,基础窗口代码可正常运行。
内容的提问来源于stack exchange,提问作者Cees Timmerman
相关产品推荐
相关产品推荐

