Mundo Maker
¡Bienvenid@ a Mundo Maker!

¿Quieres aprender todo sobre el RPG Maker?



Regístrate y forma parte de Mundo Maker.
Conectarse

Recuperar mi contraseña

Temas importantes
----------------------------------------
Páginas con recursos RPG Maker
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
----------------------------------------
Afiliados
Estadísticas
Tenemos 3763 miembros registrados.
El último usuario registrado es Carlos Rodriguez.

Nuestros miembros han publicado un total de 85779 mensajes en 12216 argumentos.

[Tutorial] iMuse

Ver el tema anterior Ver el tema siguiente Ir abajo

RPG Maker XP [Tutorial] iMuse

Mensaje por Pokepik el 2012-08-24, 13:46

Os intentaré explicar cómo hacer iMuse de dos maneras, la primera haciendo una aproximación, mas facil de hacer pero con inconvenientes, y la otra un iMuse mas real y ajustado.

A quien no sepa qué es el iMuse un gran sabio una vez dijo:
@Orochii escribió:Es algo muy curioso, el cuento es así. En Monkey Island 2 existió un lugar (un cementerio) donde al estar en la parte exterior por decirlo de alguna forma, la música es baja, con algunos instrumentos... o algo así. Al entrar un poco más, la música cambia a otra versión, con distinta instrumentalización, pero sigue desde el mismo "lugar", es decir, como si no hubiera cambiado, como si fuera que la música estuviera hecha así.
El iMuse sirve para hacer transiciones entre canciones, finales alternativos de una canción que loopea según la posición donde acaba, adición de instrumentos en una canción en distintos momentos, etc.

Aproximación de iMuse sin código

Se necesitan dos canciones con el mismo tempo y la misma duración, y que se puedan superponer sin que quede mal.
Teniendo esto ya es muy sencillo pasar de una a la otra.

1) Se copia una en el bgm y otra en el bgs
2) Se crea el mapa poniendo la del bgm al máximo de volumen y la del bgs al mínimo. Así solo se oirá la primera pero en realidad se estaran "leyendo" las dos.
Tienen que tener la misma frecuencia o no pegaran entre ellas.
Cuidado: Si al salir del mapa se cambia de bgm, recuerda quitar también el bgs, o sinó al volver al mapa otra vez ya no irían al mismo tiempo.
3) Creamos un evento que será el que al pulsarlo habrá la transición de música. Puede ser un teletransportador a otro mapa o lo que sea.
4) En él ponemos el los siguientes comandos:
Código:
> Reproducir música: (nombre), 95, 100
> Reproducir sonido: (nombre), 5, 100
> Esperar: 2 frames
> Nota: # Para evitar lag se pueden poner menos intermedios y se notará poco la diferencia
> Reproducir música: (nombre), 90, 100
> Reproducir sonido: (nombre), 10, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 85, 100
> Reproducir sonido: (nombre), 15, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 80, 100
> Reproducir sonido: (nombre), 20, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 75, 100
> Reproducir sonido: (nombre), 25, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 70, 100
> Reproducir sonido: (nombre), 30, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 65, 100
> Reproducir sonido: (nombre), 35, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 60, 100
> Reproducir sonido: (nombre), 40, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 55, 100
> Reproducir sonido: (nombre), 45, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 50, 100
> Reproducir sonido: (nombre), 50, 100
> Esperar: 2 frames
> Nota: # En este punto ha pasado casi un segundo y suenan por igual
> Reproducir música: (nombre), 45, 100
> Reproducir sonido: (nombre), 55, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 40, 100
> Reproducir sonido: (nombre), 60, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 35, 100
> Reproducir sonido: (nombre), 65, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 30, 100
> Reproducir sonido: (nombre), 70, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 25, 100
> Reproducir sonido: (nombre), 75, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 20, 100
> Reproducir sonido: (nombre), 80, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 15, 100
> Reproducir sonido: (nombre), 85, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 10, 100
> Reproducir sonido: (nombre), 90, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 5, 100
> Reproducir sonido: (nombre), 95, 100
> Esperar: 2 frames
> Reproducir música: (nombre), 0, 100
> Reproducir sonido: (nombre), 100, 100
> Esperar: 2 frames
Para hacer la transición al revés será lo mismo pero con los números girados.

iMuse ajustado con código

Necesitaremos el MCI Audio Player de ForeverZer0. Hay otros pero creo que este es el mejor para esto.
Lo edité un poco yo misma XD
Spoiler:
Código:
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
# MCI Audio Player
# Author: ForeverZer0
# Version: 1.2
# Date: 7.8.2012
# Editado por: Pokepik
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
#    - play(FILENAME, VOLUME, SPEED, REPEAT)
#    - pause
#    - restart
#    - resume
#    - stop
#    - close
#    - volume/volume=
#    - fade(DURATION, FRAMES)
#    - speed/speed=
#    - duration
#    - position/position=
#    - seek(MILLISECOND)
#    - playing?
#    - paused?
#    - status
#   
#    Audio['myName'].play('myFile.mp3')
#
#    From here on, you can access the same mixer using 'myName' as the key to
#    perform further actions. Such as...
#
#    Audio['myName'].pause            - Pauses playback
#    Audio['myName'].resume          - Resumes playback
#    Audio['myName'].volume = 50      - Sets volume to fifty
#    Audio['myName'].fade(80, 0)      - Fades volume to 0 in 80 frames
#    Audio['myName'].fade(240, 100)  - Transitions volume to 100 in 6 seconds
#    Audio['myName'].record          - Begins recording
#    Audio['myName'].save('file.wav') - Saves recorded file
#    Audio['myName'].seek(4500)      - Sets playback position to 4.5 seconds
#
#    As you can see, all mixers are accessed in a hash-like way via the Audio
#    module. By default, 'BGM', 'BGS', 'ME', and 'SE' are mixers used as
#    replacements for the built-in audio library, so use names other them if
#    creating additional mixers.
#
#    There is also a script call to make a call using mciSendString if you are
#    familiar with the library at all. I simplified it down a bit, but it can
#    be used with the following snippet:
#
#        Audio.mci_eval(MCI_COMMAND)
#
#    For more information about using MCI commands, please see the full
#    documentation at MSDN.
#
# http://msdn.microsoft.com/en-us/library/windows/desktop/dd743572(v=vs.85).aspx
#
#    There are also a few methods available via the Game_System class for
#    memorizing/restoring audio at its current position.
#
#    ex.
#
#    $game_system.memorize_audio              - Memorize all channels
#    $game_system.memorize_audio('BGM')        - Memorize BGM channel
#    $game_system.memorize_audio('BGM', 'BGS') - Memorize BGM and BGS channels
#    $game_system.restore_audio                - Restore all channels
#    $game_system.restore_audio('BGM')        - Restore BGM channel
#    $game_system.restore_audio('BGM', 'BGS')  - Restore BGM and BGS channels
#
#    You can use as many arguments for each method as you wish. Omitting
#    arguments will simply have it memorize/restore all channels.
#
# Compatibility:
#
#  - Not tested on Linux running under Wine. If anyone tests this, let me know.
#  - Not compatible with DREAM.
#
# Credits/Thanks:
#
#  - ForeverZer0, for the script
#
# Authors Notes:
#
#  - Changing pitch will be different. MCI does not have a function for this,
#    so I am changing the speed as a generic substitute. Changing the speed
#    does change the pitch, but it true sound pitch alters the sampling rate
#    as well, which this player does not. You have a couple alternatives if
#    you absolutely need the pitch change:
#
#    1. Edit the files using an external editor and import it
#    2. Use the default system to play such sounds using the alias names.
#
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=

#===============================================================================
# ** Audio
#===============================================================================

module Audio

  # Set true/false if the MCI Player should be the default audio controller. It
  # will maintain all the same functionality as the standard control, and all
  # normal calls to the Audio module will work as normal, but it will also
  # extend the its functionality. If false, RMXP's standard library will be used
  # and this player will only be used for custom mixers.
  MCI_DEFAULT = true
 
  # Due to vast differences in how the format is handled, some of this player's
  # features do not work with MIDI, most notably volume control, which also
  # effects fading. I have created alternate controls to control MIDI volume,
  # but they can only work with the sacrifice of many other functions, and the
  # volume applies to ALL playing MIDIs, not just the one the volume is applied
  # to. I decided this was not worth it, so I omitted volume control. If you
  # are willing to make them sacrifices, you can enable this mode by setting
  # MIDI_MODE to true. If you your game relies heavily on MIDI, but you still
  # would like to use this script, there are conversion programs available,
  # which I can assist you with if need be.
  MIDI_MODE = false
 
  # Enter the code for the version of RPG Maker you are using this script for.
  #  RMXP  = 0
  #  RMVX  = 1
  #  RMVXA = 2
  RPG_VERSION = 0
 
#===============================================================================
# ** Mixer
#-------------------------------------------------------------------------------
# This class acts a wrapper for Window's Media Control Interface (MCI).
#===============================================================================

  MCISendString = Win32API.new('winmm', 'mciSendString', 'PPLL', 'L')
  MIDIOutSetVolume = Win32API.new('winmm', 'midiOutSetVolume', 'LL', 'L')

  class Mixer
   
    attr_reader :name          # The arbitrary name of the mixer
    attr_reader :filepath      # The path of the currently loaded file
    attr_reader :repeat        # Flag if playback is set to repeat
    attr_reader :filename
   
    #---------------------------------------------------------------------------
    # * Object Initialization
    #    name    : The unique name of the mixer
    #---------------------------------------------------------------------------
    def initialize(name)
      @name = name
      @fade_duration = 0
      @fade_volume = 0
      @filename = filename
      @opened = false
      @repeat = false
      @midi = false
    end
    #---------------------------------------------------------------------------
    # * Load a file and prepare for playback
    #    filename  : The path to the file.
    #---------------------------------------------------------------------------
    def open(filename)
      @filename = filename
      if File.exists?(filename)
        path = filename
      else
        path = Dir::glob(filename + '.*')[0]
        if path == nil
          directory = File.dirname(filename)
          if RTP.subfolder?(directory)
            file = File.basename(filename)
            path = RTP[directory].find {|f| File.basename(f, '.*') == file }
          end
        end
      end
      @filepath = path.gsub(/\\/, '/')
      if MIDI_MODE && ['.mid', '.midi'].include?(File.extname(path))
        @midi = true
        cmd = "open \"#{path}\" type sequencer alias #{@name}"
      else
        cmd = "open \"#{path}\" type mpegvideo alias #{@name}"
      end
      MCISendString.call(cmd, nil, 0, 0)
      MCISendString.call("set #{@name} time format milliseconds", nil, 0, 0)
      MCISendString.call("set #{@name} seek exactly on", nil, 0, 0)
      @opened = true
    end
    #---------------------------------------------------------------------------
    # * Began playback on the mixer
    #    filename  : The name of the file to play
    #    volume    : The volume to play the file at
    #    speed    : The speed to play the the fule at
    #    repeat    : Flag if playback should loop after done playing
    #    start    : The position, in milliseconds, to begin playback at
    #---------------------------------------------------------------------------
    def play(filename, volume = 100, speed = 100, repeat = false, start = 0)
      @filename = filename
      self.close
      self.open(filename)
      self.speed = speed
      if MIDI_MODE && @midi
        @midi_master = @midi_right = @midi_left = volume * 10
        self.set_volume(volume)
        MCISendString.call("play #{@name} from 0", nil, 0, 0)
        return
      end
      self.set_volume(volume)
      @repeat = repeat
      if start != 0
        MCISendString.call("seek #{@name} to #{start}", nil, 0, 0)
      else
        MCISendString.call("seek #{@name} to start", nil, 0, 0)
      end
      MCISendString.call("play #{@name}#{repeat ? ' repeat' : ''}", nil, 0, 0)
    end
    #---------------------------------------------------------------------------
    # * Restarts playback of the currently loaded file from the beginning
    #---------------------------------------------------------------------------
    def restart
      MCISendString.call("seek #{@name} to start", nil, 0, 0)
      MCISendString.call("play #{@name}#{repeat ? ' repeat' : ''}", nil, 0, 0)
    end
    #---------------------------------------------------------------------------
    # * Pause playback and maintain current position
    #---------------------------------------------------------------------------
    def pause
      MCISendString.call("pause #{@name}", nil, 0, 0)
    end
    #---------------------------------------------------------------------------
    # * Resume playback on a paused mixer from previous position
    #---------------------------------------------------------------------------
    def resume
      MCISendString.call("resume #{@name}", nil, 0, 0)
    end
    #---------------------------------------------------------------------------
    # * Stops playback, setting position back to the start
    #---------------------------------------------------------------------------
    def stop
      MCISendString.call("seek #{@name} to start", nil, 0, 0)
      MCISendString.call("stop #{@name}", nil, 0, 0)
    end
    #---------------------------------------------------------------------------
    # * Closes the opened file and frees it from memory
    #---------------------------------------------------------------------------
    def close
      MCISendString.call("close #{@name}", nil, 0, 0)
      @filepath = nil
      @opened = false
    end
    #---------------------------------------------------------------------------
    # * Gets the actual volume of the mixer, an integer from 0 to 1000
    #---------------------------------------------------------------------------
    def real_volume
      if MIDI_MODE && @midi
        return @midi_master
      else
        data = "\0" * 128
        MCISendString.call("status #{@name} volume", data, 128, 0)
        return data.delete("\0").to_i
      end
    end
    #---------------------------------------------------------------------------
    # * Sets the actual volume of the mixer
    #    value    : The volume level, integer between 0 and 1000
    #---------------------------------------------------------------------------
    def real_volume=(value)
      self.set_real_volume(value)
    end
    #---------------------------------------------------------------------------
    # * Sets the actual volume of the mixer
    #    value    : The volume level, integer between 0 and 1000
    #---------------------------------------------------------------------------
    def set_real_volume(value)
      vol = [0, [value, 1000].min].max
      if MIDI_MODE && @midi
        @midi_master = value
        self.set_midi_volume(value, value)
      else
        MCISendString.call("setaudio #{@name} volume to #{vol}", nil, 0, 0)
      end
    end
    #---------------------------------------------------------------------------
    # * Returns the volume of the mixer
    #---------------------------------------------------------------------------
    def volume
      return self.real_volume / 10   
    end
    #---------------------------------------------------------------------------
    # * Sets the volume of the mixer
    #    value    : The volume level, integer between 0 and 100
    #---------------------------------------------------------------------------
    def volume=(value)
      value = [0, [value, 100].min].max
      self.set_real_volume(value * 10)
    end
    #---------------------------------------------------------------------------
    # * Sets the volume of the mixer
    #    value    : The volume level, integer between 0 and 100
    #---------------------------------------------------------------------------
    def set_volume(value)
      value = [0, [value, 100].min].max
      self.set_real_volume(value * 10)
    end
    #---------------------------------------------------------------------------
    # * Set the volume of the mixer in the left speaker only
    #    value  : Volume level, integer between 0 and 100
    #---------------------------------------------------------------------------
#    def set_volume_left(value)
#      vol = [0, [value * 10, 1000].min].max
#      if MIDI_MODE && @midi
#        self.set_midi_volume(value, @midi_right)
#      else
#        MCISendString.call("setaudio #{@name} left volume to #{vol}", nil, 0, 0)
#      end
#    end
    #---------------------------------------------------------------------------
    # * Set the volume of the mixer in the right speaker only
    #    value  : Volume level, integer between 0 and 100
    #---------------------------------------------------------------------------
#    def set_volume_right(value)
#      vol = [0, [value * 10, 1000].min].max
#      if MIDI_MODE && @midi
#        self.set_midi_volume(@midi_left, value)
#      else
#        MCISendString.call("setaudio #{@name} right volume to #{vol}", nil, 0, 0)
#      end
#    end
    #---------------------------------------------------------------------------
    # * Special handling for adjusting MIDI volume. MCI cannot handle the volume
    #  for this format directly, so we need to precalculate the channels and
    #  make the call to the MIDI synthesizer ourselves.
    #    left    : The volume of the left channel
    #    right  : The volume of the right channel
    #
    #  NOTE:
    #  It is recommended that you do not call this method directly.
    #---------------------------------------------------------------------------
    def set_midi_volume(left, right)
      @midi_left, @midi_right = left, right
      left = (0xFFFF * (left / 1000.0)).round
      right = (0xFFFF * (right / 1000.0)).round
      vol = right.to_s(16) + left.to_s(16)
      MIDIOutSetVolume.call(0, vol.to_i(16))
    end
    #---------------------------------------------------------------------------
    # * Mutes sound from the mixer
    #    bool    : True/false flag to mute/unmute sound
    #---------------------------------------------------------------------------
#    def mute(bool)
#      MCISendString.call("setaudio #{@name} #{bool ? 'on' : 'off'}", nil, 0, 0)
#    end
    #---------------------------------------------------------------------------
    # * Transition volume to another volume
    #    duration    : The number of frames the transition will take
    #    target      : The target volume to transition to
    #---------------------------------------------------------------------------
    def fade(duration, target = 0)
      @fade_volume = target * 10
      @fade_duration = [duration, 1].max
    end
    #---------------------------------------------------------------------------
    # * Returns the current speed of playback  (100 = normal)
    #---------------------------------------------------------------------------
    def speed
      data = "\0" * 256
      MCISendString.call("status #{@name} speed", data, 256, 0)
      data.delete!("\0")
      return data.to_i / 10
    end
    #---------------------------------------------------------------------------
    # * Set the current speed of playback
    #    value  : The rate of playback to set
    #---------------------------------------------------------------------------
    def speed=(value)
      set_speed(value)
    end
    #---------------------------------------------------------------------------
    # * Set the current speed of playback
    #    value  : The rate of playback to set
    #---------------------------------------------------------------------------
    def set_speed(value)
      value = [0, [2000, value * 10].min].max
      MCISendString.call("set #{@name} speed #{value}", nil, 0, 0)
    end
    #---------------------------------------------------------------------------
    # * Gets the length of the loaded file in milliseconds
    #---------------------------------------------------------------------------
    def duration
      if self.playing?
        length = "\0" * 256
        MCISendString.call("status #{@name} length", length, 256, 0)
        length.delete!("\0")
        return length.to_i
      end
      return 0
    end
    #---------------------------------------------------------------------------
    # * Returns duration as a string in normal MM:SS format
    #---------------------------------------------------------------------------
    def duration_string
      seconds = self.duration / 1000
      return sprintf('%2d:%02d', seconds / 60, seconds % 60)
    end
    #---------------------------------------------------------------------------
    # * Returns the current position of playback, in milliseconds
    #---------------------------------------------------------------------------
    def position
      pos = "\0" * 256
      MCISendString.call("status #{@name} position", pos, 256, 0)
      pos.delete!("\0")
      return pos.to_i
    end
    #---------------------------------------------------------------------------
    # * Returns current position as a string in normal MM:SS format
    #---------------------------------------------------------------------------
    def position_string
      seconds = self.position / 1000
      return sprintf('%2d:%02d', seconds / 60, seconds % 60)
    end
    #---------------------------------------------------------------------------
    # * Returns current position as a string in normal MM:SS format
    #---------------------------------------------------------------------------
    def position_frames
      return self.position / 50
    end
    #---------------------------------------------------------------------------
    # * Returns current position as a string in normal MM:SS format
    #---------------------------------------------------------------------------
    def duration_frames
      return self.duration / 50
    end
    #---------------------------------------------------------------------------
    # * Sets the current playback position
    #    value  : The time in milliseconds to set current playback
    #---------------------------------------------------------------------------
    def position=(value)
      self.seek(value)
    end
    #---------------------------------------------------------------------------
    # * Sets the current playback position
    #    value  : The time in milliseconds to set current playback
    #---------------------------------------------------------------------------
    def seek(value)
      cmd = "#{self.playing? ? 'play' : 'seek'} #{@name} from #{value}"
      MCISendString.call(cmd, nil, 0, 0)
    end
    #---------------------------------------------------------------------------
    # * Returns tha "playing" status of the mixer
    #---------------------------------------------------------------------------
    def playing?
      return self.status == 'playing'
    end
    #---------------------------------------------------------------------------
    # * Returns tha "paused" status of the mixer
    #---------------------------------------------------------------------------
    def paused?
      return self.status == 'paused'
    end
    #---------------------------------------------------------------------------
    # * Returns true/false if file is currently loaded for playback
    #---------------------------------------------------------------------------
    def opened?
      return @opened
    end
    #---------------------------------------------------------------------------
    # * Returns true/false if mixer is currently recording
    #---------------------------------------------------------------------------
#    def recording?
#      return self.status == 'recording'
#    end
    #---------------------------------------------------------------------------
    # * Returns the mixer's bass value
    #---------------------------------------------------------------------------
#    def treble
#      data = "\0" * 128
#      MCISendString.call("status #{@name} treble", data, 128, 0)
#      data.delete!("\0")
#      return data.to_i
#    end
    #---------------------------------------------------------------------------
    # * Set mixer treble
    #    value  : Treble value, integer between 0 and 1000
    #---------------------------------------------------------------------------
#    def treble=(value)
#      set_treble(value)
#    end
    #---------------------------------------------------------------------------
    # * Set mixer treble
    #    value  : Treble value, integer between 0 and 1000
    #---------------------------------------------------------------------------
#    def set_treble(value)
#      value = [0, [value, 1000].min].max
#      MCISendString.call("setaudio #{@name} treble to #{value}", nil, 0, 0)
#    end
    #---------------------------------------------------------------------------
    # * Returns the mixer's bass value
    #---------------------------------------------------------------------------
#    def bass
#      data = "\0" * 128
#      MCISendString.call("status #{@name} bass", data, 128, 0)
#      data.delete!("\0")
#      return data.to_i
#    end
    #---------------------------------------------------------------------------
    # * Set mixer bass
    #    value  : Bass value, integer between 0 and 1000
    #---------------------------------------------------------------------------
#    def bass=(value)
#      set_bass(value)
#    end
    #---------------------------------------------------------------------------
    # * Set mixer bass
    #    value  : Bass value, integer between 0 and 1000
    #---------------------------------------------------------------------------
#    def set_bass(value)
#      value = [0, [value, 1000].min].max
#      MCISendString.call("setaudio #{@name} bass to #{value}", nil, 0, 0)
#    end
    #---------------------------------------------------------------------------
    # * Gets the current status
    #---------------------------------------------------------------------------
    def status
      data = "\0" * 256
      MCISendString.call("status #{@name} mode", data, 256, 0)
      return data.delete("\0")
    end
    #---------------------------------------------------------------------------
    # * Begins recording from the input, typically the PC's microphone
    #    bits_ps    : Bits per sample the file will be recorded at
    #    sample_rate : Sample rate the the file will be recorded at
    #    channels    : Number of channels that will be opened for recording
    #
    #  * WARNING *
    #    Make sure that "stop", "close" or "save" is performed on this mixer
    #    within a reasonable of amount of time. While the mixer is recording,
    #    the file is held in RAM, which will become very large if left without
    #    closing it, and eventually slow down the PC and/or crash the game.
    #    Basically I'm just saying "don't forget you are recording"
    #---------------------------------------------------------------------------
#    def record(bits_ps = 16, sample_rate = 44100, channels = 2)
#      self.close
#      MCISendString.call("open new type waveaudio alias #{@name}", nil, 0, 0)
#      MCISendString.call("set #{@name} bitspersample #{bits_ps}", nil, 0, 0)
#      MCISendString.call("set #{@name} samplespersec #{sample_rate}", nil, 0, 0)
#      MCISendString.call("set #{@name} channels #{channels}", nil, 0, 0)
#      MCISendString.call("record #{@name}", nil, 0, 0)
#    end
    #---------------------------------------------------------------------------
    # * Saves a recording into WAV format
    #    filename  : The path of the file t save, must have '.wav' extension
    #---------------------------------------------------------------------------
#    def save(filename)
#      if self.recording?
#        MCISendString.call("stop #{@name}", nil, 0, 0)
#      end
#      if File.extname(filename) != '.wav'
#        filename += '.wav'
#      end
#      MCISendString.call("save #{@name} #{filename}", nil, 0, 0)
#      MCISendString.call("close #{@name}", nil, 0, 0)
#    end
    #---------------------------------------------------------------------------
    # * Frame update
    #---------------------------------------------------------------------------
    def update
      if @fade_duration >= 1
        d = @fade_duration
        self.set_real_volume((self.real_volume * (d - 1) + @fade_volume) / d)
        @fade_duration -= 1
      end
    end
  end

#===============================================================================
# ** Audio
#-------------------------------------------------------------------------------
# The metaclass of the Audio module. This class is a wrapper between the default
# audio controls and the MCI Player controls.
#===============================================================================
 
  class << self
    #---------------------------------------------------------------------------
    # * Use MCI Player play function
    #---------------------------------------------------------------------------
    alias mci_bgm_play bgm_play
    def bgm_play(filename, volume = 100, pitch = 100, start = 0)
      if MCI_DEFAULT
        mixer_play('BGM', filename, volume, pitch, true, start)
      elsif RPG_VERSION == 2
        mci_bgm_play(filename, volume, pitch, start)
      else
        mci_bgm_play(filename, volume, pitch)
      end
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player play function
    #---------------------------------------------------------------------------
    alias mci_bgs_play bgs_play
    def bgs_play(filename, volume = 100, pitch = 100, start = 0)
      if MCI_DEFAULT
        mixer_play('BGS', filename, volume, pitch, true, start)
      elsif RPG_VERSION == 2
        mci_bgs_play(filename, volume, pitch, start)
      else
        mci_bgs_play(filename, volume, pitch)
      end
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player play function
    #---------------------------------------------------------------------------
    alias mci_me_play me_play
    def me_play(filename, volume = 100, pitch = 100, start = 0)
      if MCI_DEFAULT
        mixer_play('ME', filename, volume, pitch, false, start)
      elsif RPG_VERSION == 2
        mci_me_play(filename, volume, pitch, start)
      else
        mci_me_play(filename, volume, pitch)
      end
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player play function
    #---------------------------------------------------------------------------
    alias mci_se_play se_play
    def se_play(filename, volume = 100, pitch = 100, start = 0)
      if MCI_DEFAULT
        mixer_play('SE', filename, volume, pitch, false, start)
      elsif RPG_VERSION == 2
        mci_se_play(filename, volume, pitch, start)
      else
        mci_se_play(filename, volume, pitch, start)
      end
    end
    #---------------------------------------------------------------------------
    # Use MCI Player to play a file on a mixer using given parameters
    #---------------------------------------------------------------------------
    def mixer_play(mixer_name, filename, volume, pitch, repeat, start = 0)
      self[mixer_name].play(filename, volume, pitch, repeat, start)
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player stop
    #---------------------------------------------------------------------------
    alias mci_bgm_stop bgm_stop
    def bgm_stop
      MCI_DEFAULT ? @mixers['BGM'].stop : mci_bgm_stop
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player stop
    #---------------------------------------------------------------------------
    alias mci_bgs_stop bgs_stop
    def bgs_stop
      MCI_DEFAULT ? @mixers['BGS'].stop : mci_bgs_stop
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player stop
    #---------------------------------------------------------------------------
    alias mci_me_stop me_stop
    def me_stop
      MCI_DEFAULT ? @mixers['ME'].stop : mci_me_stop
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player stop
    #---------------------------------------------------------------------------
    alias mci_se_stop se_stop
    def se_stop
      MCI_DEFAULT ? @mixers['SE'].stop : mci_se_stop
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player fade
    #---------------------------------------------------------------------------
    alias mci_bgm_fade bgm_fade
    def bgm_fade(time)
      rate = RPG_VERSION == 0 ? 40 : 60
      MCI_DEFAULT ? @mixers['BGM'].fade((time / 1000) * rate) :
        mci_bgm_fade(time)
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player fade
    #---------------------------------------------------------------------------
    alias mci_bgs_fade bgs_fade
    def bgs_fade(time)
      rate = RPG_VERSION == 0 ? 40 : 60
      MCI_DEFAULT ? @mixers['BGS'].fade((time / 1000) * rate) :
        mci_bgs_fade(time)
    end
    #---------------------------------------------------------------------------
    # * Use MCI Player fade
    #---------------------------------------------------------------------------
    alias mci_me_fade me_fade
    def me_fade(time)
      rate = RPG_VERSION == 0 ? 40 : 60
      MCI_DEFAULT ? @mixers['ME'].fade((time / 1000) * rate) :
        mci_me_fade(time)
    end
  end
  #-----------------------------------------------------------------------------
  # * Gives hash-type access of the mixers of the module
  #-----------------------------------------------------------------------------
  def self.[](mixer_name)
    unless @mixers.has_key?(mixer_name)
      @mixers[mixer_name] = Mixer.new(mixer_name)
    end
    return @mixers[mixer_name]
  end
  #-----------------------------------------------------------------------------
  # * Frame update
  #-----------------------------------------------------------------------------
  def self.update
    @mixers.each_value {|mixer| mixer.update }
  end
  #-----------------------------------------------------------------------------
  # * Simplified method for making calls directly to the Media Command Interface
  #-----------------------------------------------------------------------------
  def self.mci_eval(command)
    data = "\0" * 256
    MCISendString.call(command, data, 256, 0)
    return data.delete("\0")
  end
  #-----------------------------------------------------------------------------
  # * Iterator for the Audio mixers
  #-----------------------------------------------------------------------------
  def self.each_mixer
    @mixers.each_value {|mixer| yield mixer }
  end
  #-----------------------------------------------------------------------------
  # * Object initialization
  #-----------------------------------------------------------------------------
  def self.init
    if @mixers != nil
      # Don't remove this, it prevents memory leaks when F12 us used to restart
      MCISendString.call('close all', nil, 0, 0)
    end
    @mixers = {}
    ['BGM', 'BGS', 'ME', 'SE'].each {|name| @mixers[name] = Mixer.new(name) }
  end 
end

#===============================================================================
# ** Graphics
#-------------------------------------------------------------------------------
# Syncs the audio update used for fade effects with the frame update
#===============================================================================
module Graphics
 
  class << self
   
    alias mci_player_update update
    def update
      mci_player_update
      Audio.update
    end
  end
end

#===============================================================================
# ** RTP
#-------------------------------------------------------------------------------
# Provides functions for getting the games RTP path(s) and files
#===============================================================================

module RTP
 
  # RMXP
  if Audio::RPG_VERSION == 0
    SUBFOLDERS = [
      'Graphics/Animations', 'Graphics/Autotiles', 'Graphics/Battlebacks',
      'Graphics/Battlers', 'Graphics/Characters', 'Graphics/Fogs',
      'Graphics/Gameovers', 'Graphics/Icons', 'Graphics/Panoramas',
      'Graphics/Pictures', 'Graphics/Tilesets', 'Graphics/Titles',
      'Graphics/Transitions', 'Graphics/Windowskins', 'Audio/BGM',
      'Audio/BGS', 'Audio/ME', 'Audio/SE'
    ]
  # RMVX
  elsif Audio::RPG_VERSION == 1
    SUBFOLDERS = [
      'Graphics/Animations', 'Graphics/Battlers', 'Graphics/Characters',
      'Graphics/Faces', 'Graphics/Parallaxes', 'Graphics/Pictures',
      'Graphics/System', 'Audio/BGM', 'Audio/BGS', 'Audio/ME', 'Audio/SE'
    ]
  # RMVXA
  elsif Audio::RPG_VERSION == 2
    SUBFOLDERS = [
      'Graphics/Animations', 'Graphics/Battlers', 'Graphics/Characters',
      'Graphics/Faces', 'Graphics/Parallaxes', 'Graphics/Pictures',
      'Graphics/System', 'Audio/BGM', 'Audio/BGS', 'Audio/ME', 'Audio/SE'
    ]
  end
  #-----------------------------------------------------------------------------
  # * Object initialization
  #-----------------------------------------------------------------------------
  def self.init
    @ini = Win32API.new('kernel32', 'GetPrivateProfileStringA', 'PPPPLP', 'L')
    @library = "\0" * 256
    @ini.call('Game', 'Library', '', @library, 256, '.\\Game.ini')
    @library.delete!("\0")
    @rtp_path = Win32API.new(@library, 'RGSSGetRTPPath', 'L', 'L')
    @path_with_rtp = Win32API.new(@library, 'RGSSGetPathWithRTP', 'L', 'P')
    @directories = {}
    SUBFOLDERS.each {|folder| @directories[folder] = entries(folder) }
    @initialized = true
  end
  #-----------------------------------------------------------------------------
  # * Returns an array of the full paths of all the game's installed RTPs
  #-----------------------------------------------------------------------------
  def self.paths
    paths = [1, 2, 3].collect {|id| @path_with_rtp.call(@rtp_path.call(id)) }
    paths = paths.find_all {|path| path != '' }
    # This is kind of a crappy way of doing this until the RMVX call works...
    common = File.join(ENV['CommonProgramFiles'], 'Enterbrain')
    common = case Audio::RPG_VERSION
    when 0 then File.join(common, 'RGSS', 'Standard')
    when 1 then File.join(common, 'RGSS2', 'RPGVX')
    when 2 then File.join(common, 'RGSS3', 'RPGVXAce')
    end
    if !paths.include?(common) && File.directory?(common)
      paths.push(common)
    end
    return paths
  end
  #-----------------------------------------------------------------------------
  # * Gives hash-like access to the RTP subfolders
  #-----------------------------------------------------------------------------
  def self.[](folder)
    return subfolder?(folder) ? @directories[folder] : []
  end
  #-----------------------------------------------------------------------------
  # * Returns true/false if the given subfolder exists
  #-----------------------------------------------------------------------------
  def self.subfolder?(folder)
    return @directories.has_key?(folder)
  end
  #-----------------------------------------------------------------------------
  # * Get a complete list of full paths of files found in the given subfolder
  #  subfolder  : The RTP folder whose files you want to get
  #-----------------------------------------------------------------------------
  def self.entries(subfolder)
    files = []
    paths.each {|path|
      dir = path + '\\' + subfolder
      if File.directory?(dir)
        files = (Dir.entries(dir) - ['.', '..']).collect {|f| dir + '\\' + f }
      end
    }
    return files
  end
end

#===============================================================================
# ** Game_System
#===============================================================================

class Game_System
  #-----------------------------------------------------------------------------
  # * Public Instance Variables
  #-----------------------------------------------------------------------------
  attr_accessor :memorized_audio
  #-----------------------------------------------------------------------------
  # * Memorize Audio
  #      channels : Names of channels, or omit argument to memorize all channels
  #-----------------------------------------------------------------------------
  def memorize_audio(*channels)
    @audio_memory = {}
    if channels.empty?
      Audio.each_mixer {|m|
        data = [m.filepath, m.volume, m.speed, m.repeat, m.position]
        @audio_memory[m.name] = data
      }
    else
      channels.each {|channel|
        m = Audio[channel]
        data = [m.filepath, m.volume, m.speed, m.repeat, m.position]
        @audio_memory[channel] = data
      }
    end
  end
  #-----------------------------------------------------------------------------
  # * Restore Audio
  #      channels : Names of channels, or omit argument to restore all channels
  #-----------------------------------------------------------------------------
  def restore_audio(*channels)
    unless @audio_memory == nil || @audio_memory.empty?
      keys = channels.empty? ? @audio_memory.keys : channels
      keys.each {|name|
        data = @audio_memory[name]
        if data != nil && data[0] != nil
          Audio[name].play(data[0], data[1], data[2], data[3])
          Audio[name].seek(data[4])
          @audio_memory.delete(name)
        end
      }
    end
  end
end

# Intialize the MCI Player
RTP.init
Audio.init

Luego aquí vienen las complicaciones.
1) Primero creamos un mapa y ponemos una cancion (nombre de ejemplo: "A")
2) Creamos un Interruptor que se llame Music Transition y una variable que se llame Music Wait
3) Creamos un evento de transportación o lo que sea, donde tiene que ir la transición de música, y ponemos en él lo siguiente:
Código:
> Operaciones de Interruptor: [Music Transition] = ON
> Teletransportar Mapa 2
> Condiciones y Efectos: Script: Audio['BGM'].filename=="Audio/BGM/"A""
> Script: pos = Audio['BGM'].position_frames
      dur = Audio['BGM'].duration_frames
      case pos
      # Puntos de transición
      # Se multiplican los segundos por 20 para tener los frames
      # Music_Wait se consigue mirando cuanto falta para el siguiente punto
      when 0...260 # 0:14
         $game_variables[1]=(260-pos)
      when 280...520 # 0:26
         $game_variables[1]=(520-pos)
      when 520...820 # 0:41
         $game_variables[1]=(820-pos)
      when 820...1120 # 0:56
         $game_variables[1]=(1120-pos)
      when 1120...1360 # 1:08
         $game_variables[1]=(1360-pos)
      when 1360...dur
         $game_variables[1]=(dur-pos)
      end
> Operaciones de Interruptor: [Music Transition] = OFF
4) Vamos al otro mapa.
Nota: En propiedades de Mapa dejamos lo de la canción vacía.
En este segundo mapa creamos un evento en Proceso Paralelo solo activado con el interruptor Music Transition y le ponemos lo siguiente:
Código:
> Condiciones y efectos: Variable [Music Wait] > 0
>> Esperar: 1 frame
>> Operaciones de Variable [Music Wait] -= 1
> Excepción
>> Operaciones de Interruptor [Music Transition] = OFF
>> Reproducir Música: "B"
> End
Este código lo que hace es que al volver a este mapa desde el otro, pasado el tiempo Music Wait que dependerá de la posición de la otra canción "B", vuelva a reproducirse la canción "A"

Y así se consigue la transición de música de un mapa a otro.
Siento no poder poner ninguna demo. Espero que se haya entendido, al menos la manera facil.
avatar
Pokepik
Principiante
Principiante

0/3

Créditos 1834

Gracias : 4

Volver arriba Ir abajo

RPG Maker XP Re: [Tutorial] iMuse

Mensaje por Wecoc el 2012-09-02, 02:46

La aproximación sin código viene a ser lo que se me había ocurrido a mí tambien xD Creo que a nivel de RPG maker, mas que nada por no complicarse la vida demasiado, con la manera aproximada hay suficiente.

Ademas vi un error en la otra. El MCI Audio Player no está pensado para esto en realidad y por eso sale un error; usando este código luego pasa que si estas en un mapa y vas a otro que tiene la misma bgm, en vez de continuar tal y como pasaba hasta ahora, se reinicia. Y seguro que en algún caso mas igual; bgm y bgs se reinician cuando no deberían.

Resumiendo, si se quiere usar iMuse mejor lo primero y ya está, al menos hasta que salga (si saliera) un script definitivo de iMuse para RPG maker.

iMuse no es algo sencillo de programar en RGSS, pero bueno cosas mas grandes se han hecho.
El problema viene también del otro lado: tampoco es algo facil de hacer como composición.
avatar
Wecoc
Administrador
Administrador



Créditos 9370

Gracias : 517

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba


Permisos de este foro:
No puedes responder a temas en este foro.