Pygame:这个 spritesheet 代码适用于另一个项目,但不适用于这个项目。为啥?

Posted

技术标签:

【中文标题】Pygame:这个 spritesheet 代码适用于另一个项目,但不适用于这个项目。为啥?【英文标题】:Pygame: This spritesheet code works on another project, but not this one. Why?Pygame:这个 spritesheet 代码适用于另一个项目,但不适用于这个项目。为什么? 【发布时间】:2020-12-31 14:23:58 【问题描述】:

我之前将以下 spritesheet 代码实现到我正在研究的原型中并且运行良好,但我正在尝试将其实现到我当前的项目中,但它不再有效,我看不出有任何原因就这样吧。

import math, random, sys
import pygame
from pygame.locals import *


def events():
    for event in pygame.event.get():
        if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
            pygame.quit()
            sys.exit()

class spritesheet:
    def __init__(self, filename, cols, rows):
        self.sheet = pygame.image.load(filename).convert_alpha()
        self.cols = cols
        self.rows = rows
        self.totalCellCount = cols * rows
        
        self.rect = self.sheet.get_rect()
        w = self.cellWidth = self.rect.width / cols
        h = self.cellHeight = self.rect.height / rows
        hw, hh = self.cellCenter = (w / 2, h / 2)
        
        self.cells = list([(index % cols * w, index // cols * h, w, h) for index in range(self.totalCellCount)])
        self.handle = list([
            (0, 0), (-hw, 0), (-w, 0),
            (0, -hh), (-hw, -hh), (-w, -hh),
            (0, -h), (-hw, -h), (-w, -h),])
        
    def draw(self, surface, cellIndex, x, y, handle = 0):
        surface.blit(self.sheet, (x + self.handle[handle][0], y + self.handle[handle][1]), self.cells[cellIndex])

使用上面的 spritesheet 代码,我用下面的代码将它渲染到我的屏幕上:

import os,pygame, spritesheet
import time, datetime

black = (0,0,0)

SCREEN_WIDTH = 1920
SCREEN_HEIGHT = 1080
HW = SCREEN_WIDTH/2
HH= SCREEN_HEIGHT/2


# Setup the clock for a decent framerate
clock = pygame.time.Clock()

screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

index = 0


def run_game(width, height, fps):
    pygame.init()
    global screen
    screen = pygame.display.set_mode((width, height))
    global clock

    playing = True
    while playing == True:
        Render(screen)
                        
        #pygame.display.flip()
        clock.tick(fps)
        
def Render(screen):
    global index
    global clock
    CENTER_HANDLE=4
    s = spritesheet.spritesheet("art_assets/christopher_working.png", 20,1)

    spritesheet.events()
    screen.fill(black)
    s.draw(screen, index % s.totalCellCount, HW, HH, CENTER_HANDLE)
    screen = pygame.transform.scale(screen,(1920,1080))
    pygame.display.update()
    index += 1


        
run_game(1920,1080,60)    

而且效果很好!当我尝试在下面列出的当前项目中运行它时,它不再正常工作...

import pygame as pg
import battlesystem
import player_dialog
import random
import spritesheet
import sys
from os import path
from settings import *


class Game:
    def __init__(self):
        pg.mixer.pre_init(44100, -16, 1, 2048)
        pg.init()
        self.screen = pg.display.set_mode((WIDTH, HEIGHT))
        pg.display.set_caption(TITLE)
        self.clock = pg.time.Clock()
        pg.key.set_repeat(400, 80)
        self.max_player_health = 100
        self.current_player_health = self.max_player_health
        self.current_enemy = ENEMIES['homework']
        self.player_damage = 4
        self.battle_flag = False
        self.dialog_flag = False
        self.christopher_working_flag = True
        self.index = 0
        self.i = 0
        self.delay = 0
        self.load_data()

    def load_data(self):
        # holds game folder path
        game_folder = path.dirname(__file__)
        # holds art assets
        img_folder = path.join(game_folder, 'img')
        # holds maps
        self.map_folder = path.join(game_folder, 'maps')
        # holds sounds
        snd_folder = path.join(game_folder, 'snd')
        # holds music
        music_folder = path.join(game_folder, 'music')
        self.player_img = pg.image.load(path.join(img_folder, PLAYER_IMG)).convert_alpha()
        self.homework_img = pg.image.load(path.join(img_folder, HOMEWORK_IMG)).convert_alpha()
        self.christopher_working = spritesheet.spritesheet('img/christopher_working.png', 20,1)

    def run(self):
        # game loop - set self.playing = False to end game
        self.playing = True
        while self.playing:
            if self.battle_flag == True:
                self.current_player_health = battlesystem.battle_system(self.screen, self.current_enemy, self.player_damage, self.current_player_health)
                self.battle_flag = False
            if self.dialog_flag == True:
                player_dialog(temp_dialog)
            self.events()
            self.draw()

    def quit(self):
        pg.quit()
        sys.exit()
    
    def draw(self):
        pg.display.set_caption(":.2f".format(self.clock.get_fps()))
        #if self.christopher_working_flag == True:
        self.screen.fill(BLACK)
        self.christopher_working.draw(self.screen, self.index % self.christopher_working.totalCellCount, HW, HH, CENTER_HANDLE)
        self.screen = pg.transform.scale(self.screen,(1024, 768))
        self.index += 1
        print(self.index % self.christopher_working.totalCellCount)
        pg.display.update()

    def events(self):
        # catch all events here
        if self.christopher_working_flag == True:
            spritesheet.events()
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.quit()
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_ESCAPE:
                    self.quit()

    #def update(self):
        #if self.player_health <= 0:  add this later


g = Game()
while True:
    g.run()

我在这里和那里删除了几行只是 cmets 或当前未使用的代码(为了可读性和帖子长度)。

在运行我当前的代码时,打印函数显示我的 self.index 变量正在递增......但我的 spritesheet 卡在显示我的 sprite 的第一帧,从不前进。我看不到这两种实现之间的任何功能差异。我知道我更改了某些变量的范围,但在需要时它们都应该可以访问。

谁能告诉我为什么这不起作用?我真的很感激!

【问题讨论】:

旁注(这不会解决问题),您已经实现了 2 个事件循环。由于pygame.event.get() 会从队列中删除所有事件,因此只有一个事件循环会获取事件,另一个循环不会获取事件。见Faster version of pygame.event.get() 将其替换为 self.christopher_working.draw(self.screen, self.index % self.christopher_working.totalCellCount, HW, HH, self.index) 返回了 IndexError: list index out of range。我从设置文件中导入我的 CENTER_HANDLE(对不起,应该提到!),我将它设置为 4(这是 spritesheet.py 中使用的值,用于在矩形中居中精灵。这个值在我的其他代码中工作正常。 self.index 旨在增加动画帧数,与最后一个参数无关。 【参考方案1】:

删除 self.screen = pg.transform.scale(self.screen,(1024, 768)) 解决了这个问题,我不完全确定为什么。我的原始图像是 640x345,我意识到这是一个疯狂的纵横比,但我仍然对为什么转换似乎不起作用感到困惑。

【讨论】:

以上是关于Pygame:这个 spritesheet 代码适用于另一个项目,但不适用于这个项目。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Pygame 中使用 Sprite Sheets 创建动画精灵?

在 Tkinter 中使用 Spritesheets

pygame精灵组和读取图片

Spritesheet 动画 easeljs-0.7.1.min.js

SpriteSheet 类 AS3

JAVA:尝试读取 SpriteSheet 时未成形的 Sprite