Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

[Resolved] Help with a crashing loop while checking Input

Status
Not open for further replies.
Im trying to create a environmental skills system, like, there are some abilities related to events to interact with the place. To toggle these abilities, a sequence of letters must be pressed, in order to use the right ability.
To make the it possible, Im using a Input script.
A method from this script is inside the loop, which is "get_letters".
The game variable is just to test something, like, when an ability is a success, the variable is set to X.
The "pickpocket" method is an example of a environment skill, which is called via events.

def initialize
  @keyseq = []
  @envirskills = [0.00,0.00,0.00,0.00,0.00]
  if $game_variables != nil
    while $game_variables[1] = 0
      update
    end
  end
end

def update
  keynex = Input.get_letters
  if keynex != nil
    @keyseq.push(keynex)
    p @keyseq
  end
end
 

def pickpocket(dif)
  actor = $game_party.actors[1]
  if @keyseq = [a,s,d]
    if @envirskills == nil
      @envirskills = [0.00,0.00,0.00,0.00,0.00]
      p "Adj!"
      @envirskills[1] = 1.00
    end
    res = (rand(3.00) * ((actor.dex * actor.agi) / 2) * @envirskills[1]) / 20.00
    if res > dif
      @envirskills[1] += (dif) / (10 * @envirskills[1])
      p "Success!!" + @envirskills[1].to_s
      $game_variables[1] = 1
    else
      @envirskills[1] += (dif) / (30 * @envirskills[1])
      p "Failure!!"
    end
  end
end
This is the Input script:
#==============================================================================
# ** Keyboard Input Module (Revised)
#------------------------------------------------------------------------------
#    by DerVVulfman
#    version 1.2
#    08-15-2007
#------------------------------------------------------------------------------
#  Based on...
#  Keyboard Input Module version 3
#  by Near Fantastica (06.07.05)
#==============================================================================

module Input
  #-------------------------------------------------------------------------- 
  # * Get Current Keypress State (Regular presses)
  #-------------------------------------------------------------------------- 
  def Input.getstate(key)
    return true unless Win32API.new("user32","GetKeyState",["i"],"i").call(key).between?(0, 1)
    return false
  end
  #-------------------------------------------------------------------------- 
  # * Get Continuous Keyboard State (CapsLock, NumLock, ScrollLock)
  #-------------------------------------------------------------------------- 
  def Input.keyboardstate(rkey, key = 0)
    return false unless Win32API.new("user32","GetKeyState",['i'],'i').call(rkey) & 0x01 == key
    return true
  end
  #-------------------------------------------------------------------------- 
  # * Numberpad Input System
  #-------------------------------------------------------------------------- 
  def Input.get_direction
    return "Center" if Input.getstate(12)
    return "PgUp"  if Input.getstate(33)
    return "PgDn"  if Input.getstate(34)
    return "End"    if Input.getstate(35)
    return "Home"  if Input.getstate(36)
    return "Left"  if Input.getstate(37)
    return "Up"    if Input.getstate(38)
    return "Right"  if Input.getstate(39)
    return "Down"  if Input.getstate(40)
    return "Ins"    if Input.getstate(45)
    return "Del"    if Input.getstate(46)
    return "*"      if Input.getstate(106)
    return "+"      if Input.getstate(107)
    return "-"      if Input.getstate(109)
    return "/"      if Input.getstate(111)
    if Input.keyboardstate(144,1)
      for key in 96..105  #ASCII KEYS 48(0) to 57(9)
        if Input.getstate(key)
          return (key-48).chr
        end
      end
    end
    return nil
  end
  #-------------------------------------------------------------------------- 
  # * Function Keys (Tab / Enter / Ctrl / Etc)
  #-------------------------------------------------------------------------- 
  def Input.get_function
    return "Back"      if Input.getstate(8)
    if Input.getstate(16)
      return "BackTab"  if Input.getstate(9)
    else
      return "Tab"      if Input.getstate(9)
    end
    return "Enter"      if Input.getstate(13)
    return "Ctrl"      if Input.getstate(17)
    return "Alt"        if Input.getstate(18)
    return "Pause"      if Input.getstate(19)
    return "Esc"        if Input.getstate(27)
    return "PrntScr"    if Input.getstate(44)
    # Function Keys (F1 - F12)
    for key in 112..123
      if Input.getstate(key)
        num = key - 111
        return "F" + num.to_s
      end
    end
    return nil
  end
  #-------------------------------------------------------------------------- 
  # * Individual Keys (Left OR Right keys, and Windows & Application keys)
  #-------------------------------------------------------------------------- 
  def Input.get_individual
    return "CapsLock" if Input.getstate(20)
    return "NumLock"  if Input.getstate(144)
    return "ScrlLock" if Input.getstate(145)
    return "Lf Win"  if Input.getstate(91)
    return "Rt Win"  if Input.getstate(92)
    return "App Key"  if Input.getstate(93)
    return "Lf Shift" if Input.getstate(160)
    return "Rt Shift" if Input.getstate(161)
    return "Lf Ctrl"  if Input.getstate(162)
    return "Rt Ctrl"  if Input.getstate(163)
    return "Lf Alt"  if Input.getstate(164)
    return "Rt Alt"  if Input.getstate(165)
    return nil
  end
  #-------------------------------------------------------------------------- 
  # * Letter Keys (Just your regular alphabet, caps or otherwise)
  #-------------------------------------------------------------------------- 
  def Input.get_letters
    for key in 65..90 #ASCII KEYS 65(a) to 90(z)
      if Input.getstate(key)
        # Ensure lower-case if NEITHER or BOTH the shift and caps are pressed
        if (Input.getstate(16) and Input.keyboardstate(20,1) ) or
        (Input.getstate(16) != true and Input.keyboardstate(20,1) != true)
          return key.chr.downcase
        else
        # Otherwise, uppercase 
          return key.chr.upcase
        end
      end
    end
    return nil
  end
  #-------------------------------------------------------------------------- 
  # * Number Keys (only the top keys)
  #-------------------------------------------------------------------------- 
  def Input.get_numbers
    return nil if Input.getstate(16)
    for key in 48..57 #ASCII KEYS 48(0) to 57(9)
      if Input.getstate(key)
        return key.chr
      end
    end
    return nil
  end
  #-------------------------------------------------------------------------- 
  # * Keys (All others)
  #-------------------------------------------------------------------------- 
  def Input.get_key
    if Input.getstate(32)
      return " "
    end
    # Ensure lower-case if NEITHER or BOTH the shift and caps are pressed
    if (Input.getstate(16) and Input.keyboardstate(20,1) ) or
    (Input.getstate(16) != true and Input.keyboardstate(20,1) != true)
      return ";"    if Input.getstate(186)
      return "="    if Input.getstate(187)
      return ","    if Input.getstate(188)
      return "-"    if Input.getstate(189)
      return "."    if Input.getstate(190)
      return "/"    if Input.getstate(191)
      return "`"    if Input.getstate(192)
      return "["    if Input.getstate(219)
      return "\\"  if Input.getstate(220)
      return "]"    if Input.getstate(221)
      return "'"    if Input.getstate(222)
    # Otherwise, uppercase     
    else     
      return ":"    if Input.getstate(186)
      return "+"    if Input.getstate(187)
      return "<"    if Input.getstate(188)
      return "_"    if Input.getstate(189)
      return ">"    if Input.getstate(190)
      return "?"    if Input.getstate(191)
      return "~"    if Input.getstate(192)
      return "{"    if Input.getstate(219)
      return "|"    if Input.getstate(220)
      return "}"    if Input.getstate(221)
      return "\x22" if Input.getstate(222)
    end
    # Shifted Top-row Numbers (not in ASCII order)
    for key in 48..57
      if Input.getstate(key) and Input.getstate(16)
        case key
        when 48; return ")"
        when 49; return "!"
        when 50; return "@"
        when 51; return "#"
        when 52; return "$"
        when 53; return "%"
        when 54; return "^"
        when 55; return "&"
        when 56; return "*"
        when 57; return "("
        end
      end
    end
    return nil
  end
end

Thank you in advance
 

khmp

Sponsor

First do these methods belong to a class/module or something? You can define methods like that but I'll be honest and say I have no idea what scope instance variables have when they are outside a class/module definition.

Second major problem is some of your comparisons. Given the following statement:
Code:
if a = b
  #do
end
That is essentially an assignment which Ruby equates as true all the time. This is most likely not the result you want. I believe you want to do something like below.
Code:
if a == b
  #do
end
You want two equal signs to accomplish a comparison.

Next your while loop has no break condition. So the "while loop" is never ending and no other work can be done. Infinite "while loops" generate hanging script errors. Never a good thing. You need a break condition of some sort, timer, input. Something.

Moving on to bigger and better things. Inside your update method you "push" keys into an array but you never "pop" them or "clear" the array. So if you hit the "a" key once it will stay inside the array for the entirety of this objects instance.

Lastly I'm not sure you can compare an array against another array like that unless you want every element to be alike.
Code:
test1 = [a,b,c,d,e,f]
test2 = [a,b,c]
test1 == test2    #false
I think what you are looking for is something like the code below.
Code:
test1 = [0,a,b,z,c,d,e,f]
test2 = [a,b,c]
test1 & test2    #[a,b,c]
(test1 & test2).size > 0

Good luck with it Lestat.br! :thumb:

If you have any questions about my comments just let me know.
 
thank you...this I posted is'nt the actual script... these double equal signs are in the script, i just commited a mistake here.
And, yes, I want the sequence of letters to be just as it is, like, if the first letter was A, second was S, and third was D, for instance, the ability happen, so this is fine.
I tried inserting the key checking loop inside the Scene_Map, and it's working without crash, but I honestly would like to have the this inside my script, how do I make to create a class/module and make it run like any other? If I do it, I will prevent the crashing?
about the loop, if the loop is "while $game_variables[1] = 0" I think it does have a break condition, "$game_variables != 0", but I need to put it again inside the loop?
 

khmp

Sponsor

Well you can do this without using a while loop and just having its update called once a frame correct? Let's say you had this object and functionality wrapped up and defined as a class called "Pickpocket". Then you could do something like this:

Code:
class Scene_Map
  alias_method :lest_pickpocket_main, :main
  alias_method :lest_pickpocket_update, :update
  def main
    @pickpocket = Pickpocket.new
    lest_pickpocket_main
  end
  def update
    @pickpocket.update
    lest_pickpocket_update
  end
end

This way there is no need to have a while loop because the update is called once a frame. Now your pickpocket class just needs an initialize and an update. And inside the update, you would poll input and check if you need to do anything with that knowledge.

Good luck with it Lestat.br! :thumb:

If you have any questions about my comments just let me know.
 
thank you so much! now it works good!
just one problem (if there is no problem to ask it here...)

I have an event at my map that requires the 'Variable 1' set to 1 to show the page 2.
after I change the "$game_variables[1] = 1"
in the Pickpocket.new Script, the variable is set to 1, in the Debug I can see so, but the event just won't go to the page two...I go to Scene_Menu, and go back to Scene_Map and it doesn't solve...I think it is a refreshing problem...

Here is the Pickpocket script (not done yet):
class Pickpocket
 
  def initialize
    @keyseq = []
    @time_count = 0
  end
 
  def update
    keynex = Input.get_letters
    if @time_count > 0
      @time_count += 1
    end
    if keynex != nil
      @time_count = 1
      @keyseq[@keyseq.size] = keynex
      p @keyseq
    end
    if @keyseq == ['A','S','D']
      p "yes!"
      $game_variables[1] = 1
      @keyseq = []
      @time_count = 0
    end
    if @time_count == 100
      @time_count = 0
      @keyseq = []
      p "erase!"
    end
  end
 
end
 

khmp

Sponsor

I don't think I have enough information to help you with this problem. Seeing as how you have event script interaction. Could you create a demo of your project with test case scenario? If it isn't too much trouble. If your worried about privacy you could pm me the link.

I still have a question about your script if you don't mind. In order to "Pickpocket" the user has to hit A, then S, then D. Because that's the only way the array would contain those values in that order.

Or do you want them to be able to hit and hold those keys down and enable the switch?
Or do you want them to be able to press these keys in any order but if any other key was hit or is being held do not enable the switch?
 
thank you for the interest. The thing is that, all these games with interactive skills are simply like: You press the key, you do the thing. I want this to be quite different, you will need to have some skill and memory to press a sequence of keys to a determined ability. The more complex the ability is, the harder it is to remember and press.

For Instance, Woodcutting:

To cut a Bush:
A + W + E (after you need to touch the tree to use the ability on it) in 100 frames

To cut a Willow:
E + D + S + Q + A (the same) in 100 frames

To cut an Ancient Tree of the Elvish Glades of the Dark Spawn of Evil:
W + H + A + T + H + E + F + U + C + K (touch the tree) in 100 frames

And, although you know how to cut an Ancient Tree of the Elvish Glades of the Dark Spawn of Evil, you need wood to do a fireplace and you can only see a bush, and you can't remember the key word. This system would be also realistic, because the player's memory and skill have so much influence on the game.

This is just an example. Pickpocket would be the difficulty depending on the given difficulty, whether when stealing a Smuggler, or an Ancient Master Sentry of the Walls of Eternity. (Stupid examples as well)

If you want a demo, whether to get the idea, the base or anything, I send you one...

If you hadn't have helped me in this very begining, I probably would have already given up, thank you so much...

(The problem was about "Map need refresh?" and it is fixed.)
 
Status
Not open for further replies.

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top