как сделать оптимизированную карту в 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 размером на все отображаемое пространство, можно будет отображать вместо огромного количества маленьких спрайтов один большой.
