как сделать оптимизированную карту в pygame

Я пытаюсь создать игру на pygame. тип игры top down(Это важно для понимания того как выглядит карта)

карта в игре плиточная. координаты и номер изображения хранится в json файле ( он изменяется от действий игрока ):

[
 [[КООРДИНАТА Y, НОМЕР ТЕКСТУРЫ], [48, 1], [96, 2], [144, 3], [192, 2]],
                         [[0, 1], [48, 3], [96, 2], [144, 1], [192, 1]],
                         [[0, 3], [48, 2], [96, 2], [144, 2], [192, 1]],
                         [[0, 3], [48, 2], [96, 3], [144, 3], [192, 2]], 
                         [[0, 3], [48, 2], [96, 2], [144, 1], [192, 2]]
]    файл на много дольше и длиннее, но укорочен что бы не занимал тут много места

для определении координаты x используется номер списка в файле умноженое на 48

так вот. Если отображать сразу всю карту то будут лаги. а если проходится по всему списку и делать проверку находится ли текстура на экране очень долго и лаги всё равно есть.

есть вариант проверять находится ли персонаж в одном из больших квадратов, если да то проверять квадрате по меньше в этом квадрате и так дойти до нужного квадрата объектов которые надо отрисовывать. но я пока не догадался как это делать.

как оптимизировать отображение большой плиточной карты читаемой из json файла? или дайте совет на что изменить тип хранения карты для оптимизации если нужно то вот весь код игры

import pygame as pg            
import random
from pygame import image
from pygame.locals import *
from dataclasses import dataclass
import json
sc = pg.display.set_mode((1280,720), pg.FULLSCREEN | pg.SCALED, pg.RESIZABLE)

map = json.load(open("C:\\Users\\yablo\\New game\\map back.json", 'r', encoding='utf-8'))

cursor = pg.image.load('C:\\Users\\yablo\\New game\\cursor.png')
cursor = pg.transform.scale(cursor, (5,5)).convert_alpha()


@dataclass
class position:
    x = 0
    y = 0

true_scroll = [0,0]


sc.fill([255, 255, 205])

speed = 7


pg.display.set_caption('Ancient day')
clock = pg.time.Clock()                                                                                                                    

pose= {"X":200,"Y":200}

back1 = pg.image.load('C:\\Users\\yablo\\New game\\глинапісок\\BACK1.png')
back1 = pg.transform.scale(back1, (96,96)).convert_alpha()
back1_rect = back1.get_rect(
    bottomright=(300, 300))

back6 = pg.image.load('C:\\Users\\yablo\\New game\\глинапісок\\BACK6.png')
back6 = pg.transform.scale(back6, (96,96)).convert_alpha()
back6_rect = back6.get_rect(
    bottomright=(300, 300))

back7 = pg.image.load('C:\\Users\\yablo\\New game\\глинапісок\\BACK7.png')
back7 = pg.transform.scale(back7, (96,96)).convert_alpha()
back7_rect = back7.get_rect(
    bottomright=(300, 300))

selector = pg.image.load('C:\\Users\\yablo\\New game\\selector.png')
selector = pg.transform.scale(selector, (96,96)).convert_alpha()
selector_rect = selector.get_rect(
    bottomright=(300, 300))

Яма = pg.image.load('C:\\Users\\yablo\\New game\\ями\\яма1х1.png')
Яма = pg.transform.scale(Яма, (96,96)).convert_alpha()
Яма_rect = back7.get_rect(
    bottomright=(300, 300))

hud_surf = pg.image.load('C:\\Users\\yablo\\New game\\hud.png')
hud_surf = pg.transform.scale(hud_surf, (126*3, 59*3)).convert_alpha()
hud_surf.set_colorkey((0, 24, 255))
hud_rect = hud_surf.get_rect(
    bottomright=(126.5*3, 59.5*3))
sc.blit(hud_surf, hud_rect)
pg.display.flip()



o = pg.image.load('C:\\Users\\yablo\\New game\\cursor.png')
o = pg.transform.scale(o, (5, 5)).convert_alpha()
o.set_colorkey((0, 255, 28))
oo = o.get_rect(
    bottomright=(500, 500))
running = True

player = pg.image.load('C:\\Users\\yablo\\New game\\player.bmp')
player = pg.transform.scale(player, (37*2, 51*2)).convert_alpha()
player.set_colorkey((0, 255, 28))
player_rect = player.get_rect(
    bottomright=(position.x, position.y))

Dig = False

while running: 
    pg.mouse.set_visible(False)
    sc.fill((0,0,0))
    mousepose = pg.mouse.get_pos()
    userInput = pg.key.get_pressed()
    if userInput[pg.K_a]: 
        position.x -= speed
    if userInput[pg.K_d]:
        position.x += speed
    if userInput[pg.K_w]:
        position.y -= speed
    if userInput[pg.K_s]:
        position.y += speed
    if userInput[pg.K_LSHIFT]:
        speed = 10
    if not userInput[pg.K_LSHIFT]:
        speed = 7
    if userInput[pg.K_r]:
        lineX = (position.x - position.x%(96))                           # округляет координату X до числа кратного 48
        lineY = (position.y - position.y%(96)) 
        if map[int(int(lineX)/(96))][int(int(lineY)/(96))][1] != 4:                                            # округляет до минимального числа ряда
            map[int(int(lineX)/(96))][int(int(lineY)/(96))][1] = 4    #записывает в словарь "map" вложеный словрь номера ряда округлённые координаты x и y 
            json.dump(map,open("C:\\Users\\yablo\\New game\\map back.json", 'w', encoding='utf-8'))
    if userInput[pg.K_c]:
        lineX2 = (position.x - position.x%(96))
        lineY2 = (position.y - position.y%(96))
        if map[int(int(lineX2)/(96))][int(int(lineY2)/(96))][1] == 4:                                            # округляет до минимального числа ряда
            map[int(int(lineX2)/(96))][int(int(lineY2)/(96))][1] = random.randint(1,3)    #записывает в словарь "map" вложеный словрь номера ряда округлённые координаты x и y 
            json.dump(map,open("C:\\Users\\yablo\\New game\\map back.json", 'w', encoding='utf-8'))
        #map{x[x,y]}
    if userInput[pg.K_f]:
        Dig = True
    if not userInput[pg.K_f]:
        Dig = False

    true_scroll[0] += (position.x - true_scroll[0] - 640)/9
    true_scroll[1] += (position.y - true_scroll[1] - 460)/9
    scroll = true_scroll.copy()
    scroll[0] = int(scroll[0])
    scroll[1] = int(scroll[1])

    mouse = pg.mouse.get_pos() 

    for event in pg.event.get():
        if event.type == pg.QUIT:
            running = False
        if event.type == pg.MOUSEBUTTONDOWN:        #Если мышь\палец нажата
            lineX = (position.x - position.x%(96))                           # округляет координату X до числа кратного 48
            lineY = (position.y - position.y%(96)) 
            if map[int(int(lineX)/(96))][int(int(lineY)/(96))][1] != 4:                                            # округляет до минимального числа ряда
                map[int(int(lineX)/(96))][int(int(lineY)/(96))][1] = 4    #записывает в словарь "map" вложеный словрь номера ряда округлённые координаты x и y 
                json.dump(map,open("C:\\Users\\yablo\\New game\\map back.json", 'w', encoding='utf-8'))
            if mouse[0] > 500:
                istouchBUTT = True                  #Присваиваем истину
                mouse2_2 = mouse
        elif event.type == pg.MOUSEBUTTONUP:        #Если мышь\палец отпускаются
            istouchJOY = False                      #Присваиваем ложь
            istouchBUTT = False                     #Присваиваем ложь
    

    
    back1_rect = back1.get_rect(
        bottomright=(200 - scroll[0], 200- scroll[1]))
    sc.blit(back1, back1_rect)
    # position.x + 360 , position.y + 640 - нижняя правая точка єкрана
    # position.x - 360 , position.y - 640 - верхняя левая точка єкрана


    for lines in range(len(map)):                                # для всех объектов в словре map
        for cords in range(len(map[lines])):                     # для всех объектов в столбце
            if map[lines][cords][1] == 1:
                block = back1                                    
            if map[lines][cords][1] == 2:
                block = back6
            if map[lines][cords][1] == 3:
                block = back7
            if map[lines][cords][1] == 4:
                block = Яма
            sc.blit(block,(((lines*48)*2)-scroll[0],((map[lines][cords][0])*2)-scroll[1])) # отрисовает все ямы
    player_rect = player.get_rect(
        bottomright=(position.x- scroll[0], position.y-scroll[1]))
    selector_rect = selector.get_rect(
        bottomright=(position.x - position.x%(96)- scroll[0]+96, position.y - position.y%(96)-scroll[1]+96))
    sc.blit(selector,selector_rect)
    sc.blit(player,player_rect)
    sc.blit(hud_surf, hud_rect)
    sc.blit(cursor,(mousepose[0],mousepose[1]))

    clock.tick(60)          #Ограничиваем кадры в секунду до 60
    pg.display.update()     #Обновляем поверхность экрана
    
                

введите сюда описание изображения


Ответы (1 шт):

Автор решения: Велизар Селезнев

Pygame очень долго прорисовывает все спрайты из-за того, что за очень маленькое количество времени нужно отобразить большое количество изображений. Если создать объект pygame.surface.Surface размером на все отображаемое пространство, можно будет отображать вместо огромного количества маленьких спрайтов один большой.

→ Ссылка