示例#1
0
文件: Scene.py 项目: fofix/fof-reborn
class Scene(BackgroundLayer, KeyListener):
    def __init__(self, engine):
        self.engine  = engine
        self.camera  = Camera()
        self.time    = 0.0
        self.player = self.engine.world.getPlayers()[0]
        self.controls = Player.Controls()

    def shown(self):
        self.engine.input.addKeyListener(self)

    def hidden(self):
        self.engine.input.removeKeyListener(self)

    def keyPressed(self, key, unicode):
        c = self.controls.keyPressed(key)
        if c:
            return True
        return False

    def keyReleased(self, key):
        c = self.controls.keyReleased(key)
        if c:
            return True
        return False

    def run(self, ticks):
        self.time += ticks / 50.0

    def render3D(self):
        pass

    def render(self, visibility, topMost):
        font = self.engine.data.font

        # render the scene
        try:
            glMatrixMode(GL_PROJECTION)
            glPushMatrix()
            glLoadIdentity()
            gluPerspective(60, self.engine.view.aspectRatio, 0.1, 1000)
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()

            glPushMatrix()
            self.camera.apply()

            self.render3D()
        finally:
            glPopMatrix()
            glMatrixMode(GL_PROJECTION)
            glPopMatrix()
            glMatrixMode(GL_MODELVIEW)
示例#2
0
class SongChooser(Layer, KeyListener):
  """Song choosing layer."""
  def __init__(self, engine, prompt = "", selectedSong = None, selectedLibrary = None):
    self.prompt         = prompt
    self.engine         = engine
    self.time           = 0
    self.accepted       = False
    self.selectedIndex  = 0
    self.camera         = Camera()
    self.cassetteHeight = .8
    self.cassetteWidth  = 4.0
    self.libraryHeight  = 1.2
    self.libraryWidth   = 4.0
    self.itemAngles     = None
    self.itemLabels     = None
    self.selectedOffset = 0.0
    self.cameraOffset   = 0.0
    self.selectedItem   = None
    self.song           = None
    self.songCountdown  = 1024
    self.songLoader     = None
    self.initialItem    = selectedSong
    self.library        = selectedLibrary
    self.searchText     = ""

    # Use the default library if this one doesn't exist
    if not self.library or not os.path.isdir(self.engine.resource.fileName(self.library)):
      self.library = Song.DEFAULT_LIBRARY

    self.loadCollection()
    self.engine.resource.load(self, "cassette",     lambda: Mesh(self.engine.resource.fileName("cassette.dae")), synch = True)
    self.engine.resource.load(self, "label",        lambda: Mesh(self.engine.resource.fileName("label.dae")), synch = True)
    self.engine.resource.load(self, "libraryMesh",  lambda: Mesh(self.engine.resource.fileName("library.dae")), synch = True)
    self.engine.resource.load(self, "libraryLabel", lambda: Mesh(self.engine.resource.fileName("library_label.dae")), synch = True)
    
    self.engine.loadSvgDrawing(self, "background", "cassette.svg")

  def loadCollection(self):
    self.loaded = False
    self.engine.resource.load(self, "libraries", lambda: Song.getAvailableLibraries(self.engine, self.library), onLoad = self.libraryListLoaded)
    showLoadingScreen(self.engine, lambda: self.loaded, text = _("Browsing Collection..."))

  def libraryListLoaded(self, libraries):
    self.engine.resource.load(self, "songs",     lambda: Song.getAvailableSongs(self.engine, self.library), onLoad = self.songListLoaded)

  def songListLoaded(self, songs):
    if self.songLoader:
      self.songLoader.cancel()
    self.selectedIndex = 0
    self.items         = self.libraries + self.songs
    self.itemAngles    = [0.0] * len(self.items)
    self.itemLabels    = [None] * len(self.items)
    self.loaded        = True
    self.searchText    = ""
    if self.initialItem is not None:
      for i, item in enumerate(self.items):
        if isinstance(item, Song.SongInfo) and self.initialItem == item.songName:
          self.selectedIndex =  i
          break
        elif isinstance(item, Song.LibraryInfo) and self.initialItem == item.libraryName:
          self.selectedIndex =  i
          break
    # Load labels for libraries right away
    for i, item in enumerate(self.items):
      if isinstance(item, Song.LibraryInfo):
        self.loadItemLabel(i)
    self.updateSelection()
    
  def shown(self):
    self.engine.input.addKeyListener(self, priority = True)
    self.engine.input.enableKeyRepeat()
    
  def hidden(self):
    if self.songLoader:
      self.songLoader.cancel()
    if self.song:
      self.song.fadeout(1000)
      self.song = None
    self.engine.input.removeKeyListener(self)
    self.engine.input.disableKeyRepeat()
    
  def getSelectedSong(self):
    if isinstance(self.selectedItem, Song.SongInfo):
      return self.selectedItem.songName

  def getSelectedLibrary(self):
    return self.library

  def loadItemLabel(self, i):
    # Load the item label if it isn't yet loaded
    item = self.items[i]
    if self.itemLabels[i] is None:
      if isinstance(item, Song.SongInfo):
        label = self.engine.resource.fileName(self.library, item.songName,    "label.png")
      else:
        assert isinstance(item, Song.LibraryInfo)
        label = self.engine.resource.fileName(item.libraryName, "label.png")
      if os.path.exists(label):
        self.itemLabels[i] = Texture(label)

  def updateSelection(self):
    self.selectedItem  = self.items[self.selectedIndex]
    self.songCountdown = 1024
    self.loadItemLabel(self.selectedIndex)
    
  def keyPressed(self, key, unicode):
    if not self.items or self.accepted:
      return

    c = self.engine.input.controls.getMapping(key)
    if c in [Player.KEY1] or key == pygame.K_RETURN:
      if self.matchesSearch(self.selectedItem):
        if isinstance(self.selectedItem, Song.LibraryInfo):
          self.library     = self.selectedItem.libraryName
          self.initialItem = None
          self.loadCollection()
        else:
          self.engine.view.popLayer(self)
          self.accepted = True
        if not self.song:
          self.engine.data.acceptSound.play()
    elif c in [Player.CANCEL, Player.KEY2]:
      if self.library != Song.DEFAULT_LIBRARY:
        self.initialItem = self.library
        self.library     = os.path.dirname(self.library)
        self.loadCollection()
      else:
        self.selectedItem = None
        self.engine.view.popLayer(self)
        self.accepted = True
      if not self.song:
        self.engine.data.cancelSound.play()
    elif c in [Player.UP, Player.ACTION1]:
      if self.matchesSearch(self.items[self.selectedIndex]):
        while 1:
          self.selectedIndex = (self.selectedIndex - 1) % len(self.items)
          if self.matchesSearch(self.items[self.selectedIndex]):
            break
      self.updateSelection()
      if not self.song:
        self.engine.data.selectSound.play()
    elif c in [Player.DOWN, Player.ACTION2]:
      if self.matchesSearch(self.items[self.selectedIndex]):
        while 1:
          self.selectedIndex = (self.selectedIndex + 1) % len(self.items)
          if self.matchesSearch(self.items[self.selectedIndex]):
            break
      self.updateSelection()
      if not self.song:
        self.engine.data.selectSound.play()
    elif key == pygame.K_BACKSPACE and not self.accepted:
      self.searchText = self.searchText[:-1]
    elif unicode and ord(unicode) > 31 and not self.accepted:
      self.searchText += unicode
      self.doSearch()
    return True

  def matchesSearch(self, item):
    if not self.searchText:
      return True
    if isinstance(item, Song.SongInfo):
      if self.searchText.lower() in item.name.lower() or self.searchText.lower() in item.artist.lower():
        return True
    elif isinstance(item, Song.LibraryInfo):
      if self.searchText.lower() in item.name.lower():
        return True
    return False

  def doSearch(self):
    if not self.searchText:
      return
      
    for i, item in enumerate(self.items):
      if self.matchesSearch(item):
          self.selectedIndex =  i
          self.updateSelection()
          break

  def songLoaded(self, song):
    self.songLoader = None

    if self.song:
      self.song.stop()
    
    song.setGuitarVolume(self.engine.config.get("audio", "guitarvol"))
    song.setBackgroundVolume(self.engine.config.get("audio", "songvol"))
    song.setRhythmVolume(self.engine.config.get("audio", "rhythmvol"))
    song.play()
    self.song = song

  def playSelectedSong(self):
    song = self.getSelectedSong()
    if not song:
      return
    
    if self.songLoader:
      self.songLoader.cancel()
      # Don't start a new song loader until the previous one is finished
      if self.songLoader.isAlive():
        self.songCountdown = 256
        return

    if self.song:
      self.song.fadeout(1000)

    self.songLoader = self.engine.resource.load(self, None, lambda: Song.loadSong(self.engine, song, playbackOnly = True, library = self.library),
                                                onLoad = self.songLoaded)
    
  def run(self, ticks):
    self.time += ticks / 50.0

    if self.songCountdown > 0:
      self.songCountdown -= ticks
      if self.songCountdown <= 0:
        self.playSelectedSong()

    d = self.cameraOffset - self.selectedOffset
    self.cameraOffset -= d * ticks / 192.0
    
    for i in range(len(self.itemAngles)):
      if i == self.selectedIndex:
        self.itemAngles[i] = min(90, self.itemAngles[i] + ticks / 2.0)
      else:
        self.itemAngles[i] = max(0,  self.itemAngles[i] - ticks / 2.0)
    
  def renderCassette(self, color, label):
    if not self.cassette:
      return

    if color:
      glColor3f(*color)

    glEnable(GL_COLOR_MATERIAL)
    self.cassette.render("Mesh_001")
    glColor3f(.1, .1, .1)
    self.cassette.render("Mesh")

    # Draw the label if there is one
    if label is not None:
      glEnable(GL_TEXTURE_2D)
      label.bind()
      glColor3f(1, 1, 1)
      glMatrixMode(GL_TEXTURE)
      glScalef(1, -1, 1)
      glMatrixMode(GL_MODELVIEW)
      self.label.render("Mesh_001")
      glMatrixMode(GL_TEXTURE)
      glLoadIdentity()
      glMatrixMode(GL_MODELVIEW)
      glDisable(GL_TEXTURE_2D)
  
  def renderLibrary(self, color, label):
    if not self.libraryMesh:
      return

    if color:
      glColor3f(*color)

    glEnable(GL_NORMALIZE)
    glEnable(GL_COLOR_MATERIAL)
    self.libraryMesh.render("Mesh_001")
    glColor3f(.1, .1, .1)
    self.libraryMesh.render("Mesh")

    # Draw the label if there is one
    if label is not None:
      glEnable(GL_TEXTURE_2D)
      label.bind()
      glColor3f(1, 1, 1)
      glMatrixMode(GL_TEXTURE)
      glScalef(1, -1, 1)
      glMatrixMode(GL_MODELVIEW)
      self.libraryLabel.render()
      glMatrixMode(GL_TEXTURE)
      glLoadIdentity()
      glMatrixMode(GL_MODELVIEW)
      glDisable(GL_TEXTURE_2D)
    glDisable(GL_NORMALIZE)
  
  def render(self, visibility, topMost):
    v = (1 - visibility) ** 2

    # render the background
    t = self.time / 100
    w, h, = self.engine.view.geometry[2:4]
    r = .5
    self.background.transform.reset()
    self.background.transform.translate(v * 2 * w + w / 2 + math.sin(t / 2) * w / 2 * r, h / 2 + math.cos(t) * h / 2 * r)
    self.background.transform.rotate(-t)
    self.background.transform.scale(math.sin(t / 8) + 2, math.sin(t / 8) + 2)
    self.background.draw()
      
    # render the item list
    try:
      glMatrixMode(GL_PROJECTION)
      glPushMatrix()
      glLoadIdentity()
      gluPerspective(60, self.engine.view.aspectRatio, 0.1, 1000)
      glMatrixMode(GL_MODELVIEW)
      glLoadIdentity()
      
      glEnable(GL_DEPTH_TEST)
      glDisable(GL_CULL_FACE)
      glDepthMask(1)
      
      offset = 10 * (v ** 2)
      self.camera.origin = (-10 + offset, -self.cameraOffset, 4   + offset)
      self.camera.target = (  0 + offset, -self.cameraOffset, 2.5 + offset)
      self.camera.apply()
      
      y = 0.0
      for i, item in enumerate(self.items):
        if not self.matchesSearch(item):
          continue
        
        c = math.sin(self.itemAngles[i] * math.pi / 180)
        
        if isinstance(item, Song.SongInfo):
          h = c * self.cassetteWidth + (1 - c) * self.cassetteHeight
        else:
          h = c * self.libraryWidth + (1 - c) * self.libraryHeight
        
        d = (y + h * .5 + self.camera.origin[1]) / (4 * (self.camera.target[2] - self.camera.origin[2]))

        if i == self.selectedIndex:
          self.selectedOffset = y + h / 2
          Theme.setSelectedColor()
        else:
          Theme.setBaseColor()
          
        glTranslatef(0, -h / 2, 0)
        
        glPushMatrix()
        if abs(d) < 1.2:
          if isinstance(item, Song.SongInfo):
            glRotate(self.itemAngles[i], 0, 0, 1)
            self.renderCassette(item.cassetteColor, self.itemLabels[i])
          elif isinstance(item, Song.LibraryInfo):
            glRotate(-self.itemAngles[i], 0, 0, 1)
            if i == self.selectedIndex:
              glRotate(self.time * 4, 1, 0, 0)
            self.renderLibrary(item.color, self.itemLabels[i])
        glPopMatrix()
        
        glTranslatef(0, -h / 2, 0)
        y += h
      glDisable(GL_DEPTH_TEST)
      glDisable(GL_CULL_FACE)
      glDepthMask(0)
      
    finally:
      glMatrixMode(GL_PROJECTION)
      glPopMatrix()
      glMatrixMode(GL_MODELVIEW)
    
    # render the song info
    self.engine.view.setOrthogonalProjection(normalize = True)
    font = self.engine.data.font
    
    try:
      glEnable(GL_BLEND)
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
      glEnable(GL_COLOR_MATERIAL)
      Theme.setBaseColor(1 - v)

      if self.searchText:
        text = _("Filter: %s") % (self.searchText) + "|"
        if not self.matchesSearch(self.items[self.selectedIndex]):
          text += " (%s)" % _("Not found")
        font.render(text, (.05, .7 + v), scale = 0.001)
      elif self.songLoader:
        font.render(_("Loading Preview..."), (.05, .7 + v), scale = 0.001)

      x = .6
      y = .15
      font.render(self.prompt, (x, .05 - v))

      Theme.setSelectedColor(1 - v)
      
      item  = self.items[self.selectedIndex]

      if self.matchesSearch(item):
        angle = self.itemAngles[self.selectedIndex]
        f = ((90.0 - angle) / 90.0) ** 2
        pos = wrapText(font, (x, y), item.name, visibility = f, scale = 0.0016)

        if isinstance(item, Song.SongInfo):
          Theme.setBaseColor(1 - v)
          wrapText(font, (x, pos[1] + font.getHeight() * 0.0016), item.artist, visibility = f, scale = 0.0016)

          Theme.setSelectedColor(1 - v)
          scale = 0.0011
          w, h = font.getStringSize(self.prompt, scale = scale)
          x = .6
          y = .5 + f / 2.0
          if len(item.difficulties) > 3:
            y = .42 + f / 2.0
            
          for d in item.difficulties:
            scores = item.getHighscores(d)
            if scores:
              score, stars, name = scores[0]
            else:
              score, stars, name = "---", 0, "---"
            Theme.setBaseColor(1 - v)
            font.render(unicode(d),     (x, y),           scale = scale)
            font.render(unicode(Data.STAR2 * stars + Data.STAR1 * (5 - stars)), (x, y + h), scale = scale * .9)
            Theme.setSelectedColor(1 - v)
            font.render(unicode(score), (x + .15, y),     scale = scale)
            font.render(name,       (x + .15, y + h),     scale = scale)
            y += 2 * h + f / 4.0
        elif isinstance(item, Song.LibraryInfo):
          Theme.setBaseColor(1 - v)
          if item.songCount == 1:
            songCount = _("One song in this library")
          else:
            songCount = _("%d songs in this library") % item.songCount
          wrapText(font, (x, pos[1] + 3 * font.getHeight() * 0.0016), songCount, visibility = f, scale = 0.0016)
    finally:
      self.engine.view.resetProjection()
示例#3
0
class SongChooser(Layer, KeyListener):
  """Song choosing layer."""
  def __init__(self, engine, prompt = "", selectedSong = None, selectedLibrary = None):
    self.prompt         = prompt
    self.engine         = engine
    self.time           = 0
    self.accepted       = False
    self.selectedIndex  = 0
    self.camera         = Camera()
    self.cassetteHeight = .8
    self.cassetteWidth  = 4.0
    self.libraryHeight  = 1.2
    self.libraryWidth   = 4.0
    self.itemAngles     = None
    self.itemLabels     = None
    self.selectedOffset = 0.0
    self.cameraOffset   = 0.0
    self.selectedItem   = None
    self.song           = None
    self.songCountdown  = 1024
    self.songLoader     = None
    self.initialItem    = selectedSong
    self.library        = selectedLibrary
    self.searchText     = ""
    self.playSongName   = ""

    self.cassetteShow   = not self.engine.config.get("game", "compactlist")
    self.autoPreview    = self.engine.config.get("game", "autopreview")
    self.artistSort     = self.engine.config.get("game", "artistsort")
    # Use the default library if this one doesn't exist
    if not self.library or not os.path.isdir(self.engine.resource.fileName(self.library)):
      self.library = Song.DEFAULT_LIBRARY

    self.loadCollection()
    self.engine.resource.load(self, "cassette",     lambda: Mesh(self.engine.resource.fileName("cassette.dae")), synch = True)
    self.engine.resource.load(self, "label",        lambda: Mesh(self.engine.resource.fileName("label.dae")), synch = True)
    self.engine.resource.load(self, "libraryMesh",  lambda: Mesh(self.engine.resource.fileName("library.dae")), synch = True)
    self.engine.resource.load(self, "libraryLabel", lambda: Mesh(self.engine.resource.fileName("library_label.dae")), synch = True)

    self.engine.loadSvgDrawing(self, "background", "cassette.svg")

  def loadCollection(self):
    self.loaded = False
    self.engine.resource.load(self, "libraries", lambda: Song.getAvailableLibraries(self.engine, self.library), onLoad = self.libraryListLoaded)
    showLoadingScreen(self.engine, lambda: self.loaded, text = _("Browsing Collection..."))

  def libraryListLoaded(self, libraries):
    self.engine.resource.load(self, "songs",     lambda: Song.getAvailableSongs(self.engine, self.library), onLoad = self.songListLoaded)


  def enumerateSongList(self,songs):
    for number, item in enumerate(self.items):
      if isinstance(item, Song.SongInfo) and self.initialItem == item.songName:
        self.selectedIndex =  number
        break
      elif isinstance(item, Song.LibraryInfo) and self.initialItem == item.libraryName:
        self.selectedIndex =  number
        break

  def enumerateLabel(self, songs):
    for number, item in enumerate(self.items):
      if isinstance(item, Song.LibraryInfo):
        self.loadItemLabel(number)
      else:
        pass


  def songListLoaded(self, songs):
    if self.songLoader:
      self.songLoader.cancel()
    else:
      pass

    self.selectedIndex = 0
    self.items         = self.libraries + self.songs
    self.itemAngles    = [0.0] * len(self.items)
    self.itemLabels    = [None] * len(self.items)
    self.loaded        = True
    self.searchText    = ""
    if self.initialItem is not None:
      enumerateSongsList(self,songs)

    # Load labels for libraries right away
    enumerateLabel(self,songs)
    self.updateSelection()

  def shown(self):
    self.engine.input.addKeyListener(self, priority = True)
    self.engine.input.enableKeyRepeat()

  def hidden(self):
    if self.songLoader:
      self.songLoader.cancel()
    else:
      pass

    if self.song:
      self.song.fadeout(1000)
      self.song = None
    else:
      pass

    self.engine.input.removeKeyListener(self)
    self.engine.input.disableKeyRepeat()

  def getSelectedSong(self):
    if isinstance(self.selectedItem, Song.SongInfo):
      return self.selectedItem.songName

  def getSelectedLibrary(self):
    return self.library

  def loadItemLabel(self, i):
    # Load the item label if it isn't yet loaded
    item = self.items[i]
    if self.itemLabels[i] is None:
      if isinstance(item, Song.SongInfo):
        label = self.engine.resource.fileName(self.library, item.songName,    "label.png")
      else:
        assert isinstance(item, Song.LibraryInfo)
        label = self.engine.resource.fileName(item.libraryName, "label.png")
      if os.path.exists(label):
        self.itemLabels[i] = Texture(label)

  def updateSelection(self):
    self.selectedItem  = self.items[self.selectedIndex]
    self.songCountdown = 1024
    self.loadItemLabel(self.selectedIndex)

  def keyPressed(self, key, unicode):
    if not self.items or self.accepted:
      return

    c = self.engine.input.controls.getMapping(key)
    if c in [Player.KEY1] or key == pygame.K_RETURN:
      if self.matchesSearch(self.selectedItem):
        if isinstance(self.selectedItem, Song.LibraryInfo):
          self.library     = self.selectedItem.libraryName
          self.initialItem = None
          self.loadCollection()
        else:
          self.engine.view.popLayer(self)
          self.accepted = True
        if not self.song and self.autoPreview:
          self.engine.data.acceptSound.play()
    elif c in [Player.CANCEL, Player.KEY2]:
      if self.library != Song.DEFAULT_LIBRARY:
        self.initialItem = self.library
        self.library     = os.path.dirname(self.library)
        self.loadCollection()
      else:
        self.selectedItem = None
        self.engine.view.popLayer(self)
        self.accepted = True
      if not self.song:
        self.engine.data.cancelSound.play()
    elif c in [Player.UP, Player.ACTION1]:
      if self.matchesSearch(self.items[self.selectedIndex]):
        while 1:
          self.selectedIndex = (self.selectedIndex - 1) % len(self.items)
          if self.matchesSearch(self.items[self.selectedIndex]):
            break
      self.updateSelection()
      if not self.song and self.autoPreview:
        self.engine.data.selectSound.play()
    elif c in [Player.DOWN, Player.ACTION2]:
      if self.matchesSearch(self.items[self.selectedIndex]):
        while 1:
          self.selectedIndex = (self.selectedIndex + 1) % len(self.items)
          if self.matchesSearch(self.items[self.selectedIndex]):
            break
      self.updateSelection()
      if not self.song and self.autoPreview:
        self.engine.data.selectSound.play()
    elif key == pygame.K_PAGEUP:
      if self.matchesSearch(self.items[self.selectedIndex]):
        while 1:
          self.selectedIndex = (self.selectedIndex - 10) % len(self.items)
          if self.matchesSearch(self.items[self.selectedIndex]):
            break
      self.updateSelection()
      if not self.song and self.autoPreview:
        self.engine.data.selectSound.play()
    elif key == pygame.K_PAGEDOWN:
      if self.matchesSearch(self.items[self.selectedIndex]):
        while 1:
          self.selectedIndex = (self.selectedIndex + 10) % len(self.items)
          if self.matchesSearch(self.items[self.selectedIndex]):
            break
      self.updateSelection()
      if not self.song and self.autoPreview:
       self.engine.data.selectSound.play()
    elif key == pygame.K_BACKSPACE and not self.accepted:
      self.searchText = self.searchText[:-1]
      self.doSearch()
    elif key == pygame.K_SPACE:
      if self.playSongName == self.getSelectedSong():
        self.playSongName = ""
        self.song.fadeout(1000)
      else:
        self.playSelectedSong(forceplay=1)
    elif key == pygame.K_HOME:
      self.artistSort = (self.artistSort + 1) % 2
      if self.artistSort:
        self.items.sort(key=lambda l: (l.artist.lower() if isinstance(l, Song.SongInfo) else '0'))
      else:
        self.items.sort(key=lambda l: (l.name.lower()))
    elif key == pygame.K_TAB:
      self.cassetteShow = not self.cassetteShow
    elif unicode and ord(unicode) > 31 and not self.accepted:
      self.searchText += str(unicode)
      self.doSearch()
    return True

  def matchesSearch(self, item):
    if not self.searchText:
      return True
    if isinstance(item, Song.SongInfo):
      if self.searchText.lower() in item.name.lower() or self.searchText.lower() in item.artist.lower():
        return True
    elif isinstance(item, Song.LibraryInfo):
      if self.searchText.lower() in item.name.lower():
        return True
    return False

  def doSearch(self):
    if not self.searchText:
      return

    for i, item in enumerate(self.items):
      if self.matchesSearch(item):
          self.selectedIndex =  i
          self.updateSelection()
          break

  def songLoaded(self, song):
    self.songLoader = None

    if self.song:
      self.song.stop()

    song.setGuitarVolume(self.engine.config.get("audio", "guitarvol"))
    song.setBackgroundVolume(self.engine.config.get("audio", "songvol"))
    song.setRhythmVolume(self.engine.config.get("audio", "rhythmvol"))
    song.play()
    self.song = song

  def playSelectedSong(self, forceplay = 0):
    song = self.getSelectedSong()
    if not song or (not self.autoPreview and not forceplay):
      return

    if self.songLoader:
      self.songLoader.cancel()
      # Don't start a new song loader until the previous one is finished
      if self.songLoader.isAlive():
        self.songCountdown = 256
        return

    if self.song:
      self.playSongName = ""
      self.song.fadeout(1000)
      self.song = None

    self.songLoader = self.engine.resource.load(self, None, lambda: Song.loadSong(self.engine, song, playbackOnly = True, library = self.library),
                                                onLoad = self.songLoaded)
    self.playSongName = self.getSelectedSong()

  def run(self, ticks):
    self.time += ticks / 50.0

    if self.songCountdown > 0:
      self.songCountdown -= ticks
      if self.songCountdown <= 0:
        self.playSelectedSong()

    d = self.cameraOffset - self.selectedOffset
    self.cameraOffset -= d * ticks / 192.0

    for i in range(len(self.itemAngles)):
      if i == self.selectedIndex:
        self.itemAngles[i] = min(90, self.itemAngles[i] + ticks / 2.0)
      else:
        self.itemAngles[i] = max(0,  self.itemAngles[i] - ticks / 2.0)

  def renderCassette(self, color, label):
    if not self.cassette:
      return

    if color:
      glColor3f(*color)

    glEnable(GL_COLOR_MATERIAL)
    self.cassette.render("Mesh_001")
    glColor3f(.1, .1, .1)
    self.cassette.render("Mesh")

    # Draw the label if there is one
    if label is not None:
      glEnable(GL_TEXTURE_2D)
      label.bind()
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
      glColor3f(1, 1, 1)
      glMatrixMode(GL_TEXTURE)
      glScalef(1, -1, 1)
      glMatrixMode(GL_MODELVIEW)
      self.label.render("Mesh_001")
      glMatrixMode(GL_TEXTURE)
      glLoadIdentity()
      glMatrixMode(GL_MODELVIEW)
      glDisable(GL_TEXTURE_2D)

  def renderLibrary(self, color, label):
    if not self.libraryMesh:
      return

    if color:
      glColor3f(*color)

    glEnable(GL_NORMALIZE)
    glEnable(GL_COLOR_MATERIAL)
    self.libraryMesh.render("Mesh_001")
    glColor3f(.1, .1, .1)
    self.libraryMesh.render("Mesh")

    # Draw the label if there is one
    if label is not None:
      glEnable(GL_TEXTURE_2D)
      label.bind()
      glColor3f(1, 1, 1)
      glMatrixMode(GL_TEXTURE)
      glScalef(1, -1, 1)
      glMatrixMode(GL_MODELVIEW)
      self.libraryLabel.render()
      glMatrixMode(GL_TEXTURE)
      glLoadIdentity()
      glMatrixMode(GL_MODELVIEW)
      glDisable(GL_TEXTURE_2D)
    glDisable(GL_NORMALIZE)

  def render(self, visibility, topMost):
    v = (1 - visibility) ** 2

    # render the background
    t = self.time / 100
    w, h, = self.engine.view.geometry[2:4]
    r = .5
    self.background.transform.reset()
    self.background.transform.translate(v * 2 * w + w / 2 + math.sin(t / 2) * w / 2 * r, h / 2 + math.cos(t) * h / 2 * r)
    self.background.transform.rotate(-t)
    self.background.transform.scale(math.sin(t / 8) + 2, math.sin(t / 8) + 2)
    self.background.draw()

    x = .6
    y = .15

    if self.cassetteShow:
      # render the item list
      try:
        glMatrixMode(GL_PROJECTION)
        glPushMatrix()
        glLoadIdentity()
        gluPerspective(60, self.engine.view.aspectRatio, 0.1, 1000)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        glEnable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)
        glDepthMask(1)

        offset = 10 * (v ** 2)
        self.camera.origin = (-10 + offset, -self.cameraOffset, 4   + offset)
        self.camera.target = (  0 + offset, -self.cameraOffset, 2.5 + offset)
        self.camera.apply()

        y = 0.0
        for i, item in enumerate(self.items):
          if not self.matchesSearch(item):
            continue

          c = math.sin(self.itemAngles[i] * math.pi / 180)

          if isinstance(item, Song.SongInfo):
            h = c * self.cassetteWidth + (1 - c) * self.cassetteHeight
          else:
            h = c * self.libraryWidth + (1 - c) * self.libraryHeight

          d = (y + h * .5 + self.camera.origin[1]) / (4 * (self.camera.target[2] - self.camera.origin[2]))

          if i == self.selectedIndex:
            self.selectedOffset = y + h / 2
            Theme.setSelectedColor()
          else:
            Theme.setBaseColor()

          glTranslatef(0, -h / 2, 0)

          glPushMatrix()
          if abs(d) < 1.2:
            if isinstance(item, Song.SongInfo):
              glRotate(self.itemAngles[i], 0, 0, 1)
              self.renderCassette(item.cassetteColor, self.itemLabels[i])
            elif isinstance(item, Song.LibraryInfo):
              glRotate(-self.itemAngles[i], 0, 0, 1)
              if i == self.selectedIndex:
                glRotate(self.time * 4, 1, 0, 0)
              self.renderLibrary(item.color, self.itemLabels[i])
          glPopMatrix()

          glTranslatef(0, -h / 2, 0)
          y += h

        glDisable(GL_DEPTH_TEST)
        glDisable(GL_CULL_FACE)
        glDepthMask(0)

      finally:
        glMatrixMode(GL_PROJECTION)
        glPopMatrix()
        glMatrixMode(GL_MODELVIEW)
    else:
      self.engine.view.setOrthogonalProjection(normalize = True)
      font = self.engine.data.font

      try:
        glEnable(GL_BLEND)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glEnable(GL_COLOR_MATERIAL)
        n = (0, 0)
        glBegin(GL_QUADS)
        glColor4f(0,0,0, .2)
        glVertex2f(.04, .02)
        glVertex2f(.04, .652)
        glVertex2f(.58, .652)
        glVertex2f(.58, .02)
        glEnd()
        glBegin(GL_LINE_LOOP)
        Theme.setBaseColor(1 - v)
        glVertex2f(.04, .02)
        glVertex2f(.04, .652)
        glVertex2f(.58, .652)
        glVertex2f(.58, .02)
        glEnd()

        length = 0
        select = 0
        it = 0
        for i, item in enumerate(self.items):
          if not self.matchesSearch(item):
            continue
          if isinstance(item, Song.SongInfo) or isinstance(item, Song.LibraryInfo):
            length+=1
            if self.selectedIndex == i:
              select = length

        Theme.setSelectedColor(1 - v)
        scale = 0.0008
        for i, item in enumerate(self.items):
          if not self.matchesSearch(item):
            continue
          if isinstance(item, Song.SongInfo) or isinstance(item, Song.LibraryInfo):
            it+=1
            if it >= (select - 5) or it >= (select + 11):
              if self.selectedIndex == i:
                glBegin(GL_QUADS)
                glColor4f(1,1,1, .1)
              else:
                glBegin(GL_QUADS)
                if it % 2 == 0:
                  glColor4f(0,0,0, .3)
                else:
                  glColor4f(0,0,0, .5)
              glVertex2f(.045, n[1] + font.getHeight() * scale)
              glVertex2f(.045, n[1] + 3*font.getHeight() * scale)
              glVertex2f(.575, n[1] + 3*font.getHeight() * scale)
              glVertex2f(.575, n[1] + font.getHeight() * scale)
              glEnd()
              Theme.setSelectedColor(1 - v)
              if self.artistSort:
                n = wrapText(font, (.05, n[1] + font.getHeight() * scale), item.artist if isinstance(item, Song.SongInfo) else _("Songs library"), 0.57, visibility = 0.0, scale = scale, hide = 1, hidestring = "...")
                Theme.setBaseColor(1 - v)
                n = wrapText(font, (.07, n[1] + font.getHeight() * scale), item.name, 0.57, visibility = 0.0, scale = scale, hide = 1, hidestring = "..." )
              else:
                n = wrapText(font, (.05, n[1] + font.getHeight() * scale), item.name, 0.57, visibility = 0.0, scale = scale, hide = 1, hidestring = "...")
                Theme.setBaseColor(1 - v)
                n = wrapText(font, (.07, n[1] + font.getHeight() * scale), item.artist if isinstance(item, Song.SongInfo) else _("Songs library"), 0.57, visibility = 0.0, scale = scale, hide = 1, hidestring = "..." )
              if ((n[1] + 2*font.getHeight() * scale) >= .65):
                break

        # draw the scrollbar
        perc = float(select - 1)/float(length - 1) if length > 1 else 0
        glBegin(GL_QUADS)
        Theme.setBaseColor(1 - v)
        glVertex2f(.575, .02 + .59*perc)
        Theme.setBaseColor((1 - v) * .3)
        glVertex2f(.575, .02 + .59*perc + .04)
        Theme.setBaseColor(1 - v)
        glColor4f(1,1,1,.8)
        Theme.setBaseColor((1 - v) * .3)
        glVertex2f(.586, .02 + .59*perc + .04)
        glVertex2f(.586, .02 + .59*perc)
        glEnd()

      finally:
        self.engine.view.resetProjection()
    self.engine.view.setOrthogonalProjection(normalize = True)
    font = self.engine.data.font
    # render the song info
    try:
      glEnable(GL_BLEND)
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
      glEnable(GL_COLOR_MATERIAL)
      Theme.setBaseColor(1 - v)

      if self.searchText:
        text = _("Filter: %s") % (self.searchText) + "|"
        if not self.matchesSearch(self.items[self.selectedIndex]):
          text += " (%s)" % _("Not found")
        font.render(text, (.05, .7 + v), scale = 0.001)
      elif self.songLoader:
        font.render(_("Loading Preview..."), (.05, .7 + v), scale = 0.001)
      elif not self.autoPreview:
        font.render(_("Press Space to Preview"), (.05, .7 + v), scale = 0.001)

      x = .6
      y = .15
      font.render(self.prompt, (x, .05 - v))

      Theme.setSelectedColor(1 - v)

      item  = self.items[self.selectedIndex]

      if self.matchesSearch(item):
        angle = self.itemAngles[self.selectedIndex]
        f = ((90.0 - angle) / 90.0) ** 2
        pos = wrapText(font, (x, y), item.name, visibility = f, scale = 0.0016)

        if isinstance(item, Song.SongInfo):
          Theme.setBaseColor(1 - v)
          wrapText(font, (x, pos[1] + font.getHeight() * 0.0016), item.artist, visibility = f, scale = 0.0016)

          Theme.setSelectedColor(1 - v)
          scale = 0.0011
          w, h = font.getStringSize(self.prompt, scale = scale)
          x = .6
          y = .5 + f / 2.0
          if len(item.difficulties) > 3:
            y = .42 + f / 2.0

          for d in item.difficulties:
            scores = item.getHighscores(d)
            if scores:
              score, stars, name = scores[0]
            else:
              score, stars, name = "---", 0, "---"
            Theme.setBaseColor(1 - v)
            font.render(unicode(d),     (x, y),           scale = scale)
            font.render(unicode(Data.STAR2 * stars + Data.STAR1 * (5 - stars)), (x, y + h), scale = scale * .9)
            Theme.setSelectedColor(1 - v)
            font.render(unicode(score), (x + .15, y),     scale = scale)
            font.render(name,       (x + .15, y + h),     scale = scale)
            y += 2 * h + f / 4.0
        elif isinstance(item, Song.LibraryInfo):
          Theme.setBaseColor(1 - v)
          if item.songCount == 1:
            songCount = _("One song in this library")
          else:
            songCount = _("%d songs in this library") % item.songCount
          wrapText(font, (x, pos[1] + 3 * font.getHeight() * 0.0016), songCount, visibility = f, scale = 0.0016)
    finally:
      self.engine.view.resetProjection()
示例#4
0
class World:
    def __init__(self, screen):
        self.screen = screen
        self.map = Map("map.txt")
        self._worldX = self.map.width
        self._worldY = self.map.height
        self.camera = Camera(self.map.width, self.map.height)
        self.init()

    def init(self):
        self.entities = pg.sprite.Group()
        self.street = pg.sprite.Group()
        self.grass = pg.sprite.Group()
        self.manager = ResourceManager.Manager()
        self.tileset = Tileset(self.manager)
        self.coords = []
        for row, tiles in enumerate(self.map.data):
            for col, tile in enumerate(tiles):
                if tile == 'a':
                    Street(self.tileset.getTile('street100'), col, row,
                           [self.entities, self.street])
                elif tile == 'b':
                    Street(self.tileset.getTile('street101'), col, row,
                           [self.entities, self.street])
                elif tile == 'c':
                    Street(self.tileset.getTile('street102'), col, row,
                           [self.entities, self.street])
                elif tile == 'd':
                    Street(self.tileset.getTile('street000'), col, row,
                           [self.entities, self.street])
                elif tile == 'e':
                    Street(self.tileset.getTile('street200'), col, row,
                           [self.entities, self.street])
                elif tile == 'f':
                    Street(self.tileset.getTile('street201'), col, row,
                           [self.entities, self.street])
                elif tile == 'g':
                    Street(self.tileset.getTile('street202'), col, row,
                           [self.entities, self.street])
                elif tile == 'h':
                    Street(self.tileset.getTile('street203'), col, row,
                           [self.entities, self.street])
                elif tile == 'i':
                    Street(self.tileset.getTile('street210'), col, row,
                           [self.entities, self.street])
                elif tile == 'j':
                    Street(self.tileset.getTile('street211'), col, row,
                           [self.entities, self.street])
                elif tile == 'k':
                    Street(self.tileset.getTile('street212'), col, row,
                           [self.entities, self.street])
                elif tile == 'l':
                    Street(self.tileset.getTile('street213'), col, row,
                           [self.entities, self.street])
                elif tile == 'm':
                    Street(self.tileset.getTile('street230'), col, row,
                           [self.entities, self.street])
                elif tile == 'n':
                    Street(self.tileset.getTile('street231'), col, row,
                           [self.entities, self.street])
                elif tile == 'o':
                    Street(self.tileset.getTile('street232'), col, row,
                           [self.entities, self.street])
                elif tile == 'p':
                    Street(self.tileset.getTile('street233'), col, row,
                           [self.entities, self.street])
                elif tile == 'q':
                    Street(self.tileset.getTile('street240'), col, row,
                           [self.entities, self.street])
                elif tile == '1':
                    Gras(self.tileset.getTile('gras000'), col, row,
                         self.entities)
                elif tile == '2':
                    Gras(self.tileset.getTile('gras000'), col, row,
                         [self.entities, self.grass])

        self.corners = [[(1 * TILESIZE, 2 * TILESIZE),
                         (1 * TILESIZE, 13 * TILESIZE)],
                        [(1 * TILESIZE, 13 * TILESIZE),
                         (7 * TILESIZE, 13 * TILESIZE)],
                        [(7 * TILESIZE, 13 * TILESIZE),
                         (7 * TILESIZE, 10 * TILESIZE)],
                        [(7 * TILESIZE, 10 * TILESIZE),
                         (9 * TILESIZE, 10 * TILESIZE)],
                        [(9 * TILESIZE, 10 * TILESIZE),
                         (9 * TILESIZE, 12 * TILESIZE)],
                        [(9 * TILESIZE, 12 * TILESIZE),
                         (16 * TILESIZE, 12 * TILESIZE)],
                        [(16 * TILESIZE, 12 * TILESIZE),
                         (16 * TILESIZE, 1 * TILESIZE)],
                        [(16 * TILESIZE, 1 * TILESIZE),
                         (9 * TILESIZE, 1 * TILESIZE)],
                        [(9 * TILESIZE, 1 * TILESIZE),
                         (9 * TILESIZE, 5 * TILESIZE)],
                        [(9 * TILESIZE, 5 * TILESIZE),
                         (7 * TILESIZE, 5 * TILESIZE)],
                        [(7 * TILESIZE, 5 * TILESIZE),
                         (7 * TILESIZE, 2 * TILESIZE)],
                        [(7 * TILESIZE, 2 * TILESIZE),
                         (1 * TILESIZE, 2 * TILESIZE)],
                        [(4 * TILESIZE, 4 * TILESIZE),
                         (5 * TILESIZE, 4 * TILESIZE)],
                        [(5 * TILESIZE, 4 * TILESIZE),
                         (5 * TILESIZE, 7 * TILESIZE)],
                        [(4 * TILESIZE, 4 * TILESIZE),
                         (4 * TILESIZE, 7 * TILESIZE)],
                        [(3 * TILESIZE, 7 * TILESIZE),
                         (4 * TILESIZE, 7 * TILESIZE)],
                        [(5 * TILESIZE, 7 * TILESIZE),
                         (11 * TILESIZE, 7 * TILESIZE)],
                        [(11 * TILESIZE, 7 * TILESIZE),
                         (11 * TILESIZE, 3 * TILESIZE)],
                        [(11 * TILESIZE, 3 * TILESIZE),
                         (14 * TILESIZE, 3 * TILESIZE)],
                        [(14 * TILESIZE, 3 * TILESIZE),
                         (14 * TILESIZE, 10 * TILESIZE)],
                        [(14 * TILESIZE, 10 * TILESIZE),
                         (11 * TILESIZE, 10 * TILESIZE)],
                        [(11 * TILESIZE, 10 * TILESIZE),
                         (11 * TILESIZE, 8 * TILESIZE)],
                        [(11 * TILESIZE, 8 * TILESIZE),
                         (5 * TILESIZE, 8 * TILESIZE)],
                        [(5 * TILESIZE, 8 * TILESIZE),
                         (5 * TILESIZE, 11 * TILESIZE)],
                        [(5 * TILESIZE, 11 * TILESIZE),
                         (3 * TILESIZE, 11 * TILESIZE)],
                        [(3 * TILESIZE, 11 * TILESIZE),
                         (3 * TILESIZE, 7 * TILESIZE)]]
        self.car = Car(self.manager, self.entities, self._worldX, self._worldY)
        self.line = Line(self.camera, self.car, self.corners)

    def processEvents(self):
        if (len(self.entities)):
            for entity in self.entities:
                entity.processEvents()
        else:
            print("World is empty!")

    def update(self):
        self.entities.update()
        # collision check
        collisions = pg.sprite.spritecollide(self.car, self.grass, False)
        if collisions:
            self.car.reset()
        self.camera.update(self.car)
        self.line.update()

    def render(self, screen):
        offset = self.camera.getOffset()
        # render tiles
        for entity in self.entities:
            screen.blit(entity.image, self.camera.apply(entity))
        # render lines
        # for line in self.corners:
        #     coords = [(line[0][0]+offset[0], line[0][1]+offset[1]),
        #               (line[1][0]+offset[0], line[1][1]+offset[1])]
        #     pg.draw.lines(screen, RED, True, coords, 2)
        self.line.render(screen)
示例#5
0
class Editor(Layer, KeyListener):
  """Song editor layer."""
  def __init__(self, engine, songName = None, libraryName = DEFAULT_LIBRARY):
    self.engine      = engine
    self.time        = 0.0
    self.guitar      = Guitar(self.engine, editorMode = True)
    self.controls    = Player.Controls()
    self.camera      = Camera()
    self.pos         = 0.0
    self.snapPos     = 0.0
    self.scrollPos   = 0.0
    self.scrollSpeed = 0.0
    self.newNotes    = None
    self.newNotePos  = 0.0
    self.song        = None
    self.engine.loadSvgDrawing(self, "background", "editor.svg")
    self.modified    = False
    self.songName    = songName
    self.libraryName = libraryName
    self.heldFrets   = set()

    mainMenu = [
      (_("Save Song"),                  self.save),
      (_("Set Song Name"),              self.setSongName),
      (_("Set Artist Name"),            self.setArtistName),
      (_("Set Beats per Minute"),       self.setBpm),
      (_("Estimate Beats per Minute"),  self.estimateBpm),
      (_("Set A/V delay"),              self.setAVDelay),
      (_("Set Cassette Color"),         self.setCassetteColor),
      (_("Set Cassette Label"),         self.setCassetteLabel),
      (_("Editing Help"),               self.help),
      (_("Quit to Main Menu"),          self.quit),
    ]
    self.menu = Menu(self.engine, mainMenu)

  def save(self):
    if not self.modified:
      Dialogs.showMessage(self.engine, _("There are no changes to save."))
      return

    def save():
      self.song.save()
      self.modified = False

    self.engine.resource.load(function = save)
    Dialogs.showLoadingScreen(self.engine, lambda: not self.modified, text = _("Saving..."))
    Dialogs.showMessage(self.engine, _("'%s' saved.") % self.song.info.name)

  def help(self):
    Dialogs.showMessage(self.engine, _("Editing keys: ") +
                                     _("Arrows - Move cursor, ") +
                                     _("Space - Play/pause song, ") +
                                     _("Enter - Make note (hold and move for long notes), ") +
                                     _("Delete - Delete note, ") +
                                     _("Page Up/Down - Change difficulty"))


  def setSongName(self):
    name = Dialogs.getText(self.engine, _("Enter Song Name"), self.song.info.name)
    if name:
      self.song.info.name = name
      self.modified = True

  def setArtistName(self):
    name = Dialogs.getText(self.engine, _("Enter Artist Name"), self.song.info.artist)
    if name:
      self.song.info.artist = name
      self.modified = True

  def setAVDelay(self):
    delay = Dialogs.getText(self.engine, _("Enter A/V delay in milliseconds"), unicode(self.song.info.delay))
    if delay:
      try:
        self.song.info.delay = int(delay)
        self.modified = True
      except ValueError:
        Dialogs.showMessage(self.engine, _("That isn't a number."))

  def setBpm(self):
    bpm = Dialogs.getText(self.engine, _("Enter Beats per Minute Value"), unicode(self.song.bpm))
    if bpm:
      try:
        self.song.setBpm(float(bpm))
        self.modified = True
      except ValueError:
        Dialogs.showMessage(self.engine, _("That isn't a number."))

  def estimateBpm(self):
    bpm = Dialogs.estimateBpm(self.engine, self.song, _("Tap the Space bar to the beat of the song. Press Enter when done or Escape to cancel."))
    if bpm is not None:
      self.song.setBpm(bpm)
      self.modified = True

  def setCassetteColor(self):
    if self.song.info.cassetteColor:
      color = Theme.colorToHex(self.song.info.cassetteColor)
    else:
      color = ""
    color = Dialogs.getText(self.engine, _("Enter cassette color in HTML (#RRGGBB) format."), color)
    if color:
      try:
        self.song.info.setCassetteColor(Theme.hexToColor(color))
        self.modified = True
      except ValueError:
        Dialogs.showMessage(self.engine, _("That isn't a color."))

  def setCassetteLabel(self):
    label = Dialogs.chooseFile(self.engine, masks = ["*.png"], prompt = _("Choose a 256x128 PNG format label image."))
    if label:
      songPath = self.engine.resource.fileName("songs", self.songName, writable = True)
      shutil.copyfile(label, os.path.join(songPath, "label.png"))
      self.modified = True

  def shown(self):
    self.engine.input.addKeyListener(self)

    if not self.songName:
      self.libraryName, self.songName = Dialogs.chooseSong(self.engine)

    if not self.songName:
      self.engine.view.popLayer(self)
      return

    self.engine.resource.load(self, "song", lambda: loadSong(self.engine, self.songName, seekable = True, library = self.libraryName))
    Dialogs.showLoadingScreen(self.engine, lambda: self.song, text = _("Loading song..."))

  def hidden(self):
    if self.song:
      self.song.stop()
    self.engine.input.removeKeyListener(self)
    self.engine.view.pushLayer(MainMenu.MainMenu(self.engine))

  def controlPressed(self, control):
    if not self.song:
      return

    if control == Player.UP:
      self.guitar.selectPreviousString()
    elif control == Player.DOWN:
      self.guitar.selectNextString()
    elif control == Player.LEFT:
      self.pos = self.snapPos - self.song.period / 4
    elif control == Player.RIGHT:
      self.pos = self.snapPos + self.song.period / 4
    elif control in KEYS:
      self.heldFrets.add(KEYS.index(control))
    elif control in [Player.ACTION1, Player.ACTION2]:
      self.newNotePos = self.snapPos
      # Add notes for the frets that are held down or for the selected string.
      if self.heldFrets:
        self.newNotes = [Note(f, self.song.period / 4) for f in self.heldFrets]
      else:
        self.newNotes = [Note(self.guitar.selectedString, self.song.period / 4)]
      self.modified   = True

  def controlReleased(self, control):
    if not self.song:
      return

    if control in [Player.ACTION1, Player.ACTION2] and self.newNotes and not self.heldFrets:
      self.newNotes = []
    elif control in KEYS:
      self.heldFrets.remove(KEYS.index(control))
      if not self.heldFrets and self.newNotes:
        self.newNotes = []

  def quit(self):
    self.engine.view.popLayer(self)
    self.engine.view.popLayer(self.menu)

  def keyPressed(self, key, unicode):
    c = self.engine.input.controls.getMapping(key)
    if c == Player.CANCEL:
      self.engine.view.pushLayer(self.menu)
    elif key == pygame.K_PAGEDOWN and self.song:
      d = self.song.difficulty
      v = difficulties.values()
      self.song.difficulty = v[(v.index(d) + 1) % len(v)]
    elif key == pygame.K_PAGEUP and self.song:
      d = self.song.difficulty
      v = difficulties.values()
      self.song.difficulty = v[(v.index(d) - 1) % len(v)]
    elif key == pygame.K_DELETE and self.song:
      # gather up all events that intersect the cursor and delete the ones on the selected string
      t1 = self.snapPos
      t2 = self.snapPos + self.song.period / 4
      e  = [(time, event) for time, event in self.song.track.getEvents(t1, t2) if isinstance(event, Note)]
      for time, event in e:
        if event.number == self.guitar.selectedString:
          self.song.track.removeEvent(time, event)
          self.modified = True
    elif key == pygame.K_SPACE and self.song:
      if self.song.isPlaying():
        self.song.stop()
      else:
        self.song.play(start = self.pos)
    c = self.controls.keyPressed(key)
    if c:
      self.controlPressed(c)
    return True

  def keyReleased(self, key):
    c = self.controls.keyReleased(key)
    if c:
      self.controlReleased(c)
    return True

  def run(self, ticks):
    self.time += ticks / 50.0

    if not self.song:
      return

    self.guitar.run(ticks, self.scrollPos, self.controls)

    if not self.song.isPlaying():
      if self.controls.getState(Player.RIGHT) and not self.controls.getState(Player.LEFT):
        self.pos += self.song.period * self.scrollSpeed
        self.scrollSpeed += ticks / 4096.0
      elif self.controls.getState(Player.LEFT) and not self.controls.getState(Player.RIGHT):
        self.pos -= self.song.period * self.scrollSpeed
        self.scrollSpeed += ticks / 4096.0
      else:
        self.scrollSpeed = 0
    else:
      self.pos = self.song.getPosition() - self.song.info.delay

    self.pos = max(0, self.pos)

    quarterBeat = int(self.pos / (self.song.period / 4) + .5)
    self.snapPos = quarterBeat * (self.song.period / 4)

    # note adding
    if self.newNotes:
      if self.snapPos < self.newNotePos:
        self.newNotes = []
      for note in self.newNotes:
        self.song.track.removeEvent(self.newNotePos, note)
        note.length = max(self.song.period / 4, self.snapPos - self.newNotePos)
        # remove all notes under the this new note
        oldNotes = [(time, event) for time, event in self.song.track.getEvents(self.newNotePos, self.newNotePos + note.length) if isinstance(event, Note)]
        for time, event in oldNotes:
          if event.number == note.number:
            self.song.track.removeEvent(time, event)
            if time < self.newNotePos:
              event.length = self.newNotePos - time
              self.song.track.addEvent(time, event)
        self.song.track.addEvent(self.newNotePos, note)

    if self.song.isPlaying():
      self.scrollPos = self.pos
    else:
      self.scrollPos = (self.scrollPos + self.snapPos) / 2.0

  def render(self, visibility, topMost):
    if not self.song:
      return

    v = 1.0 - ((1 - visibility) ** 2)

    # render the background
    t = self.time / 100 + 34
    w, h, = self.engine.view.geometry[2:4]
    r = .5
    self.background.transform.reset()
    self.background.transform.translate(w / 2 + math.sin(t / 2) * w / 2 * r, h / 2 + math.cos(t) * h / 2 * r)
    self.background.transform.rotate(-t)
    self.background.transform.scale(math.sin(t / 8) + 2, math.sin(t / 8) + 2)
    self.background.draw()

    self.camera.target = ( 2, 0, 5.5)
    self.camera.origin = (-2, 9, 5.5)

    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(60, 4.0 / 3.0, 0.1, 1000)
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    self.camera.apply()
    self.guitar.render(v, self.song, self.scrollPos, self.controls)

    self.engine.view.setOrthogonalProjection(normalize = True)
    font = self.engine.data.font

    try:
      Theme.setSelectedColor()

      w, h = font.getStringSize(" ")

      if self.song.isPlaying():
        status = _("Playing")
      else:
        status = _("Stopped")

      t = "%d.%02d'%03d" % (self.pos / 60000, (self.pos % 60000) / 1000, self.pos % 1000)
      font.render(t, (.05, .05 - h / 2))
      font.render(status, (.05, .05 + h / 2))
      font.render(unicode(self.song.difficulty), (.05, .05 + 3 * h / 2))

      Theme.setBaseColor()
      text = self.song.info.name + (self.modified and "*" or "")
      Dialogs.wrapText(font, (.5, .05 - h / 2), text)
    finally:
      self.engine.view.resetProjection()
示例#6
0
文件: Editor.py 项目: Gamer125/fofix
class Editor(Layer, KeyListener):
    """Song editor layer."""
    def __init__(self, engine, songName=None, libraryName=DEFAULT_LIBRARY):
        self.engine = engine
        self.time = 0.0
        self.guitar = Guitar(self.engine, editorMode=True)
        self.controls = Player.Controls()
        self.camera = Camera()
        self.pos = 0.0
        self.snapPos = 0.0
        self.scrollPos = 0.0
        self.scrollSpeed = 0.0
        self.newNotes = None
        self.newNotePos = 0.0
        self.song = None
        self.engine.loadSvgDrawing(self, "background", "editor.svg")
        self.modified = False
        self.songName = songName
        self.libraryName = libraryName
        self.heldFrets = set()

        self.spinnyDisabled = self.engine.config.get("game", "disable_spinny")

        mainMenu = [
            (_("Save Song"), self.save),
            (_("Set Song Name"), self.setSongName),
            (_("Set Artist Name"), self.setArtistName),
            (_("Set Beats per Minute"), self.setBpm),
            (_("Estimate Beats per Minute"), self.estimateBpm),
            (_("Set A/V delay"), self.setAVDelay),
            (_("Set Cassette Color"), self.setCassetteColor),
            (_("Set Cassette Label"), self.setCassetteLabel),
            (_("Editing Help"), self.help),
            (_("Quit to Main Menu"), self.quit),
        ]
        self.menu = Menu(self.engine, mainMenu)

    def save(self):
        if not self.modified:
            Dialogs.showMessage(self.engine,
                                _("There are no changes to save."))
            return

        def save():
            self.song.save()
            self.modified = False

        self.engine.resource.load(function=save)
        Dialogs.showLoadingScreen(self.engine,
                                  lambda: not self.modified,
                                  text=_("Saving..."))
        Dialogs.showMessage(self.engine,
                            _("'%s' saved.") % self.song.info.name)

    def help(self):
        Dialogs.showMessage(
            self.engine,
            _("Editing keys: ") + _("Arrows - Move cursor, ") +
            _("Space - Play/pause song, ") +
            _("Enter - Make note (hold and move for long notes), ") +
            _("Delete - Delete note, ") +
            _("Page Up/Down - Change difficulty"))

    def setSongName(self):
        name = Dialogs.getText(self.engine, _("Enter Song Name"),
                               self.song.info.name)
        if name:
            self.song.info.name = name
            self.modified = True

    def setArtistName(self):
        name = Dialogs.getText(self.engine, _("Enter Artist Name"),
                               self.song.info.artist)
        if name:
            self.song.info.artist = name
            self.modified = True

    def setAVDelay(self):
        delay = Dialogs.getText(self.engine,
                                _("Enter A/V delay in milliseconds"),
                                unicode(self.song.info.delay))
        if delay:
            try:
                self.song.info.delay = int(delay)
                self.modified = True
            except ValueError:
                Dialogs.showMessage(self.engine, _("That isn't a number."))

    def setBpm(self):
        bpm = Dialogs.getText(self.engine, _("Enter Beats per Minute Value"),
                              unicode(self.song.bpm))
        if bpm:
            try:
                self.song.setBpm(float(bpm))
                self.modified = True
            except ValueError:
                Dialogs.showMessage(self.engine, _("That isn't a number."))

    def estimateBpm(self):
        bpm = Dialogs.estimateBpm(
            self.engine, self.song,
            _("Tap the Space bar to the beat of the song. Press Enter when done or Escape to cancel."
              ))
        if bpm is not None:
            self.song.setBpm(bpm)
            self.modified = True

    def setCassetteColor(self):
        if self.song.info.cassetteColor:
            color = Theme.colorToHex(self.song.info.cassetteColor)
        else:
            color = ""
        color = Dialogs.getText(
            self.engine, _("Enter cassette color in HTML (#RRGGBB) format."),
            color)
        if color:
            try:
                self.song.info.setCassetteColor(Theme.hexToColor(color))
                self.modified = True
            except ValueError:
                Dialogs.showMessage(self.engine, _("That isn't a color."))

    def setCassetteLabel(self):
        label = Dialogs.chooseFile(
            self.engine,
            masks=["*.png"],
            prompt=_("Choose a 256x128 PNG format label image."))
        if label:
            songPath = self.engine.resource.fileName("songs",
                                                     self.songName,
                                                     writable=True)
            shutil.copyfile(label, os.path.join(songPath, "label.png"))
            self.modified = True

    def shown(self):
        self.engine.input.addKeyListener(self)

        if not self.songName:
            self.libraryName, self.songName = Dialogs.chooseSong(self.engine)

        if not self.songName:
            self.engine.view.popLayer(self)
            return

        self.engine.resource.load(
            self, "song", lambda: loadSong(self.engine,
                                           self.songName,
                                           seekable=True,
                                           library=self.libraryName))
        Dialogs.showLoadingScreen(self.engine,
                                  lambda: self.song,
                                  text=_("Loading song..."))

    def hidden(self):
        if self.song:
            self.song.stop()
        self.engine.input.removeKeyListener(self)
        #self.engine.view.pushLayer(MainMenu.MainMenu(self.engine))
        self.engine.view.pushLayer(
            self.engine.mainMenu
        )  #rchiav: use already-existing MainMenu instance

    def controlPressed(self, control):
        if not self.song:
            return

        if control in Player.UPS:
            self.guitar.selectPreviousString()
        elif control in Player.DOWNS:
            self.guitar.selectNextString()
        elif control in Player.LEFTS:
            self.pos = self.snapPos - self.song.period / 4
        elif control in Player.RIGHTS:
            self.pos = self.snapPos + self.song.period / 4
        elif control in KEYS:
            self.heldFrets.add(KEYS.index(control))
        elif control in Player.ACTION1S + Player.ACTION2S:
            self.newNotePos = self.snapPos
            # Add notes for the frets that are held down or for the selected string.
            if self.heldFrets:
                self.newNotes = [
                    Note(f, self.song.period / 4) for f in self.heldFrets
                ]
            else:
                self.newNotes = [
                    Note(self.guitar.selectedString, self.song.period / 4)
                ]
            self.modified = True

    def controlReleased(self, control):
        if not self.song:
            return

        if control in Player.ACTION1S + Player.ACTION2S and self.newNotes and not self.heldFrets:
            self.newNotes = []
        elif control in KEYS:
            self.heldFrets.remove(KEYS.index(control))
            if not self.heldFrets and self.newNotes:
                self.newNotes = []

    def quit(self):
        self.engine.view.popLayer(self)
        self.engine.view.popLayer(self.menu)

    def keyPressed(self, key, unicode):
        c = self.engine.input.controls.getMapping(key)
        if c in Player.CANCELS:
            self.engine.view.pushLayer(self.menu)
        elif key == pygame.K_PAGEDOWN and self.song:
            d = self.song.difficulty[0]
            v = difficulties.values()
            self.song.difficulty[0] = v[(v.index(d) + 1) % len(v)]
        elif key == pygame.K_PAGEUP and self.song:
            d = self.song.difficulty[0]
            v = difficulties.values()
            self.song.difficulty[0] = v[(v.index(d) - 1) % len(v)]
        elif key == pygame.K_DELETE and self.song:
            # gather up all events that intersect the cursor and delete the ones on the selected string
            t1 = self.snapPos
            t2 = self.snapPos + self.song.period / 4
            e = [(time, event)
                 for time, event in self.song.track[0].getEvents(t1, t2)
                 if isinstance(event, Note)]
            for time, event in e:
                if event.number == self.guitar.selectedString:
                    self.song.track[0].removeEvent(time, event)
                    self.modified = True
        elif key == pygame.K_SPACE and self.song:
            if self.song.isPlaying():
                self.song.stop()
            else:
                self.song.play(start=self.pos)
        c = self.controls.keyPressed(key)
        if c:
            self.controlPressed(c)
        return True

    def keyReleased(self, key):
        c = self.controls.keyReleased(key)
        if c:
            self.controlReleased(c)
        return True

    def run(self, ticks):
        self.time += ticks / 50.0

        if not self.song:
            return

        self.guitar.run(ticks, self.scrollPos, self.controls)

        if not self.song.isPlaying():
            if (self.controls.getState(Player.RIGHT)
                    or self.controls.getState(Player.PLAYER_2_RIGHT)
                ) and not (self.controls.getState(Player.LEFT)
                           or self.controls.getState(Player.PLAYER_2_LEFT)):
                self.pos += self.song.period * self.scrollSpeed
                self.scrollSpeed += ticks / 4096.0
            elif (self.controls.getState(Player.LEFT)
                  or self.controls.getState(Player.PLAYER_2_LEFT)
                  ) and not (self.controls.getState(Player.RIGHT)
                             or self.controls.getState(Player.PLAYER_2_RIGHT)):
                self.pos -= self.song.period * self.scrollSpeed
                self.scrollSpeed += ticks / 4096.0
            else:
                self.scrollSpeed = 0
        else:
            self.pos = self.song.getPosition()

        self.pos = max(0, self.pos)

        quarterBeat = int(self.pos / (self.song.period / 4) + .5)
        self.snapPos = quarterBeat * (self.song.period / 4)

        # note adding
        if self.newNotes:
            if self.snapPos < self.newNotePos:
                self.newNotes = []
            for note in self.newNotes:
                self.song.track[0].removeEvent(self.newNotePos, note)
                note.length = max(self.song.period / 4,
                                  self.snapPos - self.newNotePos)
                # remove all notes under the this new note
                oldNotes = [(time, event)
                            for time, event in self.song.track[0].getEvents(
                                self.newNotePos, self.newNotePos + note.length)
                            if isinstance(event, Note)]
                for time, event in oldNotes:
                    if event.number == note.number:
                        self.song.track[0].removeEvent(time, event)
                        if time < self.newNotePos:
                            event.length = self.newNotePos - time
                            self.song.track[0].addEvent(time, event)
                self.song.track[0].addEvent(self.newNotePos, note)

        if self.song.isPlaying():
            self.scrollPos = self.pos
        else:
            self.scrollPos = (self.scrollPos + self.snapPos) / 2.0

    def render(self, visibility, topMost):
        if not self.song:
            return

        v = 1.0 - ((1 - visibility)**2)

        # render the background
        t = self.time / 100 + 34
        w, h, = self.engine.view.geometry[2:4]
        r = .5

        if self.spinnyDisabled != True and Theme.spinnyEditorDisabled:
            self.background.transform.reset()
            self.background.transform.translate(
                w / 2 + math.sin(t / 2) * w / 2 * r,
                h / 2 + math.cos(t) * h / 2 * r)
            self.background.transform.rotate(-t)
            self.background.transform.scale(
                math.sin(t / 8) + 2,
                math.sin(t / 8) + 2)
        self.background.draw()

        self.camera.target = (2, 0, 5.5)
        self.camera.origin = (-2, 9, 5.5)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluPerspective(60, 4.0 / 3.0, 0.1, 1000)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()
        self.camera.apply()
        self.guitar.render(v, self.song, self.scrollPos, self.controls)

        self.engine.view.setOrthogonalProjection(normalize=True)
        font = self.engine.data.font

        try:
            Theme.setSelectedColor()

            w, h = font.getStringSize(" ")

            if self.song.isPlaying():
                status = _("Playing")
            else:
                status = _("Stopped")

            t = "%d.%02d'%03d" % (self.pos / 60000,
                                  (self.pos % 60000) / 1000, self.pos % 1000)
            font.render(t, (.05, .05 - h / 2))
            font.render(status, (.05, .05 + h / 2))
            font.render(unicode(self.song.difficulty[0]),
                        (.05, .05 + 3 * h / 2))

            Theme.setBaseColor()
            text = self.song.info.name + (self.modified and "*" or "")
            Dialogs.wrapText(font, (.5, .05 - h / 2), text)
        finally:
            self.engine.view.resetProjection()
示例#7
0
class SCREEN:

    def __init__(self, Height = 1280, Width = 1920, fps = 120, refresh = 10, Title = "Cat Mystery Dungeon"):
        pg.init()
        self.width = Width
        self.height = Height
        self.screen = pg.display.set_mode()
        pg.display.set_caption(Title)
        self.clock = pg.time.Clock()
        self.controllers = []
        self.off = controllerOFF()
        # camera size of screen
        self.camera = Camera(Width, Height)

        # TIMING SETUP #
        self.FPS = fps
        self.REFRESH = refresh
        self.NEXT_FRAME = self.gameClock()
        self.screenRefresh = False
        self.tooSmall = False

    def initLevel(self, levelPath):
        self.levelBuffer = loadObject(levelPath)
        self.level = self.levelBuffer.unpackLevel()
        self.level.setController(self.controllers[0])
        self.camera.mapSize(self.level.background.originalHeight, self.level.background.originalWidth)
        if self.level.background.originalWidth < self.width or self.level.background.originalHeight < self.height:
            self.updateDisplay = self.updateDisplaySmall
        else:
            self.updateDisplay = self.updateDisplay

    def nextLevel(self, index, x, y):
        self.screenFade()
        PC = self.level.PC
        # remove from current sprite update
        self.level.PC.kill()

        self.initLevel(self.level.exit[index])
        # add same PC to next level
        self.level.setPC(PC, x, y)

    def screenFade(self):
        self.level.setControllerContext(self.off)
        fade = pg.Surface((self.width, self.height))
        fade.fill((0,0,0))
        for alpha in range(0, 100, 2):
            fade.set_alpha(alpha)
            self.screen.blit(fade, (0,0))
            pg.display.flip()
            pg.time.delay(10)

    def setController(self, controller, commands = None):
        self.controllers.append(controller)

    def doCommands(self):
        self.level.doCommands(self.level.context)

    def run(self):
        # game loop - set self.playing = False to end the game
        self.playing = True
        while self.playing:
            self.level.dt = self.clock.tick(self.FPS) / 1000
            self.doCommands()
            self.update()
            self.updateDisplay()


    def update(self):
        # update portion of the game loop
        self.level.all_sprites.update()

        # multiplayer take the average of player coords?
        self.camera.update(self.level.PC)

    # redraw all sprites to screen
    def updateDisplay(self):
        # explore dirty sprites
        for layer in self.level.layers:
                self.drawScrollLayer(layer)
        self.level.static_sprites.draw()
        self.level.text_layer.draw()

        pg.display.flip()
        keys = pg.key.get_pressed()
        if (keys[pg.K_ESCAPE]):
            pg.quit()
            sys.exit()
        self.frameUpdate()

    def updateDisplaySmall(self):
        # needed if background too small
        self.screen.fill((0,0,0))
        # explore dirty sprites
        for layer in self.level.layers:
                self.drawScrollLayer(layer)
        self.level.static_sprites.draw(self.screen)
        self.level.text_layer.draw(self.screen)


        pg.display.flip()
        keys = pg.key.get_pressed()
        if (keys[pg.K_ESCAPE]):
            pg.quit()
            sys.exit()
        self.frameUpdate()

    def frameUpdate(self):
        # move next frame of animation
        if self.gameClock() > self.NEXT_FRAME:
            for sprite in self.level.animated_sprites:
                sprite.animate()
            self.NEXT_FRAME += self.REFRESH

    def gameClock(self):
        current_time = pg.time.get_ticks()
        return current_time

    # end program on esc -- otherwise update fames if needed
    def tick(self):
        pg.event.clear()
        keys = pg.key.get_pressed()
        if (keys[pg.K_ESCAPE]):
            self.quit()
        self.gameClock.tick(self.FPS)
        self.frameUpdate()
        return self.gameClock.get_fps()

    def drawScrollLayer(self, layer):
        for sprite in layer:
            # keep sprite pos static and draw with camera offsets
            self.screen.blit(sprite.image, self.camera.apply(sprite))

    def quit(self):
        pg.quit()
        sys.exit()
示例#8
0
def main():

    # Local Variables
    camera = Camera(complex_camera, GAME_WIDTH, WINDOW_HEIGHT)
    up = down = False       # Indicates the jumping movement
    left = right = False    # Indicates character direction
    game_is_running = True  # Indicates when program is running
    x = y = 0               # Sprite position variables
    score = 0               # Keeps track of the current score

    # Build the level
    for row in LEVEL:
        for col in row:

            # Barriers
            if col == "G":
                grass = Platform(x, y, "Grass")
                sprites_list.add(grass)
            if col == "D":
                dirt = Platform(x, y, "Dirt")
                sprites_list.add(dirt)
            if col == "L":
                left_edge = Platform(x, y, "Left Edge")
                sprites_list.add(left_edge)
            if col == "R":
                right_edge = Platform(x, y, "Right Edge")
                sprites_list.add(right_edge)
            if col == "T":
                two_edge = Platform(x, y, "Two Edge")
                sprites_list.add(two_edge)

            # Collectibles
            if col == "W":
                water = Sprite(RECYCLABLE_IMAGE, x, y, RECYCLABLE_WIDTH, RECYCLABLE_HEIGHT, 2)
                sprites_list.add(water)
            if col == "F":
                food = Sprite(NON_RECYCLABLE_IMAGE, x, y, NON_RECYCLABLE_WIDTH, NON_RECYCLABLE_HEIGHT, 3)
                sprites_list.add(food)

            # Reminders and Signs
            if col == "0":
                recycle_dash_sign = Sprite("sprites/Recycle Dash Sign.png", x, y, SIGN_WIDTH, BLOCK_DIMENSIONS, 4)
                sprites_list.add(recycle_dash_sign)
            if col == "1":
                left_button = Sprite("sprites/Left Button.png", x, y, BLOCK_DIMENSIONS, BLOCK_DIMENSIONS, 4)
                sprites_list.add(left_button)
            if col == "2":
                up_button = Sprite("sprites/Up Button.png", x, y, BLOCK_DIMENSIONS, BLOCK_DIMENSIONS, 4)
                sprites_list.add(up_button)
            if col == "3":
                right_button = Sprite("sprites/Right Button.png", x, y, BLOCK_DIMENSIONS, BLOCK_DIMENSIONS, 4)
                sprites_list.add(right_button)
            if col == "4":
                fly_indefinitely_sign = Sprite("sprites/Fly Indefinitely Sign.png", x, y, SIGN_WIDTH, BLOCK_DIMENSIONS, 4)
                sprites_list.add(fly_indefinitely_sign)
            if col == "5":
                collect_sign = Sprite("sprites/Collect Sign.png", x, y, SIGN_WIDTH, BLOCK_DIMENSIONS, 4)
                sprites_list.add(collect_sign)
            if col == "6":
                avoid_sign = Sprite("sprites/Avoid Sign.png", x, y, SIGN_WIDTH, BLOCK_DIMENSIONS, 4)
                sprites_list.add(avoid_sign)
            if col == "7":
                finish_sign = Sprite("sprites/Finish Sign.png", x, y, BLOCK_DIMENSIONS, BLOCK_DIMENSIONS, 4)
                sprites_list.add(finish_sign)
            x += BLOCK_DIMENSIONS
        y += BLOCK_DIMENSIONS
        x = 0

    # Game execution
    while True:

        # Read input
        for event in pygame.event.get():

            # If the game is closed, turn off the game
            if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
                sys.exit()

            # If a button is pressed...
            if event.type == pygame.KEYDOWN:
                # If A is pressed, set character direction left
                if event.key == pygame.K_a:
                    left = True
                # If D is pressed, set character direction right
                if event.key == pygame.K_d:
                    right = True
                # If W is pressed, jump
                if event.key == pygame.K_w:
                    up = True
                    down = False

            # Once the user lets go of the key, set character direction to nothing
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_d:
                    right = False
                if event.key == pygame.K_a:
                    left = False
                if event.key == pygame.K_w:
                    up = False
                down = True

        # Runs the actual game
        if game_is_running:

            # Determines if game is over
            if GAME_WIDTH - 200 < character.rect.centerx < GAME_WIDTH:
                game_is_running = False

            # Acquires the list of sprites
            sprites_to_modify = sprites_list.sprites()
            for sprite in sprites_to_modify:
                # Player manipulations
                if sprite.identity == 1:
                    # Get the list of objects colliding with the current sprite
                    hit_list = pygame.sprite.spritecollide(sprite, sprites_list, False)
                    # Update positions (using pixel-perfect movement)
                    if sprite.rect.bottom <= WINDOW_HEIGHT and sprite.rect.top >= 0 and sprite.rect.right <= GAME_WIDTH and\
                            sprite.rect.left >= 0:
                        # Movement
                        if sprite.identity == 1:
                            x_speed = 0
                            y_speed = 0
                            if left and not down:
                                x_speed += -PLAYER_SPEED
                            if right and not down:
                                x_speed += PLAYER_SPEED
                            if up:
                                y_speed -= PLAYER_SPEED
                            if down:
                                y_speed += PLAYER_SPEED

                            character.rect.centerx += x_speed
                            character.rect.centery += y_speed

                            # Collision handling for player
                            for hit in hit_list:
                                # If a barrier has been hit...
                                if hit.identity == 0:
                                    if down and not pygame.sprite.collide_rect(hit, character):
                                        y_speed += 5
                                        character.rect.centery += y_speed
                                    # If the player was moving right, move the player back
                                    if x_speed > 0:
                                        while pygame.sprite.collide_rect(character, hit):
                                            character.rect.centerx -= 1
                                    # If the player was moving left, move the player back
                                    if x_speed < 0:
                                        while pygame.sprite.collide_rect(character, hit):
                                            character.rect.centerx += 1
                                    # If the player was moving up, move the player down
                                    if y_speed < 0:
                                        while pygame.sprite.collide_rect(character, hit):
                                            character.rect.centery += 1
                                    # If the player was moving down, move the player up
                                    if y_speed > 0:
                                        while pygame.sprite.collide_rect(character, hit):
                                            character.rect.centery -= 1
                                            down = False
                                # If a collectible has been hit
                                if hit.identity == 2 or hit.identity == 3:
                                    hit.image = pygame.image.load("sprites/Blank.png")
                                    if hit.identity == 2:
                                        hit.identity = 4
                                        score += 1
                                    if hit.identity == 3:
                                        hit.identity = 4
                                        score -= 1

                    # Position adjustments
                    # If an object is destructible and it hits a wall, get rid of it
                    while sprite.rect.bottom > WINDOW_HEIGHT:
                        sprite.rect.y -= 1
                    while sprite.rect.top < 0:
                        sprite.rect.y += 1
                        down = False
                    while sprite.rect.right > GAME_WIDTH:
                        sprite.rect.x -= 1
                    while sprite.rect.left < 0:
                        sprite.rect.x += 1

            # Updates screen for every passing frame
            display_score(score)
            screen.fill((0, 0, 0))
            screen.blit(background.image, background.rect)
            camera.update(character)  # Allows camera to follow the player

            # Draw everything over the .draw() function (more control with camera)
            for sprite in sprites_list:
                screen.blit(sprite.image, camera.apply(sprite))
            screen.blit(character.image, camera.apply(character))
            pygame.display.flip()
            clock.tick(240)

        # Displays the Game Over screen
        else:
            game_over(score)
def game(level_folder, lives):
    global cameraX, cameraY
    global current_level
    pygame.init()
    screen = pygame.display.set_mode(DISPLAY, pygame.FULLSCREEN)            #Създаване на прозореца, задаване на fullscreen
    pygame.display.set_caption("Robopartans: The Game V1.2")                #Задаване на име на прозореца
    

    timer = pygame.time.Clock()                               #Инициализация на таймера                 
    pygame.mouse.set_visible(0)                               #Мишката не се вижда р рамките на прозореца
    up = left = right = running = False                       #Всички функции за движение са неактивни
    directory = 'files/Levels/'+level_folder
    bg = Surface((32,32))                                     #Създаване на фона

    entities = pygame.sprite.Group()
    player = Player(40, 40, directory, lives)                                   #Създаване на играча от класа Player
    platforms = []                                            #Инициализация на списък, в който ще се съхраняват всички активни платформи 
    enemy = []                                                #Инициализация на списък, в който ще се съхраняват всики противници на играча
    gears = []
    x = y = 0 
    path_to_map = 'files/Levels/'+level_folder+'/map.txt'
    f_level = open(path_to_map) 
    level_color = f_level.readline()                                               
    level = f_level.readlines()
    f_level.close()
    level_color = re.sub(r'\n', '', level_color)
    level_color = re.sub(r'\r', '', level_color)
    lives_image = pygame.image.load(directory+"/live.png")               #Задаване на картинка, която ще илюстрира животите на играча
    lives_image = pygame.transform.scale(lives_image, (32, 32))             
    
    bg.fill(Color(level_color))                                      #Цвят на фона

    for row in level:                   #Всички моделирани елементи се добавят в списъка с активните платформи
        for col in row:
            if col == "S":
                s = Score_line(x, y, directory)
                platforms.append(s)
                entities.add(s)
            if col == "p":
                p = Platforms(x, y, 108, 32,directory+"/beam_5.png")
                platforms.append(p)
                entities.add(p)
            if col == "P":
                P = Platforms(x, y, 251, 32,directory+"/beam_11.png")
                platforms.append(P)
                entities.add(P)
            if col == "G":
                g = Ground(x, y, directory)
                platforms.append(g)
                entities.add(g)
            if col == "T":
                t = Target(x, y)
                gears.append(t)
                entities.add(t)
                player.gears_count += 1
            if col == "B":
                b = Bad_Platform(x, y)
                platforms.append(b)
                entities.add(b)
            if col == "L":
                l = Live(x, y, directory)
                platforms.append(l)
                entities.add(l)
            if col == "V":
                v = Shield(x, y, directory)
                platforms.append(v)
                entities.add(v)
            if col == "I":
                i = Sword(x, y, directory)
                platforms.append(i)
                entities.add(i)
            if col == "E":
                e = Enemy(x, y, directory)
                enemy.append(e)
                entities.add(e)
            
           
            
            x += 32
        y += 32
        x = 0
    y = 0
        
    
    total_level_width  = (len(level[0])-2)*32                               
    total_level_height = len(level)*32
    camera = Camera(total_level_width, total_level_height)
    entities.add(player)                                                                        
    font = pygame.font.Font('files/Fonts/Adventure Subtitles.ttf',20)       #Форматиране на текста в score line-а 
    while 1:
        timer.tick(60)
    
        #Пояснителен текст        
        lives_text = font.render("LIVES:", 1,(255,255,255))
        
        for e in pygame.event.get():                     #Проверка за натиснати бутони 
            if e.type == QUIT: raise SystemExit, "QUIT"
            if e.type == KEYDOWN and e.key == K_ESCAPE:
                menu_game()
            if e.type == KEYDOWN and e.key == K_SPACE:
                up = True
            if e.type == KEYDOWN and e.key == K_LEFT:
                left = True
            if e.type == KEYDOWN and e.key == K_RIGHT:
                right = True

                
            if e.type == KEYUP and e.key == K_SPACE:
                up = False
            if e.type == KEYUP and e.key == K_RIGHT:
                right = False
            if e.type == KEYUP and e.key == K_LEFT:
                left = False
           

        # Извеждане на фона
        for y in range(32):
            for x in range(64):
               screen.blit(bg, (x*32 , y*32))
        
        #Текст, който показва прогреса по събиране на точки и броя скокове, които са направени


        # Ъпдейтване на играча и извеждане на всичко останало
        for i in enemy:
            i.update(True, platforms, total_level_height)         
        player.update(up, left, right, running, platforms, enemy, gears, total_level_height)
               
        for e in entities:
            screen.blit(e.image, camera.apply(e))
        camera.update(player, WIN_WIDTH, WIN_HEIGHT)
        

        screen.blit(lives_text, (900 , 4))
        
        for i in range(player.lives):
            screen.blit(lives_image, ((1100 - i*35), 0)) 
        #Текст, който показва прогреса по събиране на точки и броя скокове, които са направени
        scoretext = font.render("Score:"+str(player.score)+"/"+str(player.gears_count*16)+"  Jumps:"+str(player.jumps), 1,(255,255,255))
        screen.blit(scoretext, (10 , 4))
 

        #Проверка дали играта е свършила
        if player.score == player.gears_count*16: #Ако са събрани всички зъбни колела, изведи съобщение и се върни в началното меню        
            font_end = pygame.font.Font('files/Fonts/Adventure Subtitles.ttf',30)
            end_text_first_line = font_end.render("Congratulations! ", 1,(255,0,0)) 
            end_text_second_line = font_end.render("You collected maximum points! ", 1,(255,0,0)) 
            screen.blit(end_text_first_line, (500 , 350))
            screen.blit(end_text_second_line, (430 , 380)) 
            screen.blit(scoretext, (10 , 4)) 
            pygame.display.update() 
            pygame.time.delay(2000)        
            pygame.event.wait() 
            current_level+=1           
            game('Level_'+str(current_level), player.lives)
        if player.lives == 0:                   #Ако играча е загубил всичките си животи, изведи съобщение и се върни в началното меню
            font_end = pygame.font.Font('files/Fonts/Adventure Subtitles.ttf',30)
            end_text_first_line = font_end.render("Game Over! ", 1,(255,0,0)) 
            end_text_second_line = font_end.render("You died!", 1,(255,0,0)) 
            screen.blit(end_text_first_line, (500 , 350))
            screen.blit(end_text_second_line, (515 , 380))
            pygame.display.update()  
            pygame.time.delay(2000)        
            pygame.event.wait()            
            menu_game()

        pygame.display.update()    
class Scene(BackgroundLayer, KeyListener):
  def __init__(self, engine):
    self.engine  = engine
    self.actors  = []
    self.camera  = Camera()
    self.world   = None
    self.space   = None
    self.time    = 0.0
    self.actors  = []
    self.players = self.engine.world.getPlayers()
    self.controls = engine.input.controls
    
    #for simplification of theme writing
    self.fontDict         = self.engine.data.fontDict
    self.geometry         = self.engine.view.geometry[2:4]
    self.fontScreenBottom = self.engine.data.fontScreenBottom
    self.aspectRatio      = self.engine.view.aspectRatio
    self.drawImage        = self.engine.drawImage
    self.drawStarScore    = self.engine.drawStarScore
  
  def addPlayer(self, player):
    self.players.append(player)

  def removePlayer(self, player):
    self.players.remove(player)
    
  def run(self, ticks):
    self.time += ticks / 50.0

  def shown(self):
    self.engine.input.addKeyListener(self)

  def hidden(self):
    self.engine.input.removeKeyListener(self)

  def keyPressed(self, key, unicode):
    c = self.controls.keyPressed(key)
    if c:
      return True
    return False

  def keyReleased(self, key):
    c = self.controls.keyReleased(key)
    if c:
      return True
    return False
    
  def render3D(self):
    pass

  def render(self, visibility, topMost):
    font = self.engine.data.font

    # render the scene
    try:
      glMatrixMode(GL_PROJECTION)
      glPushMatrix()
      glLoadIdentity()
      gluPerspective(60, self.engine.view.aspectRatio, 0.1, 1000)
      glMatrixMode(GL_MODELVIEW)
      glLoadIdentity()
      
      glPushMatrix()
      self.camera.apply()
  
      self.render3D()
    finally:
      glPopMatrix()
      glMatrixMode(GL_PROJECTION)
      glPopMatrix()
      glMatrixMode(GL_MODELVIEW)
示例#11
0
class Scene(BackgroundLayer, KeyListener):
    def __init__(self, engine):
        self.engine  = engine
        self.actors  = []
        self.camera  = Camera()
        self.world   = None
        self.space   = None
        self.time    = 0.0
        self.actors  = []
        self.players = self.engine.world.getPlayers()
        self.controls = engine.input.controls

        #for simplification of theme writing
        self.fontDict         = self.engine.data.fontDict
        self.geometry         = self.engine.view.geometry[2:4]
        self.fontScreenBottom = self.engine.data.fontScreenBottom
        self.aspectRatio      = self.engine.view.aspectRatio
        self.drawImage        = self.engine.drawImage
        self.drawStarScore    = self.engine.drawStarScore

    def addPlayer(self, player):
        self.players.append(player)

    def removePlayer(self, player):
        self.players.remove(player)

    def run(self, ticks):
        self.time += ticks / 50.0

    def shown(self):
        self.engine.input.addKeyListener(self)

    def hidden(self):
        self.engine.input.removeKeyListener(self)

    def keyPressed(self, key, unicode):
        c = self.controls.keyPressed(key)
        if c:
            return True
        return False

    def keyReleased(self, key):
        c = self.controls.keyReleased(key)
        if c:
            return True
        return False

    def render3D(self):
        pass

    def render(self, visibility, topMost):
        # render the scene
        try:
            glMatrixMode(GL_PROJECTION)
            glPushMatrix()
            glLoadIdentity()
            gluPerspective(60, self.engine.view.aspectRatio, 0.1, 1000)
            glMatrixMode(GL_MODELVIEW)
            glLoadIdentity()

            glPushMatrix()
            self.camera.apply()

            self.render3D()
        finally:
            glPopMatrix()
            glMatrixMode(GL_PROJECTION)
            glPopMatrix()
            glMatrixMode(GL_MODELVIEW)
示例#12
0
            if e.key == K_LEFT:  # Движение влево
                left = False
            if e.key == K_RIGHT:  # Движение вправо
                right = False
            if e.key == K_UP:  # Движение вверх
                up = False

    screen.fill(Color(BACKGROUND_COLOR))  # Заливка видимой поверхности
    info_string.fill(Color("#000000"))

    target.update(hero)
    if target.is_Has and not target.is_Give:
        TEXT = "Голос: Принеси его мне"
    if target.is_Give and target.is_Has:
        TEXT = "Сонч: Спасибочки!!!!"
    if target.is_Fall and not target.is_Has:
        TEXT = "Сонч: Ты не принесла его((("

    hero.update(left, right, up, platforms, target)

    camera.update(hero)
    for s in sprite_group:
        screen.blit(s.image, camera.apply(s))

    info_string.blit(inf_font.render(TEXT, 1, (255, 255, 255)), (40, 5))

    window.blit(info_string, (0, 0))
    window.blit(screen, (0, 30))
    display.flip()  # Обновление всего на экране
    timer.tick(60)
示例#13
0
    def main_game(self):

        # Set the default control flags
        up = down = left = right = False
        exit_game = False
        walking = False

        self.load_level()  # Create the environment assets

        level_size = (len(self.level[0]) * self.block_size[0], len(self.level) * self.block_size[1])

        camera = Camera(level_size, self.window_size)
        mouse = Mouse(pygame.mouse.get_pos())
        mouse_clicked = False
        mosue_right_clicked = False

        while not exit_game:

            # Reset control flags each loop
            mouse_clicked = False
            mouse_right_clicked = False

            # Handle pygame
            self.clock.tick(self.fps)

            # Load title displaying true FPS
            current_fps = float(self.clock.get_fps())
            pygame.display.set_caption("The Forming | FPS: " + str(current_fps))

            # Event Handling
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()

                # Keydown events
                if event.type == KEYDOWN:
                    if event.key == K_UP or event.key == K_w:
                        up = True
                    elif event.key == K_DOWN or event.key == K_s:
                        down = True
                    elif event.key == K_LEFT or event.key == K_a:
                        left = True
                    elif event.key == K_RIGHT or event.key == K_d:
                        right = True
                if event.type == KEYUP:
                    if event.key == K_UP or event.key == K_w:
                        up = False
                    elif event.key == K_DOWN or event.key == K_s:
                        down = False
                    elif event.key == K_LEFT or event.key == K_a:
                        left = False
                    elif event.key == K_RIGHT or event.key == K_d:
                        right = False

                    # Mouse events
                    if event.type == MOUSEBUTTONDOWN:
                        if event.button == 1:
                            mouse_clicked = True
                        elif event.button == 3:
                            mouse_right_clicked = True
                    if event.type == MOUSEBUTTONUP:
                        if event.button == 1:
                            mouse_clicked = False
                        elif event.button == 3:
                            mouse_right_clicked = False

            # Update the entities
            camera.update(self.player)
            self.player.update(up, down, left, right, level_size)

            for tile in self.environment_entities:
                self.screen.blit(tile.image, camera.apply(tile))
            for player in self.player_entities:
                self.screen.blit(player.image, camera.apply(player))

            mouse.update(pygame.mouse.get_pos())

            pygame.display.update()
示例#14
0
    def start_game(self):
        player_spawn_x = WIDTH / 2.13
        player_spawn_y = HEIGHT / 2.25
        player = Player(self.entities, self.moving_colliders, player_spawn_x,
                        player_spawn_y, 100, 300)

        sheet = Location('Surface map.txt',
                         self.location_cells,
                         'surface',
                         0,
                         0,
                         player.speed,
                         collider_group=None)
        sheet.location_creating()
        terrain = Location('Terrain map.txt',
                           self.location_objects,
                           'terrain',
                           0,
                           0,
                           player.speed,
                           collider_group=self.static_colliders,
                           sheet=sheet)
        terrain.location_creating()

        camera = Camera()
        previous_camera_works = False

        while True:
            self.frame_tick = self.clock.tick() / 1000
            set_objects_ticks(self.frame_tick, player, camera)
            determine_direction(player)
            SCREEN.fill((0, 0, 0))

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.terminate_game()

            camera_works = camera.update(player)

            if not camera_works:
                if not previous_camera_works:
                    check_colliders(self.moving_colliders,
                                    self.static_colliders, self.frame_tick)
                else:
                    check_colliders(self.moving_colliders,
                                    self.static_colliders,
                                    self.frame_tick,
                                    clearing=True)
            else:
                if previous_camera_works:
                    check_colliders(self.static_colliders,
                                    self.moving_colliders,
                                    self.frame_tick,
                                    camera=camera,
                                    location_groups=[
                                        self.location_cells,
                                        self.location_objects
                                    ])
                else:
                    check_colliders(self.static_colliders,
                                    self.moving_colliders,
                                    self.frame_tick,
                                    clearing=True,
                                    camera=camera,
                                    location_groups=[
                                        self.location_cells,
                                        self.location_objects
                                    ])

            previous_camera_works = camera_works

            for cell in self.location_cells.get_sprites():
                camera.apply(cell)
            for obj in self.location_objects.get_sprites():
                camera.apply(obj)

            self.location_cells.draw(SCREEN)
            self.entities.update()
            self.entities.draw(SCREEN)
            self.location_objects.draw(SCREEN)

            if COLLIDERS_CONTOUR:
                draw_group_contour(self.moving_colliders, 'red', 2)
                draw_group_contour(self.static_colliders, 'red', 2)

            pygame.display.flip()
示例#15
0
def game():
    count = 0
    pl = Player((width * 1.7, height // 2), sprites_of_hero)
    moving_up = moving_down = moving_right = moving_left = False
    render(load_level('map'))
    camera = Camera()
    cursor_img = pygame.transform.scale(load_image('scope.png'), (22, 22))
    pygame.mouse.set_visible(False)
    cursor_img_rect = cursor_img.get_rect()
    while True:
        screen.fill((47, 40, 58))
        count += 1

        if moving_up:
            sprites_of_hero.update('up', count, wall)
        if moving_down:
            sprites_of_hero.update('down', count, wall)
        if moving_right:
            sprites_of_hero.update('right', count, wall)
        if moving_left:
            sprites_of_hero.update('left', count, wall)

        wall_sprites.draw(screen)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    bult = Bullet(
                        pl.rect.x + 31, pl.rect.y + 32,
                        calculate_vectors(event.pos[0] - pl.rect.x - 31,
                                          event.pos[1] - pl.rect.y - 32),
                        Bullet_sprites)
                    Bullets.append(bult)

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    moving_right = True
                elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    moving_left = True
                elif event.key == pygame.K_UP or event.key == pygame.K_w:
                    moving_up = True
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    moving_down = True
                elif event.key == pygame.K_ESCAPE:
                    pause()
            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_RIGHT or event.key == pygame.K_d:
                    moving_right = False
                elif event.key == pygame.K_LEFT or event.key == pygame.K_a:
                    moving_left = False
                elif event.key == pygame.K_UP or event.key == pygame.K_w:
                    moving_up = False
                elif event.key == pygame.K_DOWN or event.key == pygame.K_s:
                    moving_down = False

        Bullet_sprites.update(wall)
        Bullet_sprites.draw(screen)

        camera.update(pl)
        camera.apply(pl)
        for sprite in wall_sprites:
            camera.apply(sprite)

        for sprite in Bullet_sprites:
            camera.apply(sprite)

        sprites_of_hero.draw(screen)

        cursor_img_rect.center = pygame.mouse.get_pos()
        screen.blit(cursor_img, cursor_img_rect)

        pygame.display.flip()
        clock.tick(fps)
        if count == 30:
            count = 0
示例#16
0
class Level():
	def __init__(self, ln=1):
		random.seed()
		self.level_number = ln
		self.delay = 100  #A bit delay after level is completed
		music_veracruz = SFX(pygame.mixer.Sound("audio/music/veracruz.wav"))
		music_puebla = SFX(pygame.mixer.Sound("audio/music/puebla.wav"))
		music_tenochtitlan = SFX(pygame.mixer.Sound("audio/music/tenochtitlan.wav"))
		music_alvarado = SFX(pygame.mixer.Sound("audio/music/alvarado.wav"))
		music_cortes = SFX(pygame.mixer.Sound("audio/music/cortes.wav"))
		self.music = music_veracruz
		
		#Level 1--------------------------------------------------------
		if self.level_number == 1:
			#Level music
			self.music = music_veracruz
			
			#No gods
			self.Teo = []
			
			#Nahui
			self.Nahui = NahuiTochtli(1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 1
			self.Enem = []
			
			self.Enem.append(Spanish1(LEVEL_WIDTH*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
				
				
		#Level 2--------------------------------------------------------
		elif self.level_number == 2:
			#Level music
			self.music = music_veracruz
			
			#Gods
			self.Teo = [
				Quetzalcoatl((LEVEL_WIDTH / 2), LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 2
			self.Enem = []
			
			self.Enem.append(Spanish1(LEVEL_WIDTH/1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
		
		#Level 3--------------------------------------------------------
		elif self.level_number == 3:
			#Level music
			self.music = music_veracruz
			
			#Gods
			self.Teo = [
				Huitzilopochtli((LEVEL_WIDTH - 20), LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(LEVEL_WIDTH/2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 3
			self.Enem = []
			
			self.Enem.append(Spanish1(1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH-1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 4--------------------------------------------------------
		elif self.level_number == 4:
			#Level music
			self.music = music_veracruz
			
			#Gods
			self.Teo = [
				Ehecatl(20, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(LEVEL_WIDTH/2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 3
			self.Enem = []
			
			self.Enem.append(Spanish1(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/3*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 5--------------------------------------------------------
		elif self.level_number == 5:
			#Puebla music
			self.music = music_puebla
			
			#Gods
			self.Teo = [
				Tlaloc(LEVEL_WIDTH/2, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(LEVEL_WIDTH - 1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 4
			self.Enem = []
			
			self.Enem.append(Spanish1(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/4*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/4*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/4, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 6--------------------------------------------------------
		elif self.level_number == 6:
			#Puebla music
			self.music = music_puebla
			
			#Gods
			self.Teo = [
				Huitzilopochtli(LEVEL_WIDTH/2, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				Mictlantecuhtli(LEVEL_WIDTH/3, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(LEVEL_WIDTH - 1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 5
			self.Enem = []
			
			self.Enem.append(Spanish1(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 7--------------------------------------------------------
		elif self.level_number == 7:
			#Puebla music
			self.music = music_puebla
			
			#Gods
			self.Teo = [
				Huitzilopochtli(LEVEL_WIDTH/3*2, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(LEVEL_WIDTH/2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 5
			self.Enem = []
			
			self.Enem.append(Spanish3(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 8--------------------------------------------------------
		elif self.level_number == 8:
			#Puebla music
			self.music = music_tenochtitlan
			
			#Gods
			self.Teo = [
				Tlaloc(LEVEL_WIDTH/3*2, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(LEVEL_WIDTH/2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 6
			self.Enem = []
			
			self.Enem.append(Spanish3(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 9--------------------------------------------------------
		elif self.level_number == 9:
			#Tenochtiltan music
			self.music = music_tenochtitlan
			
			#Gods
			self.Teo = [
				Mictlantecuhtli(LEVEL_WIDTH/3, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				Ehecatl(LEVEL_WIDTH/3*2, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 5
			self.Enem = []
			
			self.Enem.append(Spanish1(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 10--------------------------------------------------------
		elif self.level_number == 10:
			#Tenochtiltan music
			self.music = music_alvarado
			
			#Gods
			self.Teo = [
				Xiuhtecuhtli(LEVEL_WIDTH/3, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				Quetzalcoatl(LEVEL_WIDTH/3*2, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 5
			self.Enem = []
			
			self.Enem.append(Alvarado(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/5*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			
		#Level 11--------------------------------------------------------
		elif self.level_number == 11:
			#Tenochtiltan music
			self.music = music_cortes
			
			#Gods
			self.Teo = [
				Xiuhtecuhtli(LEVEL_WIDTH/4, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				Tlaloc(LEVEL_WIDTH/4*2, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				Mictlantecuhtli(LEVEL_WIDTH/4*3, LEVEL_HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)),
				]
			
			#Nahui
			self.Nahui = NahuiTochtli(1, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT))
			
			#Enemies
			self.NoE = 6
			self.Enem = []
			
			self.Enem.append(Cortes(LEVEL_WIDTH, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/5*3, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish1(LEVEL_WIDTH/5*2, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish3(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
			self.Enem.append(Spanish2(LEVEL_WIDTH/5, HEIGHT, (LEVEL_WIDTH, LEVEL_HEIGHT)))
		
			
		
		for i in range(self.NoE):
			self.Enem[i].speed_x += float(random.randint(0,47) / 100)
		
		#Codex
		self.Cdx = Codex()
		
		#Prepare scene and camera
		self.level_background = Level_Sprite("bg/levels/"+str(self.level_number)+"/bg.png", (0, LEVEL_HEIGHT))
		self.level_foreground = Level_Sprite("bg/levels/"+str(self.level_number)+"/fg.png", (0, LEVEL_HEIGHT))
		self.hud = HUD((LEVEL_WIDTH, LEVEL_HEIGHT))
		self.camera = Camera(complex_camera, LEVEL_WIDTH, LEVEL_HEIGHT)
		
	def codex_update(self):
		self.Cdx.update()
	
	def spanish_move(self, time):
		for i in range(self.NoE):
			self.Enem[i].ai(self.Nahui, time)
			self.Enem[i].update()
	
	def nahui_move(self, time, key, events):
		self.Nahui.move(time,key)
		self.Nahui.update(None)
		for event in events:
			if event.type == KEYUP:
				self.Nahui.update(event.key)
	
	def gods_update(self):
		for god in self.Teo:
			god.update(self.Nahui, self.Enem)
	
	def control_attacks(self):
		for i in range(self.NoE):
			if abs(self.Enem[i].rect.centerx - self.Nahui.rect.centerx) <= 90:
				if self.Nahui.on_attack == True:
					self.Enem[i].hitBy(self.Nahui)
				if self.Enem[i].on_attack == True:
					#Attack when invocation
					if self.Nahui.on_invoke == False:
						self.Nahui.hitBy(self.Enem[i])
					elif self.Nahui.on_invoke == True:
						self.Enem[i].hitBy(self.Nahui)
						
			if abs(self.Enem[i].rect.centery - self.Nahui.rect.centery) < 50:
				if self.Nahui.on_invoke == False:
					if self.Enem[i].on_attack == True:
						self.Nahui.hitBy(self.Enem[i])
			
			for god in self.Teo:
				if god.on_sub_action == True:
					if god.sub_action_target == self.Enem[i]:
						if type(god) is Tlaloc:
							self.Enem[i].hitBy(god)
						if type(god) is Ehecatl:
							self.Enem[i].hitBy(god)
						if type(god) is Xiuhtecuhtli:
							if god.rect.bottom >= god.ground:
								self.Enem[i].hitBy(god)
								
	def control_invocations(self):
		for god in self.Teo:
			if pygame.sprite.collide_rect(self.Nahui, god):
				if self.Nahui.on_cover == True:
					if god.invokable == True:
						self.Nahui.invoke(god)
						god.invoked(self.Nahui)
	
	def focus_camera(self, screen):
		self.camera.update(screen, self.Nahui)
	
	def blit_all(self, screen):
		screen.blit(self.level_background.image, self.camera.apply(self.level_background, False))
		screen.blit(self.level_foreground.image, self.camera.apply(self.level_foreground))
		level_elements = back2front(self.Teo, self.Enem, self.Nahui)
		for i in level_elements:
			screen.blit(i.image, self.camera.apply(i))
	
	def hud_update(self, screen):
		self.hud.update(screen, self.Nahui, self.Teo, self.Cdx)
	
	def play_music(self):
		if not self.music.is_playing():
			self.music.get_sfx().play(-1)
	
	def stop_music(self):
		self.music.get_sfx().fadeout(100)
		
	def update(self, time, key, events, screen):
		self.play_music()
		self.codex_update()
		self.spanish_move(time)
		self.nahui_move(time, key, events)
		self.gods_update()
		self.control_attacks()
		self.control_invocations()
		self.focus_camera(screen)
		self.blit_all(screen)
		self.hud_update(screen)
	
	def completed(self):
		enem_health = []
		for enemy in self.Enem:
			enem_health.append(enemy.health)
			
		if self.Nahui.health <= 0 or all(h <= 0 for h in enem_health):
			if self.delay >= 1:
				self.delay -= 0.5
				return False
			else:
				self.stop_music()
				return True
		else:
			return False
	
	def victory(self):
		if self.Nahui.health > 0: return True
		else: return False