def run(self, ticks): self.time += ticks / 50.0 if self.engine.cmdPlay == 1: #evilynux - improve cmdline support self.newLocalGame(players=Config.get("game", "players"), mode1p=Config.get("player0", "mode_1p"), mode2p=Config.get("player1", "mode_2p")) elif self.engine.cmdPlay == 2: self.quit() if self.menumusic: #MFH if not self.song.isPlaying(): #re-randomize if self.files: i = random.randint(0, len(self.files) - 1) filename = self.files[i] sound = os.path.join("themes", self.themename, "sounds", filename) self.menumusic = True #self.song = Audio.Sound(self.engine.resource.fileName(sound)) self.song = Audio.Music( self.engine.resource.fileName(sound)) self.song.setVolume( self.engine.config.get("audio", "songvol")) #self.song.play(-1) self.song.play(0) #no loop else: self.menumusic = False
def __init__(self, engine, infoFileName, songTrackName, guitarTrackName, rhythmTrackName, noteFileName, scriptFileName=None): self.engine = engine self.info = SongInfo(infoFileName) self.tracks = [Track() for t in range(len(difficulties))] self.difficulty = difficulties[AMAZING_DIFFICULTY] self._playing = False self.start = 0.0 self.noteFileName = noteFileName self.bpm = None self.period = 0 # load the tracks if songTrackName: self.music = Audio.Music(songTrackName) self.guitarTrack = None self.rhythmTrack = None try: if guitarTrackName: self.guitarTrack = Audio.StreamingSound( self.engine, self.engine.audio.getChannel(1), guitarTrackName) except Exception, e: Log.warn("Unable to load guitar track: %s" % e)
def runMusic(self): if self.menumusic and not self.song.isPlaying(): #re-randomize if self.files: i = random.randint(0,len(self.files)-1) filename = self.files[i] sound = os.path.join("themes",self.themename,"sounds",filename) self.menumusic = True self.engine.menuMusic = True self.song = Audio.Music(self.engine.resource.fileName(sound)) self.song.setVolume(self.engine.config.get("audio", "menu_volume")) self.song.play(0) else: self.menumusic = False self.engine.menuMusic = False
def __init__(self, infoFileName, songTrackName, noteFileName): self.info = SongInfo(infoFileName) #self.track = Track() self._playing = False self.start = 0.0 self.noteFileName = noteFileName self.bpm = None self.period = 0 self.delay = self.info.getDelay() # load the tracks if songTrackName: self.music = Audio.Music(songTrackName) # load the notes if noteFileName: midiIn = midi.MidiInFile(MidiReader(self), noteFileName) midiIn.read()
class MainMenu(BackgroundLayer): def __init__(self, engine): self.engine = engine Log.debug("MainMenu class init (MainMenu.py)...") self.time = 0.0 self.nextLayer = None self.visibility = 0.0 self.active = False Player.practiceMode = False #myfingershurt: removing neck menu requirement: #self.neckMenuEnabled = False #self.neckMenuEnabled = Config.get("game", "neck_select_enabled") self.gfxVersionTag = Config.get("game", "gfx_version_tag") self.chosenNeck = Config.get("coffee", "neck_choose") Config.define("coffee", "max_neck", int, 1) #neck fallback to random if doesn't exist. try: # evilynux - first assume the chosenNeck contains the full filename engine.loadImgDrawing( self, "ok", os.path.join("necks", self.chosenNeck + ".png")) except IOError: try: engine.loadImgDrawing( self, "ok", os.path.join("necks", "Neck_" + self.chosenNeck + ".png")) except IOError: exists = 0 else: exists = 1 else: exists = 1 if exists == 0: #MFH - fallback logic now supports a couple valid default neck filenames #MFH - check for Neck_1 try: engine.loadImgDrawing(self, "ok", os.path.join("necks", "Neck_1.png")) exists = 1 except IOError: exists = 0 if exists == 1: Config.set("coffee", "neck_choose", "1") Log.warn("Chosen neck not valid, fallback Neck_1.png forced.") else: #MFH - check for defaultneck try: engine.loadImgDrawing( self, "ok", os.path.join("necks", "defaultneck.png")) exists = 1 except IOError: exists = 0 if exists == 1: Log.warn( "Chosen neck not valid, fallback defaultneck.png forced." ) Config.set("coffee", "neck_choose", "defaultneck") else: Log.warn( "Warning! Chosen neck not valid, fallbacks Neck_1.png and defaultneck.png also not valid! Crash imminent!" ) #Get theme self.theme = self.engine.data.theme self.themename = self.engine.data.themeLabel try: #blazingamer self.menux = Theme.menuX self.menuy = Theme.menuY except Exception, e: Log.warn("Unable to load Theme menuX / Y positions: %s" % e) self.menux = None self.menuy = None #MFH self.main_menu_scale = Theme.main_menu_scaleVar self.main_menu_vspacing = Theme.main_menu_vspacingVar if self.main_menu_scale == None: self.main_menu_scale = .5 if self.main_menu_vspacing == None: self.main_menu_vspacing = 0.09 try: self.engine.loadImgDrawing( self, "background", os.path.join("themes", self.themename, "menu", "mainbg.png")) except IOError: self.background = None self.engine.loadImgDrawing( self, "BGText", os.path.join("themes", self.themename, "menu", "maintext.png")) try: self.engine.loadImgDrawing( self, "optionsBG", os.path.join("themes", self.themename, "menu", "optionsbg.png")) except IOError: self.optionsBG = None self.engine.loadImgDrawing( self, "optionsPanel", os.path.join("themes", self.themename, "menu", "optionspanel.png")) #racer: added version tag if self.gfxVersionTag or Theme.versiontag == True: try: self.engine.loadImgDrawing( self, "version", os.path.join("themes", self.themename, "menu", "versiontag.png")) except IOError: try: self.engine.loadImgDrawing( self, "version", "versiontag.png" ) #falls back on default versiontag.png in data\ folder except IOError: self.version = None else: self.version = None #myfingershurt: random main menu music function, menu.ogg and menuXX.ogg (any filename with "menu" as the first 4 letters) filepath = self.engine.getPath( os.path.join("themes", self.themename, "sounds")) self.files = [] allfiles = os.listdir(filepath) for name in allfiles: if os.path.splitext(name)[1] == ".ogg": if string.find(name, "menu") > -1: self.files.append(name) if self.files: i = random.randint(0, len(self.files) - 1) filename = self.files[i] sound = os.path.join("themes", self.themename, "sounds", filename) self.menumusic = True self.song = Audio.Music(self.engine.resource.fileName(sound)) self.song.setVolume(self.engine.config.get("audio", "songvol")) self.song.play(0) #no loop else: self.menumusic = False #####======= Racer: New Main Menu ======#### self.opt_text_color = Theme.hexToColor(Theme.opt_text_colorVar) self.opt_selected_color = Theme.hexToColor(Theme.opt_selected_colorVar) if self.opt_text_color == None: self.opt_text_color = (1, 1, 1) if self.opt_selected_color == None: self.opt_selected_color = (1, 0.75, 0) newMultiplayerMenu = [ (_("Host Multiplayer Game"), self.hostMultiplayerGame), (_("Join Multiplayer Game"), self.joinMultiplayerGame), ] editorMenu = Menu(self.engine, [ (_("Edit Existing Song"), self.startEditor), (_("Import New Song"), self.startImporter), (_("Import GH(tm) Songs"), self.startGHImporter), ]) trainingMenu = [ (_("Tutorial"), self.showTutorial), (_("Practice"), lambda: self.newLocalGame(mode1p=1)), ] multPlayerMenu = [ (_("Face-Off"), lambda: self.newLocalGame(players=2)), (_("Pro Face-Off"), lambda: self.newLocalGame(players=2, mode2p=1)), (_("Party Mode"), lambda: self.newLocalGame(mode2p=2)), ] settingsMenu = Settings.SettingsMenu(self.engine) self.opt_bkg_x = Theme.opt_bkg_xPos self.opt_bkg_y = Theme.opt_bkg_yPos if self.opt_bkg_x == None: self.opt_bkg_x = 0 if self.opt_bkg_y == None: self.opt_bkg_y = 0 strCareer = "" strQuickplay = "" strSolo = "" strMultiplayer = "" strTraining = "" strSettings = "" strQuit = "" if self.theme == 0 or self.theme == 1: #GH themes = 6 main menu selections mainMenu = [ (_(strCareer), lambda: self.newLocalGame(mode1p=2)), (_(strQuickplay), lambda: self.newLocalGame()), (_(strMultiplayer), multPlayerMenu), (_(strTraining), trainingMenu), (_(strSettings), settingsMenu), (_(strQuit), self.quit), ] elif self.theme == 2: #RB themes = 5 main menu selections soloMenu = [ (_("Solo Tour"), lambda: self.newLocalGame(mode1p=2)), (_("Quickplay"), lambda: self.newLocalGame()), ] mainMenu = [ (_(strSolo), soloMenu), (_(strMultiplayer), multPlayerMenu), (_(strTraining), trainingMenu), (_(strSettings), settingsMenu), (_(strQuit), self.quit), ] self.menu = Menu(self.engine, mainMenu, onClose=lambda: self.engine.view.popLayer(self), pos=(12, 12), textColor=self.opt_text_color, selectedColor=self.opt_selected_color) engine.mainMenu = self #Points engine.mainMenu to the one and only MainMenu object instance
class MainMenu(BackgroundLayer): def __init__(self, engine): self.engine = engine self.logClassInits = Config.get("game", "log_class_inits") if self.logClassInits == 1: Log.debug("MainMenu class init (MainMenu.py)...") self.time = 0.0 self.nextLayer = None self.visibility = 0.0 self.active = False Player.practiceMode = False #myfingershurt: removing neck menu requirement: #self.neckMenuEnabled = False #self.neckMenuEnabled = Config.get("game", "neck_select_enabled") self.gfxVersionTag = Config.get("game", "gfx_version_tag") #self.tut = Config.get("game", "tut") self.chosenNeck = Config.get("game", "default_neck") exists = 0 #neck fallback to random if doesn't exist. try: # evilynux - first assume the chosenNeck contains the full filename engine.loadImgDrawing( self, "ok", os.path.join("necks", self.chosenNeck + ".png")) except IOError: try: engine.loadImgDrawing( self, "ok", os.path.join("necks", "Neck_" + self.chosenNeck + ".png")) except IOError: pass else: exists = 1 else: exists = 1 #MFH - fallback logic now supports a couple valid default neck filenames #MFH - check for Neck_1 if exists == 0: try: engine.loadImgDrawing(self, "ok", os.path.join("necks", "Neck_1.png")) except IOError: pass else: Config.set("game", "default_neck", "1") Log.warn( "Default chosen neck not valid; fallback Neck_1.png forced." ) exists = 1 #MFH - check for defaultneck if exists == 0: try: engine.loadImgDrawing(self, "ok", os.path.join("necks", "defaultneck.png")) except IOError: #we don't really need to be accepting this except... ...yea, sorry. raise IOError, "Default chosen neck not valid; fallbacks Neck_1.png and defaultneck.png also not valid!" else: Log.warn( "Default chosen neck not valid; fallback defaultneck.png forced." ) Config.set("game", "default_neck", "defaultneck") exists = 1 dPlayerConfig = None #Get theme self.theme = self.engine.data.theme self.themeCoOp = self.engine.data.themeCoOp self.themename = self.engine.data.themeLabel self.useSoloMenu = Theme.use_solo_submenu allowMic = True if self.theme == 0: allowMic = False try: #blazingamer self.menux = Theme.menuX self.menuy = Theme.menuY except Exception, e: Log.warn("Unable to load Theme menuX / Y positions: %s" % e) self.menux = None self.menuy = None self.rbmenu = Theme.menuRB #MFH self.main_menu_scale = Theme.main_menu_scaleVar self.main_menu_vspacing = Theme.main_menu_vspacingVar if self.main_menu_scale == None: self.main_menu_scale = .5 if self.main_menu_vspacing == None: self.main_menu_vspacing = 0.09 try: self.engine.loadImgDrawing( self, "background", os.path.join("themes", self.themename, "menu", "mainbg.png")) except IOError: self.background = None self.engine.loadImgDrawing( self, "BGText", os.path.join("themes", self.themename, "menu", "maintext.png")) try: self.engine.loadImgDrawing( self, "optionsBG", os.path.join("themes", self.themename, "menu", "optionsbg.png")) except IOError: self.optionsBG = None self.engine.loadImgDrawing( self, "optionsPanel", os.path.join("themes", self.themename, "menu", "optionspanel.png")) #racer: added version tag if self.gfxVersionTag or Theme.versiontag == True: try: self.engine.loadImgDrawing( self, "version", os.path.join("themes", self.themename, "menu", "versiontag.png")) except IOError: try: self.engine.loadImgDrawing( self, "version", "versiontag.png" ) #falls back on default versiontag.png in data\ folder except IOError: self.version = None else: self.version = None #myfingershurt: random main menu music function, menu.ogg and menuXX.ogg (any filename with "menu" as the first 4 letters) filepath = self.engine.getPath( os.path.join("themes", self.themename, "sounds")) self.files = [] allfiles = os.listdir(filepath) for name in allfiles: if os.path.splitext(name)[1] == ".ogg": if string.find(name, "menu") > -1: self.files.append(name) if self.files: i = random.randint(0, len(self.files) - 1) filename = self.files[i] sound = os.path.join("themes", self.themename, "sounds", filename) self.menumusic = True engine.menuMusic = True self.song = Audio.Music(self.engine.resource.fileName(sound)) self.song.setVolume(self.engine.config.get("audio", "menu_volume")) self.song.play(0) #no loop else: self.menumusic = False #####======= Racer: New Main Menu ======#### self.opt_text_color = Theme.hexToColor(Theme.opt_text_colorVar) self.opt_selected_color = Theme.hexToColor(Theme.opt_selected_colorVar) if self.opt_text_color == None: self.opt_text_color = (1, 1, 1) if self.opt_selected_color == None: self.opt_selected_color = (1, 0.75, 0) newMultiplayerMenu = [ (_("Host Multiplayer Game"), self.hostMultiplayerGame), (_("Join Multiplayer Game"), self.joinMultiplayerGame), ] editorMenu = Menu(self.engine, [ (_("Edit Existing Song"), self.startEditor), (_("Import New Song"), self.startImporter), (_("Import GH(tm) Songs"), self.startGHImporter), ]) trainingMenu = [ (_("Tutorials"), self.showTutorial), (_("Practice"), lambda: self.newLocalGame(mode1p=1)), ] self.opt_bkg_size = [float(i) for i in Theme.opt_bkg_size] strCareer = "" strQuickplay = "" strSolo = "" strMultiplayer = "" strTraining = "" strSettings = "" strQuit = "" if self.theme == 1 and self.themeCoOp: #Worldrave - Put GH Co-op ahead of FoFix co-op for GH based theme's. Made more sense. multPlayerMenu = [ (_("Face-Off"), lambda: self.newLocalGame(players=2, maxplayers=-1)), (_("Pro Face-Off"), lambda: self.newLocalGame(players=2, mode2p=1, maxplayers=-1) ), (_("GH Battle"), lambda: self.newLocalGame( players=2, mode2p=6, maxplayers=-1, allowDrum=False) ), #akedrou- so you can block drums (_("Party Mode"), lambda: self.newLocalGame(mode2p=2)), (_("Co-Op"), lambda: self.newLocalGame(players=2, mode2p=5)), (_("FoFiX Co-Op"), lambda: self.newLocalGame( players=2, mode2p=3, allowMic=allowMic) ), #Worldrave - Re-added this option for now. ] elif self.theme == 1 and not self.themeCoOp: multPlayerMenu = [ (_("Face-Off"), lambda: self.newLocalGame(players=2, maxplayers=-1)), (_("Pro Face-Off"), lambda: self.newLocalGame(players=2, mode2p=1, maxplayers=-1) ), (_("Party Mode"), lambda: self.newLocalGame(mode2p=2)), ] elif self.theme == 2: multPlayerMenu = [ (_("FoFiX Co-Op"), lambda: self.newLocalGame( players=2, mode2p=3, maxplayers=4, allowMic=allowMic)), (_("RB Co-Op"), lambda: self.newLocalGame( players=2, mode2p=4, maxplayers=4, allowMic=allowMic)), (_("GH Co-Op"), lambda: self.newLocalGame(players=2, mode2p=5, maxplayers=4)), (_("Face-Off"), lambda: self.newLocalGame(players=2, maxplayers=-1)), (_("Pro Face-Off"), lambda: self.newLocalGame(players=2, mode2p=1, maxplayers=-1) ), (_("Party Mode"), lambda: self.newLocalGame(mode2p=2)), ] else: multPlayerMenu = [ (_("FoFiX Co-Op"), lambda: self.newLocalGame( players=2, mode2p=3, allowMic=allowMic)), (_("Face-Off"), lambda: self.newLocalGame(players=2, maxplayers=-1)), (_("Pro Face-Off"), lambda: self.newLocalGame(players=2, mode2p=1, maxplayers=-1) ), (_("Party Mode"), lambda: self.newLocalGame(mode2p=2)), ] if self.useSoloMenu is None: if self.theme == 0 or self.theme == 1: #GH themes = 6 main menu selections self.useSoloMenu = False else: #RB themes = 5 main menu selections self.useSoloMenu = True if not self.useSoloMenu: mainMenu = [ (strCareer, lambda: self.newLocalGame(mode1p=2, allowMic=allowMic)), (strQuickplay, lambda: self.newLocalGame(allowMic=allowMic)), ((strMultiplayer, "multiplayer"), multPlayerMenu), ((strTraining, "training"), trainingMenu), ((strSettings, "settings"), self.settingsMenu), (strQuit, self.quit), ] else: soloMenu = [ (_("Solo Tour"), lambda: self.newLocalGame(mode1p=2, allowMic=allowMic)), (_("Quickplay"), lambda: self.newLocalGame(allowMic=allowMic)), ] mainMenu = [ #( ( _(strSolo), 1, (0,0) ), soloMenu), ((strSolo, "solo"), soloMenu), ((strMultiplayer, "multiplayer"), multPlayerMenu), ((strTraining, "training"), trainingMenu), ((strSettings, "settings"), self.settingsMenu), (strQuit, self.quit), ] self.menu = Menu(self.engine, mainMenu, onClose=lambda: self.engine.view.popLayer(self), pos=(12, 12), textColor=self.opt_text_color, selectedColor=self.opt_selected_color) engine.mainMenu = self #Points engine.mainMenu to the one and only MainMenu object instance
def __init__(self, engine): self.engine = engine self.logClassInits = Config.get("game", "log_class_inits") if self.logClassInits == 1: Log.debug("MainMenu class init (MainMenu.py)...") self.time = 0.0 self.nextLayer = None self.visibility = 0.0 self.active = False self.showStartupMessages = False self.gfxVersionTag = Config.get("game", "gfx_version_tag") self.chosenNeck = Config.get("game", "default_neck") exists = 0 if engine.loadImgDrawing(self, "ok", os.path.join("necks",self.chosenNeck+".png")): exists = 1 elif engine.loadImgDrawing(self, "ok", os.path.join("necks","Neck_"+self.chosenNeck+".png")): exists = 1 #MFH - fallback logic now supports a couple valid default neck filenames #MFH - check for Neck_1 if exists == 0: if engine.loadImgDrawing(self, "ok", os.path.join("necks","Neck_1.png")): Config.set("game", "default_neck", "1") Log.warn("Default chosen neck not valid; fallback Neck_1.png forced.") exists = 1 #MFH - check for defaultneck if exists == 0: if engine.loadImgDrawing(self, "ok", os.path.join("necks","defaultneck.png")): Log.warn("Default chosen neck not valid; fallback defaultneck.png forced.") Config.set("game", "default_neck", "defaultneck") exists = 1 else: Log.error("Default chosen neck not valid; fallbacks Neck_1.png and defaultneck.png also not valid!") #Get theme self.theme = self.engine.data.theme self.themeCoOp = self.engine.data.themeCoOp self.themename = self.engine.data.themeLabel self.useSoloMenu = self.engine.theme.use_solo_submenu allowMic = True self.menux = self.engine.theme.menuPos[0] self.menuy = self.engine.theme.menuPos[1] self.rbmenu = self.engine.theme.menuRB #MFH self.main_menu_scale = self.engine.theme.main_menu_scaleVar self.main_menu_vspacing = self.engine.theme.main_menu_vspacingVar if not self.engine.loadImgDrawing(self, "background", os.path.join("themes",self.themename,"menu","mainbg.png")): self.background = None self.engine.loadImgDrawing(self, "BGText", os.path.join("themes",self.themename,"menu","maintext.png")) self.engine.loadImgDrawing(self, "optionsBG", os.path.join("themes",self.themename,"menu","optionsbg.png")) self.engine.loadImgDrawing(self, "optionsPanel", os.path.join("themes",self.themename,"menu","optionspanel.png")) #racer: added version tag if self.gfxVersionTag or self.engine.theme.versiontag == True: if not self.engine.loadImgDrawing(self, "version", os.path.join("themes",self.themename,"menu","versiontag.png")): if not self.engine.loadImgDrawing(self, "version", "versiontag.png"): #falls back on default versiontag.png in data\ folder self.version = None else: self.version = None #myfingershurt: random main menu music function, menu.ogg and menuXX.ogg (any filename with "menu" as the first 4 letters) self.files = None filepath = self.engine.getPath(os.path.join("themes",self.themename,"sounds")) if os.path.isdir(filepath): self.files = [] allfiles = os.listdir(filepath) for name in allfiles: if os.path.splitext(name)[1] == ".ogg": if string.find(name,"menu") > -1: self.files.append(name) if self.files: i = random.randint(0,len(self.files)-1) filename = self.files[i] sound = os.path.join("themes",self.themename,"sounds",filename) self.menumusic = True engine.menuMusic = True self.song = Audio.Music(self.engine.resource.fileName(sound)) self.song.setVolume(self.engine.config.get("audio", "menu_volume")) self.song.play(0) #no loop else: self.menumusic = False self.opt_text_color = self.engine.theme.opt_text_colorVar self.opt_selected_color = self.engine.theme.opt_selected_colorVar trainingMenu = [ (_("Tutorials"), self.showTutorial), (_("Practice"), lambda: self.newLocalGame(mode1p = 1)), ] self.opt_bkg_size = [float(i) for i in self.engine.theme.opt_bkg_size] self.opt_text_color = self.engine.theme.hexToColor(self.engine.theme.opt_text_colorVar) self.opt_selected_color = self.engine.theme.hexToColor(self.engine.theme.opt_selected_colorVar) if self.BGText: strCareer = "" strQuickplay = "" strSolo = "" strMultiplayer = "" strTraining = "" strSettings = "" strQuit = "" else: strCareer = "Career" strQuickplay = "Quickplay" strSolo = "Solo" strMultiplayer = "Multiplayer" strTraining = "Training" strSettings = "Settings" strQuit = "Quit" multPlayerMenu = [ (_("Face-Off"), lambda: self.newLocalGame(players = 2, maxplayers = 4)), (_("Pro Face-Off"), lambda: self.newLocalGame(players = 2, mode2p = 1, maxplayers = 4)), (_("Party Mode"), lambda: self.newLocalGame( mode2p = 2)), (_("FoFiX Co-Op"), lambda: self.newLocalGame(players = 2, mode2p = 3, maxplayers = 4, allowMic = allowMic)), (_("RB Co-Op"), lambda: self.newLocalGame(players = 2, mode2p = 4, maxplayers = 4, allowMic = allowMic)), (_("GH Co-Op"), lambda: self.newLocalGame(players = 2, mode2p = 5, maxplayers = 4)), (_("GH Battle"), lambda: self.newLocalGame(players = 2, mode2p = 6, allowDrum = False)), #akedrou- so you can block drums ] if not self.useSoloMenu: mainMenu = [ (strCareer, lambda: self.newLocalGame(mode1p = 2, allowMic = allowMic)), (strQuickplay, lambda: self.newLocalGame(allowMic = allowMic)), ((strMultiplayer,"multiplayer"), multPlayerMenu), ((strTraining,"training"), trainingMenu), ((strSettings,"settings"), self.settingsMenu), (strQuit, self.quit), ] else: soloMenu = [ (_("Solo Tour"), lambda: self.newLocalGame(mode1p = 2, allowMic = allowMic)), (_("Quickplay"), lambda: self.newLocalGame(allowMic = allowMic)), ] mainMenu = [ ((strSolo,"solo"), soloMenu), ((strMultiplayer,"multiplayer"), multPlayerMenu), ((strTraining,"training"), trainingMenu), ((strSettings,"settings"), self.settingsMenu), (strQuit, self.quit), ] w, h, = self.engine.view.geometry[2:4] self.menu = Menu(self.engine, mainMenu, onClose = lambda: self.engine.view.popLayer(self), pos = (self.menux, .75-(.75*self.menuy))) engine.mainMenu = self #Points engine.mainMenu to the one and only MainMenu object instance ## whether the main menu has come into view at least once self.shownOnce = False