Fixing bug with window prompts and adding credits message box

The game would try to catch up in frames when a window prompt was
opened, so if the window was open for 140 frames the game would process
the next 140 frames instantly after the game was closed.  To fix this, I
have the window prompt time how long it's opened and then I tell the
game to sleep for however many frames it was opened for.

Credits message works but does not yet have all the desired features,
will finish up later.
This commit is contained in:
Michael Shirt 2016-10-29 18:44:06 -06:00
parent d43e176b4c
commit 1cba1adf66
6 changed files with 277 additions and 5 deletions

235
scripts/Credits_Message.rb Normal file
View file

@ -0,0 +1,235 @@
# Displays doc message boxes
class Credits_Message
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@timer = 0
@viewport = Viewport.new(0, 0, 640, 480)
@sprite_bg = Sprite.new(@viewport)
@sprite_bg.bitmap = Bitmap.new(640, 480)
if $game_switches[104]
@sprite_bg.bitmap.fill_rect(0, 0, 640, 480, Color.new(0, 0, 0, 255))
else
@sprite_bg.bitmap.fill_rect(0, 0, 640, 480, Color.new(255, 255, 255, 255))
end
@sprite_text = Sprite.new(@viewport)
@contents = Bitmap.new(320, 240)
@contents.font.size = 16
@sprite_text.bitmap = @contents
@sprite_bg.z = 0
@sprite_text.z = 1
@sprite_text.zoom_x = @sprite_text.zoom_y = 2
@viewport.z = 9999
@viewport.visible = false
@sprite_bg.opacity = 0
@sprite_text.opacity = 0
# Animation flags
@fade_in = false
@fade_out = false
end
#--------------------------------------------------------------------------
# * Dispose
#--------------------------------------------------------------------------
def dispose
terminate_message
$game_temp.message_window_showing = false
@contents.dispose
#@sprite_bg.dispose
@sprite_text.dispose
@viewport.dispose
end
#--------------------------------------------------------------------------
# * Terminate Message
#--------------------------------------------------------------------------
def terminate_message
# Call message callback
if !@skip_message_proc && $game_temp.message_proc != nil
$game_temp.message_proc.call
$game_temp.message_proc = nil
end
$game_temp.message_credits_text = nil
end
#--------------------------------------------------------------------------
# * Refresh: Load new message text and pre-process it
#--------------------------------------------------------------------------
def refresh
if $game_switches[104]
@sprite_bg.bitmap.fill_rect(0, 0, 640, 480, Color.new(0, 0, 0, 255))
else
@sprite_bg.bitmap.fill_rect(0, 0, 640, 480, Color.new(255, 255, 255, 255))
end
# Initialize
@timer = 0
text = ''
y = -1
widths = []
# Pre-process text
text_raw = $game_temp.message_credits_text.to_str
# Substitute variables, actors, player name, newlines, etc
text_raw.gsub!(/\\v\[([0-9]+)\]/) do
$game_variables[$1.to_i]
end
text_raw.gsub!(/\\n\[([0-9]+)\]/) do
$game_actors[$1.to_i] != nil ? $game_actors[$1.to_i].name : ""
end
text_raw.gsub!("\\p", $game_oneshot.player_name)
text_raw.gsub!("\\n", "\n")
# Handle text-rendering escape sequences
text_raw.gsub!(/\\c\[([0-9]+)\]/, "\000[\\1]")
# Finally convert the backslash back
text_raw.gsub!("\\\\", "\\")
@contents.font.size = 16
# Now split text into lines by measuring text metrics
x = y = 0
maxwidth = @contents.width - 8
spacesize = @contents.text_size(' ')
for i in text_raw.split(/ /)
# Split each word around newlines
newline = false
for j in i.split("\n")
# Handle newline
if newline
text << "\n"
widths << x
x = 0
y += 1
@contents.font.size = 24
else
newline = true
end
# Get width of this word and see if it goes out of bounds
width = @contents.text_size(j.gsub(/\000\[[0-9]+\]/, '')).width
if x + width > maxwidth
text << "\n"
widths << x
x = 0
y += 1
@contents.font.size = 24
end
# Append word to list
if x == 0
text << j
else
text << ' ' << j
end
x += width + spacesize.width
end
end
widths << x
# Prepare renderer
@contents.clear
if $game_switches[104]
@contents.font.color = Color.new(255, 255, 255, 255)
else
@contents.font.color = Color.new(0, 0, 0, 255)
end
x = (320 - widths[0]) / 2
y = 0
y_top = (240 - widths.length * 24) / 2
@contents.font.size = 16
# Get 1 text character in c (loop until unable to get text)
while ((c = text.slice!(/./m)) != nil)
# \n
if c == "\n"
y += 1
@contents.font.size = 24
x = (320 - widths[y]) / 2
next
end
# \c[n]
if c == "\000"
# Change text color
text.sub!(/\[([0-9]+)\]/, "")
color = $1.to_i
if color >= 0 and color <= 7
@contents.font.color = Window_Base.text_color(color)
end
# go to next text
next
end
# Draw text
@contents.draw_text(x, y_top + (y * 24), 40, 18, c)
# Add x to drawn text width
x += @contents.text_size(c).width
end
Graphics.frame_reset
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Handle fade-out effect
if @fade_out
@sprite_text.opacity -= 5
@sprite_bg.opacity -= 5
if @sprite_text.opacity <= 0
@sprite_text.opacity = 0
@sprite_bg.opacity = 0
@fade_out = false
@viewport.visible = false
$game_temp.message_window_showing = false
end
return
end
# Handle fade-in effect
if @fade_in
@sprite_text.opacity += 5
@sprite_bg.opacity += 5
if @sprite_text.opacity >= 255
@sprite_text.opacity = 255
@sprite_bg.opacity = 255
@fade_in = false
$game_temp.message_window_showing = true
end
return
end
# Message is over and should be hidden or advanced to next
if $game_temp.message_credits_text == nil
@fade_out = true if @viewport.visible
else
if !@viewport.visible
# Fade in
refresh
@viewport.visible = true
@fade_in = true
end
end
if visible
@timer += 1
if @timer >= 150
terminate_message
@fade_out = true
end
end
end
#--------------------------------------------------------------------------
# * Variables
#--------------------------------------------------------------------------
def visible
@viewport.visible
end
def visible=(val)
@viewport.visible = val
end
end

View file

@ -3,11 +3,23 @@ module EdText
Oneshot.msgbox Oneshot::Msg::YESNO, tr("Do you understand what this means?")
end
def self.info(text)
timestart = Time.now
text.gsub!("\\p", $game_oneshot.player_name)
Oneshot.msgbox Oneshot::Msg::INFO, tr(text)
$game_temp.prompt_wait = ((Time.now - timestart) * 60).round
end
def self.yesno(text)
timestart = Time.now
text.gsub!("\\p", $game_oneshot.player_name)
Oneshot.msgbox Oneshot::Msg::YESNO, tr(text)
result = Oneshot.msgbox Oneshot::Msg::YESNO, tr(text)
$game_temp.prompt_wait = ((Time.now - timestart) * 60).round
return result
end
def self.err(text)
timestart = Time.now
text.gsub!("\\p", $game_oneshot.player_name)
result = Oneshot.msgbox Oneshot::Msg::ERR, tr(text)
$game_temp.prompt_wait = ((Time.now - timestart) * 60).round
return result
end
end

View file

@ -19,6 +19,7 @@ class Game_Temp
attr_accessor :message_ed_text # Ed message text
attr_accessor :message_doc_text # Text message text
attr_accessor :message_desktop_text # Desktop message text
attr_accessor :message_credits_text # Desktop message text
attr_accessor :choices # show choices: text
attr_accessor :choice_cancel_type # show choices: cancel
attr_accessor :choice_proc # show choices: callback (Proc)
@ -61,6 +62,7 @@ class Game_Temp
attr_accessor :debug_index # debug screen: for saving conditions
attr_accessor :footstep_sfx # current footstep sfx array
attr_accessor :filmsprite # film puzzle sprite
attr_accessor :prompt_wait # wait for delay caused by prompt
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
@ -116,6 +118,7 @@ class Game_Temp
@debug_index = 0
@footstep_sfx = nil
@filmsprite = nil
@prompt_wait = 0
end
def bgm_fadein(game_system)

View file

@ -11,7 +11,7 @@ class Interpreter
#--------------------------------------------------------------------------
def command_101
# If other text has been set to message_text
if $game_temp.message_text != nil || $game_temp.message_ed_text != nil || $game_temp.message_doc_text != nil || $game_temp.message_desktop_text != nil
if $game_temp.message_text != nil || $game_temp.message_ed_text != nil || $game_temp.message_doc_text != nil || $game_temp.message_desktop_text != nil || $game_temp.message_credits_text != nil
# End
return false
end
@ -22,6 +22,8 @@ class Interpreter
if text.start_with?('$')
is_doc = true
text.slice!(0)
elsif text.start_with?('@credits')
is_credits = true
else
is_doc = false
end
@ -30,13 +32,16 @@ class Interpreter
if @list[@index+1].code == 401
@index += 1
text << " " << @list[@index].parameters[0].rstrip
elsif @list[@index+1].code == 101 && is_doc
elsif @list[@index+1].code == 101 && (is_doc || is_credits)
# 101: Another message box
# Tack on if we're a doc
new_text = @list[@index+1].parameters[0].strip
if new_text.start_with?('$')
text << "\n\n" << new_text[1..-1]
@index += 1
elsif new_text.start_with?('@credits')
text << new_text[9..-1]
@index += 1
else
break
end
@ -71,12 +76,19 @@ class Interpreter
if face == 'ed'
is_desktop = false
is_ed = true
is_credits = false
elsif face == 'desktop'
is_desktop = true
is_ed = false
is_credits = false
elsif face == 'credits'
is_desktop = false
is_ed = false
is_credits = true
else
is_desktop = false
is_ed = false
is_credits = false
$game_temp.message_face = face
end
@ -98,6 +110,8 @@ class Interpreter
$game_temp.message_doc_text = text
elsif is_desktop
$game_temp.message_desktop_text = text
elsif is_credits
$game_temp.message_credits_text = text
else
$game_temp.message_text = text
end

View file

@ -16,6 +16,7 @@ class Scene_Map
@ed_message = Ed_Message.new
@doc_message = Doc_Message.new
@desktop_message = Desktop_Message.new
@credits_message = Credits_Message.new
# Make menus
@menu = Window_MainMenu.new
@item_menu = Window_Item.new
@ -70,6 +71,7 @@ class Scene_Map
@ed_message.dispose
@doc_message.dispose
@desktop_message.dispose
@credits_message.dispose
# Dispose of menu
@menu.dispose
@item_menu.dispose
@ -102,6 +104,10 @@ class Scene_Map
end
# Loop
loop do
if $game_temp.prompt_wait > 0
$game_temp.prompt_wait -= 1
return
end
$game_temp.bgm_fadein($game_system)
# Update map, interpreter, and player order
# (this update order is important for when conditions are fulfilled
@ -135,6 +141,7 @@ class Scene_Map
@ed_message.update
@doc_message.update
@desktop_message.update
@credits_message.update
# Deactivate item
if Input.trigger?(Input::DEACTIVATE) && $game_variables[1] > 0
$game_system.se_play($data_system.cancel_se)
@ -142,7 +149,7 @@ class Scene_Map
end
# Update the menu
if @message_window.visible || @ed_message.visible || @doc_message.visible || @desktop_message.visible
if @message_window.visible || @ed_message.visible || @doc_message.visible || @desktop_message.visible || @credits_message.visible
@item_menu_refresh = true
else
if @item_menu_refresh
@ -226,7 +233,7 @@ class Scene_Map
# Update fast travel
@fast_travel.update
# If showing message window
if $game_temp.message_window_showing || @ed_message.visible || @doc_message.visible || @desktop_message.visible
if $game_temp.message_window_showing || @ed_message.visible || @doc_message.visible || @desktop_message.visible || @credits_message.visible
return
end
# Process menu opening

View file

@ -121,6 +121,7 @@ SaveLoad
Ed_Message
Doc_Message
Desktop_Message
Credits_Message
Particles
Demo