Индексированная поверхность 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()  # Should work according to https://www.geeksforgeeks.org/how-to-make-a-pygame-window/

running: bool = True
while running:
    for e in pg.event.get():
        if e.type in (QUIT, KEYDOWN, MOUSEBUTTONDOWN):
            running = False

Необработанный код из https://www.geeksforgeeks.org/how-to-make-a-pygame-window/ работает на pygame 2.5.2 (SDL 2.28.3, Python 3.10.6) в Windows 11. .

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
61
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

convert() возвращает новую поверхность, которая не такая особенная, как та, которую вернули set_mode() и pygame.display.get_surface(). Оставьте специальный:

import pygame

# Pygame window.
screen = pygame.display.set_mode((300, 300))

# Palette stuff.
screen_indexed = screen.convert(8)
PAL = [(251, 252, 253)] * 256
screen_indexed.set_palette(PAL)
screen_indexed.fill(220)

# Update screen.
screen.blit(screen_indexed, (0, 0))
# Show screen.
pygame.display.flip()

# Keep window until user closes it.
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

Другие вопросы по теме