Chaos Project

RPG Maker => RPG Maker Scripts => RMXP Script Database => Topic started by: ForeverZer0 on September 01, 2010, 12:20:14 pm

Title: [XP] Book Scene
Post by: ForeverZer0 on September 01, 2010, 12:20:14 pm
Book/Library Scene
Authors: ForeverZer0
Version: 1.2
Type: Misc Add-on
Key Term: Misc Add-on



Introduction

Calls a scene that will allow the player to read/view books they have collected.


Features




Screenshots

None.


Demo

http://www.mediafire.com/?yvgzdoa32uahh7n


Script
Spoiler: ShowHide

#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
# Book/Library Scene
# Author: ForeverZer0
# Version: 1.2
# Date: 9.1.2010
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
#
# Version History:
#   v. 1.0  9.1.2010
#     - Original version
#   v. 1.1  9.3.2010
#     - Added option for full-screen text
#     - Made the page number window slightly wider
#   v. 1.2  9.25.2010
#     - Added option to simply call scene with the book ID argument and have
#       that book already displayed.
#
# Introduction:
#   Calls a scene that will allow player to read through books that they have
#   collected.
#
# Features:
#   - Easy to configure, text is read from an external text document
#   - Text will automatically fit itself into the proper size for the window
#     width and pages, regardless of font or font size.

# Instructions:
#   1. Fill in the configuration below.
#   2. Create a new folder within the "Data" folder, and name it "Books".
#   3. Within this folder, create simple text documents (.txt).
#   4. Name them EXACTLY as you did for its respective title (below).
#   5. Turn word-wrap OFF.
#   6. Create as large as document as you would like, but only break to a new
#      line in between paragraphs, not when the text reaches the edge of the
#      window. Every time a new line is started, it guarantees that the current
#      line will start on a new line in the scene, regardless of the font size.
#
#   Use the following Script Calls:
#     Books.unlock(BOOK_ID)     
#       - Unlocks the book with BOOK_ID
#     $scene = Scene_Book.new   
#       - Calls the Book scene.
#     $scene = Scene_Book.new(BOOK_ID)
#       - Calls the book scene. The book with BOOK_ID will already be displayed.
#         This will also disable the book list feature. The book does not have
#         to be unlocked to call this way.
#
# Credits/Thanks:
#   ForeverZer0, for the script
#   Blizzard, for the "slice_text" method
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=

module Books
 
#===============================================================================
#                           BEGIN CONFIGURATION   
#===============================================================================
 
  RETURN_SCENE = Scene_Map
  # Class of the scene that the game return to after you exit the book scene.
  SORT_BY_ID = true
  # If true, the books will be listed in order of their Book ID, else they will
  # be listed in the order they were aquired.
  PAGE_TURN_SE = ['046-Book01', 80, 100]
  # Set to the name of the SE that will be played when a player turns a page.
  # Set to nil to disable this feature. [FILENAME, VOLUME, PITCH]
  FULLSCREEN_TEXT = false
  # If true, the text window will extend over the book list and take up the
  # entire screen (minus the header).
 
  def self.title(book_id)
    # Here is where you define the labels used for the books. The titles will
    # be used as the filename to be loaded as well.
    # when BOOK_ID then 'TITLE'
    return case book_id
    when 0 then 'Genesis'
    when 1 then 'Exodus'
    when 2 then 'Leviticus'
    when 3 then 'Numbers'
    when 4 then 'Deuteronomy'
    end
  end
 
#===============================================================================
#                            END CONFIGURATION   
#===============================================================================
 
  def self.unlock(book_id)
    # Adds the Book ID to the array.
    unless $game_system.books.include?(book_id)
      $game_system.books.push(book_id)
      # Sorts the array by the Book IDs if so configured.
      if SORT_BY_ID
        $game_system.books.sort!
      end
    end
  end
 
  def self.get_text(book_id)
    # Opens a text document, makes an array whose elements consist of the lines
    # of the document, and returns it.
    filename = 'Data/Books/' + title(book_id) + '.txt'
    begin
      file = File.open(filename, 'r')
    rescue
      raise("Error occured while attempting to open the following file:\n\n" +
            "\t#{filename}\n\n" +
            "Please make sure that the file exist before you continue.")
    end
    book = []
    file.each_line {|line| book.push(line)}
    file.close
    return book
  end
end

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

class Game_System
 
  attr_accessor :books     # Array: Stores the IDs of all unlocked books.
 
  alias zer0_book_init initialize
  def initialize
    zer0_book_init
    @books = []
  end   
end

#===============================================================================
# ** Scene_Book
#===============================================================================

class Scene_Book
 
  def initialize(book_id = nil)
    @book_id = book_id
    @no_list = @book_id != nil
  end
 
  def main
    # Create a variable that is set to the window width (depending on config)
    @window_width = Books::FULLSCREEN_TEXT ? 640 : 512
    @window_width = 640 if @no_list
    # Create a blank dummy window.
    @dummy_window = Window_Base.new(128, 64, 512, 416)
    # Create Help_Window to display the book titles.
    @help_window = Window_Base.new(0, 0, 448, 64)
    @help_window.contents = Bitmap.new(416, 32)
    # Create the page number window
    @page_window = Window_Base.new(448, 0, 192, 64)
    @page_window.contents = Bitmap.new(160, 32)
    # Create the window that text will be displayed on.
    x = @window_width == 640 ? 0 : 128
    @text_window = Window_Base.new(x, 64, @window_width, 416)
    @text_window.contents = Bitmap.new(@window_width - 32, 384)
    @text_window.z = @help_window.z + 20
    @text_window.visible = false
    # Make a copy of the Books array.
    @books = $game_system.books.clone
    # Create instance variable for updating the text window.
    @update_text = false
    # Make list of all books, if possible, else make list empty.
    if @books.empty?
      help_string = 'No books are currently available.'
      @command_window = Window_Base.new(0, 64, 128, 416)
    else
      help_string = 'Whick book would you like to read?'
      @titles = []
      @books.each {|book_id| @titles.push(Books.title(book_id))}
      @command_window = Window_Command.new(128, @titles)
      @command_window.height, @command_window.y = 416, 64
    end
    # Display text on the help screen
    @help_window.contents.draw_text(0, 0, 416, 32, help_string, 1)
    # Create array that holds all the windows
    @windows = [@dummy_window, @help_window, @text_window,
                @command_window, @page_window]
               
    if @no_list
      @page_number = 1
      $game_system.se_play($data_system.decision_se)
      @help_window.contents.clear
      @help_window.contents.draw_text(0, 0, 416, 32, Books.title(@book_id), 1)
      @command_window.active, @update_text = false, true
      compile_text
      @text_window.visible = true
    end
   
    Graphics.transition
    # Main loop
    loop {Graphics.update; Input.update; update; break if $scene != self}
    Graphics.freeze
    @windows.each {|window| window.dispose}
  end
 
  def update
    # Update windows.
    @windows.each {|window| window.update}
    if @command_window.is_a?(Window_Command) && @command_window.active
      update_command_window
      return
    elsif @update_text
      update_text_window
      return
    end
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      $scene = Books::RETURN_SCENE.new
    end
  end
 
  def update_command_window
    if Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      $scene = Books::RETURN_SCENE.new
    elsif Input.trigger?(Input::C)
      @page_number = 1
      $game_system.se_play($data_system.decision_se)
      @book_id = @books[@command_window.index]
      @help_window.contents.clear
      @help_window.contents.draw_text(0, 0, 416, 32, Books.title(@book_id), 1)
      @command_window.active, @update_text = false, true
      compile_text
      @text_window.visible = true
    end
  end
 
  def update_text_window
    if Input.trigger?(Input::LEFT) || Input.trigger?(Input::RIGHT)
      old_page = @page_number
      @page_number += Input.trigger?(Input::LEFT) ? -1 : 1
      @page_number = [[@page_number, @pages.size].min, 1].max
      # Play SE if configured as such.
      if old_page != @page_number && Books::PAGE_TURN_SE != nil
        se = Books::PAGE_TURN_SE
        audio = RPG::AudioFile.new(se[0], se[1], se[2])
        $game_system.se_play(audio)
      end
      # Refresh the window
      refresh_text
    elsif Input.trigger?(Input::B)
      $game_system.se_play($data_system.cancel_se)
      if @no_list
        $scene = Books::RETURN_SCENE.new
      else
        @update_text, @command_window.active = false, true
        @text_window.visible = false
      end
    end
  end
 
  def compile_text
    # Gets an array whose elements are the lines of the text document.
    text = Books.get_text(@book_id)
    # Iterate over each line of the text. Break each line up into segments that
    # will fit into the window, then add them all together.
    @pages, lines = [], []
    text.each {|paragraph|
      segment = @text_window.contents.slice_text(paragraph, @window_width - 32)
      segment.each {|line| lines.push(line)}
    }
    # Organizes the lines (12 per page) into pages.
    page_numbers = (lines.size / 12) + 1
    (0...page_numbers).each {|i| @pages[i] = lines[i*12, 12]}
    refresh_text
  end
   
  def refresh_text
    [@text_window.contents, @page_window.contents].each {|bitmap| bitmap.clear}
    # Displays the lines of the current page onto the window.
    page = @pages[@page_number - 1]
    page.each_index {|i|
      @text_window.contents.draw_text(0, i*32, @window_width - 32, 32, page[i])}
    # Set the proper text to the page screen.
    string = "Page #{@page_number}/#{@pages.size}"
    @page_window.contents.draw_text(0, 0, 160, 32, string, 1)
  end
end

class Bitmap
 
  # The slice_text method was created by Blizzard. I take no credit for it.
  def slice_text(text, width)
    words = text.split(' ')
    return words if words.size == 1
    result, current_text = [], words.shift
    words.each_index {|i|
    if self.text_size("#{current_text} #{words[i]}").width > width
      result.push(current_text)
      current_text = words[i]
    else
      current_text = "#{current_text} #{words[i]}"
    end
    result.push(current_text) if i >= words.size - 1}
    return result
  end
end



Instructions

See script.


Compatibility

No known issues.


Credits and Thanks





Author's Notes
Please let me know if any bug/issues are found.
Enjoy!
Title: Re: [XP] Book Scene
Post by: Taiine on September 01, 2010, 05:40:38 pm
Oh my god this is fantastic! <3 No mess, no hassle, so easy to use! Best of no NO ANNOYING FORMATTING OF THE TEXT FILES!  <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3

One little little extra request? An added option to select a book to read, with out the little side menu? Like find a book, pick it up and you read, with just the title, pages, and the text? Then can have it as it currently is as a list to go back to reread past books you already found.

Oh and.. is the text size thing really part of it? :P I made the mistake of going SIZE 6 and like holy molly that's tinny, and changing all the game text. It was very much so silly XD
Title: Re: [XP] Book Scene
Post by: ForeverZer0 on September 02, 2010, 12:04:49 pm
I can make a quick mod for you to change the display.

As for the text size thing, that was just to show how the page will format to whatever the font and size are. I wouldn't use size 6 either. This will make it so that the text always is formatted correctly, even if the player has control of the font and font size. The only drawback is that the text cannot be pre-formatted and stored, which causes that half a second of lag when you first select a book and it needs to open the text document, etc.
Title: Re: [XP] Book Scene
Post by: Jragyn on September 02, 2010, 02:59:35 pm
A bit off topic, but Zer0, you should make all the list of scripts in your signature actual links to said scripts.
Dats convenient.
I think all scripters should have that! (cept maybe Blizzard, cuz he's got...a LOT.)

  :^_^':
Title: Re: [XP] Book Scene
Post by: Blizzard on September 02, 2010, 03:41:19 pm
http://www.chaos-project.com/index.php?option=com_scriptdatabase&view=scriptdatabase&Itemid=29
Title: Re: [XP] Book Scene
Post by: ForeverZer0 on September 02, 2010, 04:27:47 pm
Good idea about the sig. I think it needs updated anyway.  ;)
Title: Re: [XP] Book Scene
Post by: Taiine on September 02, 2010, 07:03:57 pm
That mod will be swell. :3

So fare I have seen no bugs even when tossed in my script computability testing game, it works fine with everything I use.
Title: Re: [XP] Book Scene
Post by: ForeverZer0 on September 03, 2010, 12:06:53 pm
* Updates to Version 1.1 *
Okay try that out. It now has the option of how you want the text window to be displayed.
Title: Re: [XP] Book Scene
Post by: Taiine on September 03, 2010, 06:31:16 pm
Nice once again! However don't think you fully grasped what I asked.  :^_^':

Like to be able to read a book with out going through the list. Like going to a library, picking a book and instantly going to the book text and reading. Then (for me anyway) the list could be of books you've already read to reread again... or not use the list scene at all and go back to each book in game to reread it.
Title: Re: [XP] Book Scene
Post by: Taiine on September 16, 2010, 01:44:00 pm
Any progress on this?
Title: Re: [XP] Book Scene
Post by: Taiine on September 20, 2010, 01:04:10 pm
I think this was forgotten about.  :hm:
Title: Re: [XP] Book Scene
Post by: ForeverZer0 on September 20, 2010, 03:52:45 pm
Quote from: Taiine on September 20, 2010, 01:04:10 pm
I think this was forgotten about.  :hm:


Patience, grasshopper. This is not on my list of high priorities.
Title: Re: [XP] Book Scene
Post by: Ravenith on September 21, 2010, 08:43:27 am
Very, very nice one! Thanks! Maybe port it to VX too? There's no book scripts for VX if I'm not mistaken, and I sure could use one..

(Why do I use VX? Long story... :/ )
Title: Re: [XP] Book Scene
Post by: ForeverZer0 on September 28, 2010, 12:13:43 pm
Okay, I updated to 1.2
You can now just call the scene with an argument that will have the desired book all ready to go, without having any book list. The other option is still there,

Use this to call the scene:
$scene - Scene_Book.new(BOOK_INDEX)


Or just ignore the argument and it will open with the list displayed.
Title: Re: [XP] Book Scene
Post by: Karltheking4 on October 04, 2010, 05:26:22 am
Hey, this is a really epic script!
But, I was wondering if there was something in the script I could edit to make a picture display at the bottom of the page, that varies from each book, any ideas?
It should be simple I think :)

something like:
if 0 then $game_screen.pictures[3].show(1, 1, 1, 1, 1, 1, 1, 1)


But I dunno...
Title: Re: [XP] Book Scene
Post by: Taiine on November 16, 2010, 11:46:06 am
Hey FZ0, Can I make a small added request with this?
I'd like to be able to change the font color of the text as well as the font used. I tried it myself, but each time I try it throws back an error.
Rather with
@text_window.font.color
@self.contents.font.color
same with font type.
yet
@text_window.windowskin
worked just fine to change the window skin O.o;;;
Title: Re: [XP] Book Scene
Post by: ForeverZer0 on November 16, 2010, 12:03:49 pm
The correct syntax would be :

@text_window.contents.font.name = 'FONTNAME'
@text_window.contents.font.size = SIZE
@text_window.contents.font.color = Color.new(R, G, B, ALPHA)


The window is a sprite, which has no methods for font, but "contents" refers the sprite's bitmap, which does.
Title: Re: [XP] Book Scene
Post by: Ryex on December 05, 2010, 12:14:54 am
oh look, more lazy mods :V
Title: Re: [XP] Book Scene
Post by: Blizzard on December 05, 2010, 05:19:34 am
I just went through the script section and found more than 10 script topics that haven't been moved. O_o
Title: Re: [XP] Book Scene
Post by: Ryex on December 05, 2010, 05:46:04 am
they are all topics that don't have the template applied I take it? because I couldn't find these topics.


Zer0, I'm sorry were gonna hijack your thread and discuses moderation of the RGSS section now :V:
Title: Re: [XP] Book Scene
Post by: Blizzard on December 05, 2010, 06:39:13 am
LMAO!

Actually only 2 of them. The rest had a proper template applied. There were even a couple of F0's topics. xD
Title: Re: [XP] Book Scene
Post by: ForeverZer0 on December 05, 2010, 12:58:45 pm
Hijack away. I'm easy going and don't mind.
Title: Re: [XP] Book Scene
Post by: Elemental Crisis on February 01, 2011, 10:17:14 am
Hello,

Thanks for creating this script, spent quite a bit of time looking for such a script before stumbling onto this one. Just got a few questions.

A couple of my book titles are pretty long and such the text becomes pretty scrunched up, I've thought of 2 possible solutions but seeing how I'm pretty new at scripting haven't been able to incorporate them. 

Method 1: If the book name is longer then X characters then a "..." is added.
Method 2: Creating a similar function as FULLSCREEN_ENTRY but for the book names.

In a future version could you add the ability to include chapters? Where when you click the desired book a sub-menu opens allowing you to select which chapter? Also if your able to name the chapters that would be great as well.

Again, thanks for the script.
Title: Re: [XP] Book Scene
Post by: Xuroth on February 08, 2011, 09:09:37 am
Yes, thank you ForeverZer0 for this awesome script. I agree with Elemental Crisis about the chapters addition with the ability to name chapters. I may try to tweak this script (I am still learning RGSS lol) to add that function for my own use. Thanks again!