Ошибка - Fatal Python error: PyEval_SaveThread - Python3.9

Пишу игру при помощи модуля PyGame. В игре присутствует объект танк, который может поворачивать на все 8 сторон. Повороты на 4 стороны: вверх, вниз, влево и вправо - срабатывают как нужно, но при поворотах на 45 градусов происходит начто непонятное: картинки, из которых состоит танк, размываются с каждым поворотом в одну из таких сторон всё сильнее и сильнее, при каждом последующем повороте на угол в 45 градусов игра начинает лагать и зависать, в итоге останавливается и один раз выдало ошибку:

Fatal Python error: PyEval_SaveThread: the function must be called with t
he GIL held, but the GIL is released (the current Python thread state is 
NULL)                                                                    
Python runtime state: initialized                                        
                                                                         
Current thread 0x00003394 (most recent call first):                      
  File "Z:\myProgs\Python\Project\tanks.py", line 493 in turn            
  File "Z:\myProgs\Python\Project\tanks.py", line 360 in check           
  File "Z:\myProgs\Python\Project\tanks.py", line 613 in run             
  File "Z:\myProgs\Python\Project\tanks.py", line 587 in __init__        
  File "Z:\myProgs\Python\Project\tanks.py", line 619 in <module>        

Не могу понять в чём моя ошибка, всё работает так как нужно: танк правильно поворачивает, едет также правильно, но при переходе с угла в 45 градусов в любую другую сторону, происходит ошибка по непонятным причинам.

Полный код:

import os, sys, time, random, math
import pygame as pg, numpy as np


class Game:
    pg.init()


    class Color:
        WHITE = (255, 255, 255)
        RED = (255, 0, 0)
        GREEN = (0, 255, 0)
        BLUE = (0, 0, 255)
        BLACK = (0, 0, 0)


    class Location:
        SIZE = (100, 100)
        IMAGE = pg.transform.scale(pg.image.load('objects/floor/floor.jpg'), SIZE)
        PLACE = IMAGE.get_rect()


        def __init__(self, screen, info):
            self.screen = screen
            self.info = info
            # create size
            self.WIDTH, self.HEIGHT = self.info.current_w, self.info.current_h
            # create surface
            self.surface = pg.Surface((self.WIDTH, self.HEIGHT))
            # rendering and adding
            self.render()
            self.add()

        def add(self):
            self.screen.blit(self.surface, (0, 0))

        def update(self):
            pass

        def render(self):
            for i in range(1000):
                self.surface.blit(self.IMAGE, self.PLACE)
                if self.PLACE.x >= self.info.current_w:
                    self.PLACE.x = 0
                    self.PLACE.y += 100
                else:
                    self.PLACE.x += 100
                if self.PLACE.y >= self.info.current_h:
                    break


    class Tank:
        SIZE = (80, 100)


        class Move:
            def __init__(self, upstairs=True, downstairs=False, left=False, right=False):
                self.upstairs = upstairs
                self.downstairs = downstairs
                self.left = left
                self.right = right

            def update(self, to):
                if to == 'upstairs-left':
                    self.upstairs = True
                    self.downstairs = False
                    self.left = True
                    self.right = False
                elif to == 'upstairs-right':
                    self.upstairs = True
                    self.downstairs = False
                    self.left = False
                    self.right = True
                elif to == 'downstairs-left':
                    self.upstairs = False
                    self.downstairs = True
                    self.left = True
                    self.right = False
                elif to == 'downstairs-right':
                    self.upstairs = False
                    self.downstairs = True
                    self.left = False
                    self.right = True
                elif to == 'upstairs':
                    self.upstairs = True
                    self.downstairs = False
                    self.left = False
                    self.right = False
                elif to == 'downstairs':
                    self.upstairs = False
                    self.downstairs = True
                    self.left = False
                    self.right = False
                elif to == 'left':
                    self.upstairs = False
                    self.downstairs = False
                    self.left = True
                    self.right = False
                elif to == 'right':
                    self.upstairs = False
                    self.downstairs = False
                    self.left = False
                    self.right = True


        move = Move(
            upstairs=True,
            downstairs=False,
            left=False,
            right=False,
        )
        speed = 1

        def __init__(self, screen, pos=(0, 0)):
            self.screen = screen
            self.info = pg.display.Info()
            # create surface
            self.person = pg.Surface(self.SIZE)
            self.person.set_colorkey((0, 0, 0))
            # create object with position's data
            self.object = self.person.get_rect()
            # rendering
            self.render()
            # update positions and add to window
            self.update(pos)
            self.add()

        def render(self):
            def foot():
                images = {
                    '1':pg.image.load('objects/tank/foot.png'),
                    '2':pg.transform.flip(pg.image.load('objects/tank/foot.png'), True, False),
                    '3':pg.transform.flip(pg.image.load('objects/tank/foot.png'), True, True),
                    '4':pg.transform.flip(pg.image.load('objects/tank/foot.png'), False, True),
                }
                for i, image in images.items():
                    rect = image.get_rect()
                    rect.width, rect.height = rect.width/4, rect.height/4
                    image = pg.transform.scale(image, (rect.width, rect.height))

                    if i == '1':
                        pass
                    elif i == '2':
                        rect.right = self.object.width
                    elif i == '3':
                        rect.right = self.object.width
                        rect.bottom = self.object.height
                    elif i == '4':
                        rect.bottom = self.object.height
                    
                    self.person.blit(image, rect)

            def body():
                image = pg.image.load('objects/tank/body.png')
                rect = image.get_rect()
                rect.width, rect.height = rect.width/4, rect.height/4
                image = pg.transform.scale(image, (rect.width, rect.height))
                rect.centerx, rect.centery = self.object.centerx, self.object.centery+3
                self.person.blit(image, (rect.x, rect.y))

            def head():
                image = pg.image.load('objects/tank/head.png')
                rect = image.get_rect()
                rect.width, rect.height = rect.width/4, rect.height/4
                image = pg.transform.scale(image, (rect.width, rect.height))
                rect.centerx, rect.centery = self.object.centerx, self.object.centery-10
                self.person.blit(image, (rect.x, rect.y))

            foot()
            body()
            head()

        def add(self):
            self.screen.blit(self.person, (self.object.x, self.object.y))

        def update(self, pos):
            self.object.x, self.object.y = pos[0]-40, pos[1]-50

        def rotate(self, pos):
            pass

        def start(self):
            self.speed = 1

        def stop(self):
            self.speed = 0

        def check(self, key):
            if (key[pg.K_w] or key[pg.K_UP]) and (key[pg.K_s] or key[pg.K_DOWN]):
                return self.stop()
            elif (key[pg.K_a] or key[pg.K_LEFT]) and (key[pg.K_d] or key[pg.K_RIGHT]):
                return self.stop()
            else:
                self.start()

            if key[pg.K_w] or key[pg.K_UP]:
                if key[pg.K_a] or key[pg.K_LEFT]:
                    if self.move.upstairs and self.move.left:
                        of = to = 'upstairs-left'
                    elif self.move.upstairs and self.move.right:
                        of, to = 'upstairs-right', 'upstairs-left'
                    elif self.move.downstairs and self.move.left:
                        of, to = 'downstairs-left', 'upstairs-left'
                    elif self.move.downstairs and self.move.right:
                        of, to = 'downstairs-right', 'upstairs-left'
                    elif self.move.upstairs:
                        of, to = 'upstairs', 'upstairs-left'
                    elif self.move.downstairs:
                        of, to = 'downstairs', 'upstairs-left'
                    elif self.move.left:
                        of, to = 'left', 'upstairs-left'
                    elif self.move.right:
                        of, to = 'right', 'upstairs-left'
                elif key[pg.K_d] or key[pg.K_RIGHT]:
                    if self.move.upstairs and self.move.left:
                        of, to = 'upstairs-left', 'upstairs-right'
                    elif self.move.upstairs and self.move.right:
                        of = to = 'upstairs-right'
                    elif self.move.downstairs and self.move.left:
                        of, to = 'downstairs-left', 'upstairs-right'
                    elif self.move.downstairs and self.move.right:
                        of, to = 'downstairs-right', 'upstairs-right'
                    elif self.move.upstairs:
                        of, to = 'upstairs', 'upstairs-right'
                    elif self.move.downstairs:
                        of, to = 'downstairs', 'upstairs-right'
                    elif self.move.left:
                        of, to = 'left', 'upstairs-right'
                    elif self.move.right:
                        of, to = 'right', 'upstairs-right'

                elif self.move.upstairs and self.move.left:
                    of, to = 'upstairs-left', 'upstairs'
                elif self.move.upstairs and self.move.right:
                    of, to = 'upstairs-right', 'upstairs'
                elif self.move.downstairs and self.move.left:
                    of, to = 'downstairs-left', 'upstairs'
                elif self.move.downstairs and self.move.right:
                    of, to = 'downstairs-right', 'upstairs'
                elif self.move.upstairs:
                    of = to = 'upstairs'
                elif self.move.downstairs:
                    of, to = 'downstairs', 'upstairs'
                elif self.move.left:
                    of, to = 'left', 'upstairs'
                elif self.move.right:
                    of, to = 'right', 'upstairs'
            
            elif key[pg.K_s] or key[pg.K_DOWN]:
                if key[pg.K_a] or key[pg.K_LEFT]:
                    if self.move.upstairs and self.move.left:
                        of, to = 'upstairs-left', 'downstairs-left'
                    elif self.move.upstairs and self.move.right:
                        of, to = 'upstairs-right', 'downstairs-left'
                    elif self.move.downstairs and self.move.left:
                        of = to = 'downstairs-left'
                    elif self.move.downstairs and self.move.right:
                        of, to = 'downstairs-right', 'downstairs-left'
                    elif self.move.upstairs:
                        of, to = 'upstairs', 'downstairs-left'
                    elif self.move.downstairs:
                        of, to = 'downstairs', 'downstairs-left'
                    elif self.move.left:
                        of, to = 'left', 'downstairs-left'
                    elif self.move.right:
                        of, to = 'right', 'downstairs-left'
                elif key[pg.K_d] or key[pg.K_RIGHT]:
                    if self.move.upstairs and self.move.left:
                        of, to = 'upstairs-left', 'downstairs-right'
                    elif self.move.upstairs and self.move.right:
                        of, to = 'upstairs-right', 'downstairs-right'
                    elif self.move.downstairs and self.move.left:
                        of, to = 'downstairs-left', 'downstairs-right'
                    elif self.move.downstairs and self.move.right:
                        of = to = 'downstairs-right'
                    elif self.move.upstairs:
                        of, to = 'upstairs', 'downstairs-right'
                    elif self.move.downstairs:
                        of, to = 'downstairs', 'downstairs-right'
                    elif self.move.left:
                        of, to = 'left', 'downstairs-right'
                    elif self.move.right:
                        of, to = 'right', 'downstairs-right'

                elif self.move.upstairs and self.move.left:
                    of, to = 'upstairs-left', 'downstairs'
                elif self.move.upstairs and self.move.right:
                    of, to = 'upstairs-right', 'downstairs'
                elif self.move.downstairs and self.move.left:
                    of, to = 'downstairs-left', 'downstairs'
                elif self.move.downstairs and self.move.right:
                    of, to = 'downstairs-right', 'downstairs'
                elif self.move.upstairs:
                    of, to = 'upstairs', 'downstairs'
                elif self.move.downstairs:
                    of = to = 'downstairs'
                elif self.move.left:
                    of, to = 'left', 'downstairs'
                elif self.move.right:
                    of, to = 'right', 'downstairs'

            elif key[pg.K_a] or key[pg.K_LEFT]:
                if self.move.upstairs and self.move.left:
                    of, to = 'upstairs-left', 'left'
                elif self.move.upstairs and self.move.right:
                    of, to = 'upstairs-right', 'left'
                elif self.move.downstairs and self.move.left:
                    of, to = 'downstairs-left', 'left'
                elif self.move.downstairs and self.move.right:
                    of, to = 'downstairs-right', 'left'
                elif self.move.upstairs:
                    of, to = 'upstairs', 'left'
                elif self.move.downstairs:
                    of, to = 'downstairs', 'left'
                elif self.move.left:
                    of = to = 'left'
                elif self.move.right:
                    of, to = 'right', 'left'
            
            elif key[pg.K_d] or key[pg.K_RIGHT]:
                if self.move.upstairs and self.move.left:
                    of, to = 'upstairs-left', 'right'
                elif self.move.upstairs and self.move.right:
                    of, to = 'upstairs-right', 'right'
                elif self.move.downstairs and self.move.left:
                    of, to = 'downstairs-left', 'right'
                elif self.move.downstairs and self.move.right:
                    of, to = 'downstairs-right', 'right'
                elif self.move.upstairs:
                    of, to = 'upstairs', 'right'
                elif self.move.downstairs:
                    of, to = 'downstairs', 'right'
                elif self.move.left:
                    of, to = 'left', 'right'
                elif self.move.right:
                    of = to = 'right'
            else:
                of = to = None

            self.turn(of=of, to=to)
            self.move.update(to=to)

        def turn(self, of, to):
            if of is None and to is None:
                pass

            if of == to:
                return self.moving(to=to)

            degs = 0
            if of == 'upstairs-left':
                if to == 'upstairs-right':
                    degs = -90
                elif to == 'downstairs-left':
                    degs = 90
                elif to == 'downstairs-right':
                    degs = 180
                elif to == 'upstairs':
                    degs = -45
                elif to == 'downstairs':
                    degs = 135
                elif to == 'left':
                    degs = 45
                elif to == 'right':
                    degs = -135
            elif of == 'upstairs-right':
                if to == 'upstairs-left':
                    degs = 90
                elif to == 'downstairs-left':
                    degs = 180
                elif to == 'downstairs-right':
                    degs = 90
                elif to == 'upstairs':
                    degs = 45
                elif to == 'downstairs':
                    degs = -135
                elif to == 'left':
                    degs = 135
                elif to == 'right':
                    degs = -45
            elif of == 'downstairs-left':
                if to == 'upstairs-left':
                    degs = -90
                elif to == 'upstairs-right':
                    degs = 180
                elif to == 'downstairs-right':
                    degs = 90
                elif to == 'upstairs':
                    degs = -135
                elif to == 'downstairs':
                    degs = 45
                elif to == 'left':
                    degs = -45
                elif to == 'right':
                    degs = 135
            elif of == 'downstairs-right':
                if to == 'upstairs-left':
                    degs = 180
                elif to == 'upstairs-right':
                    degs = 90
                elif to == 'downstairs-left':
                    degs = -90
                elif to == 'upstairs':
                    degs = 135
                elif to == 'downstairs':
                    degs = -45
                elif to == 'left':
                    degs = -135
                elif to == 'right':
                    degs = 45
            elif of == 'upstairs':
                if to == 'upstairs-left':
                    degs = 45
                elif to == 'upstairs-right':
                    degs = -45
                elif to == 'downstairs-left':
                    degs = 135
                elif to == 'downstairs-right':
                    degs = -135
                elif to == 'downstairs':
                    degs = 180
                elif to == 'left':
                    degs = 90
                elif to == 'right':
                    degs = -90
            elif of == 'downstairs':
                if to == 'upstairs-left':
                    degs = -135
                elif to == 'upstairs-right':
                    degs = 135
                elif to == 'downstairs-left':
                    degs = -45
                elif to == 'downstairs-right':
                    degs = 45
                elif to == 'upstairs':
                    degs = 180
                elif to == 'left':
                    degs = -90
                elif to == 'right':
                    degs = 90
            elif of == 'left':
                if to == 'upstairs-left':
                    degs = -45
                elif to == 'upstairs-right':
                    degs = -135
                elif to == 'downstairs-left':
                    degs = 45
                elif to == 'downstairs-right':
                    degs = 135
                elif to == 'upstairs':
                    degs = -90
                elif to == 'downstairs':
                    degs = 90
                elif to == 'right':
                    degs = 180
            elif of == 'right':
                if to == 'upstairs-left':
                    degs = 135
                elif to == 'upstairs-right':
                    degs = 45
                elif to == 'downstairs-left':
                    degs = -135
                elif to == 'downstairs-right':
                    degs = -45
                elif to == 'upstairs':
                    degs = 90
                elif to == 'downstairs':
                    degs = -90
                elif to == 'left':
                    degs = 180
                
            self.person = pg.transform.rotate(self.person, degs)
            self.object = self.person.get_rect(center=self.object.center)

        def moving(self, to):
            # check bounds
            if self.object.top == 0:
                self.stop()
                if to != 'upstairs' and to != 'upstairs-left' and to != 'upstairs-right':
                    if self.object.left == 0:
                        self.stop()
                        if to != 'left':
                            self.start()
                    elif self.object.right == (self.info.current_w-17):
                        self.stop()
                        if to != 'right':
                            self.start()
                    else:
                        self.start()
            elif self.object.bottom == self.info.current_h:
                self.stop()
                if to != 'downstairs' and to != 'downstairs-left' and to != 'downstairs-right':
                    if self.object.left == 0:
                        self.stop()
                        if to != 'left':
                            self.start()
                    elif self.object.right == (self.info.current_w-17):
                        self.stop()
                        if to != 'right':
                            self.start()
                    else:
                        self.start()
            elif self.object.left == 0:
                self.stop()
                if to != 'left':
                    self.start()
            elif self.object.right == (self.info.current_w-17):
                self.stop()
                if to != 'right':
                    self.start()
            else:
                self.start()

            # moving
            if to == 'upstairs-left':
                self.object.x -= self.speed
                self.object.y -= self.speed
            elif to == 'upstairs-right':
                self.object.x += self.speed
                self.object.y -= self.speed
            elif to == 'downstairs-left':
                self.object.x -= self.speed
                self.object.y += self.speed
            elif to == 'downstairs-right':
                self.object.x += self.speed
                self.object.y += self.speed
            elif to == 'upstairs':
                self.object.y -= self.speed
            elif to == 'downstairs':
                self.object.y += self.speed
            elif to == 'left':
                self.object.x -= self.speed
            elif to == 'right':
                self.object.x += self.speed


    TITLE = 'Tanks'
    SIZE = (0, 0)
    TYPE = pg.FULLSCREEN

    FPS = 50
    CLOCK = pg.time.Clock()

    BACKGROUND = Color.BLACK

    EXIT = False

    def __init__(self):
        pg.display.set_caption(self.TITLE)
        self.screen = pg.display.set_mode(self.SIZE, self.TYPE)
        self.window = pg.display.Info()

        self.run()

    def update(self):
        self.screen.fill(self.BACKGROUND)

    def run(self):
        self.location = self.Location(self.screen, self.window)
        self.tank = self.Tank(self.screen, (self.window.current_w//2, self.window.current_h//2))
        while not self.EXIT:
            # check FPS
            self.CLOCK.tick(self.FPS)
            # render objects for each FPS
            self.screen.fill((0, 0, 0))
            self.location.add()
            self.tank.add()
            # flip window
            pg.display.flip()

            for event in pg.event.get():
                if event.type == pg.QUIT:
                    self.EXIT = True
                elif event.type == pg.KEYDOWN:
                    if event.key == pg.K_ESCAPE:
                        self.EXIT = True

            key = pg.key.get_pressed()
            self.tank.check(key)

            pg.event.pump()


if __name__ == '__main__':
    game = Game()

Ответы (0 шт):