Example #1
0
    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)
Example #2
0
class Inventory(object):
    def __init__(self):
        self._guitars = staticList1

    def addGuitar(self, serialNumber, price, spec):
        self.guitar = Guitar(serialNumber, price, spec)
        self._guitars.append(self.guitar)

    def getGuitar(self, serialNumber):
        index = 0
        for i in self._guitars:
            self.guitar = self._guitars[index]
            if self.guitar.getSerialNumber() == serialNumber:
                return self.guitar
            index += 1
        return None

    def search(self, searchSpec):
        self.matchingGuitars = staticList2
        index = 0
        for i in self._guitars:
            self.guitar = self._guitars[index]
            if self.guitar.GetSpec().matches(searchSpec):
                self.matchingGuitars.append(self.guitar)
            index += 1
        return self.matchingGuitars
Example #3
0
  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)
Example #4
0
def establish_controller(index, logger, light_sender, gui):
    try:
        controller = Xbox360Controller(index=index)
        logger.info(controller.name)
    except Exception:
        logger.error(
            f'Encountered exception initiating controller at index {index}',
            exc_info=True)
        return

    if 'Drum' in controller.name:
        light_sender.add_controller(
            'drums',
            Drums(controller, logger, 'drums', (0, 0, 0), light_sender, gui),
            1)
    elif 'WingMan' in controller.name:
        controller.axis_threshold = 0.05
        light_sender.add_controller(
            'car', Car(controller, logger, 'car', (0, 0, 0), light_sender,
                       gui), 2)
    elif 'Guitar' in controller.name:
        light_sender.add_controller(
            'guitar1',
            Guitar(controller, logger, 'guitar1', (0, 0, 0), light_sender,
                   gui), 3)
    else:
        logger.error(
            f'Unrecognized controller found with name {controller.name}. Skipping it.'
        )
        controller.close()
Example #5
0
  def createClient(self, libraryName, songName):
    self.guitar           = Guitar(self.engine)
    self.visibility       = 0.0
    self.libraryName      = libraryName
    self.songName         = songName
    self.done             = False
    self.sfxChannel       = self.engine.audio.getChannel(self.engine.audio.getChannelCount() - 1)
    self.lastMultTime     = None
    self.cheatCodes       = [
      ([117, 112, 116, 111, 109, 121, 116, 101, 109, 112, 111], self.toggleAutoPlay),
      ([102, 97, 115, 116, 102, 111, 114, 119, 97, 114, 100],   self.goToResults)
    ]
    self.enteredCode      = []
    self.song             = None
    self.autoPlay         = False
    self.lastPickPos      = None
    self.lastSongPos      = 0.0
    self.keyBurstTimeout  = None
    self.keyBurstPeriod   = 30
    self.camera.target    = (0, 0, 4)
    self.camera.origin    = (0, 3, -3)

    self.loadSettings()
    self.engine.resource.load(self, "song",          lambda: loadSong(self.engine, songName, library = libraryName), onLoad = self.songLoaded)

    self.stage            = Stage.Stage(self, self.engine.resource.fileName("stage.ini"))

    self.engine.loadSvgDrawing(self, "fx2x",   "2x.svg", textureSize = (256, 256))
    self.engine.loadSvgDrawing(self, "fx3x",   "3x.svg", textureSize = (256, 256))
    self.engine.loadSvgDrawing(self, "fx4x",   "4x.svg", textureSize = (256, 256))

    Dialogs.showLoadingScreen(self.engine, lambda: self.song, text = _("Tuning Guitar..."))

    settingsMenu = Settings.GameSettingsMenu(self.engine)
    settingsMenu.fadeScreen = True

    self.menu = Menu(self.engine, [
      (_("Return to Song"),    lambda: None),
      (_("Restart Song"),      self.restartSong),
      (_("Change Song"),       self.changeSong),
      (_("Settings"),          settingsMenu),
      (_("Quit to Main Menu"), self.quit),
    ], fadeScreen = True, onClose = self.resumeGame)

    self.restartSong()
def main():
    # Set up Rick's guitar inventory
    inventory = Inventory()
    initialize_inventory(inventory)

    what_erin_likes = Guitar("", 0, "fender", "Stratocastor", "electric",
                             "Alder", "Alder")

    guitar = inventory.search(what_erin_likes)
    if guitar != None:
        print("Erin you might like this", guitar.builder, guitar.model,
              guitar.type, "guitar:\n", guitar.back_wood, "back and sides,\n",
              guitar.top_wood, "top.\n You can have it for only $",
              guitar.price, "!")
    else:
        print("Sorry, Erin, we have nothing for you.")
Example #7
0
    def __init__(self, engine, libraryName, songName):
        super(GuitarScene, self).__init__(engine)

        self.guitar           = Guitar(self.engine)
        self.visibility       = 0.0
        self.libraryName      = libraryName
        self.songName         = songName
        self.done             = False
        self.sfxChannel       = self.engine.audio.getChannel(self.engine.audio.getChannelCount() - 1)
        self.lastMultTime     = None
        self.cheatCodes       = [
            ([117, 112, 116, 111, 109, 121, 116, 101, 109, 112, 111], self.toggleAutoPlay),
            ([102, 97, 115, 116, 102, 111, 114, 119, 97, 114, 100],   self.goToResults)
        ]
        self.enteredCode      = []
        self.song             = None
        self.autoPlay         = False
        self.lastPickPos      = None
        self.lastSongPos      = 0.0
        self.keyBurstTimeout  = None
        self.keyBurstPeriod   = 30
        self.camera.target    = (0, 0, 4)
        self.camera.origin    = (0, 3, -3)

        self.loadSettings()
        self.engine.resource.load(self, "song",          lambda: loadSong(self.engine, songName, library = libraryName), onLoad = self.songLoaded)

        self.stage            = Stage.Stage(self, self.engine.resource.fileName("stage.ini"))

        self.engine.loadImgDrawing(self, "fx2x",   "2x.png", textureSize = (256, 256))
        self.engine.loadImgDrawing(self, "fx3x",   "3x.png", textureSize = (256, 256))
        self.engine.loadImgDrawing(self, "fx4x",   "4x.png", textureSize = (256, 256))

        Dialogs.showLoadingScreen(self.engine, lambda: self.song, text = _("Tuning Guitar..."))

        settingsMenu = Settings.GameSettingsMenu(self.engine)
        settingsMenu.fadeScreen = True

        self.menu = Menu(self.engine, [
            (_("Return to Song"),    self.resumeHideMenu),
            (_("Restart Song"),      self.restartSong),
            (_("Change Song"),       self.changeSong),
            (_("Settings"),          settingsMenu),
            (_("Quit to Main Menu"), self.quit),
        ], fadeScreen = True, onClose = self.resumeGame)

        self.restartSong()
Example #8
0
class GuitarSceneClient(GuitarScene, SceneClient):
    def createClient(self, libraryName, songName):
        self.guitar           = Guitar(self.engine)
        self.visibility       = 0.0
        self.libraryName      = libraryName
        self.songName         = songName
        self.done             = False
        self.sfxChannel       = self.engine.audio.getChannel(self.engine.audio.getChannelCount() - 1)
        self.lastMultTime     = None
        self.cheatCodes       = [
            ([117, 112, 116, 111, 109, 121, 116, 101, 109, 112, 111], self.toggleAutoPlay),
            ([102, 97, 115, 116, 102, 111, 114, 119, 97, 114, 100],   self.goToResults)
        ]
        self.enteredCode      = []
        self.song             = None
        self.autoPlay         = False
        self.lastPickPos      = None
        self.lastSongPos      = 0.0
        self.keyBurstTimeout  = None
        self.keyBurstPeriod   = 30
        self.camera.target    = (0, 0, 4)
        self.camera.origin    = (0, 3, -3)

        self.loadSettings()
        self.engine.resource.load(self, "song",          lambda: loadSong(self.engine, songName, library = libraryName), onLoad = self.songLoaded)

        self.stage            = Stage.Stage(self, self.engine.resource.fileName("stage.ini"))

        self.engine.loadImgDrawing(self, "fx2x",   "2x.png", textureSize = (256, 256))
        self.engine.loadImgDrawing(self, "fx3x",   "3x.png", textureSize = (256, 256))
        self.engine.loadImgDrawing(self, "fx4x",   "4x.png", textureSize = (256, 256))

        Dialogs.showLoadingScreen(self.engine, lambda: self.song, text = _("Tuning Guitar..."))

        settingsMenu = Settings.GameSettingsMenu(self.engine)
        settingsMenu.fadeScreen = True

        self.menu = Menu(self.engine, [
            (_("Return to Song"),    lambda: None),
            (_("Restart Song"),      self.restartSong),
            (_("Change Song"),       self.changeSong),
            (_("Settings"),          settingsMenu),
            (_("Quit to Main Menu"), self.quit),
        ], fadeScreen = True, onClose = self.resumeGame)

        self.restartSong()

    def pauseGame(self):
        if self.song:
            self.song.pause()

    def resumeGame(self):
        self.loadSettings()
        if self.song:
            self.song.unpause()

    def loadSettings(self):
        self.delay            = self.engine.config.get("audio", "delay")
        self.screwUpVolume    = self.engine.config.get("audio", "screwupvol")
        self.guitarVolume     = self.engine.config.get("audio", "guitarvol")
        self.songVolume       = self.engine.config.get("audio", "songvol")
        self.rhythmVolume     = self.engine.config.get("audio", "rhythmvol")
        self.guitar.leftyMode = self.engine.config.get("game",  "leftymode")

        if self.song:
            self.song.setBackgroundVolume(self.songVolume)
            self.song.setRhythmVolume(self.rhythmVolume)

    def songLoaded(self, song):
        song.difficulty = self.player.difficulty
        self.delay += song.info.delay

        # If tapping is disabled, remove the tapping indicators
        if not self.engine.config.get("game", "tapping"):
            for time, event in self.song.track.getAllEvents():
                if isinstance(event, Note):
                    event.tappable = False

    def quit(self):
        if self.song:
            self.song.stop()
            self.song  = None
        self.done = True
        self.engine.view.popLayer(self.menu)
        self.session.world.finishGame()

    def changeSong(self):
        if self.song:
            self.song.stop()
            self.song  = None
        self.engine.view.popLayer(self.menu)
        self.session.world.deleteScene(self)
        self.session.world.createScene("SongChoosingScene")

    def restartSong(self):
        self.engine.data.startSound.play()
        self.engine.view.popLayer(self.menu)
        self.player.reset()
        self.stage.reset()
        self.enteredCode     = []
        self.autoPlay        = False
        self.engine.collectGarbage()

        if not self.song:
            return

        self.countdown    = 8.0
        self.guitar.endPick(0)
        self.song.stop()

    def run(self, ticks):
        SceneClient.run(self, ticks)
        pos = self.getSongPosition()

        # update song
        if self.song:
            # update stage
            self.stage.run(pos, self.guitar.currentPeriod)

            if self.countdown <= 0 and not self.song.isPlaying() and not self.done:
                self.goToResults()
                return

            if self.autoPlay:
                notes = self.guitar.getRequiredNotes(self.song, pos)
                notes = [note.number for time, note in notes]

                changed = False
                held = 0
                for n, k in enumerate(KEYS):
                    if n in notes and not self.controls.getState(k):
                        changed = True
                        self.controls.toggle(k, True)
                    elif not n in notes and self.controls.getState(k):
                        changed = True
                        self.controls.toggle(k, False)
                    if self.controls.getState(k):
                        held += 1
                if changed and held:
                    self.doPick()

            self.song.update(ticks)
            if self.countdown > 0:
                self.guitar.setBPM(self.song.bpm)
                self.countdown = max(self.countdown - ticks / self.song.period, 0)
                if not self.countdown:
                    self.engine.collectGarbage()
                    self.song.setGuitarVolume(self.guitarVolume)
                    self.song.setBackgroundVolume(self.songVolume)
                    self.song.setRhythmVolume(self.rhythmVolume)
                    self.song.play()

        # update board
        if not self.guitar.run(ticks, pos, self.controls):
            # done playing the current notes
            self.endPick()

        # missed some notes?
        if self.guitar.getMissedNotes(self.song, pos) and not self.guitar.playedNotes:
            self.song.setGuitarVolume(0.0)
            self.player.streak = 0

        # late pick
        if self.keyBurstTimeout is not None and self.engine.timer.time > self.keyBurstTimeout:
            self.keyBurstTimeout = None
            notes = self.guitar.getRequiredNotes(self.song, pos)
            if self.guitar.controlsMatchNotes(self.controls, notes):
                self.doPick()

    def endPick(self):
        score = self.getExtraScoreForCurrentlyPlayedNotes()
        if not self.guitar.endPick(self.song.getPosition()):
            self.song.setGuitarVolume(0.0)
        self.player.addScore(score)

    def render3D(self):
        self.stage.render(self.visibility)

    def renderGuitar(self):
        self.guitar.render(self.visibility, self.song, self.getSongPosition(), self.controls)

    def getSongPosition(self):
        if self.song:
            if not self.done:
                self.lastSongPos = self.song.getPosition()
                return self.lastSongPos - self.countdown * self.song.period - self.delay
            else:
                # Nice speeding up animation at the end of the song
                return self.lastSongPos + 4.0 * (1 - self.visibility) * self.song.period - self.delay
        return 0.0

    def doPick(self):
        if not self.song:
            return

        pos = self.getSongPosition()

        if self.guitar.playedNotes:
            # If all the played notes are tappable, there are no required notes and
            # the last note was played recently enough, ignore this pick
            if self.guitar.areNotesTappable(self.guitar.playedNotes) and \
               not self.guitar.getRequiredNotes(self.song, pos) and \
               pos - self.lastPickPos <= self.song.period / 2:
                return
            self.endPick()

        self.lastPickPos = pos

        if self.guitar.startPick(self.song, pos, self.controls):
            self.song.setGuitarVolume(self.guitarVolume)
            self.player.streak += 1
            self.player.notesHit += len(self.guitar.playedNotes)
            self.player.addScore(len(self.guitar.playedNotes) * 50)
            self.stage.triggerPick(pos, [n[1].number for n in self.guitar.playedNotes])
            if self.player.streak % 10 == 0:
                self.lastMultTime = pos
        else:
            self.song.setGuitarVolume(0.0)
            self.player.streak = 0
            self.stage.triggerMiss(pos)
            self.sfxChannel.play(self.engine.data.screwUpSound)
            self.sfxChannel.setVolume(self.screwUpVolume)

    def toggleAutoPlay(self):
        self.autoPlay = not self.autoPlay
        if self.autoPlay:
            Dialogs.showMessage(self.engine, _("Jurgen will show you how it is done."))
        else:
            Dialogs.showMessage(self.engine, _("Jurgen has left the building."))
        return self.autoPlay

    def goToResults(self):
        if self.song:
            self.song.stop()
            self.song  = None
            self.done  = True
            self.session.world.deleteScene(self)
            self.session.world.createScene("GameResultsScene", libraryName = self.libraryName, songName = self.songName)

    def keyPressed(self, key, unicode):
        control = self.controls.keyPressed(key)

        if control in (Player.ACTION1, Player.ACTION2):
            for k in KEYS:
                if self.controls.getState(k):
                    self.keyBurstTimeout = None
                    break
            else:
                self.keyBurstTimeout = self.engine.timer.time + self.keyBurstPeriod
                return True

        if control in (Player.ACTION1, Player.ACTION2) and self.song:
            self.doPick()
        elif control in KEYS and self.song:
            # Check whether we can tap the currently required notes
            pos   = self.getSongPosition()
            notes = self.guitar.getRequiredNotes(self.song, pos)

            if self.player.streak > 0 and \
               self.guitar.areNotesTappable(notes) and \
               self.guitar.controlsMatchNotes(self.controls, notes):
                self.doPick()
        elif control == Player.CANCEL:
            self.pauseGame()
            self.engine.view.pushLayer(self.menu)
            return True
        elif key >= ord('a') and key <= ord('z'):
            # cheat codes
            n = len(self.enteredCode)
            for code, func in self.cheatCodes:
                if n < len(code):
                    if key == code[n]:
                        self.enteredCode.append(key)
                        if self.enteredCode == code:
                            self.enteredCode     = []
                            self.player.cheating = True
                            func()
                        break
            else:
                self.enteredCode = []

    def getExtraScoreForCurrentlyPlayedNotes(self):
        if not self.song:
            return 0

        noteCount  = len(self.guitar.playedNotes)
        pickLength = self.guitar.getPickLength(self.getSongPosition())
        if pickLength > 1.1 * self.song.period / 4:
            return int(.1 * pickLength * noteCount)
        return 0

    def keyReleased(self, key):
        if self.controls.keyReleased(key) in KEYS and self.song:
            # Check whether we can tap the currently required notes
            pos   = self.getSongPosition()
            notes = self.guitar.getRequiredNotes(self.song, pos)
            if self.player.streak > 0 and \
               self.guitar.areNotesTappable(notes) and \
               self.guitar.controlsMatchNotes(self.controls, notes):
                self.doPick()
            # Otherwise we end the pick if the notes have been playing long enough
            elif self.lastPickPos is not None and pos - self.lastPickPos > self.song.period / 2:
                self.endPick()
    def render(self, visibility, topMost):
        SceneClient.render(self, visibility, topMost)

        font    = self.engine.data.font
        bigFont = self.engine.data.bigFont

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

        self.engine.view.setOrthogonalProjection(normalize = True)
        try:
            # show countdown
            if self.countdown > 1:
                Theme.setBaseColor(min(1.0, 3.0 - abs(4.0 - self.countdown)))
                text = _("Get Ready to Rock")
                w, h = font.getStringSize(text)
                font.render(text,  (.5 - w / 2, .3))
                if self.countdown < 6:
                    scale = 0.002 + 0.0005 * (self.countdown % 1) ** 3
                    text = "%d" % (self.countdown)
                    w, h = bigFont.getStringSize(text, scale = scale)
                    Theme.setSelectedColor()
                    bigFont.render(text,  (.5 - w / 2, .45 - h / 2), scale = scale)

            w, h = font.getStringSize(" ")
            y = .05 - h / 2 - (1.0 - v) * .2

            # show song name
            if self.countdown and self.song:
                Theme.setBaseColor(min(1.0, 4.0 - abs(4.0 - self.countdown)))
                Dialogs.wrapText(font, (.05, .05 - h / 2), self.song.info.name + " \n " + self.song.info.artist, rightMargin = .6, scale = 0.0015)

            Theme.setSelectedColor()

            font.render("%d" % (self.player.score + self.getExtraScoreForCurrentlyPlayedNotes()),  (.6, y))
            font.render("%dx" % self.player.getScoreMultiplier(), (.6, y + h))

            # show the streak counter and miss message
            if self.player.streak > 0 and self.song:
                text = _("%d hit") % self.player.streak
                factor = 0.0
                if self.lastPickPos:
                    diff = self.getSongPosition() - self.lastPickPos
                    if diff > 0 and diff < self.song.period * 2:
                        factor = .25 * (1.0 - (diff / (self.song.period * 2))) ** 2
                factor = (1.0 + factor) * 0.002
                tw, th = font.getStringSize(text, scale = factor)
                font.render(text, (.16 - tw / 2, y + h / 2 - th / 2), scale = factor)
            elif self.lastPickPos is not None and self.countdown <= 0:
                diff = self.getSongPosition() - self.lastPickPos
                alpha = 1.0 - diff * 0.005
                if alpha > .1:
                    Theme.setSelectedColor(alpha)
                    glPushMatrix()
                    glTranslate(.1, y + 0.000005 * diff ** 2, 0)
                    glRotatef(math.sin(self.lastPickPos) * 25, 0, 0, 1)
                    font.render(_("Missed!"), (0, 0))
                    glPopMatrix()

            # show the streak balls
            if self.player.streak >= 30:
                glColor3f(.5, .5, 1)
            elif self.player.streak >= 20:
                glColor3f(1, 1, .5)
            elif self.player.streak >= 10:
                glColor3f(1, .5, .5)
            else:
                glColor3f(.5, 1, .5)

            s = min(39, self.player.streak) % 10 + 1
            font.render(Data.BALL2 * s + Data.BALL1 * (10 - s),   (.67, y + h * 1.3), scale = 0.0011)

            # show multiplier changes
            if self.song and self.lastMultTime is not None:
                diff = self.getSongPosition() - self.lastMultTime
                if diff > 0 and diff < self.song.period * 2:
                    m = self.player.getScoreMultiplier()
                    c = (1, 1, 1)
                    if self.player.streak >= 40:
                        texture = None
                    elif m == 1:
                        texture = None
                    elif m == 2:
                        texture = self.fx2x.texture
                        c = (1, .5, .5)
                    elif m == 3:
                        texture = self.fx3x.texture
                        c = (1, 1, .5)
                    elif m == 4:
                        texture = self.fx4x.texture
                        c = (.5, .5, 1)

                    f = (1.0 - abs(self.song.period * 1 - diff) / (self.song.period * 1)) ** 2

                    # Flash the screen
                    glBegin(GL_TRIANGLE_STRIP)
                    glColor4f(c[0], c[1], c[2], (f - .5) * 1)
                    glVertex2f(0, 0)
                    glColor4f(c[0], c[1], c[2], (f - .5) * 1)
                    glVertex2f(1, 0)
                    glColor4f(c[0], c[1], c[2], (f - .5) * .25)
                    glVertex2f(0, 1)
                    glColor4f(c[0], c[1], c[2], (f - .5) * .25)
                    glVertex2f(1, 1)
                    glEnd()

                    if texture:
                        glPushMatrix()
                        glEnable(GL_TEXTURE_2D)
                        texture.bind()
                        size = (texture.pixelSize[0] * .002, texture.pixelSize[1] * .002)

                        glTranslatef(.5, .15, 0)
                        glBlendFunc(GL_SRC_ALPHA, GL_ONE)

                        f = .5 + .5 * (diff / self.song.period) ** 3
                        glColor4f(1, 1, 1, min(1, 2 - f))
                        glBegin(GL_TRIANGLE_STRIP)
                        glTexCoord2f(0.0, 0.0)
                        glVertex2f(-size[0] * f, -size[1] * f)
                        glTexCoord2f(1.0, 0.0)
                        glVertex2f( size[0] * f, -size[1] * f)
                        glTexCoord2f(0.0, 1.0)
                        glVertex2f(-size[0] * f,  size[1] * f)
                        glTexCoord2f(1.0, 1.0)
                        glVertex2f( size[0] * f,  size[1] * f)
                        glEnd()

                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                        glPopMatrix()

            # show the comments
            if self.song and self.song.info.tutorial:
                glColor3f(1, 1, 1)
                pos = self.getSongPosition()
                for time, event in self.song.track.getEvents(pos - self.song.period * 2, pos + self.song.period * 4):
                    if isinstance(event, PictureEvent):
                        if pos < time or pos > time + event.length:
                            continue

                        try:
                            picture = event.picture
                        except:
                            self.engine.loadImgDrawing(event, "picture", os.path.join(self.libraryName, self.songName, event.fileName))
                            picture = event.picture

                        w, h, = self.engine.view.geometry[2:4]
                        fadePeriod = 500.0
                        f = (1.0 - min(1.0, abs(pos - time) / fadePeriod) * min(1.0, abs(pos - time - event.length) / fadePeriod)) ** 2
                        picture.transform.reset()
                        picture.transform.translate(w / 2, (f * -2 + 1) * h / 2)
                        picture.transform.scale(1, -1)
                        picture.draw()
                    elif isinstance(event, TextEvent):
                        if pos >= time and pos <= time + event.length:
                            text = _(event.text)
                            w, h = font.getStringSize(text)
                            font.render(text, (.5 - w / 2, .67))
        finally:
            self.engine.view.resetProjection()
Example #9
0
class Editor(Layer, KeyListener):
  """Song editor layer."""
  def __init__(self, engine, songName = None, libraryName = DEFAULT_LIBRARY):
    self.engine      = engine
    self.time        = 0.0
    self.guitar      = Guitar(self.engine, editorMode = True)
    self.controls    = Player.Controls()
    self.camera      = Camera()
    self.pos         = 0.0
    self.snapPos     = 0.0
    self.scrollPos   = 0.0
    self.scrollSpeed = 0.0
    self.newNotes    = None
    self.newNotePos  = 0.0
    self.song        = None
    self.engine.loadSvgDrawing(self, "background", "editor.svg")
    self.modified    = False
    self.songName    = songName
    self.libraryName = libraryName
    self.heldFrets   = set()

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if not self.song:
      return

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

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

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

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

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

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

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

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

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

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

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

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

    try:
      Theme.setSelectedColor()

      w, h = font.getStringSize(" ")

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

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

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

        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()
Example #11
0
    def __init__(self):
        QMainWindow.__init__(self)

        # Setup the ui form
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Create a new QGraphicsScene and show it on the ui
        self.scene = QGraphicsScene(self)
        self.scene.setBackgroundBrush(QColor(120, 120, 120))
        self.ui.graphicsView.setScene(self.scene)
        self.ui.graphicsView.show()

        # Setup tuning
        self.tuning = [('Standard Tuning', [
            Note("E", 2),
            Note("A", 2),
            Note("D", 3),
            Note("G", 3),
            Note("B", 3),
            Note("E", 4)
        ]),
                       ('Dropped D', [
                           Note("D", 2),
                           Note("A", 2),
                           Note("D", 3),
                           Note("G", 3),
                           Note("B", 3),
                           Note("E", 4)
                       ]),
                       ('Dropped C', [
                           Note("C", 2),
                           Note("G", 2),
                           Note("C", 3),
                           Note("F", 3),
                           Note("A", 3),
                           Note("D", 4)
                       ])]

        t1 = QGraphicsTextItem()
        t2 = QGraphicsTextItem()
        t3 = QGraphicsTextItem()
        t4 = QGraphicsTextItem()
        t5 = QGraphicsTextItem()
        t6 = QGraphicsTextItem()
        self.tuning_list = [t1, t2, t3, t4, t5, t6]

        # Define fret number
        self.FRETS = 22

        # Create a new Guitar object
        self.GibsonGuitar = Guitar(self.FRETS, self.tuning[0][1])

        # Create a new Guitar Fretboard object and show it on the scene
        self.GibsonGuitar_Fretboard = GraphicsFretboard(self.FRETS)
        self.GibsonGuitar_Fretboard.setPos(0, 0)
        self.scene.addItem(self.GibsonGuitar_Fretboard)

        # Draw the tuning
        self.draw_tuning(self.tuning[0][1])

        # Populate the notes pool
        self.notes = [
            'A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'
        ]

        # Populate the scales pool
        self.scales = [
            Scale("Pentatonic Major", [2, 2, 3, 2, 3], 'box_pattern'),
            Scale("Pentatonic Minor", [3, 2, 2, 3, 2], 'box_pattern'),
            Scale("Pentatonic Blues", [3, 2, 1, 1, 3, 2], 'box_pattern'),
            Scale("Major", [2, 2, 1, 2, 2, 2, 1], 'three_notes'),
            Scale("Ionian", [2, 2, 1, 2, 2, 2, 1], 'three_notes'),
            Scale("Dorian", [2, 1, 2, 2, 2, 1, 2], 'three_notes'),
            Scale("Phrygian", [1, 2, 2, 2, 1, 2, 2], 'three_notes'),
            Scale("Lydian", [2, 2, 2, 1, 2, 2, 1], 'three_notes'),
            Scale("Mixolydian", [2, 2, 1, 2, 2, 1, 2], 'three_notes'),
            Scale("Aeolian", [2, 1, 2, 2, 1, 2, 2], 'three_notes'),
            Scale("Locrian", [1, 2, 2, 1, 2, 2, 2], 'three_notes'),
            Scale("Minor", [2, 1, 2, 2, 1, 2, 2], 'three_notes'),
            Scale("Harmonic Minor", [2, 1, 2, 2, 1, 3, 1], 'three_notes'),
            Scale("Melodic Minor - Ascending", [2, 1, 2, 2, 2, 2, 1],
                  'three_notes'),
            Scale("Melodic Minor - Descending", [2, 1, 2, 2, 1, 2, 2],
                  'three_notes'),
            Scale("Chromatic", [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                  'three_notes'),
            Scale("Whole Tone", [2, 2, 2, 2, 2, 2], 'three_notes'),
            Scale("Diminished", [2, 1, 2, 1, 2, 1, 2], 'four_notes')
        ]

        # Add notes and scales to the comboboxes
        for note in self.notes:
            self.ui.rootComboBox.addItem(note)
        for scale in self.scales:
            self.ui.scaleComboBox.addItem(scale.name)
        for item in self.tuning:
            self.ui.tuningComboBox.addItem(item[0])

        # Set the init value to the first item
        self.ui.rootComboBox.setCurrentIndex = 0
        self.ui.scaleComboBox.setCurrentIndex = 0

        # Setup the root note and the current scale to be the first item from the combobox
        self.root_note = self.notes[self.ui.rootComboBox.currentIndex()]
        self.currentScale = self.scales[self.ui.scaleComboBox.currentIndex()]
        self.scale = self.currentScale.get_scale_notes(self.root_note)
        self.update_repr()

        # Signaling if combobox has changed
        self.ui.rootComboBox.currentIndexChanged.connect(self.update_ui)
        self.ui.scaleComboBox.currentIndexChanged.connect(self.update_ui)
        self.ui.tuningComboBox.currentIndexChanged.connect(self.update_tuning)

        # Set the initial position for the scale draw
        self.newPos = 0

        # Set the initial string number for the one sting per scale representation
        self.sting_num = 0

        # Length of the scale
        self.intervalLength = len(self.currentScale.intervals)

        # QTimer object for animation
        self.timer = QTimer()
        self.is_animation_active = False

        # Variable to store the actual scale on the guitar for drawing
        # It based on the Radio Button selection
        self.notes_to_draw = []
Example #12
0
class Main(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        # Setup the ui form
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Create a new QGraphicsScene and show it on the ui
        self.scene = QGraphicsScene(self)
        self.scene.setBackgroundBrush(QColor(120, 120, 120))
        self.ui.graphicsView.setScene(self.scene)
        self.ui.graphicsView.show()

        # Setup tuning
        self.tuning = [('Standard Tuning', [
            Note("E", 2),
            Note("A", 2),
            Note("D", 3),
            Note("G", 3),
            Note("B", 3),
            Note("E", 4)
        ]),
                       ('Dropped D', [
                           Note("D", 2),
                           Note("A", 2),
                           Note("D", 3),
                           Note("G", 3),
                           Note("B", 3),
                           Note("E", 4)
                       ]),
                       ('Dropped C', [
                           Note("C", 2),
                           Note("G", 2),
                           Note("C", 3),
                           Note("F", 3),
                           Note("A", 3),
                           Note("D", 4)
                       ])]

        t1 = QGraphicsTextItem()
        t2 = QGraphicsTextItem()
        t3 = QGraphicsTextItem()
        t4 = QGraphicsTextItem()
        t5 = QGraphicsTextItem()
        t6 = QGraphicsTextItem()
        self.tuning_list = [t1, t2, t3, t4, t5, t6]

        # Define fret number
        self.FRETS = 22

        # Create a new Guitar object
        self.GibsonGuitar = Guitar(self.FRETS, self.tuning[0][1])

        # Create a new Guitar Fretboard object and show it on the scene
        self.GibsonGuitar_Fretboard = GraphicsFretboard(self.FRETS)
        self.GibsonGuitar_Fretboard.setPos(0, 0)
        self.scene.addItem(self.GibsonGuitar_Fretboard)

        # Draw the tuning
        self.draw_tuning(self.tuning[0][1])

        # Populate the notes pool
        self.notes = [
            'A', 'A#', 'B', 'C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#'
        ]

        # Populate the scales pool
        self.scales = [
            Scale("Pentatonic Major", [2, 2, 3, 2, 3], 'box_pattern'),
            Scale("Pentatonic Minor", [3, 2, 2, 3, 2], 'box_pattern'),
            Scale("Pentatonic Blues", [3, 2, 1, 1, 3, 2], 'box_pattern'),
            Scale("Major", [2, 2, 1, 2, 2, 2, 1], 'three_notes'),
            Scale("Ionian", [2, 2, 1, 2, 2, 2, 1], 'three_notes'),
            Scale("Dorian", [2, 1, 2, 2, 2, 1, 2], 'three_notes'),
            Scale("Phrygian", [1, 2, 2, 2, 1, 2, 2], 'three_notes'),
            Scale("Lydian", [2, 2, 2, 1, 2, 2, 1], 'three_notes'),
            Scale("Mixolydian", [2, 2, 1, 2, 2, 1, 2], 'three_notes'),
            Scale("Aeolian", [2, 1, 2, 2, 1, 2, 2], 'three_notes'),
            Scale("Locrian", [1, 2, 2, 1, 2, 2, 2], 'three_notes'),
            Scale("Minor", [2, 1, 2, 2, 1, 2, 2], 'three_notes'),
            Scale("Harmonic Minor", [2, 1, 2, 2, 1, 3, 1], 'three_notes'),
            Scale("Melodic Minor - Ascending", [2, 1, 2, 2, 2, 2, 1],
                  'three_notes'),
            Scale("Melodic Minor - Descending", [2, 1, 2, 2, 1, 2, 2],
                  'three_notes'),
            Scale("Chromatic", [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
                  'three_notes'),
            Scale("Whole Tone", [2, 2, 2, 2, 2, 2], 'three_notes'),
            Scale("Diminished", [2, 1, 2, 1, 2, 1, 2], 'four_notes')
        ]

        # Add notes and scales to the comboboxes
        for note in self.notes:
            self.ui.rootComboBox.addItem(note)
        for scale in self.scales:
            self.ui.scaleComboBox.addItem(scale.name)
        for item in self.tuning:
            self.ui.tuningComboBox.addItem(item[0])

        # Set the init value to the first item
        self.ui.rootComboBox.setCurrentIndex = 0
        self.ui.scaleComboBox.setCurrentIndex = 0

        # Setup the root note and the current scale to be the first item from the combobox
        self.root_note = self.notes[self.ui.rootComboBox.currentIndex()]
        self.currentScale = self.scales[self.ui.scaleComboBox.currentIndex()]
        self.scale = self.currentScale.get_scale_notes(self.root_note)
        self.update_repr()

        # Signaling if combobox has changed
        self.ui.rootComboBox.currentIndexChanged.connect(self.update_ui)
        self.ui.scaleComboBox.currentIndexChanged.connect(self.update_ui)
        self.ui.tuningComboBox.currentIndexChanged.connect(self.update_tuning)

        # Set the initial position for the scale draw
        self.newPos = 0

        # Set the initial string number for the one sting per scale representation
        self.sting_num = 0

        # Length of the scale
        self.intervalLength = len(self.currentScale.intervals)

        # QTimer object for animation
        self.timer = QTimer()
        self.is_animation_active = False

        # Variable to store the actual scale on the guitar for drawing
        # It based on the Radio Button selection
        self.notes_to_draw = []

    def update_ui(self):
        """ Callback for ComboBox signaling
            Update the root note and the scale """

        self.root_note = self.notes[self.ui.rootComboBox.currentIndex()]
        self.currentScale = self.scales[self.ui.scaleComboBox.currentIndex()]
        self.scale = self.currentScale.get_scale_notes(self.root_note)
        self.intervalLength = len(self.currentScale.intervals)
        self.update_repr()

    def update_tuning(self):
        """ Update the tuning based on the combo box selection"""
        # Get the current tuning from the combobox index
        current_tuning = self.tuning[self.ui.tuningComboBox.currentIndex()]

        # Update the Guitar object
        self.GibsonGuitar.tuning(current_tuning[1])

        # Update the scene
        for note, text in zip(current_tuning[1], self.tuning_list):
            text.setPlainText(note.name)

    def update_repr(self):
        """ Update the scale representation """
        if self.currentScale.get_scale_repr() == 'box_pattern':
            self.ui.boxPatternRadioButton.setChecked(True)
        if self.currentScale.get_scale_repr() == 'three_notes':
            self.ui.threeNotesRadioButton.setChecked(True)
        if self.currentScale.get_scale_repr() == 'four_notes':
            self.ui.fourNotesRadioButton.setChecked(True)

    def update_scale_pos(self, pos):
        """ Update the scale position """
        self.newPos = pos

        if self.ui.boxPatternRadioButton.isChecked():
            self.notes_to_draw = self.GibsonGuitar.get_box_pattern(
                self.scale, self.newPos)
        if self.ui.threeNotesRadioButton.isChecked():
            self.notes_to_draw = self.GibsonGuitar.get_three_notes(
                self.scale, self.newPos)
        if self.ui.fourNotesRadioButton.isChecked():
            self.notes_to_draw = self.GibsonGuitar.get_four_notes(
                self.scale, self.newPos)
        if self.ui.oneStringRadioButton.isChecked():
            self.notes_to_draw = self.GibsonGuitar.get_one_string_pattern(
                self.scale, self.newPos)

    def clear_fretboard(self):
        """ Delete all GraphicsNoteItem from the scene """
        for item in self.scene.items():
            if item.type() == GraphicsNoteItem.UserType + 1:
                self.scene.removeItem(item)
        self.scene.update()

    def draw_tuning(self, tuning):
        """ Draw the tuning on the scene """
        # Reverse the order
        tuning_notes = tuning[::-1]
        y = 150
        # Iterate over the tuning_notes and the QGraphicsTextItem parallel
        # Set the tuning_notes content for the self.tuning_list QGraphicsTextItems
        for note, text in zip(tuning_notes, self.tuning_list):
            text.setPlainText(note.name)
            text.setFont(QFont("Verdana", 14))
            text.setDefaultTextColor(QColor(Qt.white))
            # Set the position and add it to the scene
            text.setPos(-30, y)
            self.scene.addItem(text)
            y -= 30
        self.scene.update()

    def draw_notes(self, notes):
        """ Draw guitar notes on the scene from the notes list """
        for s, string in enumerate(notes):
            for note in string:
                if note[0].name == self.root_note:
                    note_color = QColor('red')
                else:
                    note_color = QColor('green')
                # First item from the tuple is the Note object
                note_item = GraphicsNoteItem(note[0].name, note_color)
                # Second item from the tuple is the position on the string
                note_index = note[1]
                # Get the note coordinate from the fretboard
                note_item.setPos(
                    self.GibsonGuitar_Fretboard.note_coordinates[s]
                    [note_index])
                self.scene.addItem(note_item)

    def draw_one_string_scale(self, notes, string_num):
        """ Draw guitar notes on the scene from the notes list """
        for item in notes:
            for note in item:
                if note[0].name == self.root_note:
                    note_color = QColor('red')
                else:
                    note_color = QColor('green')
                # First item from the tuple is the Note object
                note_item = GraphicsNoteItem(note[0].name, note_color)
                # Second item from the tuple is the position on the string
                note_index = note[1]
                # Get the note coordinate from the fretboard
                note_item.setPos(
                    self.GibsonGuitar_Fretboard.note_coordinates[string_num]
                    [note_index])
                self.scene.addItem(note_item)

    def drawFirstPos(self):
        """ Callback function for firstPushButton """
        # If the animation still running stop it
        if self.is_animation_active:
            self.stopAnimation()

        # Clear the fretboard
        self.clear_fretboard()

        # Set the string number back to zero if oneStringRadioButton is checked
        # Get the updated scale notes and draw them
        if self.ui.oneStringRadioButton.isChecked():
            self.sting_num = 0
            self.update_scale_pos(self.sting_num)
            self.draw_one_string_scale(self.notes_to_draw, self.sting_num)
        else:
            # Set the position back to zero
            self.newPos = 0
            # Update the pos and draw the notes on the fretboard
            self.update_scale_pos(self.newPos)
            self.draw_notes(self.notes_to_draw)

    def drawNextPos(self):
        """ Callback function for nextPushButton """
        # If the animation still running stop it
        # if self.is_animation_active:
        #     self.stopAnimation()

        # Clear the fretboard
        self.clear_fretboard()

        # Set the string number back to zero if oneStringRadioButton is checked
        # Get the updated scale notes and draw them
        if self.ui.oneStringRadioButton.isChecked():
            # Increase the string_num by one if possible, if not set it back to zero
            if self.sting_num == 5:
                self.sting_num = 0
            else:
                self.sting_num += 1
            self.update_scale_pos(self.sting_num)
            self.draw_one_string_scale(self.notes_to_draw, self.sting_num)
        else:
            # Check the position, it cannot be larger than the available notes in the scale
            # Increase it by one if possible, if not set it back to zero
            if self.newPos == self.intervalLength:
                self.newPos = 0
            else:
                self.newPos += 1
            # Update the pos and draw the notes on the fretboard
            self.update_scale_pos(self.newPos)
            self.draw_notes(self.notes_to_draw)

    def drawPrevPos(self):
        """ Callback function for prevPushButton """
        # If the animation still running stop it
        if self.is_animation_active:
            self.stopAnimation()

        # Clear the fretboard
        self.clear_fretboard()

        # Set the string number back to zero if oneStringRadioButton is checked
        # Get the updated scale notes and draw them
        if self.ui.oneStringRadioButton.isChecked():
            # Increase the string_num by one if possible, if not set it back to zero
            if self.sting_num <= 0:
                self.sting_num = 5
            else:
                self.sting_num -= 1
            self.update_scale_pos(self.sting_num)
            self.draw_one_string_scale(self.notes_to_draw, self.sting_num)
        else:
            # Check the position, it cannot be larger than the available notes in the scale
            # Decrease it by one if possible
            if self.newPos <= 0:
                self.newPos = self.intervalLength
            else:
                self.newPos -= 1
            # Update the pos and draw the notes on the fretboard
            self.update_scale_pos(self.newPos)
            self.draw_notes(self.notes_to_draw)

    def drawAllPos(self):
        """ Callback function for allPushButton """
        # If the animation still running stop it
        if self.is_animation_active:
            self.stopAnimation()

        # Clear the fretboard
        self.clear_fretboard()

        # Draw all scale notes on the fretboard
        notes = self.GibsonGuitar.get_all_scale_notes(self.scale)
        self.draw_notes(notes)

    def __animate(self):
        """ Callback function for QTimer timeout signal """
        self.is_animation_active = True
        self.drawNextPos()

    def startAnimation(self):
        """ Callback function for startAnimPushButton """
        self.timer.timeout.connect(self.__animate)
        self.timer.start(1000)

    def stopAnimation(self):
        """ Callback function for stopAnimPushButton """
        self.is_animation_active = False
        self.timer.stop()
Example #13
0
 def add_guitar(self, serial_number, price, builder, model, type, back_wood,
                top_wood):
     guitar = Guitar(serial_number, price, builder, model, type, back_wood,
                     top_wood)
     self.__guitars.append(guitar)
Example #14
0
class GuitarSceneClient(GuitarScene, SceneClient):
    def createClient(self, libraryName, songName):
        self.guitar = Guitar(self.engine)
        self.visibility = 0.0
        self.libraryName = libraryName
        self.songName = songName
        self.done = False
        self.sfxChannel = self.engine.audio.getChannel(
            self.engine.audio.getChannelCount() - 1)
        self.lastMultTime = None
        self.cheatCodes = [
            ([117, 112, 116, 111, 109, 121, 116, 101, 109, 112,
              111], self.toggleAutoPlay),
            ([102, 97, 115, 116, 102, 111, 114, 119, 97, 114,
              100], self.goToResults)
        ]
        self.enteredCode = []
        self.song = None
        self.autoPlay = False
        self.lastPickPos = None
        self.lastSongPos = 0.0
        self.keyBurstTimeout = None
        self.keyBurstPeriod = 30
        self.camera.target = (0, 0, 4)
        self.camera.origin = (0, 3, -3)

        self.loadSettings()
        self.engine.resource.load(
            self,
            "song",
            lambda: loadSong(self.engine, songName, library=libraryName),
            onLoad=self.songLoaded)

        self.stage = Stage.Stage(self,
                                 self.engine.resource.fileName("stage.ini"))

        self.engine.loadSvgDrawing(self,
                                   "fx2x",
                                   "2x.svg",
                                   textureSize=(256, 256))
        self.engine.loadSvgDrawing(self,
                                   "fx3x",
                                   "3x.svg",
                                   textureSize=(256, 256))
        self.engine.loadSvgDrawing(self,
                                   "fx4x",
                                   "4x.svg",
                                   textureSize=(256, 256))

        Dialogs.showLoadingScreen(self.engine,
                                  lambda: self.song,
                                  text=_("Tuning Guitar..."))

        settingsMenu = Settings.GameSettingsMenu(self.engine)
        settingsMenu.fadeScreen = True

        self.menu = Menu(self.engine, [
            (_("Return to Song"), lambda: None),
            (_("Restart Song"), self.restartSong),
            (_("Change Song"), self.changeSong),
            (_("Settings"), settingsMenu),
            (_("Quit to Main Menu"), self.quit),
        ],
                         fadeScreen=True,
                         onClose=self.resumeGame)

        self.restartSong()

    def pauseGame(self):
        if self.song:
            self.song.pause()

    def resumeGame(self):
        self.loadSettings()
        if self.song:
            self.song.unpause()

    def loadSettings(self):
        self.delay = self.engine.config.get("audio", "delay")
        self.screwUpVolume = self.engine.config.get("audio", "screwupvol")
        self.guitarVolume = self.engine.config.get("audio", "guitarvol")
        self.songVolume = self.engine.config.get("audio", "songvol")
        self.rhythmVolume = self.engine.config.get("audio", "rhythmvol")
        self.guitar.leftyMode = self.engine.config.get("game", "leftymode")

        if self.song:
            self.song.setBackgroundVolume(self.songVolume)
            self.song.setRhythmVolume(self.rhythmVolume)

    def songLoaded(self, song):
        song.difficulty = self.player.difficulty
        self.delay += song.info.delay

        # If tapping is disabled, remove the tapping indicators
        if not self.engine.config.get("game", "tapping"):
            for time, event in self.song.track.getAllEvents():
                if isinstance(event, Note):
                    event.tappable = False

    def quit(self):
        if self.song:
            self.song.stop()
            self.song = None
        self.done = True
        self.engine.view.popLayer(self.menu)
        self.session.world.finishGame()

    def changeSong(self):
        if self.song:
            self.song.stop()
            self.song = None
        self.engine.view.popLayer(self.menu)
        self.session.world.deleteScene(self)
        self.session.world.createScene("SongChoosingScene")

    def restartSong(self):
        self.engine.data.startSound.play()
        self.engine.view.popLayer(self.menu)
        self.player.reset()
        self.stage.reset()
        self.enteredCode = []
        self.autoPlay = False
        self.engine.collectGarbage()

        if not self.song:
            return

        self.countdown = 8.0
        self.guitar.endPick(0)
        self.song.stop()

    def run(self, ticks):
        SceneClient.run(self, ticks)
        pos = self.getSongPosition()

        # update song
        if self.song:
            # update stage
            self.stage.run(pos, self.guitar.currentPeriod)

            if self.countdown <= 0 and not self.song.isPlaying(
            ) and not self.done:
                self.goToResults()
                return

            if self.autoPlay:
                notes = self.guitar.getRequiredNotes(self.song, pos)
                notes = [note.number for time, note in notes]

                changed = False
                held = 0
                for n, k in enumerate(KEYS):
                    if n in notes and not self.controls.getState(k):
                        changed = True
                        self.controls.toggle(k, True)
                    elif not n in notes and self.controls.getState(k):
                        changed = True
                        self.controls.toggle(k, False)
                    if self.controls.getState(k):
                        held += 1
                if changed and held:
                    self.doPick()

            self.song.update(ticks)
            if self.countdown > 0:
                self.guitar.setBPM(self.song.bpm)
                self.countdown = max(self.countdown - ticks / self.song.period,
                                     0)
                if not self.countdown:
                    self.engine.collectGarbage()
                    self.song.setGuitarVolume(self.guitarVolume)
                    self.song.setBackgroundVolume(self.songVolume)
                    self.song.setRhythmVolume(self.rhythmVolume)
                    self.song.play()

        # update board
        if not self.guitar.run(ticks, pos, self.controls):
            # done playing the current notes
            self.endPick()

        # missed some notes?
        if self.guitar.getMissedNotes(self.song,
                                      pos) and not self.guitar.playedNotes:
            self.song.setGuitarVolume(0.0)
            self.player.streak = 0

        # late pick
        if self.keyBurstTimeout is not None and self.engine.timer.time > self.keyBurstTimeout:
            self.keyBurstTimeout = None
            notes = self.guitar.getRequiredNotes(self.song, pos)
            if self.guitar.controlsMatchNotes(self.controls, notes):
                self.doPick()

    def endPick(self):
        score = self.getExtraScoreForCurrentlyPlayedNotes()
        if not self.guitar.endPick(self.song.getPosition()):
            self.song.setGuitarVolume(0.0)
        self.player.addScore(score)

    def render3D(self):
        self.stage.render(self.visibility)

    def renderGuitar(self):
        self.guitar.render(self.visibility, self.song, self.getSongPosition(),
                           self.controls)

    def getSongPosition(self):
        if self.song:
            if not self.done:
                self.lastSongPos = self.song.getPosition()
                return self.lastSongPos - self.countdown * self.song.period - self.delay
            else:
                # Nice speeding up animation at the end of the song
                return self.lastSongPos + 4.0 * (
                    1 - self.visibility) * self.song.period - self.delay
        return 0.0

    def doPick(self):
        if not self.song:
            return

        pos = self.getSongPosition()

        if self.guitar.playedNotes:
            # If all the played notes are tappable, there are no required notes and
            # the last note was played recently enough, ignore this pick
            if self.guitar.areNotesTappable(self.guitar.playedNotes) and \
               not self.guitar.getRequiredNotes(self.song, pos) and \
               pos - self.lastPickPos <= self.song.period / 2:
                return
            self.endPick()

        self.lastPickPos = pos

        if self.guitar.startPick(self.song, pos, self.controls):
            self.song.setGuitarVolume(self.guitarVolume)
            self.player.streak += 1
            self.player.notesHit += len(self.guitar.playedNotes)
            self.player.addScore(len(self.guitar.playedNotes) * 50)
            self.stage.triggerPick(
                pos, [n[1].number for n in self.guitar.playedNotes])
            if self.player.streak % 10 == 0:
                self.lastMultTime = pos
        else:
            self.song.setGuitarVolume(0.0)
            self.player.streak = 0
            self.stage.triggerMiss(pos)
            self.sfxChannel.play(self.engine.data.screwUpSound)
            self.sfxChannel.setVolume(self.screwUpVolume)

    def toggleAutoPlay(self):
        self.autoPlay = not self.autoPlay
        if self.autoPlay:
            Dialogs.showMessage(self.engine,
                                _("Jurgen will show you how it is done."))
        else:
            Dialogs.showMessage(self.engine,
                                _("Jurgen has left the building."))
        return self.autoPlay

    def goToResults(self):
        if self.song:
            self.song.stop()
            self.song = None
            self.done = True
            self.session.world.deleteScene(self)
            self.session.world.createScene("GameResultsScene",
                                           libraryName=self.libraryName,
                                           songName=self.songName)

    def keyPressed(self, key, unicode):
        control = self.controls.keyPressed(key)

        if control in (Player.ACTION1, Player.ACTION2):
            for k in KEYS:
                if self.controls.getState(k):
                    self.keyBurstTimeout = None
                    break
            else:
                self.keyBurstTimeout = self.engine.timer.time + self.keyBurstPeriod
                return True

        if control in (Player.ACTION1, Player.ACTION2) and self.song:
            self.doPick()
        elif control in KEYS and self.song:
            # Check whether we can tap the currently required notes
            pos = self.getSongPosition()
            notes = self.guitar.getRequiredNotes(self.song, pos)

            if self.player.streak > 0 and \
               self.guitar.areNotesTappable(notes) and \
               self.guitar.controlsMatchNotes(self.controls, notes):
                self.doPick()
        elif control == Player.CANCEL:
            self.pauseGame()
            self.engine.view.pushLayer(self.menu)
            return True
        elif key >= ord('a') and key <= ord('z'):
            # cheat codes
            n = len(self.enteredCode)
            for code, func in self.cheatCodes:
                if n < len(code):
                    if key == code[n]:
                        self.enteredCode.append(key)
                        if self.enteredCode == code:
                            self.enteredCode = []
                            self.player.cheating = True
                            func()
                        break
            else:
                self.enteredCode = []

    def getExtraScoreForCurrentlyPlayedNotes(self):
        if not self.song:
            return 0

        noteCount = len(self.guitar.playedNotes)
        pickLength = self.guitar.getPickLength(self.getSongPosition())
        if pickLength > 1.1 * self.song.period / 4:
            return int(.1 * pickLength * noteCount)
        return 0

    def keyReleased(self, key):
        if self.controls.keyReleased(key) in KEYS and self.song:
            # Check whether we can tap the currently required notes
            pos = self.getSongPosition()
            notes = self.guitar.getRequiredNotes(self.song, pos)
            if self.player.streak > 0 and \
               self.guitar.areNotesTappable(notes) and \
               self.guitar.controlsMatchNotes(self.controls, notes):
                self.doPick()
            # Otherwise we end the pick if the notes have been playing long enough
            elif self.lastPickPos is not None and pos - self.lastPickPos > self.song.period / 2:
                self.endPick()

    def render(self, visibility, topMost):
        SceneClient.render(self, visibility, topMost)

        font = self.engine.data.font
        bigFont = self.engine.data.bigFont

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

        self.engine.view.setOrthogonalProjection(normalize=True)
        try:
            # show countdown
            if self.countdown > 1:
                Theme.setBaseColor(min(1.0, 3.0 - abs(4.0 - self.countdown)))
                text = _("Get Ready to Rock")
                w, h = font.getStringSize(text)
                font.render(text, (.5 - w / 2, .3))
                if self.countdown < 6:
                    scale = 0.002 + 0.0005 * (self.countdown % 1)**3
                    text = "%d" % (self.countdown)
                    w, h = bigFont.getStringSize(text, scale=scale)
                    Theme.setSelectedColor()
                    bigFont.render(text, (.5 - w / 2, .45 - h / 2),
                                   scale=scale)

            w, h = font.getStringSize(" ")
            y = .05 - h / 2 - (1.0 - v) * .2

            # show song name
            if self.countdown and self.song:
                Theme.setBaseColor(min(1.0, 4.0 - abs(4.0 - self.countdown)))
                Dialogs.wrapText(font, (.05, .05 - h / 2),
                                 self.song.info.name + " \n " +
                                 self.song.info.artist,
                                 rightMargin=.6,
                                 scale=0.0015)

            Theme.setSelectedColor()

            font.render(
                "%d" % (self.player.score +
                        self.getExtraScoreForCurrentlyPlayedNotes()), (.6, y))
            font.render("%dx" % self.player.getScoreMultiplier(), (.6, y + h))

            # show the streak counter and miss message
            if self.player.streak > 0 and self.song:
                text = _("%d hit") % self.player.streak
                factor = 0.0
                if self.lastPickPos:
                    diff = self.getSongPosition() - self.lastPickPos
                    if diff > 0 and diff < self.song.period * 2:
                        factor = .25 * (1.0 - (diff /
                                               (self.song.period * 2)))**2
                factor = (1.0 + factor) * 0.002
                tw, th = font.getStringSize(text, scale=factor)
                font.render(text, (.16 - tw / 2, y + h / 2 - th / 2),
                            scale=factor)
            elif self.lastPickPos is not None and self.countdown <= 0:
                diff = self.getSongPosition() - self.lastPickPos
                alpha = 1.0 - diff * 0.005
                if alpha > .1:
                    Theme.setSelectedColor(alpha)
                    glPushMatrix()
                    glTranslate(.1, y + 0.000005 * diff**2, 0)
                    glRotatef(math.sin(self.lastPickPos) * 25, 0, 0, 1)
                    font.render(_("Missed!"), (0, 0))
                    glPopMatrix()

            # show the streak balls
            if self.player.streak >= 30:
                glColor3f(.5, .5, 1)
            elif self.player.streak >= 20:
                glColor3f(1, 1, .5)
            elif self.player.streak >= 10:
                glColor3f(1, .5, .5)
            else:
                glColor3f(.5, 1, .5)

            s = min(39, self.player.streak) % 10 + 1
            font.render(Data.BALL2 * s + Data.BALL1 * (10 - s),
                        (.67, y + h * 1.3),
                        scale=0.0011)

            # show multiplier changes
            if self.song and self.lastMultTime is not None:
                diff = self.getSongPosition() - self.lastMultTime
                if diff > 0 and diff < self.song.period * 2:
                    m = self.player.getScoreMultiplier()
                    c = (1, 1, 1)
                    if self.player.streak >= 40:
                        texture = None
                    elif m == 1:
                        texture = None
                    elif m == 2:
                        texture = self.fx2x.texture
                        c = (1, .5, .5)
                    elif m == 3:
                        texture = self.fx3x.texture
                        c = (1, 1, .5)
                    elif m == 4:
                        texture = self.fx4x.texture
                        c = (.5, .5, 1)

                    f = (1.0 - abs(self.song.period * 1 - diff) /
                         (self.song.period * 1))**2

                    # Flash the screen
                    glBegin(GL_TRIANGLE_STRIP)
                    glColor4f(c[0], c[1], c[2], (f - .5) * 1)
                    glVertex2f(0, 0)
                    glColor4f(c[0], c[1], c[2], (f - .5) * 1)
                    glVertex2f(1, 0)
                    glColor4f(c[0], c[1], c[2], (f - .5) * .25)
                    glVertex2f(0, 1)
                    glColor4f(c[0], c[1], c[2], (f - .5) * .25)
                    glVertex2f(1, 1)
                    glEnd()

                    if texture:
                        glPushMatrix()
                        glEnable(GL_TEXTURE_2D)
                        texture.bind()
                        size = (texture.pixelSize[0] * .002,
                                texture.pixelSize[1] * .002)

                        glTranslatef(.5, .15, 0)
                        glBlendFunc(GL_SRC_ALPHA, GL_ONE)

                        f = .5 + .5 * (diff / self.song.period)**3
                        glColor4f(1, 1, 1, min(1, 2 - f))
                        glBegin(GL_TRIANGLE_STRIP)
                        glTexCoord2f(0.0, 0.0)
                        glVertex2f(-size[0] * f, -size[1] * f)
                        glTexCoord2f(1.0, 0.0)
                        glVertex2f(size[0] * f, -size[1] * f)
                        glTexCoord2f(0.0, 1.0)
                        glVertex2f(-size[0] * f, size[1] * f)
                        glTexCoord2f(1.0, 1.0)
                        glVertex2f(size[0] * f, size[1] * f)
                        glEnd()

                        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
                        glPopMatrix()

            # show the comments
            if self.song and self.song.info.tutorial:
                glColor3f(1, 1, 1)
                pos = self.getSongPosition()
                for time, event in self.song.track.getEvents(
                        pos - self.song.period * 2,
                        pos + self.song.period * 4):
                    if isinstance(event, PictureEvent):
                        if pos < time or pos > time + event.length:
                            continue

                        try:
                            picture = event.picture
                        except:
                            self.engine.loadSvgDrawing(
                                event, "picture",
                                os.path.join(self.libraryName, self.songName,
                                             event.fileName))
                            picture = event.picture

                        w, h, = self.engine.view.geometry[2:4]
                        fadePeriod = 500.0
                        f = (1.0 - min(1.0,
                                       abs(pos - time) / fadePeriod) *
                             min(1.0,
                                 abs(pos - time - event.length) / fadePeriod)
                             )**2
                        picture.transform.reset()
                        picture.transform.translate(w / 2,
                                                    (f * -2 + 1) * h / 2)
                        picture.transform.scale(1, -1)
                        picture.draw()
                    elif isinstance(event, TextEvent):
                        if pos >= time and pos <= time + event.length:
                            text = _(event.text)
                            w, h = font.getStringSize(text)
                            font.render(text, (.5 - w / 2, .67))
        finally:
            self.engine.view.resetProjection()
Example #15
0
 def addGuitar(self, serialNumber, price, spec):
     self.guitar = Guitar(serialNumber, price, spec)
     self._guitars.append(self.guitar)