Jump to content
New account registrations are disabed. This website is now an archive. Read more here.
  • 0
Foxkit

Script works a little too well.

Question

hello again, I know I ask everyone here to critique my scripts a lot, but I actually have a pretty good reason to this time.

 

I've been working on a CMS for a bit now, and it works, just not in the way I wish it to. No matter what I try, I can't seem to keep the window from moving right, and it applies to all windows, even the battle system.

 

Script: http://pastebin.com/hKCWR5Cs

 

thanks in advance for looking it over, and I swear I'm getting better, considering that I'm not looking at errors this time but a working script that just isn't doing what it's supposed to.

Share this post


Link to post
Share on other sites

Recommended Posts

  • 0

[list=1]
[*]	
#==============================================================================#
[*]	
# Name: DizzyFoxkit_CMS                                                                                                                                                                                                                          #
[*]	
# Refrence Number: 001                                                         #
[*]	
# Coder: DizzyFoxkit (Foxkit)                                                  #
[*]	
# Purpose: A custom Menu system for the Tales Series                                                                                               #
[*]	
#==============================================================================#
[*]	
#==============================================================================#
[*]	
# Refrence Number: 002                                                         #
[*]	
#------------------------------------------------------------------------------#
[*]	
# Adds the Basic move elements to the Window_Base class so that the window can #
[*]	
# move about. And allows the Window to move on updates if @move_y or _x = true #
[*]	
#------------------------------------------------------------------------------#
[*]	
#==============================================================================#
[*]	
class Window_Base < Window
[*]	
       attr_accessor :move_x
[*]	
       attr_accessor :move_y
[*]	
       attr_accessor :dest_x
[*]	
       attr_accessor :dest_y
[*]	
       attr_accessor :curent_x
[*]	
       attr_accessor :current_y
[*]	
       def start
[*]	
               @move_x = move_x
[*]	
               @move_y = move_y
[*]	
               @dest_x = dest_x
[*]	
               @dest_y = dest_y
[*]	
       end
[*]	
       def win_move_x
[*]	
               if @dest_x != self.x
[*]	
                       @move_x = true
[*]	
               else
[*]	
                       @move_x = false
[*]	
               end
[*]	
       end
[*]	
       def win_move_y
[*]	
               if @dest_y != self.y
[*]	
                       @move_y = true
[*]	
               else
[*]	
                       @move_y = false
[*]	
               end
[*]	
       end
[*]	
       def update
[*]	
               if @move_x == true  #Forgot an '=' sign here.
[*]	
                       self.x = self.x + 1
[*]	
               elsif @move_y = true
[*]	
                       self.y = self.y + 1
[*]	
               end
[*]	
       end
[*]	
end
[*]	

Share this post


Link to post
Share on other sites
  • 0

Ooooo, I see several problems here.

  1. Your start method does not take any parameters. This means that when you call start, the four local variables move_x, move_y, dest_x and dest_y are undefined, and thus the instance variables will be set to nil.
  2. You're overriding Window_Base's update method, so any previously set behaviour is now erased. You should use an alias there.
  3. In the last few lines, you're not testing for equality, but rather assigning a value to @move_x and @move_y. Use == instead.
  4. Your window cannot move both horizontally and vertically because of the elsif statement. That's fine if it was intended that way, but I doubt it.
  5. Your window cannot move up or left because you only increase x and y's value. Once again, fine if that's what you wanted to do.
  6. The way your code is written, the win_move_x and win_move_y methods do not serve any purpose. Since you set the @move_x and @move_y flags in the start method, I don't see why you would want to specifically call two methods just to update them. Better remove the flags at all and test if the destination values were reached directly

All in all, I would do things that way:

class Window_Base < Window
 alias old_initialize initialize
 def initialize
old_initialize
# Set the @dest_x and @dest_y values to avoid NoNameErrors
@dest_x = self.x
@dest_y = self.y
 end

 def start_movement(dest_x, dest_y)
@dest_x = dest_x
@dest_y = dest_y
 end

 alias old_update update
 def update
old_update
if @dest_x < self.x
  self.x -= 1
end
if @dest_x > self.x
  self.x += 1
end
if @dest_y < self.y
  self.y -= 1
end
if @dest_y > self.y
  self.y += 1
end
 end
end

 

 

And this should do it. Also, if you want to be able to test whether a window is moving or not, use something like:

 def moving_x?
return @dest_x != self.x
 end


 def moving_y?
return @dest_y != self.y
 end

Edited by Moonpearl

Share this post


Link to post
Share on other sites
  • 0
Ooooo, I see several problems here.
  • Your start method does not take any parameters. This means that when you call start, the four local variables move_x, move_y, dest_x and dest_y are undefined, and thus the instance variables will be set to nil
  • In the last few lines, you're not testing for equality, but rather assigning a value to @move_x and @move_y. Use == instead.

 

These are actually and legitimately helpful pearl thanks smile.png

 

  • You're overriding Window_Base's update method, so any previously set behaviour is now erased. You should use an alias there.

 

This explains why the initialize method was being a grouch :?

 

  • Your window cannot move both horizontally and vertically because of the elsif statement. That's fine if it was intended that way, but I doubt it.

 

actually, for what the script is going to be used for it doesn't matter if it can move diagonally or not. Does that also mean that one window cannot move along X while another window moves along y?

 

  • Your window cannot move up or left because you only increase x and y's value. Once again, fine if that's what you wanted to do.

 

[facepalm begin] Ok, that's my bad, that is a very good point and I have no idea why that didn't occur to me while I was writing the script. thanks smile.png[/facepalm end]

 

  • The way your code is written, the win_move_x and win_move_y methods do not serve any purpose. Since you set the @move_x and @move_y flags in the start method, I don't see why you would want to specifically call two methods just to update them. Better remove the flags at all and test if the destination values were reached directly

 

I'm using the win_move_x and win_move_y to get the windows a purpose to start moving. Is this just a redundant failsafe I'm using?

Share this post


Link to post
Share on other sites
  • 0
This explains why the initialize method was being a grouch :?

I have no idea what you mean.

 

Does that also mean that one window cannot move along X while another window moves along y?

No, it only matters for a same and only window. The way your code is written, each window checks if it should move horizontally, and if so, it doesn't test whether it should move vertically, hence the impossiblity to move along both axes for a single window.

 

I'm using the win_move_x and win_move_y to get the windows a purpose to start moving. Is this just a redundant failsafe I'm using?

It's no failsafe at all, it's a redundant... redundancy. shifty.gif The thing is, either you set the movement once and for all using a method (like in the script I wrote) and checking whether you should move serves no purpose at all, either you have the script check by itself if dest_x and/or dest_y were changed by a third party object, and thus if movement should occur - but in this case, there's no need to put those tests in separate methods, like you would if you were to call them from several places, just put their content directly into the update method.

Share this post


Link to post
Share on other sites
  • 0

alright, so its safe to just get rid of Move_win_x and move_win_y? I think I only put it in there because my refrence script had it in there.

 

And I don't need to move windows diagonally, just need them moving in one direction so it works fine as long as I can move different windows in different directions.

Share this post


Link to post
Share on other sites
  • 0

the point of the excersise is for ME to write it, not have someone else write it for me. So, I thank you for pointing errors out for me, but I'm not asking someone to write it, just critique what I've done wrong. I also apologize if that came across as being angry, I am not the most polite person here.

 

EDIT: also, I have written the script out and fixed any known bugs/ errors. So if anyone has any further commenting, please limit them to critiques instead of errors

 

Script's New Version: http://pastebin.com/1ZJduhbB

 

thats for those of you who still want to look at it.

Edited by Foxkit

Share this post


Link to post
Share on other sites
  • 0

I'm not saying you should use mine, only that the fact that I didn't use such methods is proof they're useless. Of course you're free to write code in whatever bizarre way you may think of, as long as you let me do likewise on my side.

 

Notes:

  • move_x and move_y are still unknown variables in your start method
  • I'm wondering why you're declaring current_x and current_y as accessors since they don't appear in your script
  • you wrote "move" in your update method instead of move_x/move_y
  • you aliased the update method alright, but you still need to call the older version, you're not accomplishing anything by aliasing it otherwise

Share this post


Link to post
Share on other sites
  • 0

I'm not saying you should use mine, only that the fact that I didn't use such methods is proof they're useless. Of course you're free to write code in whatever bizarre way you may think of, as long as you let me do likewise on my side.

 

Notes:

  • move_x and move_y are still unknown variables in your start method

  • I'm wondering why you're declaring current_x and current_y as accessors since they don't appear in your script
  • you wrote "move" in your update method instead of move_x/move_y
  • you aliased the update method alright, but you still need to call the older version, you're not accomplishing anything by aliasing it otherwise

  • This avoids the NoNameError
  • this is for transitioning purposes that I'm planning on building in later.
  • already fixed the move errors for the up and left parts of the update.
  • you can't call the older version or else it errors... are we talking RPGMXP or VX here?

Share this post


Link to post
Share on other sites
  • 0
  • This avoids the NoNameError
  • this is for transitioning purposes that I'm planning on building in later.
  • already fixed the move errors for the up and left parts of the update.
  • you can't call the older version or else it errors... are we talking RPGMXP or VX here?

  • Well, you should be getting one with this, wondering why not
  • Okay...
  • I'm still reading "@move" at lines 52 and 60
  • Neither, we're talking Ruby. I think it must be because you used uppercase characters in the alias (uppercase names are constants and unsuitable for method names)

Share this post


Link to post
Share on other sites
  • 0
  • Well, you should be getting one with this, wondering why not
  • Okay...
  • I'm still reading "@move" at lines 52 and 60
  • Neither, we're talking Ruby. I think it must be because you used uppercase characters in the alias (uppercase names are constants and unsuitable for method names)

  • Well I'm not, getting an error
  • Thats an older version, I haven't changed the online version to reflect what I actually have.
  • I did try to alias the initialize the way you aliased it, and I kept getting errors.

Share this post


Link to post
Share on other sites
  • 0
I did try to alias the initialize the way you aliased it, and I kept getting errors.

I'm not talking about the initialize method, but the update method. It's only natural that you would get an error calling Window_Base#initialize without the 4 parameters it requires (x, y, width, height).

Share this post


Link to post
Share on other sites
  • 0

[necropost begin] I'm so sorry for being so rude at that time moonpearl. v.v

 

If I could be rude enough to request more help, I can get the menu to move into place, I would also like the menu to move away back into its original place when I select a menu Item/return to map/back out of a window. Currently its not doing that, it just fades and changes scenes.

 

the movement script: http://pastebin.com/agze8PM2 (I was unsure if I had made any changes since the OP, and I'm being too lazy to actually go and check.)

 

The Main Menu: http://pastebin.com/8vGi1eVd (Before you say it; it does look like a mess, I'm not even sure how I got the damn thing working in the first place with this.)

[necropost end]

Edited by Foxkit

Share this post


Link to post
Share on other sites
  • 0

What you're asking for is especially tricky. I managed to do it with my Animated CMS, but it took my every metaprogramming skills to achieve this.

 

The problem is that, when you changes menus, you're calling for a different scene, automatically "activating" the new menu and thus trashing the previous one. Well then, what you would want to do is have the current scene continue and execute some code before the new scene takes its place. What I did roughly is bypass the 'new' method, which is supposed to make the target menu, and have it do stuff before actually making it. If you're interested, I'm okay to share the technique, but as I told you, you have to know this isn't for the faint-hearted.

Share this post


Link to post
Share on other sites
  • 0

First, just so you know, you've aliased Window_Base's update and overrode the method but you aren't making a call to the original update....

 

That may/may not cause some issues (depending on what you do with windows that inherit from Window_Base)

 

*ahem*

 

But, the reason you are just getting a fade, then the scene changes, is because, you change the scene and return before the Windows have a chance to move

 

if Input.trigger?(Input::B)
 # Move both the command window and gold window back
 @command_window.start(-160,0)
 @gold_window.start(0, 480)
 @command_window.win_move
 @gold_window.win_move
 # Play cancel SE
 $game_system.se_play($data_system.cancel_se)
 # Switch to map screen
 $scene = Scene_Map.new
 return
end

 

I find the easiest way to test these things, is work out the call stack in your head:

1. Player presses B button

2. @command_window/@gold_window .start(....) is called (some values get set)

3. @command_window/@gold_window .win_move(...) is called (this sets some flags, to instruct the window to move, when update is called)

4. $game_system.se_play(...) is called (sound effect is played)

5. $scene = Scene_Map.new is called (calls Scene_Map#initialize)

6. return to calling statement (update)

 

# from Scene_Menu#update
if @command_window.active
 update_command
 return
end

 

7. return to the calling statement

 

# from Scene_Menu#main
update
# Abort loop if screen is changed
if $scene != self
 break
end

 

8. $scene is now an instance of Scene_Map, therefore, $scene != self is true

9. break from loop

 

# Prepare for transition
Graphics.freeze
# Dispose of windows
@command_window.dispose
@gold_window.dispose
@status_window.dispose

 

9. Graphics.freeze is called

10. all windows are disposed

11. self (this instance of Scene_Menu) is now officially out of scope, and may as well be considered garbage collected. (well, assuming you aren't still storing a reference to it somewhere...and, technically, the garbage collector may not have kicked in yet *ahem* but that's another story, and isn't important.)

 

So, as you probably noticed, once the menu is done with, there isn't a single call to any of those windows in question's update methods. Therefore, they are disposed before they can move.

 

So, to fix it, you'll probably want to do something like this:

 

PSEUDO-PSEUDO-CODE due to my laziness

while command_window or gold_window is still moving
 Graphics.update
 update command_window
 update gold_window
end
Graphics.freeze
dispose windows

 

That way, when the scene is about to dispose itself (after it breaks out of the main loop), it will continue to update the windows, until they've finished moving THEN dispose them and move to the next scene.

 

Also, some more advice:

 

You should probably make Window_Base#update turn off the move_x/move_y flags (set them to false), when they have finished moving. That way it should be easier for you to test if they ARE still moving. (currently, the flags will be set true, but they never get set false; unless another call to win_move is made)

 

EDIT: haha, yea, basically what Moonpearl was saying. Except, much more verbose. Although, I don't see the need for metaprogramming...

Moonpearl, could you share with me what you are speaking of? Unless I misunderstand your usage of "bypassing new"; I don't really see a need to bypass new...

Share this post


Link to post
Share on other sites
  • 0

EDIT: haha, yea, basically what Moonpearl was saying. Except, much more verbose. Although, I don't see the need for metaprogramming...

Moonpearl, could you share with me what you are speaking of? Unless I misunderstand your usage of "bypassing new"; I don't really see a need to bypass new...

It's true that using metaprogramming is not mandatory if you're at your own CMS and wish to do everything "from scratch". The reason I did this is because I wanted my ACMS to only reshape the menus graphically speaking. All scenes actually still work on their base code, meaning you can use a modified version of a menu scene along with the ACMS with no need to modify the latter. To achieve this, since I couldn't make any modifications to the way scenes work, and thus how they call each others, I had to work out a way to pass some code to the current scene whenever a new one was called.

 

If you want to see how I managed this, please download the ACMS's script bundle from my blog and take a look at the Scene_Menu_Super and Scene_Menu_Base entries. I'll be glad to post some details if needed, but for now I think i have to go to sleep...

Share this post


Link to post
Share on other sites
  • 0

Oh ho ho, my mistake.

 

I missed the fact you were more specifically referring to YOUR script, rather than THIS script.

 

EDIT:

 

Finally took a look, looks like someone knows how deep the Ruby...er.... rabbit hole goes ;)

it's nice to meet someone who has an appreciation for metaprogramming.

 

Let me tell you I finished a 2 year programming diploma recently, and every time I went off on a tangent about metaprogramming my class mates kinda just looked at me like I was crazy. Mind you, I might be.

Share this post


Link to post
Share on other sites
  • 0

Metaprogramming?? This is the first I've heard of it, but it sounds interesting at the least, sounds like it could also be the devil in disguise. Would either of you mind explaining?

Share this post


Link to post
Share on other sites
  • 0

Well, an application of metaprogramming is exactly what I explained above to both you and Kell. Metaprogramming is basically programming the programming language, i.e. you take core features from the programming language and mess with them. For instance, each class's 'new' method is meant to create a new object of this class, but you may redefine it to have the class do something else instead (or in addition). A simple example is a skip title script (mine works on this very idea) - instead of modifying what's around the Scene_Title class (that is, wherever Scene_Title#new is invoked), you modify the Scene_Title#new method instead, having it check whether this is the very first scene to be called, and if so, return a new Scene_Map object instead of a Scene_Title object. Aside from showing off your knowledge of Ruby, the benefit you draw from this technique is that you may somehow manipulate objects' behavior before they were even created, without altering anything in the rest of the program. This is especially useful for custom scripting in RPG Maker because scripters do not necessarily communicate with each other and it's not uncommon to find scripts that are incompatible because either of them rewrites a part of the other. By doing what I did with the ACMS, for instance, you highly minimize this risk because you do not need rewrite the part where objects call each others - in other words, you don't alter the caller, only the called one.

 

I hope this helps clarify things a little, it's kinda hard to explain.

Share this post


Link to post
Share on other sites
  • 0

it's nice to meet someone who has an appreciation for metaprogramming.

Well, I have some sort of an aesthetical concern when programming - I like getting what I'm aiming at in the most simple, economical way there can be. Making loads of copy/paste from the base engine just to modify a few lines did not sound right, so I tried and find an alternative solution to that. Besides, I like making things that fit anywhere, and frequent compatibility issues with external scripts (of which authors are not always as concerned as I am with external compatibility) encourage me to always try harder and harder to avoid them.

 

I'm an artist at heart, more than an engineer. Most programmers don't care how they did if the result is achieved, but as far as i'm concerned, what thrills me is not getting things to work, but getting things to work in an elegant and smart way.

Share this post


Link to post
Share on other sites
  • 0

I think you did a pretty good job of explaining ruby's meta-programming facilities. I mean, you only scracthed the surface but I don't know how you feel about writing an essay about how deep that rabbit hole goes...And I think I might be the only one insane enough to read such an essay.

 

Metaprogramming, as moonpearl was saying is simply, is you're basically writing code, that kinda writes code.

 

And that's 2 aspects of it: In terms of ruby (or, i.e. languages with the ability to metaprogram themselves, which is also referred to as "reflection" or "reflexivity") which more leans to the side of you are actually manipulating the code itself at run time or the ability to "peer" into the runtime itself; through code

 

In some languages/applications this is deemed dangerous (we're talking embedded systems, C and that fun stuff...would you want the software that's preventing your car from crashing to be modifying itself would you?)

 

However, technically, C could be used to "metaprogram" other languages.

 

Hell, RPG Maker does a lot of metaprogramming for you. Think about eventing, the database, etc. You click and point, and suddenly your project DOES stuff (that requires code, no?) and you didn't write a lick of code. Just like any popular IDE -> you start up a project, suddenly there's a bunch of source code, some makefiles maybe or other build systems...and all you did was say "File > New Project... > Some Project Type" (which is a love-hate relationship for me. I trust machines to do what their told, but I don't always trust others to tell them to do the right thing xD)

 

That's the other end of the spectrum; writing programs to write other programs (well, more in terms of getting it to all that automated boring stuff...who seriously wants to spend all day typing out data classes for their game?)

 

Or that boring stuff like xml, html, SQL. Sure, they're easy, but pretty damn boring -> so just make a program that writes it for you (I am a firm believer that xml WAS NOT intended to be written by man, but by machines)

 

If you REALLY wanna get into meta-programming I advise learning any dialect of Lisp (scheme is probably the minimal, and easiest dialect to learn, or so I've heard. And I've heard great things about how functional programming languages play very nicely with concurrency)

 

Lisp is really neat, and works perfect with meta-programming. Lisp code, although obscure looking, is actually written in essentially what the ruby interpreter might turn your code into, before it can start executing stuff (Abstract Syntax Trees and all that goodness)....so really, Lisp code can be walked through, executed or manipulated directly with Lisp, since it's pretty much already executable lisp.

 

When you hear something like, a Lisp interpreter completely implemented in Lisp, then you might see what I'm getting at.

 

Well, I have some sort of an aesthetical concern when programming - I like getting what I'm aiming at in the most simple, economical way there can be. Making loads of copy/paste from the base engine just to modify a few lines did not sound right, so I tried and find an alternative solution to that. Besides, I like making things that fit anywhere, and frequent compatibility issues with external scripts (of which authors are not always as concerned as I am with external compatibility) encourage me to always try harder and harder to avoid them.

 

I'm an artist at heart, more than an engineer. Most programmers don't care how they did if the result is achieved, but as far as i'm concerned, what thrills me is not getting things to work, but getting things to work in an elegant and smart way.

 

That's good; and I really hope your last sentence isn't true. In my opinion, there is a very fine line between being an artist and an engineer, in terms of programming.

 

Being able to write elegant, concise yet simple solutions (therefore maintainable and scalable, solutions) is a key ingredient to being an engineer (that's what software design is all about, and why it's always a bad idea to skip that step)

 

So, I think, by your definition I would almost call you just as much an "engineer" as an "artist" (I won't, however, call you an architect, they just like to draw diagrams with fancy lines and arrows. Just kidding, I like diagrams with fancy arrows :(modelling's pretty fun...not what I'd want to do for living, but sometimes a picture really is worth a 1000 words. And they can save you a 1000 lines of code if they're real good. Okay, maybe not that much...but maybe)

 

Like Joel Spolsky likes to say: "No code without specs!"

 

END RANT

 

This was a pleasant conversationtangent I hadwent withoff on you guys

 

Time to go home, I have homework to do and ironically, it's not here with me at school.

Share this post


Link to post
Share on other sites
  • 0

Thanks for the explanation Pearl, It sort of makes sense, I just have no idea how you would do it. (a conversation better left to another time from the sounds of it.) Also, I broke my CMS .... again ... >.< (ironically after trying to streamline it so it didn't seem so messy to me [i try to strive for readability first, mostly because I have trouble reading code] and ironically the result I got is pretty much word for word what you have post up above moon.) So I'll fix it before trying to get the windows to move before disposal. I have plenty more questions but I'm glad you two can help out so much. Thanks again.

Share this post


Link to post
Share on other sites
  • 0
It sort of makes sense, I just have no idea how you would do it.

Basically, what interests us is achieved by writing the following:

class Stuff
 class << self
   alias old_new new
   def new(*args)
  # Do stuff, then return the result of the original method, that is the new object to be created
  old_new(*args)
   end
 end
end

What this does is define the 'new' method of the class (rather than an hypothetical 'new' method for the objects which belong to this class). More generally, this code:

class Stuff
 class << self
   def method
  # Do stuff
   end
 end
end

Allows to make the following call:

Stuff.method

That is, you're calling the method directly from the class, no need to create an instance of it. Furthermore, the following:

object = Stuff.new
object.method

Would result in a 'no method' error, because 'method' is defined for the Stuff class itself, not its instances.

 

Does that make any sense at all?

Share this post


Link to post
Share on other sites
  • 0

Yea fox, I wouldn't necessarily advise converting scripts over to take advantage of it; unless it makes things work better.

 

But to expand on what pearl is saying, it's all about Ruby's concept of metaclasses.

 

consider this:

 

class Foo
 def self.bar
   "bar"
 end
 class << self
   def do_something
     "do something!"
   end
 end
end

def Foo.something_else
 "something else!"
end

 

Each method definition, essentially, defines a class method for Foo:

Foo.bar
Foo.do_something
Foo.something_else

 

Would work, but an instance of Foo could not call those methods...however, you can get the class of Foo conveniently from an instance:

f = Foo.new
f.class.bar

 

Would work. The metaclass (or, sometimes referred to as the "singleton class" which I don't like that term because it reminds me too much of the singleton pattern, which is not EXACTLY what it is), is essentially an anonymous class that Ruby constructs behind the scenes, kinda like a parent class of class Foo.

 

However, it only acts as a parent in terms of the class scope, not instance scope. This is because, Foo, nothing more than a constant instance of the class Class. Remember, everything in ruby is an object:

 

irb(main):017:0> Foo.class
=> Class
irb(main):018:0> Foo.superclass
=> Object
irb(main):019:0> Foo.class.superclass
=> Module
irb(main):020:0> Foo.class.superclass.superclass
=> Object

 

So, Foo is an instance of Class, which inherits from Module, which inherits from Object.

However, Foo inherits from Object.

 

Which might explain why, if you look at Ruby's documentation for class and look at the (not so) pretty diagram:


                        +---------+             +-...
                        |         |             |
        BasicObject-----|-->(BasicObject)-------|-...
            ^           |         ^             |
            |           |         |             |
         Object---------|----->(Object)---------|-...
            ^           |         ^             |
            |           |         |             |
            +-------+   |         +--------+    |
            |       |   |         |        |    |
            |    Module-|---------|--->(Module)-|-...
            |       ^   |         |        ^    |
            |       |   |         |        |    |
            |     Class-|---------|---->(Class)-|-...
            |       ^   |         |        ^    |
            |       +---+         |        +----+
            |                     |
obj--->OtherClass---------->(OtherClass)-----------...

 

http://www.ruby-doc.org/core-1.9.3/Class.html

 

And it goes even deeper than this...

 

*Ahem*

 

But, if you want a good introduction:

http://www.infoq.com/presentations/metaprogramming-ruby

 

It's a nice video + slideshow presentation on introducing metaprogramming in ruby. It's only an hour long, with examples and explanations. Still an introduction, but a very good one.

Share this post


Link to post
Share on other sites
  • 0

one question... is this rabbit hole for all OOP languages??

Edit1: moonpearl, if I'm reading/understanding this correctly, (this is specific to your example above) your redifining the .new 'method' (I think that's what i would be...) scene_title? because it doesn't construct anything but defines the items at run time?

 

Edit 2: Also, can I ask for another proofread?... blush.png

Now windows such as Window_Tittle, Window_Status, and Scene_End's window seem to have a magnetic attraction to (0,0) in the game, and I only know that's it's connected to my window base script. I can only think I did something wrong in the update method, but other windows arn't affected, just those three, and if they change positions during the scene's duration, they don't move back to the place, they just act like they are supposed to.

patebin http://pastebin.com/WwWJnN7B

Edited by Foxkit

Share this post


Link to post
Share on other sites
  • 0

As I said in the chat it's more a Ruby thing, than an OOP thing (and like-wise, it's not really a "Ruby" thing, other languages of various paradigms).

 

Although, I've noticed most programming languages have their own "rabbit-holes" if you will.

 

Now, based on just the script you have there, I can't see anything that would lead to "magnetic attraction" to 0, 0

 

Have you changed the actual Scene_ script(s)? I think the issue is probably *mostly* in the Scene itself. However, it could be a combination of both; and I'd have to take a look at both of them.

 

One thing I'd like to point out, you alias update; then override update, but you don't make any calls to the original update. You *might* want to make that call to "cms_update" so the original method can be called. Unless you want to override the method completely, then, in that case you don't need to alias.

 

*ahem* but I don't really think that's the issue at all, as if I can recall correctly, your new version of update covers all functionality of the old update (so you probably don't need to alias the method at all)

Share this post


Link to post
Share on other sites
  • 0
One thing I'd like to point out, you alias update; then override update, but you don't make any calls to the original update. You *might* want to make that call to "cms_update" so the original method can be called. Unless you want to override the method completely, then, in that case you don't need to alias.

 

*ahem* but I don't really think that's the issue at all, as if I can recall correctly, your new version of update covers all functionality of the old update (so you probably don't need to alias the method at all)

 

I've been having trouble getting the alias functions to work so I just copy/pasted the original in. I hope that's at least acceptable even though its certainly not elegant. whistle.gif

I'll post the scenes in question, gimme just a sec, and the only one i've really done some tweaking with is the Scene_Menu Status window, and the wording and positioning of both Scene_Title and Scene_End. I'll post them none the less.

Edit: I've also done the same thing for the initialize function, same issues and same headache.

 

Scene_Menu: http://pastebin.com/txsBrFGP

Scene_Title: http://pastebin.com/QpLEJGu2

Scene_End: http://pastebin.com/eiguEqeC

 

Thanks in advance

Edited by Foxkit

Share this post


Link to post
Share on other sites
  • 0

OH I figured it out!

 

My mistake, there was an issue with the window script. However, the Scene_ scripts made me clue into this.

 

First, I'd like to point out the fact that, the windows that are causing you issues, start out like this:

#window_status

class Window_MenuStatus < Window_Selectable
 def initialize
   super(0, 0, 480, 480)
   # ETC...
 end
 # ETC..
end
# Window_Title/End

class Window_Command < Window_Selectable
 def initialize(width, commands)
   super(0, 0, width, commands.size * 32 + 32)
   # ETC...
 end
 # ETC...
end

 

Note the most important point, is the parameters passed up to the super class:

super(0, 0, 480, 480)
super(0, 0, width, commands.size * 32 + 32)

 

So, eventually, the (x, y) parameters (0, 0) in these cases, eventually trickle up to Window_Base:

class Window_Base < Window
 def initialize(x, y, width, height)
   super()
   self.x = x
   self.y = y
   # intitialization stuff
   @dest_x = self.x
   @dest_y = self.y
 end
 # ETC...
end

 

Note: @dest_x & @dest_y are both equal to x & y respectively, and in these cases, are 0 & 0

 

Now, let's look at your update method:

 


def update
 # stuff
 if self.x < @dest_x
   self.x += 32
 end
 if self.x > @dest_x
   self.x -= 32
 end
 if self.y < @dest_y
   self.y += 32
 end
 if self.y > @dest_y
   self.y -= 32
 end
end

 

So, what is happening, is @dest_x and @dest_y are set to 0 and 0 when those windows in question, are being instantiated.

Then, you set the windows' x, y coordinates after they are instantiated.

 

Since the windows' x/y coordinates are NOT 0, 0; the window now is "magnetically" attracted to 0, 0.

Does this make sense?

 

So, what you could do (perhaps, there are MANY options) is after setting the x/y of a window (when you don't want it to move), make a call to window.start(window.x, window.y) before its next update, that way the dest_x/dest_y are ENSURED to be the same as x/y

 

That's probably not the cleanest way, but the only other ways I can think of, involve redesigning the entire script or modifying the default scripts (so you can pass x, y as a parameter).

 

That might be the easiest method. If you want me to go over other options, I can do that.

 

As for the alias thing, here's another example; it might clear some things up:

 

 

class Foo
 def bar
   print "hello, "
 end

 # duplicate bar definition, with new name
 def new_bar
   print "hello,"
 end

 # redefine bar
 def bar
   new_bar
   print " world\n"
 end
end

 

is functionally the same as:

 

class Foo
 def bar
   print "hello,"
 end

 # duplicate bar definition, with new name
 alias new_bar bar

 # redefine bar
 def bar
   new_bar
   print " world\n"
 end
end

 

Now notice the main advantage with alias over the first method:

1. less typing, less copy pasting. less repetition (DRY, don't repeat yourself!)

2. much more maintainable

 

Now, while I KNOW this is a contrived example, think about this:

with alias, you don't really care what bar actually does: regardless, it WILL be duplicated AND be given a new name. So what if the implementation of the OLD (original) bar changes?

 

Say we decide, rather than being so optimistic/innocent with "Hello, world!" we want to output "Goodbye, cruel world!"

So, we change bar:

def bar
 print "goodbye, cruel"
end

 

However, when bar gets redefined, it will call new_bar; which is still

print "hello,"

Only when the new_bar method is modified to reflect the changes in bar, the correct string show up.

 

But, with alias (since it copies the definition at the time of alias being called, i.e. not hardcoded) all you will need to change IS the original bar, and the new bar will say "goodbye, cruel world!"

 

Does that clear things up? Or does that not explain why the alias method was not working for you? I'm not sure what you mean by not being able to get alias to work right.

 

I do know, there is a bug in RPG Maker, where if you press "f-12" (that resets the game right? or is it something else...?), somehow the aliased methods get re-aliased or something, and you end up with this infinite recursive method call, and rpg maker crashes because it doesn't support recursion. Or something, either way it crashes; so you can usually just add a method_defined? guard to all your aliases:

unless method_defined? :new_method_name
 alias :new_method_name :old_method_name
end

 

 

Share this post


Link to post
Share on other sites
  • 0

Ah, I thought that it might have been that when I first was working, I wonder if I could just set dest_x and dest_y to nil, I'll probably run into an error, so if that doesn't work I'll just put that damn if @move = true stuff back in... and I thought I came up with a good method T-T.

 

Edit: and thanks for the Alias talk, question though. If your aliasing initialize, like I am trying to, do you have to put in the same commands for it? (x, y, width, height)? Um... if your initializing a method that takes parameters like so (full editor isn't working, so pardon me)

 

def hello_world(word1, word 2)
 puts word1
 puts word2
end

alias cruel_world hello_world
def new_world
 cruel_world(would I need to stick the parameters here?)
end

Edited by Foxkit

Share this post


Link to post
Share on other sites
  • 0

You could set them to nil, just remember; before using the variables for ANYTHING, check if they are nil first:

if @dest_x != nil
 # do stuff with @dest_x
end

 

(or you can just do

if @dest_x

nil and false both evaluate to "false" in any conditional statement in ruby. Everything else evaluates to "true")

 

How about you try something like this?

class Window_Base < Window
def has_dest?
 @dest_x && @dest_y
end

def moved?
 return has_dest? ? (@dest_x == self.x && @dest_y == self.y) : false
end

def update
 # update stuff
 if has_dest?
if moved?
  @dest_x = @dest_y = nil
else
  if self.x < @dest_x
	self.x += 32
  end
  if self.x > @dest_x
	self.x -= 32
  end
  if self.y < @dest_y
	self.y += 32
  end
  if self.y > @dest_y
	self.y -= 32
  end
end
 end
end
end

 

Those that help any?

 

And yes, for the alias you would have to pass the required number of parameters. When you alias the method, it copies over the definition and the parameters (I'd argue that parameters could be defined as part of the definition, but that's another story).

 

EDIT: I missed a couple ends lol

EDIT2: parent class xD

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...