【问题标题】:Pygame TypeError: join() argument must be str, bytes, or os.PathLike object, not 'Surface'Pygame TypeError: join() 参数必须是 str、bytes 或 os.PathLike 对象,而不是“Surface”
【发布时间】:2020-03-29 06:23:25
【问题描述】:

我学习 Python 才几周,这个问题让我很困惑。我正在尝试使用 Pygame 创建一个简单的塔防风格游戏。谷歌搜索和研究超过 4 小时(pygame 文档网站在发布时已关闭,依赖于缓存版本)。我相信它最终会变得很容易修复,但我没有想法。

我将 Tower 类放在一个文件中,而将主游戏循环放在另一个文件中。图像文件存储在名为“assets”的文件夹中,该文件夹与塔类和主游戏循环位于同一目录中。当我尝试创建一个新塔时,特别是加载塔的图像,我得到标题中列出的错误。

我知道我以某种方式传递了“表面”作为参数,但我终其一生都无法弄清楚它在哪里。我让玩家使用 1 或 2 键选择他们正在建造的塔的类型,然后查找该按键的相应图像,然后将塔放置在他们在屏幕上单击的位置。在点击鼠标的 pygame 事件之后的 print 语句正确地将“elf_tower.png”列为文件名,但类的 init 中的 print 语句显示为“”。如果我为图像硬编码文件名,该类将正常运行,但我怀疑这是最好的解决方案。我还尝试将变量设置为“assets/”+ tower_type,但它同样表示它无法将 Surface 连接到 str。

主文件:

"""Homebrew tower defense game using pygame and object oriented programming.
This is a learning project"""
import pygame
from tower import Tower
from scaling import get_scaling_info

get_scaling_info()

def run_game():
    """Runs the game"""
    pygame.init()
    get_scaling_info()
    width, height = get_scaling_info()[1:]
    screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN, 32)
    pygame.display.set_caption("Tower Defense")
    game_surface = screen.copy()

    def toggle_fullscreen():
        """Toggles between fullscreen and windowed mode"""
        if screen.get_flags() & pygame.FULLSCREEN:
            return pygame.display.set_mode((800, 600), pygame.RESIZABLE)
        return pygame.display.set_mode((width, height), pygame.FULLSCREEN)

    def update_display():
        """Update the game display"""
        scaling_info = get_scaling_info()[0]
        screen.fill((0, 0, 0))
        for tower in Tower.towers:
            tower.draw()
        screen.blit(pygame.transform.scale(
            game_surface, (scaling_info.current_w, scaling_info.current_h)), (0, 0))
        pygame.display.update()

    run = True
    tower_type = 0
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    run = False
                if event.key == pygame.K_F11:
                    toggle_fullscreen()
                if event.key == pygame.K_1 or event.key == pygame.K_2:
                    tower_type = Tower.selection_dict[event.key]
            if event.type == pygame.MOUSEBUTTONDOWN and tower_type != 0: #to prevent game from breaking if no tower selected.
                print(tower_type) #returns elf_tower.png which is the expected result
                mouse_x, mouse_y = pygame.mouse.get_pos()
                Tower(tower_type, mouse_x, mouse_y).create_tower()

        update_display()

    pygame.quit()

run_game()

塔类文件:

"""Contains the class used to generate towers"""
import os
import pygame
from scaling import get_scaling_info

get_scaling_info()

class Tower:
    """Tower information"""
    selection_dict = {49:"elf_tower.png", 50:"dwarf_tower.png"} #pygame keypress of 1 corresponds to value 49, 2 to 50.
    towers = []
    def __init__(self, img, x, y, display_surface="game_surface"):
        x_scale, y_scale = get_scaling_info()[1:]
        self.img = pygame.image.load(os.path.join('assets', img))
        print(self.img) # returns <Surface(40x40x32 SW)>
        self.x_coord = x * x_scale
        self.y_coord = y * y_scale
        self.display_surface = display_surface

    def create_tower(self):
        """Creates a tower of the selected type and scales to the correct size"""
        Tower.towers.append(Tower(self.img, self.x_coord, self.y_coord))
        print(Tower.towers)

    def draw(self):
        """Draws the tower on the screen using the specified image at coordinates x and y"""
        pygame.transform.scale(self.img, (32, 32))
        self.display_surface.blit(self.img, (self.x_coord, self.y_coord))
        print(self.img)

 #   def attack(self):
 #       """Causes the tower to attack enemies in range
 #       Not yet written"""

图像缩放文件

"""Gets the scaling info used in the other modules of the game"""
import pygame

def get_scaling_info():
    """Gathers display info for scaling elements of the game"""
    pygame.init()
    display_info = pygame.display.Info()
    scaling_info = pygame.display.Info()
    x_ratio = display_info.current_w/scaling_info.current_w
    y_ratio = display_info.current_h/scaling_info.current_h
    return scaling_info, x_ratio, y_ratio

【问题讨论】:

    标签: python python-3.x pygame


    【解决方案1】:

    您正在查看错误的 Tower 构造(即在 run_game 中);问题实际上出现在这一行

    Tower.towers.append(Tower(self.img, self.x_coord, self.y_coord))
    

    create_tower 方法中,您使用self.img 作为第一个参数构造一个新的Tower。在__init__中,self.img被初始化为pygame.image.load(os.path.join('assets', img)),返回一个Surface

    您可能希望将构造 Towerimg 参数存储为另一个实例属性,然后在 create_tower 方法中使用它,例如:

    class Tower:
        """Tower information"""
        selection_dict = {49:"elf_tower.png", 50:"dwarf_tower.png"} #pygame keypress of 1 corresponds to value 49, 2 to 50.
        towers = []
        def __init__(self, img, x, y, display_surface="game_surface"):
            x_scale, y_scale = get_scaling_info()[1:]
            self.img_file = img
            self.img = pygame.image.load(os.path.join('assets', self.img_file))
            print(self.img) # returns <Surface(40x40x32 SW)>
            self.x_coord = x * x_scale
            self.y_coord = y * y_scale
            self.display_surface = display_surface
    
        def create_tower(self):
            """Creates a tower of the selected type and scales to the correct size"""
            Tower.towers.append(Tower(self.img_file, self.x_coord, self.y_coord))
            print(Tower.towers)
    

    【讨论】:

      猜你喜欢
      • 2022-11-24
      • 2020-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 1970-01-01
      • 1970-01-01
      • 2019-12-05
      相关资源
      最近更新 更多