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