Реализация движения танка по консоли Pygame

Вопрос из серии: "почему не работает?" Есть программа (код ниже), реализующая передвижение танка по экрану. За движение отвечают кнопки WASD (впрочем, как обычно). В левом нижнем углу окна есть квадратики, которые меняют цвет, если нажата соответствующая кнопка (из WASD), и меняют его обратно при отпускании. Также нужно добавить текстовое отображение направления движения танка. В этом-то и заключается вся проблема: функционал этого текстового отчета есть, а почему не работает - ума не приложу. За отображение текста отвечает класс Text, за саму отрисовку - функция draw, которая, в свою очередь вызывается в классах: UpCommand, DownCommand, LeftCommand и RightCommand. Вот сам код:

import sys
from abc import ABC, abstractmethod
from math import cos, sin, pi

import pygame


class Color:
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)


class PG:
    _instance = None

    def __init__(self, width=500, height=400):
        if PG._instance is not None:  # singleton implementation
            raise ReferenceError('Tying to create singleton object twice')
        else:
            PG._instance = self
        pygame.init()
        self.screen = pygame.display.set_mode((width, height))
        self.width = width
        self.height = height

    @staticmethod
    def get():
        if not PG._instance:
            PG()
        return PG._instance


class PGObject(ABC):
    def __init__(self):
        self.screen = PG.get().screen

    def draw(self, string):
        pass

    def logic(self):
        pass


class PGScene(ABC):
    bgcolor = (0, 0, 0)

    def __init__(self):
        self.screen = PG.get().screen
        self.sceneover = False
        self.objects = []

    def draw(self):
        self.screen.fill(self.bgcolor)
        for item in self.objects:
            item.draw()

    def process_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.sceneover = True
            self.process_event(event)

    def process_event(self, event):
        pass

    @abstractmethod
    def process_logic(self):
        for item in self.objects:
            item.logic()

    def main_loop(self):
        while not self.sceneover:
            self.process_events()
            self.process_logic()
            self.draw()
            pygame.display.flip()
            pygame.time.wait(10)


class GameScene(PGScene):

    def __init__(self):
        super().__init__()
        self.panzer = Panzer(200, 200)
        self.buttons = {
            'up': StateRect(100, 500, 20, 20, Color.GREEN, Color.RED),
            'down': StateRect(100, 530, 20, 20, Color.GREEN, Color.RED),
            'left': StateRect(70, 530, 20, 20, Color.GREEN, Color.RED),
            'right': StateRect(130, 530, 20, 20, Color.GREEN, Color.RED),
        }
        self.objects.append(self.panzer)
        self.objects += self.buttons.values()

    def process_logic(self):
        super().process_logic()

    def process_event(self, event):
        if event.type == pygame.KEYUP and event.key in KeyUpMoment.keyup_events.keys():
            KeyUpMoment.keyup_events[event.key](self).execute()
        if event.type == pygame.KEYDOWN and event.key in KeyDownMoment.keydown_events.keys():
            KeyDownMoment.keydown_events[event.key](self).execute()


class Text(PGObject):
    def __init__(self):
        super().__init__()
        pygame.font.init()
        self.font = pygame.font.SysFont('Comic Sans MS', 14, None)
        self.color = Color.GREEN

    def draw(self, string):
        text = self.font.render(string, False, self.color)
        self.screen.blit(text, (250, 150))


class Command(ABC):
    def __init__(self, scene):
        self.scene = scene

    @abstractmethod
    def execute(self):
        pass


class UpCommand(Command):
    def execute(self):
        self.scene.panzer.move()
        self.scene.buttons['up'].set_enabled(True)
        self.scene.buttons['down'].set_enabled(False)
        UpText = Text()
        UpText.draw('движение вперёд')
        print('движение вперёд')


class DownCommand(Command):
    def execute(self):
        self.scene.panzer.move_back()
        self.scene.buttons['down'].set_enabled(True)
        self.scene.buttons['up'].set_enabled(False)
        DownText = Text()
        DownText.draw('движение назад')
        print('движение назад')


class LeftCommand(Command):
    def execute(self):
        self.scene.panzer.rotate(-0.5)
        self.scene.buttons['left'].set_enabled(True)
        self.scene.buttons['right'].set_enabled(False)
        LeftText = Text()
        LeftText.draw('движение влево')
        print('движение влево')


class RightCommand(Command):
    def execute(self):
        self.scene.panzer.rotate(0.5)
        self.scene.buttons['right'].set_enabled(True)
        self.scene.buttons['left'].set_enabled(False)
        RightText = Text()
        RightText.draw('движение вправо')
        print('движение вправо')


class KeyDownMoment(GameScene):
    keydown_events = {
        pygame.K_w: UpCommand,
        pygame.K_s: DownCommand,
        pygame.K_a: LeftCommand,
        pygame.K_d: RightCommand,
    }


class StopCommand(Command):
    def execute(self):
        self.scene.panzer.stop()


class StopUpCommand(StopCommand):
    def execute(self):
        super().execute()
        self.scene.buttons['up']


class StopDownCommand(StopCommand):
    def execute(self):
        super().execute()
        self.scene.buttons['down']


class StopLeftCommand(StopCommand):
    def execute(self):
        super().execute()
        self.scene.buttons['left']


class StopRightCommand(StopCommand):
    def execute(self):
        super().execute()
        self.scene.buttons['right']


class KeyUpMoment(GameScene):
    keyup_events = {
        pygame.K_w: StopUpCommand,
        pygame.K_s: StopDownCommand,
        pygame.K_a: StopLeftCommand,
        pygame.K_d: StopRightCommand
    }


class Panzer(PGObject):
    def __init__(self, x, y):
        super().__init__()
        self.rotated_image = self.image = pygame.image.load("panzer.png")
        self.rotated_rect = self.rect = self.image.get_rect()
        self.x = x
        self.y = y
        self.direction = 0
        self.speed = 0
        self.max_speed = 1

    def draw(self):
        self.rect.x = self.x - self.rect.width // 2
        self.rect.y = self.y - self.rect.height // 2
        self.rotated_rect = self.rotated_image.get_rect(center=self.rect.center)
        self.screen.blit(self.rotated_image, self.rotated_rect)

    def move(self):
        self.speed = self.max_speed

    def move_back(self):
        self.speed = -self.max_speed

    def stop(self):
        self.speed = 0

    def step(self):
        self.x += cos(self.direction) * self.speed
        self.y += sin(self.direction) * self.speed

    def rotate(self, angle):
        self.direction += angle
        self.rotated_image = pygame.transform.rotate(self.image, -self.direction / pi * 180)
        self.rotated_rect = self.rotated_image.get_rect(center=self.rect.center)

    def logic(self):
        self.step()


class StateRect(PGObject):
    def __init__(self, x, y, width, height, color_enabled, color_disabled):
        super().__init__()
        self.rect = (x, y, width, height)
        self.color_enabled = color_enabled
        self.color_disabled = color_disabled
        self.enabled = False

    def draw(self):
        color = self.color_enabled if self.enabled else self.color_disabled,
        pygame.draw.rect(self.screen, color, self.rect, 0)

    def set_enabled(self, enabled):
        self.enabled = enabled


if __name__ == "__main__":
    PG(800, 600)
    gs = GameScene()
    gs.main_loop()
    sys.exit()

Помогите, пожалуйста, с задачей. Если вдруг увидите ошибку, пожалуйста, подскажите решение проблемы. Заранее спасибо


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