0

I previously implemented the following spritesheet code into a prototype that I was working on and it worked perfectly, but I'm attempting to implement it into my current project and it is no longer working and I cannot see any reason why that would be the case.

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])

Using the above spritesheet code, I render it to my screen with the below code:

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)    

and it works perfectly fine! When I try to run it in my current project, listed below, it no longer works properly...

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()

I've removed a few lines here and there that were either just comments or code that isn't currently being used (for readability and post length).

When running my current code, the print function shows that my self.index variable is incrementing... but my spritesheet is stuck displaying the first frame of my sprite, never advancing. I cannot see any functional difference between the two implementations. I know that I changed the scope of certain variables, but they should all be accessible when needed.

Can anyone give me any input as to why this isn't working? I'd really appreciate it!

  • Side note (this won't solve the issue), you've implemented 2 event loops. Since `pygame.event.get()` removes all the events from the queue, only 1 event loop will get the events, the other loop doesn't get the events. See [Faster version of pygame.event.get()](https://stackoverflow.com/questions/58086113/faster-version-of-pygame-event-get/58087070#58087070) – Rabbid76 Sep 13 '20 at 19:19
  • replacing it with self.christopher_working.draw(self.screen, self.index % self.christopher_working.totalCellCount, HW, HH, self.index) returned an IndexError: list index out of range. I import my CENTER_HANDLE from a settings file (sorry, should've mentioned!) where I set it to 4 (which is the value used in spritesheet.py to center the sprite in the rect. This value works fine in my other code. self.index is intended to increment the frames of animation and shouldn't have anything to do with that last argument. – Lucid003 Sep 13 '20 at 20:13

1 Answers1

0

Removing self.screen = pg.transform.scale(self.screen,(1024, 768)) resolved the issue and I'm not entirely sure why. My original image is 640x345, which I realize is a crazy aspect ratio, but I'm still confused as to why the transform doesn't seem to work.