如何解决如果我将图像 blit 到 pygame 的主窗口上,它不会按预期显示
我目前正在尝试使用 pygame 库在 python 中开发我的第一个简单的独立游戏。最近我开始编写地图编辑器。一切正常,除了如果我想显示地图,我会得到某种缩放或“压缩”的图像(见图片)It looks like this,但它应该看起来像 this。 这是我的地图构建器的完整代码:
import Map_
import sheet
import Tile_
FPS = 60
WINDOW_SIZE = (640,480)
WHITE = (255,255,255)
BLACK = (0,0)
RED = (255,0)
GREEN = (0,0)
BLUE = (0,255)
DEFAULT_TILE_SET = ("roguelikeCity_magenta","png")
class Builder:
def __init__(self):
if not pygame.get_init():
pygame.init()
self.SCREEN = "MENU"
self.LEFT_CLICK = False
self.tilesize = 16
self.scale_factor = 3
self.true_tilesize = self.scale_factor*self.tilesize
self.TILE_SHEET = sheet.Tile_Sheet(DEFAULT_TILE_SET[0],DEFAULT_TILE_SET[1])
self.MAP = Map_.Map(self.TILE_SHEET,self.true_tilesize)
self.WINDOW = pygame.display.set_mode(WINDOW_SIZE)
pygame.display.set_caption("Map Editor v.1")
self.FONT = pygame.font.SysFont("Arial",18,True)
self.CLOCK = pygame.time.Clock()
self.new_map()
def quit(self):
print("Quitting....")
exit(0)
def menu(self):
self.SCREEN = "MENU"
self.new_map_button = pygame.Rect(0,100,25)
self.new_map_button.center = (WINDOW_SIZE[0]/8,WINDOW_SIZE[1]-100)
self.exit_button = pygame.Rect(0,25)
self.exit_button.center = (WINDOW_SIZE[0]/8,WINDOW_SIZE[1]-70)
def new_map(self):
self.MAP.generate_map(32,32,"untitled.json")
self.SCREEN = "NEW MAP"
self.save_button = pygame.Rect(0,25)
self.save_button.center = (WINDOW_SIZE[0]-100,WINDOW_SIZE[1]-50)
self.init_tile_list()
self.init_scrollbar()
def init_scrollbar(self):
ratio = WINDOW_SIZE[1]/self.Tile_list.h
self.thumb_w = 20
thumb_h = WINDOW_SIZE[1]*ratio
self.thumb_col = (123,123,123)
scrollbar_x,scrollbar_y = self.Tile_list.w,0
self.Thumb = pygame.Rect(self.Tile_list.w,self.thumb_w,thumb_h)
self.Scrollbar = pygame.Rect(scrollbar_x,scrollbar_y,WINDOW_SIZE[1])
self.scrollbar_jump = (self.Tile_list.h-WINDOW_SIZE[1])/(WINDOW_SIZE[1]-thumb_h)
def init_tile_list(self):
tile_list_count_x = 4
tile_margin = 4
tile_list_w = self.true_tilesize*tile_list_count_x+tile_list_count_x*tile_margin
tile_list_h = int(len(self.TILE_SHEET.Sprites)/4)*(tile_margin+self.true_tilesize)
self.Tile_list = pygame.Rect(0,tile_list_w,tile_list_h)
self.Tile_list_img = []
loc = []
tiles_per_row = int((tile_margin+self.Tile_list.w)/(tile_margin+self.true_tilesize))
margin_counter_x = 0
margin_counter_y = 0
for y in range(len(self.TILE_SHEET.Sprites)):
for x in range(tiles_per_row):
pos_x = x*self.true_tilesize+margin_counter_x
pos_y = y*self.true_tilesize+margin_counter_y
margin_counter_x += tile_margin
loc.append([pos_x,pos_y])
margin_counter_x = 0
margin_counter_y += tile_margin
index_counter = 0
for img in self.TILE_SHEET.Sprites:
self.Tile_list_img.append(Tile_.Tile(loc[index_counter][0],loc[index_counter][1],self.TILE_SHEET.get_img(self.TILE_SHEET.get_key(img)),self.TILE_SHEET.get_key(img)))
index_counter+=1
def move_tile_list(self,chx,chy):
if not (self.Thumb.y + -chy) < 0 or (self.Thumb.bottomleft + chy) > WINDOW_SIZE[1]:
self.Thumb.y += -chy
for tile in self.Tile_list_img:
tile.move(chx*int(self.scrollbar_jump),chy*int(self.scrollbar_jump))
def render_builder(self):
self.display_map()
for tile in self.Tile_list_img:
self.display(tile.Image,(tile.pos_x,tile.pos_y),scale=True)
self.display(self.Scrollbar)
self.display(self.Thumb,color=self.thumb_col)
def display_map(self):
map_pos = (self.Tile_list.w + self.Scrollbar.w,0)
self.WINDOW.blit(self.MAP.Image_background,map_pos)
def display(self,what,where=None,color=None,scale=True):
'''"WHAT" is either a Rect,Surface or String
If displaying a String,no "WHERE" is needed,otherwise use a Tuple (x,y)
Default "COLOR" is White,use a tuple to change that (Red,Green,Blue)'''
if type(what) == pygame.Rect:
if color:
pygame.draw.rect(self.WINDOW,color,what)
else:
pygame.draw.rect(self.WINDOW,WHITE,what)
elif type(what) == pygame.Surface:
what = pygame.transform.scale(what,(self.true_tilesize,self.true_tilesize))
self.WINDOW.blit(what,where)
elif type(what) == str:
if color:
text_surface = self.FONT.render(what,False,color)
else:
text_surface = self.FONT.render(what,BLACK)
text_rect = text_surface.get_rect()
text_rect.center = where
self.WINDOW.blit(text_surface,text_rect)
def update_display(self):
pygame.display.update()
self.WINDOW.fill(BLACK)
if self.SCREEN == "MENU":
self.display(self.new_map_button)
self.display("New Map",self.new_map_button.center)
self.display(self.exit_button)
self.display("Exit",self.exit_button.center)
if self.SCREEN == "NEW MAP":
self.display(self.save_button,self.save_button.center)
self.display("Save",self.save_button.center)
self.render_builder()
pygame.display.flip()
def check_collide(self):
if self.SCREEN == "MENU":
if self.new_map_button.collidepoint(self.mx,self.my) and self.LEFT_CLICK:
self.new_map()
if self.exit_button.collidepoint(self.mx,self.my) and self.LEFT_CLICK:
self.quit()
if self.SCREEN == "NEW MAP":
if self.Thumb.collidepoint(self.mx,self.my) and self.LEFT_CLICK:
self.thumb_col = (255,0)
if not self.LEFT_CLICK:
self.thumb_col = (123,123)
def event_handle(self):
self.mx,self.my = pygame.mouse.get_pos()
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
self.LEFT_CLICK = True
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
self.LEFT_CLICK = False
if event.type == pygame.MOUSEMOTION:
if self.SCREEN == "NEW MAP":
if self.Thumb.collidepoint(self.mx,self.my) and self.LEFT_CLICK:
chy = event.rel[1]
self.move_tile_list(0,-chy)
def tick(self):
self.MAP.tick()
self.update_display()
self.event_handle()
self.check_collide()
self.CLOCK.tick(FPS)
a = Builder()
while True:
a.tick()
import sheet
import json
import Tile_
import Chunk_
import pygame
DEFAULT_TILE = "RENAME_889"
class Map():
def __init__(self,Sheet_object,tile_size):
self.MAP = {
"BACKGROUND":{
"TILES":[],"CHUNKS":[]
},"FOREGROUND":{
"TILES":[],"CHUNKS":[]
}
}
self.Tile_Sheet = Sheet_object
self.tile_size = tile_size
self.width = 0
self.height = 0
self.chunk_size = 16
self.DEFAULT_TILE_ID = self.Tile_Sheet.get_key(DEFAULT_TILE)
self.DEFAULT_TILE_IMG = self.Tile_Sheet.get_img(self.DEFAULT_TILE_ID)
def generate_map(self,w,h,name,DEFAULT_TILE_="RENAME_889"):
if DEFAULT_TILE_ == 0:
self.DEFAULT_TILE_ID = -1
self.DEFAULT_TILE_IMG = pygame.Surface((self.tile_size,self.tile_size))
else:
self.DEFAULT_TILE_ID = self.Tile_Sheet.get_key(DEFAULT_TILE_)
self.DEFAULT_TILE_IMG = self.Tile_Sheet.get_img(self.DEFAULT_TILE_ID)
map_name = name
self.width = w
self.height = h
for y in range(self.height):
for x in range(self.width):
new_tile_background = Tile_.Tile(x,y,self.DEFAULT_TILE_IMG,self.DEFAULT_TILE_ID)
new_tile_foreground = Tile_.Tile(x,None,-1)
self.MAP["BACKGROUND"]["TILES"].append(new_tile_background)
self.MAP["FOREGROUND"]["TILES"].append(new_tile_foreground)
self.save_new(map_name)
chunks_per_row = int(self.width/self.chunk_size)
chunks_per_collum = int(self.height/self.chunk_size)
for y in range(chunks_per_collum):
for x in range(chunks_per_row):
pos_x = x*self.tile_size*self.chunk_size
pos_y = y*self.tile_size*self.chunk_size
self.MAP["FOREGROUND"]["CHUNKS"].append(Chunk_.Chunk(pos_x,pos_y,self.tile_size,self.chunk_size))
for y in range(chunks_per_collum):
for x in range(chunks_per_row):
pos_x = x*self.tile_size*self.chunk_size
pos_y = y*self.tile_size*self.chunk_size
self.MAP["BACKGROUND"]["CHUNKS"].append(Chunk_.Chunk(pos_x,self.chunk_size))
for tile in self.MAP["FOREGROUND"]["TILES"]:
for chunk in self.MAP["FOREGROUND"]["CHUNKS"]:
if chunk == self.MAP["FOREGROUND"]["CHUNKS"][-1]:# <----|
if chunk.pos_x <= tile.pos_x <= chunk.bound_x: #|
if chunk.pos_y <= tile.pos_y <= chunk.bound_y: #|
chunk.add_tile(tile) #|
break #|
else: #|
if chunk.pos_x <= tile.pos_x < chunk.bound_x: #|
if chunk.pos_y <= tile.pos_y < chunk.bound_y: #|
chunk.add_tile(tile) #|
break #|
#|
# I dont kNow why,but i have to do this ------------------------|
for tile in self.MAP["BACKGROUND"]["TILES"]:
for chunk in self.MAP["BACKGROUND"]["CHUNKS"]:
if chunk == self.MAP["BACKGROUND"]["CHUNKS"][-1]:# <----|
if chunk.pos_x <= tile.pos_x <= chunk.bound_x: #|
if chunk.pos_y <= tile.pos_y <= chunk.bound_y: #|
chunk.add_tile(tile) #|
break #|
else: #|
if chunk.pos_x <= tile.pos_x < chunk.bound_x: #|
if chunk.pos_y <= tile.pos_y < chunk.bound_y: #|
chunk.add_tile(tile) #|
break #|
self.save_new(name)
return self.MAP
def update_img(self):
self.Image_background = pygame.Surface((self.width*self.tile_size,self.height*self.tile_size))
for chunk in self.MAP["BACKGROUND"]["CHUNKS"]:
self.Image_background.blit(chunk.Image,(chunk.pos_x,chunk.pos_y))
self.Image_foreground = pygame.Surface((self.width*self.tile_size,self.height*self.tile_size))
for chunk in self.MAP["FOREGROUND"]["CHUNKS"]:
self.Image_foreground.blit(chunk.Image,chunk.pos_y))
self.IMAGE = pygame.Surface((self.width*self.tile_size,self.height*self.tile_size))
self.IMAGE.blit(self.Image_background,(0,0))
self.IMAGE.blit(self.Image_foreground,0))
def load_map(self,map_name):
map_dir = "E:\\Projects\\Python\\Crumbles-Cookie-Adventure\\maps\\"
path = map_dir + map_name
with open(path) as file:
data = json.load(file)
self.width = data["map_info"]["size_x"]
self.height = data["map_info"]["size_y"]
self.map_data = data["map_data"]
self.map_data_background = data["map_data_background"]
y_counter = 0
x_counter = 0
for row in self.map_data:
for tile in row:
pos_x = x_counter*self.tile_size
pos_y = y_counter*self.tile_size
new_tile = Tile_.Tile(pos_x,self.Tile_Sheet.get_img(tile),int(tile))
self.MAP["FOREGROUND"]["TILES"].append(new_tile)
if x_counter*self.tile_size == self.width*self.tile_size:
x_counter = 0
else:
x_counter+=1
if y_counter*self.tile_size == self.height*self.tile_size-1*self.tile_size: # Why this > -1*self.tile_size
y_counter = 0
else:
y_counter+=1
x_counter = 0
y_counter = 0
for row in self.map_data_background:
for tile in row:
pos_x = x_counter*self.tile_size
pos_y = y_counter*self.tile_size
new_tile = Tile_.Tile(pos_x,int(tile))
self.MAP["BACKGROUND"]["TILES"].append(new_tile)
if x_counter*self.tile_size == self.width*self.tile_size-1*self.tile_size: # Why this > -1*self.tile_size
x_counter = 0
else:
x_counter+=1
if y_counter*self.tile_size == self.height*self.tile_size:
y_counter = 0
else:
y_counter+=1
chunks_per_row = int(self.width/self.chunk_size)
chunks_per_collum = int(self.height/self.chunk_size)
for y in range(chunks_per_collum):
for x in range(chunks_per_row):
pos_x = x*self.tile_size*self.chunk_size
pos_y = y*self.tile_size*self.chunk_size
self.MAP["FOREGROUND"]["CHUNKS"].append(Chunk_.Chunk(pos_x,but i have to do this ------------------------|
for tile in self.MAP["BACKGROUND"]["TILES"]:
for chunk in self.MAP["BACKGROUND"]["CHUNKS"]:
if chunk == self.MAP["BACKGROUND"]["CHUNKS"][-1]:# <----|
if chunk.pos_x <= tile.pos_x <= chunk.bound_x: #|
if chunk.pos_y <= tile.pos_y <= chunk.bound_y: #|
chunk.add_tile(tile) #|
break #|
else: #|
if chunk.pos_x <= tile.pos_x < chunk.bound_x: #|
if chunk.pos_y <= tile.pos_y < chunk.bound_y: #|
chunk.add_tile(tile) #|
break #|
# I dont kNow why,but i have to do this ------------------------|
# chunk_tiles = 0
# for chunk in self.MAP["FOREGROUND"]["CHUNKS"]:
# chunk_tiles+=len(chunk.Tiles)
# print(chunk_tiles)
# print(len(self.MAP["FOREGROUND"]["TILES"]))
self.update_img()
def save_new(self,name):
dir = "E:\\Projects\\Python\\Crumbles-Cookie-Adventure\\maps\\"
path = dir + name
data = {}
data["map_info"] = {}
data["map_info"]["size_x"] = self.width
data["map_info"]["size_y"] = self.height
data["map_info"]["tilesets"] = [self.Tile_Sheet.sheet_name]
data["map_data"] = []
data["map_data_background"] = []
x_counter = 0
row = []
for tile in self.MAP["FOREGROUND"]["TILES"]:
if x_counter == self.width:
data["map_data"].append(row)
row = []
x_counter = 0
row.append(tile.get_id())
if x_counter<=self.width-1:
x_counter+=1
data["map_data"].append(row)
x_counter = 0
row = []
for tile in self.MAP["BACKGROUND"]["TILES"]:
if x_counter == self.width:
data["map_data_background"].append(row)
row = []
x_counter = 0
row.append(tile.get_id())
if x_counter<=self.width-1:
x_counter+=1
data["map_data_background"].append(row)
with open(path,"w+") as file:
json.dump(data,file)
def tick(self):
for chunk in self.MAP["FOREGROUND"]["CHUNKS"]:
chunk.tick()
for chunk in self.MAP["BACKGROUND"]["CHUNKS"]:
chunk.tick()
self.update_img()
import pygame
class Chunk:
def __init__(self,pos_x,tsz,size):
self.pos_x = pos_x
self.pos_y = pos_y
self.size = size
self.tile_size = tsz
self.Tiles = []
self.data = {
(self.pos_x,self.pos_y):self.Tiles
}
self.bound_x = pos_x+size*tsz
self.bound_y = pos_y+size*tsz
self.Image = pygame.Surface((size*tsz,size*tsz))
def update_image(self):
for tile in self.Tiles:
if tile.Image != None:
scaled_img = pygame.transform.scale(tile.Image,(self.tile_size,self.tile_size))
self.Image.blit(scaled_img,(tile.pos_x-self.pos_x,tile.pos_y-self.pos_y))
def tick(self):
for tile in self.Tiles:
tile.tick()
self.update_image()
def add_tile(self,tile):
self.Tiles.append(tile)
我已经完全检查了我的 sheet.py 文件。它只是将给定图块的图像加载到内存中。 预先感谢您的帮助!
编辑: 我发现了我的错误。我没有计算瓷砖的位置可能在 Tile_.py 文件中....
解决方法
在我的 Tile_.py 文件中,我在其中初始化所有图块并将它们分配给一个图像,我需要将它们的位置与图块大小相乘
def __init__(self,pos_x,pos_y,img,id,tsz,calculate_position=True):
self.Image = img
self.id = id
self.tilesize = tsz
if calculate_position:
self.pos_x = pos_x*tsz
self.pos_y = pos_y*tsz
else:
self.pos_x = pos_x
self.pos_y = pos_y
self.hitbox = pygame.Rect(self.pos_x,self.pos_y,48,48)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。