Method Calling & Array Usage

Rime

Veteran
Veteran
Joined
Jul 12, 2014
Messages
37
Reaction score
11
Primarily Uses
Hello.

I tried learning RGSS3 Scripting. It has only been one day since learning, so please bear with me.

I first learned how to create Windows. For my first trial, I attempted making a script that will list locations the player can teleport to.

The first problem I have come across is that I am having difficulty calling the add_map() method using an event.

The second problem is I am not sure if I am using the @Locations array properly to store map information.

Please note that this script is incomplete, and does not have the functionality to teleport or draw content in the help window yet.

Code:
class Window_Fly_Location < Window_Selectable    def initialize    super(0,0,182,416)    @Locations = []    draw_content()  end    def add_map(name, id, x, y)    @Data = [name, id, x, y]    # 0 = Name    # 1 = Map ID    # 2 = X-Coordinate    # 3 = Y-Coordinate    @Locations[@Locations.size] = @Data  end    def draw_content()    #Locations Read Loop    #draw_text(x, y, text)    @Locations.size.times {|i| draw_text(0, i*24, @Locations[i-1][0]) }  end    def item_max    super    @Locations ? @Locations.size() : 1  end  endclass Window_Fly_Help < Window_Base    def initialize    super(182,0,362,416)  end  endclass Scene_Fly < Scene_Base    def start    super    create_location_window()    create_help_window()  end    def create_location_window()    @Location_Window = Window_Fly_Location.new()  end    def create_help_window()    @Help_Window = Window_Fly_Help.new()  end    def update    super    SceneManager.call(Scene_Map) if Input.trigger?(:  end    def terminate    super    @Location_Window.dispose()    @Help_Window.dispose()  end  end
 
 
Last edited by a moderator:

??????

Diabolical Codemaster
Veteran
Joined
May 11, 2012
Messages
6,513
Reaction score
3,204
First Language
Binary
Primarily Uses
RMMZ
Using the add map method on the window from an in game event?

If thats what you mean, stop it !! :p

The reason you would have trouble with that is because the window isnt active (its not even been created when your not within the scene).

Instead you should always add all map locations and then simply disable the inactive ones - alternatively, iterate over an the possible locations and then add the enabled ones. Both these methods should be called during the intialize method of your window.

Also - I recommend learning pure Ruby before delving into writing RGSS scripts. You will learn how to handle your code much more efficiently if you do it that way :)
 

Venka

Veteran
Veteran
Joined
Jun 20, 2012
Messages
945
Reaction score
365
First Language
English
Primarily Uses
Looks like a good start for your script. Here's a few things to think about.. How do you want your locations to work? Do they always exist or does the player unlock locations as they advance in the game? If they are always there, then you can set up all the locations at once. If you'd like them to unlock as the player advances then you will need to store them some place where the data will be saved when the game file is saved.

If you look in the DataManager you'll see some of your options without doing a bunch of heavy modifications:

#-------------------------------------------------------------------------- # * Create Save Contents #-------------------------------------------------------------------------- def self.make_save_contents contents = {} contents[:system] = $game_system # Game_System contents[:timer] = $game_timer # Game_Timer contents[:message] = $game_message # Game_Message contents[:switches] = $game_switches # Game_Switches contents[:variables] = $game_variables # Game_Variables contents[:self_switches] = $game_self_switches # Game_SelfSwitches contents[:actors] = $game_actors # Game_Actors contents[:party] = $game_party # Game_Party contents[:troop] = $game_troop # Game_Troop contents[:map] = $game_map # Game_Map contents[:player] = $game_player # Game_Player contents endI added the comments to the right for the script it's referencing. Of those options.. since it's about teleporting to map locations, I'd probably stick the information in the Game_Map or in the Game_Player (since it's also things the are tied to the player).

So I'd change your def to something like this:

class Game_Player < Game_Character def add_map(name, id, x, y) @locations ||= [] # This says make a new array unless this array already exists @locations[@locations.size] = [name, id, x, y] end def locations return @locations.uniq # the .uniq will take out any dupes that might happen endendthe first method you can do a script call like $game_player.add_map(name, id, x, y) to add a location to the array.

the 2nd method will let you look at the array.. so $game_player.locations would bring the array info into play.

Now to revisit your window that had the locations info in it. You made it a window selectable and that looks great :) It does some organize for you so you don't really have to worry about it. Check out the draw_item(index) method in selectable and command windows from some examples of how it works. This is a method you will use often when scripting windows with choices. So I did some edits but the new window would look something like this:

class Window_Fly_Location < Window_Selectable def initialize super(0,0,182,416) draw_content() end def draw_item(index) super rect = rect_for_text(index) draw_text(rect, $game_player.locations[index][0]) end def item_max $game_player.locations.size endendI didn't play test it so sorry if  I missed an error, but hope this helps some
 

??????

Diabolical Codemaster
Veteran
Joined
May 11, 2012
Messages
6,513
Reaction score
3,204
First Language
Binary
Primarily Uses
RMMZ
^ much more informative reply :D
 

Rime

Veteran
Veteran
Joined
Jul 12, 2014
Messages
37
Reaction score
11
Primarily Uses
Thank you for the replies.

Both replies were very informative. I'm really grateful. :)

Thank you for your help, I shall try it out and hope to finish the script.
 

??????

Diabolical Codemaster
Veteran
Joined
May 11, 2012
Messages
6,513
Reaction score
3,204
First Language
Binary
Primarily Uses
RMMZ
B) No problem.
I wish you luck on finishing your script ^_^
 

Solistra

Veteran
Veteran
Joined
Aug 15, 2012
Messages
593
Reaction score
247
Primarily Uses
class Game_Player < Game_Character def add_map(name, id, x, y) @locations ||= [] # This says make a new array unless this array already exists @locations[@locations.size] = [name, id, x, y] end def locations return @locations.uniq # the .uniq will take out any dupes that might happen endend
Calling uniq returns a copy of the original array with unique entries removed -- it doesn't actually remove anything. Also, if your response to that is "well, let's use uniq!," I hope you like nil return values:

a = [1, 2, 2, 3]a.uniq # => [1, 2, 3]a # => [1, 2, 2, 3]a.uniq! # => [1, 2, 3]a # => [1, 2, 3]a.uniq! # => nilThe code posted before has the potential to blindly push into the @locations array every time add_map is called; the duplicates are not removed, and all of this information will become a part of any player's save games. This is not good -- so don't push into an array unless you're certain the value should exist within it.Also, by the way, this array full of arrays is asking for trouble, especially for someone new to Ruby and RGSSx. For the kind of structure you're looking for, a hash works very well -- particularly if the id parameter is unique for each map (which I'm assuming it will be).

Code:
class Game_Player < Game_Character  attr_reader :locations    alias_method :sol_example_gp_init, :initialize  def initialize(*args, &block)    # Note: this is where to initialize your instance variables,    # **not** inside of a method that uses them.    @locations = {}    sol_example_gp_init(*args, &block)  end    def add_map(name, id, x, y)    return if @locations[id]    @locations[id] = { name: name, x: x, y: y }  endend
The code above should be very usable and functionally equivalent without any of the problems I just outlined above. As a bonus, if you haven't learned to work with hashes yet, this is a great opportunity to learn about them.

Code:
$game_player.add_map('Example', 5, 1, 1)$game_player.locations[5][:name] # => "Example"
Good luck.
 
Last edited by a moderator:

Venka

Veteran
Veteran
Joined
Jun 20, 2012
Messages
945
Reaction score
365
First Language
English
Primarily Uses
Good point on the uniq method. I like using attr_reader/attr_accessor, but avoided in this case cause I didn't want to confuse the issue. It was my understanding that creating a def to get the information was basically the same thing. Was I wrong in that assumption?
 

Solistra

Veteran
Veteran
Joined
Aug 15, 2012
Messages
593
Reaction score
247
Primarily Uses
Was I wrong in that assumption?
Not exactly, but a large part of your problem with defining a locations method to access the instance variable is that you were directly calling uniq on it without actually ensuring that the value of @locations responds to uniq. Essentially, it was asking for an error just due to the lazily-evaluated array that you used in add_map, which is also why you want to initialize instance variables in the (aptly named) initialize method.

To put it as an example (using the code you posted above):

Code:
# Without calling `add_map`, `@locations` has a `nil` value.$game_player.locations # => NoMethodError# Calling `add_map`, `@locations` is lazily-evaluated with an# an empty array.$game_player.add_map('Example', 5, 1, 1)$game_player.locations # => [['Example', 5, 1, 1]]
Also, all of that completely misses the point of duplicate values and how to properly ensure that they are not blindly pushed into an array which is expected to have unique entries.
 

Venka

Veteran
Veteran
Joined
Jun 20, 2012
Messages
945
Reaction score
365
First Language
English
Primarily Uses
gotcha, and "lazily-evaluated array" was right on.. I should have taken the extra steps. I usually check if the info is already included in the array and then skip adding it.
 

Solistra

Veteran
Veteran
Joined
Aug 15, 2012
Messages
593
Reaction score
247
Primarily Uses
"lazily-evaluated array" was right on.. I should have taken the extra steps.
That wasn't derogatory or anything -- I wasn't saying you were being lazy. That's literally what that kind of variable assignment is called: it's lazy evaluation. That just means that the variable isn't initialized until the moment that it's needed.
 

Venka

Veteran
Veteran
Joined
Jun 20, 2012
Messages
945
Reaction score
365
First Language
English
Primarily Uses
oh I didn't take any insult ;) I just took it as a fact hehe, but I haven't heard that term before
 

Rime

Veteran
Veteran
Joined
Jul 12, 2014
Messages
37
Reaction score
11
Primarily Uses
Solistra, thank you for the information about hash. 

I will try to rewrite it in order to optimize memory usage. 
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

People3_5 and People3_8 added!

so hopefully tomorrow i get to go home from the hospital i've been here for 5 days already and it's driving me mad. I miss my family like crazy but at least I get to use my own toiletries and my own clothes. My mom is coming to visit soon i can't wait to see her cause i miss her the most. :kaojoy:
Couple hours of work. Might use in my game as a secret find or something. Not sure. Fancy though no? :D
Holy stink, where have I been? Well, I started my temporary job this week. So less time to spend on game design... :(
Cartoonier cloud cover that better fits the art style, as well as (slightly) improved blending/fading... fading clouds when there are larger patterns is still somewhat abrupt for some reason.

Forum statistics

Threads
105,868
Messages
1,017,083
Members
137,583
Latest member
write2dgray
Top