Mouse Recognition for Windows (i.e. buttons)
This script makes it easy to create windows that use buttons instead of keyboard input. I know a lot of people loved the mouse input script but never understood how to use it so maybe this will help.
Instructions:Step 1: Add these two scripts above main:
Mouse Positioning:
http://www.rmxp.net/forums/index.php?showtopic=22674Keyboard and Mouse Input:
http://www.rmxp.net/forums/index.php?showtopic=16550They are made by Near Fantastica so credit to him for these.
Step 2: Add this script above those two:
CODE
# Easy Mouse Recognition
# By Prexus
class Window_Base
alias button_initialize initialize
def initialize(x, y, width, height)
button_initialize(x, y, width, height)
@buttons = []
end
alias button_dispose dispose
def dispose
for i in 0...@buttons.size
if @buttons != nil
@buttons[i].dispose
end
end
button_dispose
end
class Button
attr_reader :x
attr_reader :y
attr_reader :wid
attr_reader :hei
attr_accessor :name
attr_accessor :graphic
attr_accessor :color
attr_accessor :text
def initialize(name, win_x, win_y, x, y, wid, hei, text, color, graphic = nil)
@name = name
@x = win_x + x
@y = win_y + y
@wid = wid
@hei = hei
@text = text
@color = color
@graphic = graphic
@button = Sprite.new
@button.bitmap = Bitmap.new(wid, hei)
@button.x = @x
@button.y = @y
@button.z = 101
refresh
end
def refresh
@button.bitmap.clear
@button.bitmap.font.name = $fontface
@button.bitmap.font.size = $fontsize
@button.bitmap.font.color = @color
if @graphic != nil
# Draw Graphic Button
bitmap = RPG::Cache.picture(@graphic)
@button.bitmap.blt(0, 0, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height))
else
# Draw Default Button
@button.bitmap.fill_rect(Rect.new(0, 0, @wid, @hei), Color.new(63, 63, 63, 255))
@button.bitmap.fill_rect(Rect.new(0, 0, @wid-1, @hei-1), Color.new(255, 255, 255, 255))
@button.bitmap.fill_rect(Rect.new(1, 1, @wid-2, @hei-2), Color.new(128, 128, 128, 255))
@button.bitmap.fill_rect(Rect.new(1, 1, @wid-3, @hei-3), Color.new(212, 208, 200, 255))
end
@button.bitmap.draw_text(0, 0, @wid, @hei, @text, 1)
end
def update
super
@button.update
end
def dispose
@button.dispose
end
end
end
[i]Step 3: You're done, but you probably don't understand how to use it so..
TUTORIAL:I imagine its not too simple to understand so here is a tutorial on how to mod the Title Screen.
First, create a new script above the Easy Mouse script, name it "Window Title".
Then, paste into that script these lines:
CODE
class Window_Title < Window_Base
def initialize
super(240, 288, 160, 128)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.font.name = $fontface
self.contents.font.size = $fontsize
They're all important Window lines so bare with me here, you may even learn something.
Since the window is fairly basic, there isn't much else other than to define the buttons. To do that, paste these lines of script in after the last one you pasted:
CODE
# Format:
# Button.new(Reference_Name, Window_X, Window_Y, X_Position, Y_Position, Width, Height, Text, Text_Color, Graphic)
@buttons.push(Window_Base::Button.new("New Game", self.x, self.y, 16, 16, 128, 32, "New Game", Color.new(0, 0, 0, 255)))
@buttons.push(Window_Base::Button.new("Load Game", self.x, self.y, 16, 48, 128, 32, "Load Game", Color.new(0, 0, 0, 255)))
@buttons.push(Window_Base::Button.new("End Game", self.x, self.y, 16, 80, 128, 32, "End Game", Color.new(0, 0, 0, 255)))
refresh
end
Confusing, eh? Lets break it down.
@buttons is an Array which holds all the button objects. Its important because its what is updated/disposed. But no worries, all that is handled in the Easy Mouse script.
Window_Base::Button.new() is the Button object. But its nothing without parameters, right? Parameters go in the ( and ) brackets. The parameters are as follows:
(Reference_Name, Window_X, Window_Y, X_Position, Y_Position, Width, Height, Text, Text_Color, Graphic)
Reference_Name: A string value which names the object. Incase you want the text to read differently than the name. This is similar to the way Visual Basic controls are labelled.
Window_X: This is the X value of the window, very important or else the buttons will appear outside of the window. The line
self.x is usually best for this parameter.
Window_Y: This is the Y value of the window, same idea as above. The line
self.y is usually best for this parameter.
X_Position, Y_Position: These are for placing the buttons in the window. They can't all be in the same place, right? If both are equal to 0, the object will appear in the window at the top right corner (assuming you used self.x and self.y), This usually looks pretty wonky because of the border on the windowskin so its probably best to give at least 8,8 or 16,16 to keep it off the edge.
Width, Height: These are obvious, really. They define the size of the button. If you are using a graphic for the button (explained below), its best you use the Width and Height of the graphic.
Text: This is the text that will be drawn on top of the button. Very important, unless you don't want text, in which case just put "". Since Text is a string, it has to be contained in quotation marks such as "Test" or "Dude u sux"
Text_Color: This is the color that the text is drawn, make sure not to leave this blank. If you must, just put
normal_color and it'll use RMXP's default window color (white by default).
Graphic: First of all, this parameter is OPTIONAL. If you leave it blank, it will draw the button to look just like a Window's button (Microsoft Windows, that is.) You can change how the default button looks by changing the
.fill_rect commands in the Easy Mouse script.
So anyhow, the above lines of code set the buttons up nice and pretty already for us, so lets continue.
After the above lines of code, paste in this bit:
CODE
def refresh
self.contents.clear
for i in 0...@buttons.size
@buttons[i].refresh
end
end
This makes sure that all the buttons are drawn.
After that, paste this:
CODE
def check
if Keyboard.trigger?(Keyboard::Mouse_Left)
for i in 0...@buttons.size
pos = Mouse.position
if (pos[0]) > @buttons[i].x and (pos[0]) < (@buttons[i].x + @buttons[i].wid)
if (pos[1]) > @buttons[i].y and (pos[1]) < (@buttons[i].y + @buttons[i].hei)
return @buttons[i].name
end
end
end
return nil
end
end
end
This is the kicker right here. The ultimus maximus of this script. What this does, is takes the left mouse button click, and checks all the buttons on the window to see if its overtop of them. You shouldn't need to change any of this, though.
So thats the Window_Title created. You'll have to do this for any window you want buttons. Also, Window_Command which is the default for making menus, does not currently support button input.
However, we're not done. This window is great and all, but nothing thrives on it. Nothing USES it. So, lets go edit Scene_Title then, shall we?
Paste this in a new script below Window_Title:
CODE
class Scene_Title
def main
if $BTEST
battle_test
return
end
$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")
$game_system = Game_System.new
@sprite = Sprite.new
@sprite.bitmap = RPG::Cache.title($data_system.title_name)
@command_window = Window_Title.new
@command_window.back_opacity = 160
@continue_enabled = false
for i in 0..3
if FileTest.exist?("Save#{i+1}.rxdata")
@continue_enabled = true
end
end
$game_system.bgm_play($data_system.title_bgm)
Audio.me_stop
Audio.bgs_stop
Graphics.transition
loop do
Graphics.update
Input.update
Keyboard.update
Mouse.update
update
if $scene != self
break
end
end
Graphics.freeze
@command_window.dispose
@sprite.bitmap.dispose
@sprite.dispose
end
def update
@command_window.update
entry = @command_window.check
return if entry == nil
case entry
when "New Game"
command_new_game
return
when "Load Game"
command_continue
return
when "End Game"
command_shutdown
return
end
entry = nil
end
end
Okay, I kinda pushed that one on you guys quickly but alot of the code is from the original Scene_Title so it should be pretty understandable. The most important things:
CODE
@command_window = Window_Title.new
@command_window.back_opacity = 160
I changed the original @command_window lines seen here:
CODE
s1 = "New Game"
s2 = "Continue"
s3 = "Shutdown"
@command_window = Window_Command.new(192, [s1, s2, s3])
@command_window.back_opacity = 160
@command_window.x = 320 - @command_window.width / 2
@command_window.y = 288
Because they are no longer necessary, the window handles it all.
Additionally, I remove these lines from the original Scene_Title:
CODE
if @continue_enabled
@command_window.index = 1
else
@command_window.disable_item(1)
end
Because I haven't added support for disabling buttons yet.
I added these two lines:
CODE
Keyboard.update
Mouse.update
To give support with Near Fantastica's input modules. The lines go after Input.update in the main loop.
Next, I redefined the update class because the old one was out of date. Since the new button windows don't use an index, but instead, relay a button reference name, it must be changed to this:
CODE
def update
@command_window.update
entry = @command_window.check
return if entry == nil
case entry
when "New Game"
command_new_game
return
when "Load Game"
command_continue
return
when "End Game"
command_shutdown
return
end
entry = nil
end
It updates the window, like always, because its important, then sets a variable (which I named <span style='color:red'>entry</span>) to the result of the window check.
Remember the ultimus maximus? Yeah, here it is again. If the check finds nothing, it returns nil. I made sure to finish the update if that occurs because frankly its silly to continue. Now, I added a case. A case is a special IF statement so if you are more familiar with IF statements you can use those. But what the case statement does is it checks the <span style='color:red'>entry</span> variable for the reference name that it gathered, and performs the commands based on that.
I of course, didn't get every last piece of code from Scene_Title and change it, because again, that'd be silly, because most of it doesn't change.
Now you should have a fully functional mouse input Title screen.
KNOWN ISSUES:- If a window moves, the buttons DON'T go with it. Its a simply fix but since the default RMXP windows don't move, I didn't include it.
- There is no graphical mouse cursor, which means, if you are running full screen you won't be able to see the cursor.
That should be about it, enjoy.