text: import pygame,os
  from pygame.locals import *
  import numpy as np
  import delegates
  from random import randint
  
  class GameScene:
  
      """
  É a classe que será responsavel, pelas alterações que deverão ser constante pelo game,
  como o tamanho da tela,funcionalidade do pygame,como inicializar o jogo,pegar o tempo entre os frames
  """
  class Game:
      def __init__(self,width = 800, height = 500,fps = 24,icon = None,gameName = "pyKombat"):
          self.width = width
          self.height = height
          self.displayWidth = width
          self.displayHeight = height
          self.gameExit = False
          self.frame = 0
          self.fps = fps
          self.gameName = gameName
          self.icon = icon
          self.scale = 1.0
          self.ppm = 70 #pixel por metros
          os.environ['SDL_VIDEO_CENTERED'] = '1'
          #self.display = pygame.display.set_mode((self.width,self.height),pygame.FULLSCREEN)
          self.display = pygame.display.set_mode((self.width,self.height))
          pygame.mouse.set_visible(False)
          self.clock = pygame.time.Clock()
          self.deltaTime = 0.0
          self.musicVolume = 10
          self.fxVolume = 10
          self.hasQuit = False
          self.gameScene = GameScene()
  
          pygame.display.set_caption(self.gameName)
          self.event = self.getEvent()
  
      def setGameScene(self,scene = GameScene()):
          self.gameScene = scene
      def getDisplayWidth(self):
          """Retorna o comprimento do 'display'"""
          return self.diplayWidth
  
      def getDisplayHeight(self):
          """Retorna a altura do 'display'"""
          return self.diplayHeight
  
      def setDisplaySize(self,value = (800,500)):
          """altera o tamanho do display,onde 'value =(int = 800,int=500)' """
          scale = value[0]/self.width
          if int(scale*self.displayHeight) > value[1]:
              print("não proporçã do almento do comprimento da tela não pode ser maior que da altura")
              print("logo a tela,não será alterada")
              return
          self.displayWidth = value[0]
          self.scale = value[0]/self.width
          self.displayHeight = value[1]
          self.display = pygame.display.set_mode(value,HWSURFACE|DOUBLEBUF)
  
      def setScale(self, value=1.0):
          """
          Põe o valor da escala, onde o '1.0' é o o tamanho original,se value menor que ou igual à'0.0'
          a scale não é alterada
          """
          if value <= 0.0:
              return
          self.scale = value
  
      def getScale(self):
          """Retorna o valor da escala"""
          return self.scale
  
      def setPpm(self,value = 1.0):
          """
          Põe o valor da ppm(pixel por metro), onde o '0.0' é o o tamanho original,se value menor que ou igual à'0.0'
          a scale não é alterada
          """
          if value <= 0.0:
              return
          self.ppm = value
  
      def getPpm(self):
          """Retorna o valor da ppm, o padrão é 70"""
          return self.ppm
  
      def setMusicVolume(self, value):
          """
          define o valor do volume do som,varia entre inteiro de 0-10
          """
          if value > 10:
              value = 10
          elif value < 0:
              value = 0
          self.musicVolume = value
  
  
      def setFxMusicVolume(self, value):
          """
          define o valor do volume dos efeitos sonoros,varia entre inteiro de 0-10
          """
          if value > 10:
              value = 10
          elif value < 0:
              value = 0
          self.fxVolume = value
      """retorna se teve quit"""
      def getQuit(self):
          return self.hasQuit
  
      def getScaleTime(self):
          """
          Retorna a escala do tempo '0.0' é parado, '1.0' normal,
          essa escala pode variar livremente entre os reais positivo
          """
          return self.scaleTime
  
  
      def getMusicVolume(self):
          """
          Retorna o volume de musica '0' é mudo, '10' maximo,
          """
          return self.musicVolume
  
  
      def getFxVolume(self):
          """
          Retorna o volume dos efeitos sonoros '0' é mudo, '10' maximo,
          """
          return self.fxVolume
  
  
      def getDisplay(self):
          """
          Retorna o display do pygame,
          """
          return self.display
  
  
      def getWidth(self):
          """
          Retorna o comprimento da tela em pixels
          """
          return self.width
  
  
      def getHeight(self):
          """
          Retorna o altura da tela em pixels
          """
          return self.height
  
  
      def waitFrame(self):
          """
          espera um determinado, até o frame terminar em tempo de (1/fps) e retorna o tempo em segundos
          """
          return self.clock.tick(self.fps)/1000
  
      def changeFps(self,newFPS = 24):
          """
          muda o valor do fps
          """
          self.fps = newFPS
  
  
      def getEvent(self):
          """pega e retorna os eventos no pygame"""
          self.event = pygame.event.get()
          return self.event
  
  
      def getEventList(self):
          "retorna os eventos no pygame"
          return self.event
  
      """espera um determinado tempo(1/fps), pega esse tempo e põe no deltaTime"""
      def waitFrame(self):  # espera um determinado tempo(1/fps)
          self.deltaTime = self.clock.tick(self.fps) / 1000
  
      """Retorna o tempo entre os frames"""
      def getDeltaTime(self):
          return self.deltaTime
  
      """update o display"""
      def displayUpdate(self,rect = []):
          self.display.update(rect)
  
      """para redesenhar o display inteiro"""
      def displayFlip(self, rect=[]):
          self.display.flip()
  
      """inicia o loop infinito do jogo"""
      def start(self):
          while not self.hasQuit:
              self.gameScene.updateScene()
  
          self.quit()
  
      def quit(self):
          "fecha o jogo"
          pygame.quit()
  
  """
  imageManager é uma classe que altera outros objetos de imagem,não a si mesmo
  """
  class ImageManager:
  
      def scaleImage(image, scale = 1.0):
          "retorna uma imagem que crresponde a 'image',escalonada"
          if scale == 1.0:
              return
          ScaledImage = pygame.transform.smoothscale(image,(int(scale*image.get_width()),
                                                            int(scale*image.get_height())))
          return ScaledImage
  
  
      def cutImage(image,shown = ((0.0,1.0) , (0.0,1.0))):
          "retorna a imagem correspondente à 'image' cortada com o indice do shown '0' significa 'x' "
          CutImage = pygame.transform.chop(image,(shown[0][0]*image.get_width(),shown[1][0]*image.get_height(),
                                                  shown[0][1]*image.get_width(),shown[1][1]*image.get_height()))
          return CutImage
  
      def drawImage(image, pos = (0.0,0.0), game = None):
          "prepara o desenho da imagem, e retorna o rect que determina a area que tera que ser redesenhada"
          rect = image.rect()
          return game.getDisplay().blit(image,(int(pos[0] - rect.center[0]),int(pos[1] - rect.center[1])))
  
  """
  classe image é feito para armazenar as imagens na memoria,escalona-las,
  corta-las, e retornar os blitRect para a função update do display desenha-las na região desejada
  """
  class Image:
      def __init__(self,local):
          self.local = local #local onde a imagem se encontra na pasta do jogo
          self.anchor = [0.0,0.0]
          self.scale = 1.0
          self.blitRect = []
          """retangulo que determina a regigão que o display irá redesenhar,será  
                                             usada para imagens que n são redesenhadas todos os frames"""
          if not local == "":
              self.Image = pygame.image.load(local).convert_alpha()
              self.Rect = self.Image.get_rect()
              self.anchor = [self.Rect.center[0], self.Rect.center[1]]
  
      def setAnchor(self, x, y):
          """determina a posição da ancora(ponto que fica constante,pode-se dizer que é o ponto central) da imagem"""
          self.anchor = [x, y]
  
      def getAnchor(self,x,y):
          """retorna a ancora"""
          return self.anchor
  
      def getScale(self):
          """retorna o valor da 'scale' da imagem"""
          return self.scale
      def reScale(self,scale = 1.0):
          """ré-escala o tamanho da imagem"""
          if scale == 1.0 and self.scale == 1.0:
              return
          self.Image = ImageManager.scaleImage(self.Image, scale/self.scale)
          self.scale = scale
  
      def drawImage(self,pos = (0.0,0.0), game = None):
          """irá retornar o rect do desenho anterios e o novo"""
          beforeRect = self.blitRect
          self.blitRect = game.getDisplay().blit(self.Image,(int(pos[0]-self.anchor[0]),
                                                             int(pos[1]-self.anchor[1])))
          return beforeRect + self.blitRect
  
  
      def changeImage(self,image):
          """altera o a imagem principal,podera ser por ela mesma reescalonada,cortada ou invertida"""
          self.Image = image.convert_alpha()
          self.Rect = self.Image.get_rect()
  
  
      def getImage(self):
          """retorna a imagem"""
          return self.Image
  
  
      def getRect(self):
          """retorna rect"""
          return self.Rect
  
  
      def getWidth(self):
          """retorna o comprimento da imagem"""
          return self.Image.get_width()
  
  
  
      def getHeight(self):
          """retorna a altura da imagem"""
          return self.Image.get_height()
  
  """classe de vetor de 2 dimensões, representa o vetor do mundo do jogo,
  onde soma,subtração de 'vector2' são possiveis,chama-a 'vector(float,float)'"""
  class Vector2:
      def __init__(self,x = 0.0,y = 0.0):
          self.vec = np.array((x,y))#usa numpy,pois ela possue operações de arrays e matrizes mais velozes
  
      def x(self):
          """retorna x"""
          return self.vec[0]
  
      def y(self):
          """retorna y"""
          return self.vec[1]
  
      def __add__(self, vec):
          """operação de soma, retorna self + vec"""
          return Vector2(self.x()+vec.x(), self.y()+vec.y())
  
      def __sub__(self,vec):
          """operação de subtração, retorna self - vec"""
          return Vector2(self.x()-vec.x(), self.y()-vec.y())
  
      def __mul__(self, multiplicador=1.0):
          """operação de multiplicação, retorna self*multiplicação.Talvez vá ter opção com matrizes"""
          return Vector2(self.x()*multiplicador, self.y()*multiplicador)
      def __truediv__(self, divisor = 1.0):
          """operação de divisão"""
          return Vector2(self.x()/divisor, self.y()/divisor)
  
      def __str__(self):
          """operação que retorna string para 'print'"""
          return "(" + str(self.x())+" ," +str(self.y()) + ")"
  
  
  """classe de tramsfor ele recebe uma determinada posição no mundo do jogo,
  onde soma,subtração de 'vector2' ou 'transform' são possiveis,chama-a 'transform(vector2(float,float))'"""
  class Transform:
      def __init__(self, position = Vector2(0.0,0.0)):
          """.position será publica"""
          self.position = position
  
      def getPostion(self):
          """retorna 'vector2' que representa a posição do objeto no mundo do jogo"""
          return self.position
  
      def getX(self):
          return self.position.x()
  
      def getY(self):
          return self.position.y()
  
  
  """classe gameObjeto sera classe super de todas as classe de instaancias"""
  
  class GameObject:
  
      def __init__(self, name="object", vec=Vector2(0.0, 0.0),gameScene = GameScene()):
          self.name = name
          self.gameScene = gameScene
          self.layer = 0
          self.transform = Transform(vec)
          #self.maxlength = self.getmaxlength()
          #self.tick = 0
          self.children = []
          self.parent = None
          # self.faceRight = True
          self.rect = []
          self.start()
  
      def destroy(self):
          self.parent.children.remove(self)
          self.parent = None
          for obj in self.children:
              obj.destroy()
          self.gameScene.getObjectList().remove(self)
          self.gameScene.getCamera().renderLayerObject[self.layer].remove(self)
          self.gameScene.camera.frameRects = self.gameScene.camera.frameRects + self.rect
      def positionToWorld(self):
          """retorna a posição do objeto em relação ao mundo"""
          if self.parent is None:
              return self.transform.position
          else:
              return self.transform.position + self.parent.positionToWorld()
  
      def getTransform(self):
          return self.transform
  
      '''
      def isFacingRight(self):
          """retorna uma booleana,caso esteja olhando para a direita será 'True'"""
          return self.faceRight
  
      def changeFacingRight(self,facing=True):
          """insere 'True' para faceRight"""
          self.faceRight = facing
      '''
  
      def xInvertion(self):
          """inverte o 'gameObject' em 'x' e altera o faceRight"""
          # self.faceRight = not self.faceRight
          if len(self.children) > 0:
              for child in self.children:
                  child.getTransform().position = child.getTransform().position - \
                                                  Vector2(2.0 * child.getTransform().position.x(), 0.0)
                  child.xInvertion()
  
      def yInvertion(self):
          """inverte o 'gameObject' em 'y' e altera o faceRight"""
          if len(self.children) > 0:
              for child in self.children:
                  child.getTransform().position = child.getTransform().position - \
                                                  Vector2(0.0, 2.0 * child.getTransform().position.y())
                  child.yInvertion()
  
      def start(self, game=None):
          """
          chama quando for inicializado
          """
          return
  
      def __Update(self, game=None):#não altere
          """
          Update é um metodo abstrata,que o objeto chama todo frame, em que ele estiver ativo,mas
          este não será alterado
          """
          self.update(game)
          self.updateChildren(game)
          return
  
      def updateChildren(self, game=None):#não pode ser alterado
          """
          faz o __Update de todos os childrens do objeto
          """
          for obj in self.children:
              obj.__Update(game)
  
      def update(self, game=None):
          """
          Update é um metodo abstrata,que o objeto chama todo frame, em que ele essta ativo
          ela vai ser responsavel de atualizar o objeto durante a gameScene.
          """
          return
  
      def render(self, positionInDisplay=(0.0, 0.0), game=None):
          """
          render é um metodo abstrata,que o objeto chama todo frame, em que ele essta ativo.
          ela vai ser responsavel de desenhar o objeto na camera na camera.
          """
          self.rect = []
          return rect
  
      def __add__(self, obj):
          """operação de adciona a lista de children"""
          obj.parent = self
          self.children.append(obj)
  
      def __sub__(self, obj):
          """operação de remove a lista de children"""
          self.children.remove(obj)
  
  """
  classe responsavel pela animação,não é responsavel pela alocação das imagens
  """
  class Animation:
      def __init__(self):
          self.frameList = []
          self.waitFrame = []
          self.i = 0
          self.frame = 1
          self.ended = False
          """tem que fazer os box colliders"""
      def setWaitFrameList(self,lista = []):
          """
          recebe a lista de wait frames, ela diz quantos frames do jogo tem que se passar,
          para passar a proxima imagem
          """
          if lista == []:
              if self.waitFrame == []:
                  n = len(self.frame)
                  i = 0
                  while i < n:
                      lista.append(1)
                      i = i + 1
          self.waitFrame = lista
  
      def setFrameList(self,lista = []):
          """pega a lista da animação"""
          self.frameList = lista
  
      def start(self):
          self.i = 0
          self.frame = self.waitFrame[self.i]
  
      def update(self):
          """atualiza o frame"""
          self.frame = self.frame - 1
          if self.frame == 0 and len(self.frameList[0]) == self.i + 1:
              self.ended = True
          elif self.frame < 0:
              self.i = self.i + 1
              self.frame = self.waitFrame[self.i]
  
      """animation ended?"""
      def hasEnded(self):
          return self.ended
  
      def render(self,positionInDisplay = (0.0,0.0), game = None):
          """desenha imagem"""
          return self.frameList[self.i].drawImage(positionInDisplay, game)
      def rescaleFrames(self,scale = 1.0):
          """muda o tamanho das imagens"""
          if scale == 1.0:
              return
          for img in self.frameList:
              img.reScale(scale*img.getScale())
  
  class AnimatorController:
      def __init__(self):
          self.animationList = []
          self.index = 0
          self.animation = Animation()
  
      def getAnimation(self):
          return self.animation
  
      def setAnimation(self, index = 0):
          self.index = index
          self.animation = self.animationList[index]
          self.animation.start()
  
      def hasAnimationEnded(self):
          return self.animationList[self.index].hasEnded()
  
  
  
  """classe GameObject,que será responsavel pela camera do jogo"""
  class Camera(GameObject):
      def __init__(self,name = "camera",vec = Vector2(0.0,0.0),game = Game()):
          super().__init__(name ,vec )
          self.game = game
          self.renderLayerObject = [[]]
          self.frameRects = []
          self.Ui = []
  
      """retorna a lista de rects"""
      def getRectList(self):
          return self.frameRects
  
      def getObjectListbyLayer(self):
          """
          retorna o 'delegate' das renders, para que a camera possa desenhar a imagem
          """
          return self.renderLayerObject
  
      def setLayers(self, lastlayer = 0):
          i = 0
          while i <= lastlayer:
              self.renderLayerObject.append([])
  
      """
      pega a lista de objetos
      """
      def setObjectListbyLayer(self,listObject = []):
          for obj in listObject:
              self.renderLayerObject[obj.layer].append(obj)
              self.setObjectListbyLayer(obj.children)
  
  
  
      def getPositionInDisplay(self,obj = GameObject()):
          """retorna a posição do objeto no display,retorna '(float,float)' para por no drawImage"""
          pos = obj.positionToWorld()
          camPos = self.positionToWorld()
          rel = pos - camPos
          scal = self.game.getPpm()*self.game.getScale()
          print(rel)
          print(scal*rel.x())
          return self.gameState.getWidth()/2 + scal*rel.x(), self.gameState.getHeight()/2 - scal*rel.y()
  
      """renderiza todos os objetos captados pela camera"""
      def render(self, positionInDisplay=(0.0, 0.0),game = None):
  
          for layer in self.renderLayerObject:
              for obj in layer:
                  self.frameRects = self.frameRects + obj.render(self.getPositionInDisplay(obj),self.game)
  
          self.game.displayUpdate(self.frameRects)
          self.frameRects = []
  
  
  """
  Classe que será usada para fazer as gameScenes,ela tem que receber o objeto 'Game'
  """
  
  class GameScene:
      def __init__(self,game = Game()):
          self.game = game
          self.gameObjectList = []
          self.camera = Camera("camera",Vector2(0.0,0.0),game)
          self.paused = False
          self.numLayers = 0
  
  
      """retorna a lista de objetos"""
      def getObjectList(self):
          return self.gameObjectList
  
      """retorna a camera"""
      def getCamera(self):
          return self.camera
  
      """faz alocações importantes para o funcionamento da scene"""
      def startScene(self):
          for obj in self.gameObjectList:
              obj.start(self.game)
  
          self.camera.setLayers(self.numLayers)
          self.camera.setObjectListbyLayer(self.gameObjectList)
  
      def updateScene(self):
          if not self.paused:
              for obj in self.gameObjectList:
                  obj.__Update(self.game)
              self.camera.render()
              self.game.waitFrame()
  
      def pauseGame(self):
          self.paused = True
  
      def unPauseGame(self):
          self.paused = False
  
  class Sound:
      def __init__(self, name = "selection"):
          self.sound = pygame.mixer.Sound('../res/Sound/'+ name +'.ogg')  
      def getSound(self):
          return self.sound
      def setSound(self,name):
          self.sound = pygame.mixer.Sound('../res/Sound/'+ name +'.ogg') 
          return self.sound
      def play(self):
          self.sound.play()
      def roundHit(self):
          self.sounds = []
          for i in range(0,12):
              self.sounds.append('Hit'+str(i+1))
          aux = randint(0,11)
          temp = self.setSound(self.sounds[aux])
          temp.play()
  
  class Music:
      def __init__(self, name = "intro"):
          self.music = pygame.mixer.music.load('../res/Music/'+ name +'.ogg')  
      def getMusic(self):
          return self.music
      def setMusic(self,name):
          self.music = pygame.mixer.music.load('../res/Music/'+ name +'.ogg') 
      def play(self,times = 1):
          pygame.mixer.music.play(times)
      def pause(self):
          pygame.mixer.music.pause()
      def resume(self):
          pygame.music.unpause()
      def volume(self, value=1):
          pygame.mixer.music.set_volume(value)
            
          
          
          