So, gestern habe ich mein erstes Script fertiggestellt. Es bedarf sicherlich einiger stilistischer Verbesserung, ich plane auch, noch mehr Features einzufügen, aber der Musikspieler steht soweit.
Die Funktionen:
- Jede beliebige Musik aus dem BGM-Ordner abspielen
- Pitch zwischen 5 und 225 regulieren
- Lautstärke zwischen 50 und 100 Prozent verändern
Geplant für die nächsten Versionen:
- Saubererer Codestil
- Mehr Kommentare
- Ausblendemöglichkeit für die Erklärung
- Evtl. Bewegender Hintergrund
– Evtl. grafische Aufbesserung
Benötigt wird das Scene-Script von KD:
Code:
#==============================================================================
# ** Scene
#------------------------------------------------------------------------------
# Die Superklasse für unsere Szenen
#==============================================================================
class Scene
#--------------------------------------------------------------------------
# * Ablauf der Szene (durch Main-Script aufgerufen)
#--------------------------------------------------------------------------
def main()
# Initialisierung der Instanzvariablen
load_contents()
# Ausführen des Überblendeffektes
Graphics.transition
# Hauptschleife
loop do
# Aktualisieren der Grafiken
Graphics.update
# Aktualisieren der Tasteneingabe
Input.update
# Aktualisieren der Instanzvariablen
update
# Abbruch der Schleife, wenn eine neue Szene beginnt
if $scene != self
break
end
end
# Bildschirm einfrieren für Überblendeffekt
Graphics.freeze
# Disposing der verwendeten Grafiken
dispose_graphics()
end
#--------------------------------------------------------------------------
# * Initialisierung der Instanzvariablen und Laden der Grafiken
#--------------------------------------------------------------------------
def load_contents()
end
#--------------------------------------------------------------------------
# * Aktualisierung der Instanzvariablen
#--------------------------------------------------------------------------
def update()
end
#--------------------------------------------------------------------------
# * Disposen der Grafiken
#--------------------------------------------------------------------------
def dispose_graphics()
end
end
Hier ist das eigentliche Script. Es enthält außerdem eine Modifizierung von Scene_Title, die einen vierten Menüpunkt hinzufügt. Wer die nicht will, sollte alles ab
Code:
class Scene_Title
in Zweile 292 bis zum Ende des Scripts löschen.
Code:
#==============================================================================
# ** Scene_Music
#------------------------------------------------------------------------------
# Eine Klasse für ein Menü zum Abspielen der Musik im BGM-Ordner
#==============================================================================
class Scene_MusicPlayer < Scene
def initialize(on_map = true, menu_index = 0) # Menü-Cursor-Startposition = 0
@menu_index = menu_index
@on_map = on_map # Return to map after closing the player if @on_map is true
end
def load_contents()
begin
@max_length = 15 # Standard-Maximal-Länge eines Dateinamens
# So breit ist das Auswahlfenster mindestens (15*12 Pixel)
dir = Dir.new("Audio/BGM/") # Neuer Ordnerpfad: Musikordner des Spiels
@musicarray = dir.entries # Alle Dateinamen in einem Array abspeichern
if @musicarray.size < 1 then
print "Es befinden sich keine Dateien im BGM-Ordner"
$scene = Scene_Title.new
end
2.times do @musicarray.shift end # Die ersten beiden Elemente löschen
# (Ist beides jeweils ein Punkr)
@musicarray.each {|index|
index.slice!(index.length-4, index.length) # Schneide die Dateiendung ab
if @max_length < index.length then @max_length = index.length end # Prüfe, ob es eine neue Maximal-Länge gibt
}
@max_length = 30 if @max_length > 30 # Wenn die Länge über 30 Zeichen ist,
# passe die Breite nicht weiter an
# Erzeuge Auswahlfenster
@navi_window = Window_Navigation.new(@max_length * 12, @musicarray)
@navi_window.index = @menu_index
# Lege Höhe manuell fest, wenn das höher als 360 Pixel ist
@navi_window.height = 360 if @navi_window.height > 360
@navi_window.x = (640 - @navi_window.width) / 2 # Zentriere horizontal
@navi_window.y = (480 - @navi_window.height) / 2 # Zentriere vertikal
# Erzeuge Pitch- und Volume-Fenster in Abhängigkeit zum Auswahlfenster
@pitch_window = Window_Pitch.new(@navi_window.x, @navi_window.y, @navi_window.width, @navi_window.height)
@volume_window = Window_Volume.new(@navi_window.x, @navi_window.y, @navi_window.width, @navi_window.height)
# Schreibe Standad-Werte in die Fenster
@pitch_window.contents.draw_text(-16, -16, 64, 64, "100", 1)
@volume_window.contents.draw_text(-16, -16, 64, 64, "100", 1)
# Mache Fenster inaktiv
@pitch_window.active = false
@volume_window.active = false
# Bestimme die Größe der möglichen Cursor-Rects
@rect2 = Rect.new(0, 0, 32, 32)
@no_rect = Rect.new(0, 0, 0, 0)
# Schreibe die Namen über das Fenster ("Pitch" und "Volume")
draw_pitch()
draw_volume()
# Erzeuge Plane-Grafik und wähle ein Panorama als Hintergrund aus
@background = Plane.new
@background.bitmap = RPG::Cache.panorama("003-StarlitSky01", 0)
@description = Sprite.new
@description.bitmap = Bitmap.new(500, 80)
@description.x = 70
@description.bitmap.draw_text(0, 0, 500, 30, "Rechts/Links: Fenster wechseln", 1)
@description.bitmap.draw_text(0, 30, 500, 30, "Hoch/Runter: Auswahl ändern, Pitch/Lautstärke verändern", 1)
end
def update()
# Update Fenster...
@navi_window.update
@pitch_window.update if @pitch_window.active #... wenn es aktiv ist
@volume_window.update if @volume_window.active #... wenn es aktiv ist
if @volume_window.active and @current_bgm
if Input.trigger?(Input::DOWN) or Input.trigger?(Input::UP)
Audio.bgm_play("Audio/BGM/" + @musicarray[@current_bgm], @volume_window.volume, @current_pitch)
end
end
# Wenn X gedrückt, dann zurück
if Input.trigger?(Input::B) then exit end
# Wenn C/Enter/Leertaste gedrückt, dann...
if Input.trigger?(Input::C) and @navi_window.active == true
#... spiele ausgewählte BGM
Audio.bgm_play("Audio/BGM/" + @musicarray[@navi_window.index], @volume_window.volume, @pitch_window.pitch)
@current_bgm = @navi_window.index
@current_pitch = @pitch_window.pitch
end
# Wenn LINKS o. RECHTS gedrückt, dann mache Fenster aktiv oder inaktiv
if Input.trigger?(Input::LEFT)
if @volume_window.active == true then
@volume_window.active = false
@navi_window.active = true
check_active
elsif @navi_window.active == true
@navi_window.active = false
@pitch_window.active = true
check_active
end
elsif Input.trigger?(Input::RIGHT)
if @pitch_window.active == true then
@pitch_window.active = false
@navi_window.active = true
check_active
elsif @navi_window.active == true
@navi_window.active = false
@volume_window.active = true
check_active
end
end
end
rescue
print "Der BGM-Ordner ist leer."
def dispose_graphics
end
$scene = nil
end
# Lösche die Grafiken am Ende der Szene
def dispose_graphics
@navi_window.dispose
@pitch_window.dispose
@volume_window.dispose
@sprite.dispose
@sprite2.dispose
@background.dispose
end
# Erzeuge Sprite und schreibe "Pitch"
def draw_pitch()
@sprite = Sprite.new
@sprite.z = 100
@sprite.x = @pitch_window.x + 8
@sprite.y = @pitch_window.y - 23
@sprite.bitmap = Bitmap.new(64, 32)
@sprite.bitmap.draw_text(0, 0, 64, 32, "Pitch")
end
# Erzeuge Sprite und schreibe "Volume"
def draw_volume()
@sprite2 = Sprite.new
@sprite2.z = 100
@sprite2.x = @volume_window.x - 2
@sprite2.y = @volume_window.y - 23
@sprite2.bitmap = Bitmap.new(96, 32)
@sprite2.bitmap.draw_text(0, 0, 96, 32, "Volume")
end
# Kehre zurück zum Title Screen
def exit
$game_system.se_play($data_system.cancel_se)
if @on_map == true then
$scene = Scene_Map.new
else
$scene = Scene_Title.new
end
end
# Wenn ein Fenster ausgewählt ist, bekommt es ein passendes
# Rect zugewiesen, ansonsten ein leeren Rect als Cursor-Rect
def check_active
if @pitch_window.active then
@pitch_window.cursor_rect = @rect2
else
@pitch_window.cursor_rect = @no_rect
end
if @volume_window.active then
@volume_window.cursor_rect = @rect2
else
@volume_window.cursor_rect = @no_rect
end
end
def update_scrolling
if @navi_window.index == @upper_index and @navi_window.index > 0
@navi_window.contents.y += 32
@navi_window.index -= 1
elsif @navi_window.index == @lower_index and
@navi_window.index > 0 and @navi_window.index < @musicarray.length
@navi_window.contents.y -= 32
@navi_window.index += 1
end
end
end
#==============================================================================
# ** Window_Pitch
#------------------------------------------------------------------------------
# Eine Klasse zum Anzeigen und Verändern eines Pitch-Fensters
#==============================================================================
class Window_Pitch < Window_Base
attr_reader :pitch
def initialize(x, y, width, height)
@pitch = 100 # Standard-Pitchwert
@@pitch = 90
super(x - 80, y + height/2 - 32, 64, 64) # Erzeuge Fenster
self.contents = Bitmap.new (32, 32) # Erzeuge Bitmap und weise sie
end # contents zu
# Erhöhe oder senke den Pitchwert und aktualisiere das Fenster
def update()
if Input.trigger?(Input::UP)
$game_system.se_play($data_system.cursor_se) unless @pitch >= 225
@pitch += 5 unless @pitch >= 225 # 225 = Maximum
self.contents.clear
self.contents.draw_text(-16, -16, 64, 64, @pitch.to_s, 1)
elsif Input.trigger?(Input::DOWN)
$game_system.se_play($data_system.cursor_se) unless @pitch <= 5
@pitch -= 5 unless @pitch <= 5 # 5 = Minimum
self.contents.clear
self.contents.draw_text(-16, -16, 64, 64, @pitch.to_s, 1)
end
end
end
#==============================================================================
# ** Window_Volume
#------------------------------------------------------------------------------
# Eine Klasse zum Anzeigen und Verändern eines Lautstärke-Fensters
#==============================================================================
class Window_Volume < Window_Base
attr_reader :volume
def initialize(x, y, width, height, pitch = true, volume = false)
@volume = 100 # Standard-Lautstärke
super(x + 16 + width, y + height/2 - 32, 64, 64) # Erzeuge Fenster
self.contents = Bitmap.new (32, 32) # Erzeuge Bitmap und weise sie
end # contents zu
# Erhöhe oder senke die Lautstärke und aktualisiere das Fenster
def update()
if Input.trigger?(Input::UP)
$game_system.se_play($data_system.cursor_se) unless @volume >= 100
@volume += 5 unless @volume >= 100 # 100 = Maximum
self.contents.clear
self.contents.draw_text(-16, -16, 64, 64, @volume.to_s, 1)
elsif Input.trigger?(Input::DOWN)
$game_system.se_play($data_system.cursor_se) unless @volume <= 50
@volume -= 5 unless @volume <= 50 # 50 = Minimum
self.contents.clear
self.contents.draw_text(-16, -16, 64, 64, @volume.to_s, 1)
end
end
end
#==============================================================================
# ** Window_Navigation
#------------------------------------------------------------------------------
# Eine Klasse zum Anzeigen eines angepassten Auswahlfensters
#==============================================================================
class Window_Navigation < Window_Command
def initialize(length, elements)
@array = elements
@upper_index = 0
@lower_index = @array.length
super(length, elements)
end
def update
super
if Input.trigger?(Input::DOWN)
update_scrolling(false)
elsif Input.trigger?(Input::UP)
update_scrolling(true)
end
end
def update_scrolling(direction)
if direction == true
if self.index == @upper_index and self.index > 0
self.contents.y += 32
@upper_index -= 1
@lower_index -= 1
self.index -= 1
end
else direction == false
if self.index == @lower_index and self.index > 0 and
self.index < @array.length
self.contents.y -= 32
@upper_index += 1
@lower_index += 1
self.index += 1
end
end
end
end
#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
# This class performs title screen processing.
#==============================================================================
class Scene_Title
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
# If battle test
if $BTEST
battle_test
return
end
# Load database
$data_actors = load_data("Data/Actors.rxdata")
$data_classes = load_data("Data/Classes.rxdata")
$data_skills = load_data("Data/Skills.rxdata")
$data_items = load_data("Data/Items.rxdata")
$data_weapons = load_data("Data/Weapons.rxdata")
$data_armors = load_data("Data/Armors.rxdata")
$data_enemies = load_data("Data/Enemies.rxdata")
$data_troops = load_data("Data/Troops.rxdata")
$data_states = load_data("Data/States.rxdata")
$data_animations = load_data("Data/Animations.rxdata")
$data_tilesets = load_data("Data/Tilesets.rxdata")
$data_common_events = load_data("Data/CommonEvents.rxdata")
$data_system = load_data("Data/System.rxdata")
# Make system object
$game_system = Game_System.new
# Make title graphic
@sprite = Sprite.new
@sprite.bitmap = RPG::Cache.title($data_system.title_name)
# Make command window
s1 = "New Game"
s2 = "Continue"
s3 = "Shutdown"
s4 = "Musikspieler"
@command_window = Window_Command.new(192, [s1, s2, s3, s4])
@command_window.back_opacity = 160
@command_window.x = 320 - @command_window.width / 2
@command_window.y = 288
# Continue enabled determinant
# Check if at least one save file exists
# If enabled, make @continue_enabled true; if disabled, make it false
@continue_enabled = false
for i in 0..3
if FileTest.exist?("Save#{i+1}.rxdata")
@continue_enabled = true
end
end
# If continue is enabled, move cursor to "Continue"
# If disabled, display "Continue" text in gray
if @continue_enabled
@command_window.index = 1
else
@command_window.disable_item(1)
end
# Stop playing ME and BGS
Audio.me_stop
Audio.bgs_stop
# Execute transition
Graphics.transition
# Main loop
loop do
# Update game screen
Graphics.update
# Update input information
Input.update
# Frame update
update
# Abort loop if screen is changed
if $scene != self
break
end
end
# Prepare for transition
Graphics.freeze
# Dispose of command window
@command_window.dispose
# Dispose of title graphic
@sprite.bitmap.dispose
@sprite.dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Update command window
@command_window.update
# If C button was pressed
if Input.trigger?(Input::C)
# Branch by command window cursor position
case @command_window.index
when 0 # New game
command_new_game
when 1 # Continue
command_continue
when 2 # Shutdown
command_shutdown
when 3
command_musicplayer
end
end
end
def command_musicplayer
# Play decision SE
$game_system.se_play($data_system.decision_se)
# Stop BGM
Audio.bgm_stop
# Reset frame count for measuring play time
Graphics.frame_count = 0
$scene = Scene_MusicPlayer.new(false)
end
end
Um das Script von der Map aus aufzurufen, muss über den Befehl „Script...“ die Codezeile
Code:
$scene = Scene_MusikPlayer.new
eingegeben werden.
Wichtiger Hinweis zum Einbauen: Das Script muss sich unter dem oben geposteten Scene-Script und unter Scene_Title befinden, und – wie üblich – über Main
Das ist gar nicht übel. Sowas kann eventuell für Arcade- und Brettspiele ganz nützlich sein, bei denen man häufiger die Hintergrundmelodie wechseln möchte.