##################################################################### # -*- coding: iso-8859-1 -*- # # # # Frets on Fire # # Copyright (C) 2006 Sami Kyöstilä # # 2008 myfingershurt # # 2008 evilynux # # # # This program is free software; you can redistribute it and/or # # modify it under the terms of the GNU General Public License # # as published by the Free Software Foundation; either version 2 # # of the License, or (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with this program; if not, write to the Free Software # # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # # MA 02110-1301, USA. # ##################################################################### import pygame import OpenGL from OpenGL.GL import * from OpenGL.GLU import * import math #evilynux: needed for multi-OS file fetching import os #MFH - needed to check if running from compiled app or sources import sys from View import Layer from Input import KeyListener from Language import _ import Song import Version import Player import Config import Dialogs import Theme class Element: """A basic element in the credits scroller.""" def getHeight(self): """@return: The height of this element in fractions of the screen height""" return 0 def render(self, offset): """ Render this element. @param offset: Offset in the Y direction in fractions of the screen height """ pass class Text(Element): def __init__(self, font, scale, color, alignment, text): self.text = text self.font = font self.color = color self.alignment = alignment self.scale = scale self.size = self.font.getStringSize(self.text, scale = scale) def getHeight(self): return self.size[1] def render(self, offset): offset = (offset*4.0)/3.0 # akedrou - font rendering fix if self.alignment == "left": x = .1 elif self.alignment == "right": x = .9 - self.size[0] elif self.alignment == "center": x = .5 - self.size[0] / 2 glColor4f(*self.color) self.font.render(self.text, (x, offset), scale = self.scale) class Picture(Element): def __init__(self, engine, fileName, height): self.height = height self.engine = engine engine.loadImgDrawing(self, "drawing", fileName) def getHeight(self): return self.height def render(self, offset): offset = (offset*4.0)/3.0 #stump: get it back into alignment... self.drawing.transform.reset() w, h = self.engine.view.geometry[2:4] self.drawing.transform.translate(.5 * w, h - (.5 * self.height + offset) * h * float(w) / float(h)) self.drawing.transform.scale(1, -1) self.drawing.draw() # evilynux - Updated to latest MFH-Alarian mod. Alot changed compared to upstream FoF. # Removed song, our revamped MainMenu already provides songs. class Credits(Layer, KeyListener): """Credits scroller.""" def __init__(self, engine, songName = None): self.engine = engine self.time = 0.0 self.offset = 0.5 # akedrou - this seems to fix the delay issue, but I'm not sure why. Return here! self.speedDiv = 20000.0 self.speedDir = 1.0 self.doneList = [] self.themename = Config.get("coffee", "themename") Config.set("game", "selected_library", "songs") nf = self.engine.data.font bf = self.engine.data.bigFont ns = 0.002 bs = 0.001 hs = 0.003 c1 = (1, 1, .5, 1) c2 = (1, .75, 0, 1) self.text_size = nf.getLineSpacing(scale = hs) #akedrou - Translatable Strings: self.bank = {} self.bank['intro'] = [_("This mod was built on Alarian's mod,"), _("which was built on UltimateCoffee's Ultimate mod,"), _("which was built on RogueF's RF_mod 4.15,"), _("which was, of course, built on Frets on Fire 1.2.451,"), _("which was created by Unreal Voodoo")] self.bank['noOrder'] = [_("No Particular Order")] self.bank['coders'] = [_("Active Coders:")] self.bank['pastCoders'] = [_("Past Coders:")] self.bank['graphics'] = [_("Main Graphic Contributors:")] self.bank['translators']= [_("Translators:")] self.bank['Team Hero'] = [_("Team Hero:")] self.bank['careerMode'] = [_("Creators of Career Mode")] self.bank['honorary'] = [_("Honorary Credits to:")] self.bank['donations'] = [_("Donations to MFH")] self.bank['adonations'] = [_("Donations to akedrou")] self.bank['majorDonor'] = [_("Major Donations:")] self.bank['otherDonor'] = [_("Other Donations:")] self.bank['other'] = [_("Other Credits:")] self.bank['tutorial'] = [_("Jurgen FoF tutorial inspired by adam02"), _("Drum test song tutorial by Heka"), _("Bang Bang Mystery Man song tutorial is from the original FoF"), _("Drum Rolls practice tutorial by venom426")] self.bank['disclaimer'] = [_("If you see your work included in this game and you aren't"), _("in the credits, please leave a polite post stating what you"), _("did and when, as specific as possible."), _("If you can, please provide a link to your original posting"), _("of the work in question."), _("Then we can properly credit you.")] self.bank['thanks'] = [_("Thank you for your contribution.")] self.bank['oversight'] = [_("Please keep in mind that it is not easy to trace down and"), _("credit every single person who contributed; if your name is"), _("not included, it was not meant to slight you."), _("It was an oversight.")] # evilynux - Theme strings self.bank['themeCreators'] = [_("%s theme credits:") % self.themename] self.bank['themeThanks'] = [_("%s theme specific thanks:") % self.themename] # Languages self.bank['french'] = [_("French")] self.bank['french90'] = [_("French (reform 1990)")] self.bank['german'] = [_("German")] self.bank['italian'] = [_("Italian")] self.bank['piglatin'] = [_("Pig Latin")] self.bank['portuguese-b'] = [_("Portuguese (Brazilian)")] self.bank['russian'] = [_("Russian")] self.bank['spanish'] = [_("Spanish")] self.bank['swedish'] = [_("Swedish")] try: self.engine.loadImgDrawing(self, 'background', os.path.join('themes', self.themename, 'menu', 'credits.png')) try: self.engine.loadImgDrawing(self, 'topLayer', os.path.join('themes', self.themename, 'menu', 'creditstop.png')) except IOError: self.topLayer = None except IOError: self.topLayer = None self.background = None space = Text(nf, hs, c1, "center", " ") self.credits = [ Picture(self.engine, "fofix_logo.png", .10), Text(nf, ns, c1, "center", "%s" % Version.version()) ] # evilynux: Main FoFiX credits (taken from CREDITS). self.parseText("CREDITS") # evilynux: Theme credits (taken from data/themes//CREDITS). self.parseText(os.path.join('data', 'themes', self.themename, 'CREDITS')) self.credits.append(space) for i in self.bank['disclaimer']: self.credits.append( Text(nf, ns, c2, "center", i ) ) self.credits.append(space) for i in self.bank['thanks']: self.credits.append( Text(nf, ns, c2, "center", i ) ) self.credits.append(space) for i in self.bank['oversight']: self.credits.append( Text(nf, ns, c2, "center", i ) ) self.credits.extend( [ space, Text(nf, ns, c1, "left", _("Made with:")), Text(nf, ns, c2, "right", "Python " + sys.version.split(' ')[0]), #stump: the version that's actually in use Text(nf, bs, c2, "right", "http://www.python.org"), space, Text(nf, ns, c2, "right", "PyGame " + pygame.version.ver.replace('release', '')), #stump: the version that's actually in use Text(nf, bs, c2, "right", "http://www.pygame.org"), space, Text(nf, ns, c2, "right", "PyOpenGL " + OpenGL.__version__), #evilynux: the version that's actually in use Text(nf, bs, c2, "right", "http://pyopengl.sourceforge.net"), space, #Text(nf, ns, c2, "right", "Amanith Framework"), #Text(nf, bs, c2, "right", "http://www.amanith.org"), #space, Text(nf, ns, c2, "right", "Illusoft Collada module 1.4"), Text(nf, bs, c2, "right", "http://colladablender.illusoft.com"), space, Text(nf, ns, c2, "right", "Psyco specializing compiler"), Text(nf, bs, c2, "right", "http://psyco.sourceforge.net"), space, Text(nf, ns, c2, "right", "MXM Python Midi Package 0.1.4"), Text(nf, bs, c2, "right", "http://www.mxm.dk/products/public/pythonmidi"), space, space, Text(nf, bs, c1, "center", _("Source Code available under the GNU General Public License")), Text(nf, bs, c2, "center", "http://code.google.com/p/fofix"), space, space, Text(nf, bs, c1, "center", _("Copyright 2006, 2007 by Unreal Voodoo")), Text(nf, bs, c1, "center", _("Copyright 2008, 2009 by Team FoFiX")), space, space ]) # evilynux - Text parsing method. Provides some style functionnalities. def parseText(self, filename): nf = self.engine.data.font bf = self.engine.data.bigFont ns = 0.002 bs = 0.001 hs = 0.003 c1 = (1, 1, .5, 1) c2 = (1, .75, 0, 1) space = Text(nf, hs, c1, "center", " ") path = filename if not hasattr(sys,"frozen"): #MFH - add ".." to path only if running from sources - not if running from EXE path = os.path.join("..", path) if not os.path.exists(path): return file = open(path) for line in file: line = line.strip("\n") if line.startswith("=====") or line.startswith("-----"): continue if line == "": self.credits.append(space) elif line.startswith("`") and line.endswith("`"): line = line.strip("`") if line.startswith("%") and line.endswith("%"): line = line.strip("%") try: for text in self.bank[line]: self.credits.append( Text(nf, bs, c1, "left", "%s" % text) ) except KeyError: self.credits.append( Text(nf, bs, c1, "left", "%s" % line) ) else: self.credits.append( Text(nf, bs, c1, "left", "%s" % line) ) elif line.startswith("_") and line.endswith("_"): line = line.strip("_") if line.startswith("%") and line.endswith("%"): line = line.strip("%") try: for text in self.bank[line]: self.credits.append( Text(nf, ns, c2, "center", "%s" % text) ) except KeyError: self.credits.append( Text(nf, ns, c2, "center", "%s" % line) ) else: self.credits.append( Text(nf, ns, c2, "center", "%s" % line) ) elif line.startswith("=") and line.endswith("="): line = line.strip("=") if line.startswith("%") and line.endswith("%"): line = line.strip("%") try: for text in self.bank[line]: self.credits.append( Text(nf, ns, c1, "left", "%s" % text) ) except KeyError: self.credits.append( Text(nf, ns, c1, "left", "%s" % line) ) else: self.credits.append( Text(nf, ns, c1, "left", "%s" % line) ) else: if line.startswith("%") and line.endswith("%"): line = line.strip("%") try: for text in self.bank[line]: self.credits.append( Text(nf, ns, c2, "right", "%s" % text) ) except KeyError: self.credits.append( Text(nf, ns, c2, "right", "%s" % line) ) else: self.credits.append( Text(nf, ns, c2, "right", "%s" % line) ) def shown(self): self.engine.input.addKeyListener(self) def hidden(self): self.engine.input.removeKeyListener(self) self.engine.view.pushLayer(self.engine.mainMenu) #rchiav: use already-existing MainMenu instance def quit(self): self.engine.view.popLayer(self) def keyPressed(self, key, unicode): if self.engine.input.controls.getMapping(key) in (Player.menuYes + Player.menuNo) or key == pygame.K_RETURN or key == pygame.K_ESCAPE: self.quit() elif self.engine.input.controls.getMapping(key) in (Player.menuDown) or key == pygame.K_DOWN: #akedrou: so I was bored. if self.speedDiv > 1000.0: self.speedDiv -= 1000.0 if self.speedDiv < 1000.0: self.speedDiv = 1000.0 elif self.engine.input.controls.getMapping(key) in (Player.menuUp) or key == pygame.K_UP: if self.speedDiv < 30000.0: self.speedDiv += 1000.0 if self.speedDiv > 30000.0: self.speedDiv = 30000.0 elif self.engine.input.controls.getMapping(key) in (Player.key3s): self.speedDir *= -1 elif self.engine.input.controls.getMapping(key) in (Player.key4s): if self.speedDir != 0: self.speedDir = 0 else: self.speedDir = 1.0 return True def run(self, ticks): self.time += ticks / 50.0 #self.offset -= ticks / 7500.0 # evilynux - corresponds to scroll speed #self.offset -= ticks / 15000.0 #MFH - slowin it down - # evilynux - corresponds to scroll speed self.offset -= (ticks / self.speedDiv) * self.speedDir #akedrou - some credits fun. # evilynux - approximating the end of the list from the (mostly used font size * lines) #if self.offset < -( self.text_size * len(self.credits) ): if self.offset < -( self.text_size * len(self.credits) ) or self.offset > 1.5: #(MFH - adding 5% to estimated font height) undone: using larger scale for estimation. self.quit() if len(self.credits) == len(self.doneList): #akedrou - goofy workaround for string size glitch. self.quit() def render(self, visibility, topMost): v = 1.0 - ((1 - visibility) ** 2) # render the background t = self.time / 100 + 34 w, h, = self.engine.view.geometry[2:4] self.engine.view.setOrthogonalProjection(normalize = True) if self.background: wFactor = 640.000/self.background.width1() self.engine.drawImage(self.background, scale = (wFactor,-wFactor), coord = (w/2,h/2)) else: Dialogs.fadeScreen(.4) font = self.engine.data.font self.doneList = [] # render the scroller elements y = self.offset glTranslatef(-(1 - v), 0, 0) try: for element in self.credits: hE = element.getHeight() if y + hE > 0.0 and y < 1.0: element.render(y) if y + hE < 0.0: self.doneList.append(element) y += hE if y > 1.0: break if self.topLayer: wFactor = 640.000/self.topLayer.width1() hPos = h - ((self.topLayer.height1() * wFactor)*.75) if hPos < h * .6: hPos = h * .6 self.engine.drawImage(self.topLayer, scale = (wFactor,-wFactor), coord = (w/2,hPos)) finally: self.engine.view.resetProjection()