if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
return
end
[Help] Button Inputs
Started by bigace, May 17 2012 01:08 PM
9 replies to this topic
#1
Posted 17 May 2012 - 01:08 PM
I was wondering if anyone knew of a way to close a scene by clicking any button on the keyboard and not just the usually:
#2
Posted 17 May 2012 - 02:48 PM
You could make a hash or something, that maps keys to Scenes:
Or something similar. Unfortunately, since there isn't an easy way to figure out which key is being pressed you're probably going to have to loop through each key in some way. A hash should be a simple way to Map the values anyways.
Keys_To_Scene = {
Input::B => Scene_Map
}
Keys_To_Scene.each_key do |key|
if Input.trigger?(key)
$scene = Keys_To_Scene[key].new
break
end
end
Or something similar. Unfortunately, since there isn't an easy way to figure out which key is being pressed you're probably going to have to loop through each key in some way. A hash should be a simple way to Map the values anyways.
#3
Posted 17 May 2012 - 05:32 PM
So something like this:
So is there a way to make this shorter, because this is a long list of commands. Something like,
Keys_To_Scene = {
Input::DOWN => Scene_Map
Input::LEFT => Scene_Map
Input::RIGHT => Scene_Map
Input::UP => Scene_Map
Input::A => Scene_Map
Input::B => Scene_Map
Input::C => Scene_Map
Input::X => Scene_Map
Input::Y => Scene_Map
Input::Z => Scene_Map
Input::L => Scene_Map
Input::R => Scene_Map
Input::SHIFT => Scene_Map
Input::CTRL => Scene_Map
Input::ALT => Scene_Map
Input::F5 => Scene_Map
Input::F6 => Scene_Map
Input::F7 => Scene_Map
Input::F8 => Scene_Map
Input::F9 => Scene_Map
}
Keys_To_Scene.each_key do |key|
if Input.trigger?(key)
$scene = Keys_To_Scene[key].new
break
end
end
So is there a way to make this shorter, because this is a long list of commands. Something like,
Keys_To_Scene = {}
Keys_To_Scene[Scene_Map] => {Input::DOWN, Input::LEFT, Input::RIGHT, Input::UP,
Input::A, Input::B, Input::C, Input::X, Input::Y, Input::Z, Input::L, Input::R,
Input::SHIFT, Input::CTRL, Input::ALT, Input::F5, Input::F6, Input::F7,
Input::F8, Input::F9}
Edited by bigace, 17 May 2012 - 05:59 PM.
#4
Posted 17 May 2012 - 05:46 PM
Not really, either way you go about it, you're gonna have to map out the commands. However, if what you're worried about is the loop (to tes which key) i can send you an edit i did of blizzard's custom key input script, where it returns the key being pressed, rather than true/false based on an input
#5
Posted 17 May 2012 - 06:01 PM
oh lol I didn't knew you posted already I edited my previous post, but I doubt that way will as effective anyways. Sure I'll take a look at the blizzard script.
#6
Posted 17 May 2012 - 08:58 PM
Here's blizz's script with modifications. I was using the method so I could allow custom player key bindings.
I left in blizzard's instructions and of course, the license is included.
There are a couple of methods in there (Input.key? and Input.keys?)
Input.keys?
Returns an array of integers (ascii values) of the last keys TRIGGERED
Input.key?
Slightly optimized version of Input.keys?, only returns the integer (ascii value) of the last key TRIGGERED (it would be similar to saying: Input.key?[0] or Input.key?.first)
NOTE: Some keys (such as Shift) will usually return 2 values (Shit and Left Shift or Right Shift) and it may NOT necessarily be the value you intended. Any values that do not exist in the key map WILL not be returned, i.e. removing "Shift" from the map will force only "Left Shift" or "Right Shift" to be returned.
So, to use this to do what you are trying to do:
1st Solution: Blizzard uses Arrays to store multiple key bindings for each key, for this next part to work properly, you'll want to use one key per binding (non-array), so the single key values will map to the hash properly
2nd Solution: If you are like me, you'll like the notion of different keys mapping to a single game key, (like Input::B corresponds to x, and escape, etc.)
To do this, we'll have to modify the keys? and key? methods, to return something a little more meaningful than ascii values (although, arguably, this is the most meaningful information ABOUT a key)
So, my thought might be to add another wrapping list, to then map the ascii values to an actual key constant.
Then, just tweak the keys? and key? methods:
Now, you can do the same as the first solution, except it will play nicely with arrays (so, multiple key bindings)
Unfortunately it adds another loop to it all, and puts some ugly dependencies, and doesn't necessarily follow the DRY principle.
Although, I am definitely without a doubt that this entire script could be redesigned to support these concepts, and still be compatible with the standard RMXP input style.
Another improvement, might be to create & cache the Key.invert at the start of the game, that way every call to Input.key? doesn't have to do that for you.
It should also be easy to extend this to support "pressed" and "released" keys, just replace @triggered with @pressed, @released or @repeated.
EDIT:
Sorry, those solutions were bugging me. Here's a cleaner solution, and is plug and play. No configurations/workarounds necessary:
This provides support for:
Input.triggered_keys?
Input.triggered_key?
Input.pressed_keys?
Input.pressed_key?
Input.repeated_keys?
Input.repeated_key?
And, it wraps nicely around the default Input module.
Also, this will work "out of the box"
I left in blizzard's instructions and of course, the license is included.
Spoiler
There are a couple of methods in there (Input.key? and Input.keys?)
Input.keys?
Returns an array of integers (ascii values) of the last keys TRIGGERED
Input.key?
Slightly optimized version of Input.keys?, only returns the integer (ascii value) of the last key TRIGGERED (it would be similar to saying: Input.key?[0] or Input.key?.first)
NOTE: Some keys (such as Shift) will usually return 2 values (Shit and Left Shift or Right Shift) and it may NOT necessarily be the value you intended. Any values that do not exist in the key map WILL not be returned, i.e. removing "Shift" from the map will force only "Left Shift" or "Right Shift" to be returned.
So, to use this to do what you are trying to do:
1st Solution: Blizzard uses Arrays to store multiple key bindings for each key, for this next part to work properly, you'll want to use one key per binding (non-array), so the single key values will map to the hash properly
Keys_To_Scene = {
# Omitted for brevity
Input::A => Scene_Map,
# Omitted for brevity
}
# Call scene from key:
key = Input.key?
scene = Keys_To_Scene[key]
if scene
$scene = scene.new
end
2nd Solution: If you are like me, you'll like the notion of different keys mapping to a single game key, (like Input::B corresponds to x, and escape, etc.)
To do this, we'll have to modify the keys? and key? methods, to return something a little more meaningful than ascii values (although, arguably, this is the most meaningful information ABOUT a key)
So, my thought might be to add another wrapping list, to then map the ascii values to an actual key constant.
KEY_LIST = [ UP, LEFT, DOWN, RIGHT, A, B, C, X, Y, Z, L, R, F5, F6, F7, F8, F9 SHIFT, CTRL, ALT ]
Then, just tweak the keys? and key? methods:
def self.keys?
input = []
keys = Key.invert
@triggered.each_index { |i|
if @triggered[i] && keys[i]
KEY_LIST.each { |k|
if k.include?(i)
input << k
break
end
}
end
}
return input
end
def self.key?
input = []
keys = Key.invert
@triggered.each_index { |i|
if @triggered[i] && keys[i]
KEY_LIST.each { |k|
if k.include?(i)
return k
end
}
end
}
return nil
end
Now, you can do the same as the first solution, except it will play nicely with arrays (so, multiple key bindings)
Unfortunately it adds another loop to it all, and puts some ugly dependencies, and doesn't necessarily follow the DRY principle.
Although, I am definitely without a doubt that this entire script could be redesigned to support these concepts, and still be compatible with the standard RMXP input style.
Another improvement, might be to create & cache the Key.invert at the start of the game, that way every call to Input.key? doesn't have to do that for you.
It should also be easy to extend this to support "pressed" and "released" keys, just replace @triggered with @pressed, @released or @repeated.
EDIT:
Sorry, those solutions were bugging me. Here's a cleaner solution, and is plug and play. No configurations/workarounds necessary:
Spoiler
This provides support for:
Input.triggered_keys?
Input.triggered_key?
Input.pressed_keys?
Input.pressed_key?
Input.repeated_keys?
Input.repeated_key?
And, it wraps nicely around the default Input module.
Also, this will work "out of the box"
Keys_To_Scene = {
# Omitted for brevity
Input::A => Scene_Map,
# Omitted for brevity
}
# Call scene from key:
key = Input.triggered_key?
if Keys_To_Scene.has_key?(key)
$scene = Keys_To_Scene[key].new
end
#7
Posted 18 May 2012 - 10:31 PM
Thanks for the edited version, as I'm about to release a script thats not that big and I don't need blizzards huge script for something thats this small.
Small problem when I try to open the scene I created I get a error on line 18 after added the your new methods to the module Input when I try to access it from the menu or the map.
Small problem when I try to open the scene I created I get a error on line 18 after added the your new methods to the module Input when I try to access it from the menu or the map.
Quote
Script 'Module Input; line 18: TypeError occured.
cannot convert String tinto Interger.
cannot convert String tinto Interger.
module Input
include ACE::Help
class << self
alias ace_init_quick_awards_lat update unless $@
def triggered_keys?
input = []
constants.each do |const|
key = const_get(const.to_sym)
if trigger?(key)
input << key
end
end
return input
end
def triggered_key?
constants.each do |const|
key = const_get(const.to_sym)
if trigger?(key)
return key
end
end
return nil
end
def pressed_keys?
input = []
constants.each do |const|
key = const_get(const.to_sym)
if press?(key)
input << key
end
end
return input
end
def pressed_key?
constants.each do |const|
key = const_get(const.to_sym)
if press?(key)
return key
end
end
return nil
end
def repeated_keys?
input = []
constants.each do |const|
key = const_get(const.to_sym)
if repeat?(key)
input << key
end
end
return input
end
def repeated_key?
constants.each do |const|
key = const_get(const.to_sym)
if repeat?(key)
return key
end
end
return nil
end
end
def self.update_old; ace_init_quick_awards_lat; end
def self.check_blocked
Block_Scenes.each {|s| return true if $scene.is_a?(s)}
return false
end
def self.update
if Quick_Access != nil && Input.trigger?(Quick_Access) &&
@scene == nil && !self.check_blocked
$game_system.se_play($data_system.decision_se)
@scene = Scene_Help.new
@scene = nil
end
ace_init_quick_awards_lat
end
end
#8
Posted 19 May 2012 - 02:44 AM
Well, it's because I took the lazy path, and relied on the fact that the only constants defined for Input would be the key values. By bringing in ACE::Help you are probably pulling in extra constants, which will be evaluated in
That's why you are getting the error "string can't be converted into integer", as line 18 (trigger?(key)) expects an integer, not a string (and I'll bet one of the constants pulled in, is a string.)
What you can do is, take the proper route:
There, now it shouldn't matter what constants you bring in, as long as you aren't redefining the existing constants (keys)
constants.each do |const| # ... etc ... end
That's why you are getting the error "string can't be converted into integer", as line 18 (trigger?(key)) expects an integer, not a string (and I'll bet one of the constants pulled in, is a string.)
What you can do is, take the proper route:
module Input
KEYS = [
DOWN,
LEFT,
RIGHT,
UP,
A,
B,
C,
X,
Y,
Z,
L,
R,
SHIFT,
CTRL,
ALT,
F5,
F6,
F7,
F8,
F9
]
class << self
def triggered_keys?
input = []
KEYS.each do |key|
if trigger?(key)
input << key
end
end
return input
end
def triggered_key?
KEYS.each do |key|
if trigger?(key)
return key
end
end
return nil
end
def pressed_keys?
input = []
KEYS.each do |key|
if press?(key)
input << key
end
end
return input
end
def pressed_key?
KEYS.each do |key|
if press?(key)
return key
end
end
return nil
end
def repeated_keys?
input = []
KEYS.each do |key|
if repeat?(key)
input << key
end
end
return input
end
def repeated_key?
KEYS.each do |key|
if repeat?(key)
return key
end
end
return nil
end
end
end
There, now it shouldn't matter what constants you bring in, as long as you aren't redefining the existing constants (keys)
#9
Posted 19 May 2012 - 05:16 AM
I just posted the script that this module is part of: Scene_Help If you want to take a look.
I might of done something wrong but when I tryed doing that the scene wouldn't close? The one I posted doesn't have the new methods in module Input I'm still working on it.
I might of done something wrong but when I tryed doing that the scene wouldn't close? The one I posted doesn't have the new methods in module Input I'm still working on it.
#10
Posted 21 May 2012 - 03:56 PM
Hmm, I'd have to see your implementation, but, shouldn't the Scene objects handle the closing and what not themselves?
Like, user presses button and then this is called:
then, the loop in the new scene will start up.
Finally, when the user exits that scene (or however it's set up to leave) it will do the same.
But, I dunno. Thought experiments always seem work better than in practice...let's see what you are trying to do.
Like, user presses button and then this is called:
$scene = Scene_Whatever.newthen, the loop in the current scene will say "hey! $scene != self! cleanup time" (according to RMXP design)
then, the loop in the new scene will start up.
Finally, when the user exits that scene (or however it's set up to leave) it will do the same.
But, I dunno. Thought experiments always seem work better than in practice...let's see what you are trying to do.
0 user(s) are reading this topic
members, guests, anonymous users











