My Assistant
Dubealex"If you havent failed yet, try again"
| Entertainment
| Game Making
| Creative Forum
| Technology & Computers
| Translations
![]() ![]() |
Nov 7 2005, 09:39 PM
Post
#1
|
||
![]() Administrator of this Asylum AdminMember No.: 1 Posts Liked: 48 * Joined: 8-November 04 Posts: 2,704 --> From: Longueuil, Canada RPG Maker Level: Master Class Title: Writer, Scripter & Designer Last.fm ID: Dubealex Country: ![]() |
RGSS & Ruby Lesson - Chapter 2
:icon_fleche_ff3: You need to have read Chapter 1 before reading Chapter 2. :icon_fleche_ff3: Remember the RGSS Reference on the main website-- It contains many info, even regarding If Statement and the likes. edit: I fixed a little error I did with Else if stamement. Sorry. The basic structure of a RGSS (Ruby) code was explained in Chapter 1. We learned how to do ATTR, how objects communicate and how to create simple class and objects. In Chapter 2, we will learn all the basic components that you must be able to use in order to create your very own scripts. Those components are stuff like "For..Loop", "If Statement", "Case" and "Variable Managements". We will go through each of them individually, and we will create small programs showing off how each components work, and we will finish this chapter with some script example (exercise) that uses many components at once. We will also learn how to manipulate many important component in RGSS, like the relation between a Scene and a Window, and how to do a Scene and a Window. We will thus create our own scene and display data in it. We won't do a complete CMS with menus and selectable items now, this will come in Chapter 3. (Otherwise this chapter would have been really too huge...) 1- Variables & Constants In every program, you need variables and sometimes you need contants. To save space and time in this chapter, if you don't feel confortable with variables, I suggest you go read my Variable Tutorial named "RMXP Variables Demystified" and come back here once you read it. Local Variables A local variable begins with a lowercase letter. This kind of variable can be used only within the method it was created in. In the following sample, both local variable exist only within their method, they do not conflict each others. Sample: CODE class Local_Variable def method_1 local_variable=2 end def method_2 local_variable=3 end end Instances Variables An instance variable begins with a @ and must be created inside a method. This kind of variable can be used in any method contained in the same class. In the following sample, the instance variable created in method_1 is equal to 2, and we change it to 4 in method_2. An instance variable is global within a class, it exist for all the method inside that class. Sample: CODE class Instance_Variable def method_1 @instance_variable=2 end def method_2 @instance_variable=4 end end Class Variables A class variable begins with two @@ and must be created anywhere in the class, as long as it's not inside a method. It is recommended to put them below the class name definition. A class variable is shared among all objects of a class and all method from that class can use it. In the following example, we created a class that counts the number of objects it created so far. Sample: CODE class Class_Variable @@class_variable=0 def initialize @@class_variable+=1 end end Global Variables A global variable exist in the entire program, once created, it can be used in any other class. In the following sample, we created a global variable in a class, and we add 1 to it in another class. Sample: CODE class Global_Variable_1 def initialize $global_variable=0 end end class Global_Variable_2 def initialize $global_variable+=1 end end Constants A constant is a "container" that contains a certain value, it should not be changed; but in Ruby, you can... But only from within the class in which you changed it, the value stored in a constant always remains the one you set in it's definition. In the following sample, I created 3 class to show how constant can be used. Sample: CODE A_CONSTANT=100 class Constant_Test_1 ANOTHER_CONSTANT=50 def initialize print ANOTHER_CONSTANT print A_CONSTANT end end class Constant_Test_2 def initialize print Constant_Test_1::ANOTHER_CONSTANT print A_CONSTANT end end class Constant_Test_3 A_CONSTANT+=1 def initialize print A_CONSTANT end end First, we created a global constant named "A_CONSTANT" and we set it to 100. You also saw that a global constant is defined outside a class; it will be useable in every class of your program. In the first class, we created a class constant, that is useable from within the class... But you can use it from another class when you use the right syntax. In the second class we actually accessed the constant we created in the first class. The syntax rule is the following: CODE Class_Name::CONSTANT_NAME Using this syntax, you can define a constant inside a class, do whatever you want to it, and be able to access it from another class. In the third and last class sample, we actually add 1 to our global constant "A_CONSTANT", and we print it's content, which gives us 101. Try to execute all those class one after the other, and repeat it 2 times... I.E: Do this in a event Call Script: CODE Constant_Test_1.new Constant_Test_2.new Constant_Test_3.new Constant_Test_1.new As you can see, the constant "A_CONSTANT" is equal to 101 only when you call Constant_Test_3.new, and it stays at 101 because it always uses the static value found in "A_CONSTANT", which is 100. Simply put, a constant is constant, it doesn't really changes. Remember that a constant should not be created/modified inside a method. 2- Conditional Statements In this section you will learn how to do "If Statement", "Case Stements", and so on. I already explained the basics of those syntax in the RGSS Reference, here's a link to it. You should go there, read it all, and come back here to read the details and see real script sample: -> Go on the main website and go in RGSS Reference - Ruby Syntax. When you do conditional statement, always remember to uses double sign, I.E: CODE if my_variable=0 # <-- ISN'T CORRECT if my_variable==0 # <-- IS CORRECT A full list of sign to used in conditions can be found in the page given in the link above. There is multiple way of doing those conditions in Ruby, and I will give you some example that will give you the same result if run. If Statements Sample A: CODE class If_Statement_1 @@a_class_variable=10 def initialize @@a_class_variable+=1 a_local_variable=13 if @@a_class_variable==a_local_variable print "Yay, we are equal !" else print "Arg, it's not fair !" end end end If you run 4 times this class, I.E: Do this in a call script: CODE If_Statement_1.new If_Statement_1.new If_Statement_1.new If_Statement_1.new You will get the message "Yay, we are equal !" at the third window; since we add 1 to our class variable each times you call that class, and the condition check if our class variable equals our local variable. So, the process that RMXP does when you call it 4 times is the following: [First Time] @@a_class_variable=10+1 --> gives 11 a_local_variable=13 The IF statement compare the two, and they aren't equal. The if statement thus execute the ELSE actions and show that message. [Second Time] @@a_class_variable=11+1 --> gives 12 a_local_variable=13 The IF statement compare the two, and they aren't equal. The if statement thus execute the ELSE actions and show that message. [Third Time] @@a_class_variable=12+1 --> gives 13 a_local_variable=13 The IF statement compare the two, and they are now equal. The if statement thus execute it's main body actions, and show the right message on screen. [Forth Time] @@a_class_variable=13+1 --> gives 14 a_local_variable=13 The IF statement compare the two, and they aren't equal anymore. The if statement thus execute the ELSE actions and show that message. Sample B: CODE class If_Statement_1 @@a_class_variable=10 def initialize @@a_class_variable+=1 a_local_variable=13 if @@a_class_variable==a_local_variable then print "Yay" else print "Arg" end end end This sample shows that you can write the If Statement in one single line if you want to. It can be useful for small condition. Here's 2 other sample with the same effect, but without the else handler: Sample C: CODE class If_Statement_1 @@a_class_variable=10 def initialize @@a_class_variable+=1 a_local_variable=13 print @@a_class_variable if @@a_class_variable==a_local_variable : print "Yay" end end end Here you can see that we can replace THEN by a semicolon : Those are synonims. We print the content of @@a_class_variable and we see that we print the message "Yay" only if it equals 13. So, as I said, it's useful for small stuff like this. You can also write that condition like this: Sample D: CODE class If_Statement_1 @@a_class_variable=10 def initialize @@a_class_variable+=1 a_local_variable=13 print @@a_class_variable print "Yay" if @@a_class_variable==a_local_variable end end In this sample, we can omit the END keyword, so it's even smaller. We inversed both component in the condition. So we will print "Yay" ONLY if @@a_class_variable is equal to a_local_variable. So, now you know there are many different ways of doing condition, and we will use them later in our more advanced example. You can also use ELSE IF keyword to add condition into your If Statement, you aren't limited to one ELSE handler as in an event Conditional Branches... RGSS is programming, so it's more powerful and more flexible. Here some example: Sample E: CODE class If_Statement_1 @@a_class_variable=10 def initialize @@a_class_variable+=1 a_local_variable=13 if @@a_class_variable==a_local_variable print "We Are Equal !" elsif @@a_class_variable==12 print "I Equal 12 !" elsif @@a_class_variable != a_local_variable print "We aren't equal !" end end end As you can see, the trick with Else If is to remember to use elsif and not Else If. Using Else If will force the program to take one of the choices in the If Statement, and never two at once. Otherwise, when @@a_class_variable would equal 12, we would have seen 2 messages, we would have seen "I Equal 12 !" and "We Aren't Equals", but the If Statement shows the first one that returns to be true, and skip the others. If you want to do this, you can simply do all your else if as new If Stamement, the program will thus check them all, and execute only those who happen to be true. Like this`: CODE class If_Statement_1 @@a_class_variable=10 def initialize @@a_class_variable+=1 a_local_variable=13 if @@a_class_variable==a_local_variable print "We Are Equal !" end if @@a_class_variable==12 print "I Equal 12 !" end if @@a_class_variable != a_local_variable print "We aren't equal !" end end end If you run this, you will see that when @@a_class_variable equals 12, two messages are shown, "I Equal 12 !" followed by "We Aren't Equal". However, in much case where you would use else if, it's better to use a Case Statement, explained below. Case Statement A case statement is used to check the content of a given variable, and list a group of actions that will happens at each given value. This is used a lot in Scene and Menus. We will still uses the exact same sample as above, we our class_variable: Remember, you must change the names you used in your Call Script to the class name, in this section, it's Case_Statement_1.new Sample A: CODE class Case_Statement_1 @@a_class_variable=0 def initialize @@a_class_variable+=1 case @@a_class_variable when 1 print "I am 1" when 2 print "I am 2" when 3 print "I am 3" else print "What Am I ?" end end end If you read my RGSS reference as I said above, you should not have any problem understanding the sample I just gave. As you can see, it really look nicer with a Case Statement than with else if. Once again, remember that a semicolon can replace the THEN keyword in conditional statement, so you can make your code smaller using this: Sample B: CODE class Case_Statement_1 @@a_class_variable=0 def initialize @@a_class_variable+=1 case @@a_class_variable when 1: print "I am 1" when 2: print "I am 2" when 3: print "I am 3" else print "What Am I ?" end end end We can also make "Ranges", a range is defined by specifying a start value and an end value, with points in the middle. (We will talk more about range later.) Basic Range Rules: CODE START..END -->Include the END value START...END -->Exclude the END value So, you can use those "Range" in your case statement, like this: Sample C: CODE class Case_Statement_1 @@a_class_variable=0 def initialize @@a_class_variable+=1 print @@a_class_variable case @@a_class_variable when 1..3: print "I am between 1 and 3" when 4..6: print "I am between 4 and 6" when 7..9: print "I am between 7 and 9" else print "What Am I ?" end end end To test this, simply add more Case_Statement_1.new to your Call Script. 10 is enough to see all the test. You can also uses specific condition list, seperated by comas, like this: Sample D: CODE class Case_Statement_1 @@a_class_variable=0 def initialize @@a_class_variable+=1 print @@a_class_variable case @@a_class_variable when 1,3: print "I am wether 1 or 3" when 4,6: print "I am wether 4 or 6" when 7,9: print "I am wether 7 or 9" else print "What Am I ?" end end end In this sample, the program check if the value found inside @@a_class_variable is one of those listed at each "when" keyword. So, (in this case) a comas (,) is like an OR keyword. Remember that you can also uses other thing instead of numbers (integers), like text (strings), like this: Sample E: CODE class Case_Statement_1 @@a_class_variable="a" def initialize @@a_class_variable.next! case @@a_class_variable when "b": print "I am B" when "c": print "I am C" when "d": print "I am D" else print "What Am I ?" end end end In this sample, we do a .next! command, that is used to increment a string to it's next logical value depending on the character found at the extreme right of the string. Example: a_string="ab" a_string.next! --> a_string now equals "ac" another_string="name102" another_string.next! --> another_string now equals "name103" So, back to our Case sample, we see that it's working with string too. I won't list all the others conditional statement, as Unless, While and Until, they are explained in my RGSS Reference, and by reading the If Statement and the Case Statement from this lesson, I'm sure you can understand them pretty well. 3- Loop Once again, in the link given above (The RGSS Reference), there is a good For..Loop reference. Here's a working sample, once again using the same kind of code shown in previous sample: Sample A: CODE class For_Loop_Sample def initialize a_local_variable=0 for i in 1..10 a_local_variable+=1 print a_local_variable end end end This will add 1 to "a_local_variable" and print it's content 10 times... from 1 to 10, including 10. Remember the Range rules I explained above, it's the same rule in a for loop. So if we would have written "0...10" instead of "1..10", it would have given us the exact same results. Some of you may be confused by the i in the line... What the hell is that i for ? What I like to say is that the i stand for "Iteration", as Iteration is repeating. Here's an extract from the RGSS Reference: QUOTE [...]A For Loop will execute it's body (actions) until it reaches the end value. The For Loop actually "iterate" the actions found in its body and store the numbers of iteration in the variable i. We can use any numbers or string (text) as start and end value. This will create the For Loop range. A range is defined using points (..) or (...). Using two points, as in the example above will make a range starting from the start value and ending at the end value, including the end value. Using 3 points (...) will exclude the end value. [...] I won't list all the possible syntax for a For..Loop, as I did them in the RGSS Reference, just go check it out. Your i value can be used to create condition from within your for..loop or to use as reference. Check the following example: Sample B: CODE class For_Loop_Sample def initialize for i in 1..4 print $game_actors[i].name end end end In order to test that example, you need to have your 4 first hero defined in RPG Maker. Basically, our i value is equal to the value in the range where we are at, and increment at each loop. Here's what is the process that RMXP did: [First Iteration] i=1 --> We print name of hero ID#1 (i being a variable, $game_actors[ i].name is now known as $game_actors[1].name) [Second Iteration] i=2 --> We print name of hero ID#2 (i being a variable, $game_actors[ i].name is now known as $game_actors[2].name) [Third Iteration] i=3 --> We print name of hero ID#3 (i being a variable, $game_actors[ i].name is now known as $game_actors[3].name) [Forth Iteration] i=4 --> We print name of hero ID#4 (i being a variable, $game_actors[ i].name is now known as $game_actors[4].name) You can see that this kind of code is used a lot in RMXP, especially in Window_MenuStatus, where RMXP list the actors datas in a For..Loop. Just remember that you can use variable in the range, as this will have the same effect as the sample shown above: Sample C: CODE class For_Loop_Sample def initialize a_loacal_variable=1 another_local_variable=4 for i in a_loacal_variable..another_local_variable print $game_actors[i].name end end end 4- Inheritance You will have to understand the power and the structure of Ruby inheritance before trying to understand how exactly a window and a scene works. You can make a class "inherit" methods and other data (variables) from another class. Class working with inheritance are called SubClass and SuperClass in Ruby; this can also be known as ChildClass and ParentClass. Here's an example: Sample A: CODE class Inheritance_Sample_1 def initialize @a_local_variable=1 end end class Inheritance_Sample_2 < Inheritance_Sample_1 def initialize super print @a_local_variable end end To test it out, simply do a Call Script in an event, and write this in it: CODE Inheritance_Sample_2.new To make a class inherit from another, you write a < symbol aside it's name, followed by the name of the class you want to be the SuperClass. In our sample, "Inheritance_Sample_2" is the SubClass and "Inheritance_Sample_1" is the SuperClass. Which means we can access stuff from Inheritance_Sample_1 from Inheritance_Sample_2 if used correctly. You can see the keyword "super" in our initialize method in the class "Inheritance_Sample_2"; what does this do ? Well, it simply execute the method in the SuperClass that has the same name as the one in which we wrote the "super" syntax. Meaning that we used "super" in the initialize method, this will have the effect of executing the initialize method of the SuperClass, in our case it's "Inheritance_Sample_1" --> here's the process that RMXP did with that code: [Receives the .new command] -Execute the initialize method of Inheritance_Sample_2 -Found a "super" keyword. --> Check what is the SuperClass; found that it is Inheritance_Sample_1 - Execute the initialize method of the SuperClass Inheritance_Sample_1 --> The initialize method of Inheritance_Sample_1 set @a_local_variable=1 - The program then continue in the initialize method of Inheritance_Sample_2 --> @a_local_variable is now equal to 1 - We print @a_local_variable on screen [End of program] Here's a diagram to better visualize what I mean:
inheritance1.jpg ( 32.19k )
Number of downloads: 1083So, as you can see, if we do a super keyword, it execute the method in the SuperClass, as putting a "super" keyword in method_a of the SubClass will execute the method_a of the SuperClass.... And so on. You can also use the "super" keyword with arguments, as explained in Chapter 1, this can be seen in every Window class of RMXP; will be explained in section 5 below. 5- Scene And Window RPG Maker XP interfaces are built with Scene and Window. Each scene is composed of many windows. The way it works is like having a lot of little blocks on a table, and we arrange the blocks a certain way to built what we desire. The table is the scene, and the blocks are the windows. So, it's logical to built a block before we can do a scene.... So let's do a window now: Creating a window The basic of a window is simple, you may have seen it in all the Window_ script in the default RMXP Script Editor. We will built a new window called "My_Window". To test it when you're done, simply do a Call Script in an event and write this in it: CODE My_Window.new My_Window code: CODE class My_Window < Window_Base def initialize super(0, 0, 200, 200) end end *I'm aware of the fact that the window disapears after a while; it's normal, it's because of Scene_Map; we did not told Scene_Map to update that window. We'll talk about that later. Let's just built a simple window for now: As you can see, this have the effect of creating a window on the top left corner of the screen. Here's the syntax: super(x position, y position, width size, height size) As you have learned in section 4, inheritance, "super" is used to execute a method in the SuperClass. Our window have Window_Base as SuperClass, so let's take a look at the initialize method of Window_Base: Window_Base Initialize method: CODE def initialize(x, y, width, height) super() @windowskin_name = $game_system.windowskin_name self.windowskin = RPG::Cache.windowskin(@windowskin_name) self.x = x self.y = y self.width = width self.height = height self.z = 100 end This is invoked each time you do a window, this defined it's sizes and position, it's windowskins and such other attributes. What is important to look at is the following line: def initialize(x, y, width, height) As explained in Chapter 1, those are Attribute Receivers (as I call them), so by using our "super(0, 0, 200, 200)" in the code of our window, RMXP actually did this: [Super keyword interpreted...] - Read arguments sent with "super" --> In Window_Base, we set the following attribute with the data sent with super: -> x=0 -> y=0 -> width=200 ->height=200 --> The window is created -Back to our window code [End of program] This window is plain... It's empty. Let's write something in it. My_Window Code (+Text): CODE class My_Window < Window_Base def initialize super(0, 0, 200, 200) self.contents = Bitmap.new(width-32, height-32) self.contents.font.name = "Arial" self.contents.font.size = 24 self.contents.draw_text(0, 0, 200, 32, "Yay, some text !") end end 3 lines are necessary to add text. You must specify a font name, a font size, and write the text itself. Let's explain those line: self.contents = Bitmap.new(width-32, height-32) This tells that the content of our window should be of the "Bitmap" type (Bitmap is defined within RMXP, not in the Script Editor). This allow to write text in the window, basically. The argument we send is the size of that bitmap area. Usually, we set it equal to the window size, hence width and height. (Remember, width and height are defined in the SuperClass, and we set them with our super line above.) Wanna know the big dark secret of the minus 32 ? I.E: width-32 ? It's because that arrow will appears pointing that data can still be viewed; this is probably because the bitmap is genuily larger than the window... dunno. We could have written (200-32, 200-32), it would have given the same result. (This could also be the reason of the text being cut-off in the borders of the window). The 2 other lines are straight forward. self.contents.draw_text(0, 0, 200, 32, "Yay, some text !") This line actually defines your text. The arguments you send in the parenthesis are the same as with the creation of a window. i.e: (x position, y position, width size, height size). The last argument is simply the text to draw in the window. *I am also aware that when looking at the Window code by default in the Script Editor, the text is actually drawn in another method, usually called "refresh". This is useful only if the content of the window will change as the window is shown. In other words, it is relevant to code it like that in Window_PlayTime, but not really in Window_Gold. Now that we are able to create a basic window, we can try to built a scene that will show, let's say, 3 windows. Window #1 will show the playtime, the gold held and the map ID on which you are. Window #2 will list the hero present in your party one above another, and window#3 will show stats for the hero in your party. (Take note that there isn't any window command (menu) in that scene yet. This will come later.) Here's the basic layout of what we want to achieve:
scene_sample.jpg ( 46.21k )
Number of downloads: 2544*OK ! I know, it's plain, it's ugly and kind of useless design... But we just want to know how to code a scene, without too many thing at the same time. Don't worry, I will explains how to work with selectable menu, even with multiple selectable menu, in chapter 3. Creating Window #1 The first window is the window on the top that shows the playing time, the gold held and the map ID. This is the simplest window to code. You could put all three window code and the scene in the same page in the script editor, but as this is a lesson, it's better to create a page for each window, and another for the scene, that way you won't get confused in all the code. So, first thing first, create a new page and call it Window_1 and add this code in it: (Important: You must add the page below the page containing the SuperClass of any script you do. This means that our window will work as long as they are below Window_Base. --> What I always do is add new custom script just above MAIN, all the time.) Window_1 Code: CODE class Window_1 < Window_Base def initialize super(0, 0, 640,100) self.contents = Bitmap.new(width-32, height-32) self.contents.font.name = "Arial" self.contents.font.size = 24 refresh end def refresh self.contents.clear self.contents.font.color = text_color(6) self.contents.draw_text(0, 0, 100, 32, "PlayTime:") #CODE TO SHOW PLAYTIME (Copied from Window_PlayTime) @total_sec = Graphics.frame_count / Graphics.frame_rate hour = @total_sec / 60 / 60 min = @total_sec / 60 % 60 sec = @total_sec % 60 text = sprintf("%02d:%02d:%02d", hour, min, sec) self.contents.font.color = normal_color self.contents.draw_text(100, 0, 120, 32, text) #END OF CODE TO SHOW PLAYTIME self.contents.font.color = text_color(6) self.contents.draw_text(250, 0, 50, 32, "Gold:") self.contents.font.color = text_color(0) self.contents.draw_text(305, 0, 100, 32, $game_party.gold.to_s) self.contents.font.color = text_color(6) self.contents.draw_text(400, 0, 100, 32, "Map ID:") self.contents.font.color = text_color(0) self.contents.draw_text(480, 0, 100, 32, $game_map.map_id.to_s) end def update if Graphics.frame_count / Graphics.frame_rate != @total_sec refresh end end end As you can see, I seperated the script in 5 differents blocks, and I will explains those block lines by lines. BLOCK 1: 1 def initialize 2 super(0, 0, 640,100) 3 self.contents = Bitmap.new(width-32, height-32) 4 self.contents.font.name = "Arial" 5 self.contents.font.size = 24 6 refresh 7 end This is the initialize method, with what you have already read in this chapter, and in chapter 1, you should be able to know what is going on in this block. Line 1 to 5 were explained in above sections, so I won't repeats myself. The 7th line simply calls the "refresh" method, that is defined below. BLOCK 2: 1 def refresh 2 self.contents.clear 3 self.contents.font.color = text_color(6) 4 self.contents.draw_text(0, 0, 100, 32, "PlayTime:") 5 #CODE TO SHOW PLAYTIME (Copied from Window_PlayTime) 6 @total_sec = Graphics.frame_count / Graphics.frame_rate 7 hour = @total_sec / 60 / 60 8 min = @total_sec / 60 % 60 9 sec = @total_sec % 60 10 text = sprintf("%02d:%02d:%02d", hour, min, sec) 11 self.contents.font.color = normal_color 12 self.contents.draw_text(100, 0, 120, 32, text) 13 #END OF CODE TO SHOW PLAYTIME [...] This is the first block that begins the method refresh. The first thing we do is clear the content of the window... why the heck do we want to do that in the first place ? Well, it's because we will refresh the content of that window in our later scene to show the play time running; and we do not want the text to show over and over again, or else it would get messy. Line 2: self.contents.clear actually take care of that. Line 3 and 4 were explained in above sections, they take care of showing the text "Playing Time:" in the window, at the desired location. The only thing that I haven't yet shown is line #3: self.contents.font.color = text_color(6). This line specify the color used to draw the text. The number between parenthesis at the end represent the color ID defined in Window_Base starting at line #39. (I.E: They are the same color ID used in messages event, using \c[ID].) The code to show the playing time start at line 5. This code is the same as in Window_PlayTime, except for the location of the time in the window. If you wonder what is all that giberrish in the code, I will clear it out: Line 6: @total_sec = Graphics.frame_count / Graphics.frame_rate This create a new variable named @total_sec, and makes it equals to the total frame count that occured in the game divised by the frame per seconds (The frame rate - FPS). Basically, it can be converted like that: - 12450 Frames has been counted since the begining of the game. - The FPS (Frame Rate or Frame Per Second) is 30. - If you want to know the numbers of seconds, you do 12450/30=415 --> 415 sec. So, basing ourselves on that new seconds variable, we can define a number of minutes and a number of hours, since we all know that there are 60 seconds in a minutes, and 60 minutes in an hour. Line 7: hour = @total_sec / 60 / 60 This line thus calculate the number of hours played. If we take the example from above, it would give us that result: -> 415 / 60 / 60 = 0.115 --> 0 hour. RMXP gives us 0 as an asnwer since it's using Integers in the equation; and Integers does not allow decimals. We'll talk about maths in chapter 3. Line 8: min = @total_sec / 60 % 60 Ok, this is the line that may have confused you... What on earth is the use of the % ? Well, it does a modulo (known as mod). I already explained what was a modulus (modulo, mod) in my RMXP Variable Demystified. Here's an extract of it: QUOTE The modulus is the ramainder of a division. If we divide 17 by 3 on a calculator, its answer would be "5.666666667", but this anwser has nothing to do with modulus. The mod function is defined as the amount by which a number exceeds the largest integer multiple of the divisor that is not greater than that number. Here's how it's working: 17 mod 3 = 2 Because 17 / 3 = 5 remaining 2, wich means that 17 = 3 * 5 + 2 Try this: Take a calculator and divide 17 by 3, it will give you 5.666666667. Now, take only the full integer 5 (don't take what is after the decimal). Multiply 5 by 3, and it gives you 15. Then what remains from 17 - 15 ? Exactly, 2. This makes the 17 mod 3 = 2 take all it's sense. So, this means that 60 modulo 60 would equals 0, since 60/60=1, and that 1 has no remaining value. All that means that this little line will reset the minutes variables to 0 when it has reached 60. So, keeping our example, here's what it logically gives us: (415 / 60) mod 60 = 6.916 --> 6 minutes (RMXP doesn't floor the value.) I do not have to explain line 9, it's the same thing as line 8, but to count the number of seconds. Line 10: text = sprintf("%02d:%02d:%02d", hour, min, sec) sprintf is used to format a string (A text variable) using format code. What is between the quote marks " " are the format code. A format code is actually composed of "flag characters" and "field type". The flag character will set the view format of the resulting string, and the field type will specify how to interpret the argument sent into sprintf. Each implementation of sprintf begins with a % sign, and every other symbols added into a format code that isn't known as wether a "field type code" or a "falg character code" is shown as is in the resulting string. The argument sent in sprintf are listed after the format code, seperated with comas. The number of argument sent must be equals to the number of format code used (begins with a %). So, let's see what this line actually did: We created "text", that is a local variable as explained in section 1, and we set it equal to the result of our sprintf command. Let's see each format code: %02d This is the first one, and the 2 other are identical. How does this work ? Well, the % sign tells the program that what follows is a format code. "0" is a "flag character" that is used to set the view format. 0 is to add the number 0 (zero) before the string instead of spaces, and the following number "2" tells the program to write 2 zeros. Just try to change this 2 by a 3, and you will see 3 zeros in your Window_PlayTime menus. The letter "d" tells the program to interpret the argument we will send as decimal numbers. Then, we wrote :, and since this isn't a code, it's written in the string as is. So, this means that we format a new string that will look like that: 00:00:00 Yay, it's a clock ! There are many other format code, you can found them on the web, a website containing them can be found on my website links sections. You can see that after the quote marks come the 3 other local variable we created on line #7, 8 and 9 (hour, min, sec). Here's a small diagram, and we can go to the next line:
sprintf.jpg ( 31.15k )
Number of downloads: 1048Line 11 to 13 were also explained in earlier section and chapters, they show the text we just formated with our sprintf. Let's jump to the next block: BLOCK 3: 1 self.contents.font.color = text_color(6) 2 self.contents.draw_text(250, 0, 50, 32, "Gold:") 3 self.contents.font.color = text_color(0) 4 self.contents.draw_text(305, 0, 100, 32, $game_party.gold.to_s) This should not be too hard, it was, once again, already explained. I need only to explain a small thing about line #4. Line 4: self.contents.draw_text(305, 0, 100, 32, $game_party.gold.to_s) The .to_s at the end of the variable is to convert it into a string, so we can draw it as text. If we try to put a variable containing numbers there, an error will pop up saying "Cannot convert Fixnum into String". So we tell the program to convert it in the code, and it thus work fine. I don't have to explain the next block, as it is the same thing as block 3; it just shows the map ID instead of the gold held. So let's jump to the last block, update: BLOCK 5: 1 def update 2 if Graphics.frame_count / Graphics.frame_rate != @total_sec 3 refresh 4 end 5 end 6 end This is our update method. As you can see, this method isn't used from within our window, it will be used by our Scene later on. The method update of our window most exist, because we will make it update in our scene. Window that doesn't have to be updated as they are seen don't need any update method. You will see what I mean when we will code our Scene later on. But let's explain the lines anyway: (I'll skip the line that you are supposed to understand now, because chapter 1 and the earlier section of chapter 2 should have teached you those lines.) Line 2: if Graphics.frame_count / Graphics.frame_rate != @total_sec This is an If Statement as described earlier. And if you have read my RGSS Reference as I told eariler, you will know that != means "Not Equal To". So, what we do in that IF is the following: We divise the total amount of frames that occured in the game by the frame rate (this gives us the total amount of seconds, as explained above), and we check if that answer is equal or not with our variable @total_sec (which contains the total amount of sec that was created when we show the window for the first time.) If it's not equal to it, we call the refresh method, and thus we clear the content, and recalculate the new time, and show it once again. So, this update method check if the time has changed, and when it does, we show the new time. Creating Window #2 The second window is the one to the left, which list the hero in your party, with their class beneath them. Add a new page and name it Window_2. Window_2 Code: CODE class Window_2 < Window_Base #BLOCK 1 def initialize super(0, 0, 200,380) self.contents = Bitmap.new(width-32, height-32) self.contents.font.name = "Arial" self.contents.font.size = 24 #BLOCK 2 for i in 0...$game_party.actors.size x = 0 y = i * 90 actor = $game_party.actors[i] self.contents.font.color = text_color(6) self.contents.draw_text(x, y, 200, 32, $game_party.actors[i].name) self.contents.font.color = text_color(4) self.contents.draw_text(x, y+32, 200, 32, actor.class_name) end end end This window contains less code, it's because it draw the text in a for loop. I won't explain BLOCK #1 as it was already explained in above sections. Let's jump once again to our next block: BLOCK #2: 1 for i in 0...$game_party.actors.size 2 x = 0 3 y = i * 90 4 actor = $game_party.actors[ i] 5 self.contents.font.color = text_color(6) 6 self.contents.draw_text(x, y, 200, 32, actor.name) 7 self.contents.font.color = text_color(4) 8 self.contents.draw_text(x, y+32, 200, 32, actor.class_name) 9 end 10 end 11 end Line 1: for i in 0...$game_party.actors.size As shown earlier, this is our for loop. The .size command is a ruby command to know the size of an array, or a string. If you read my RMXP Variable Demystified, you'll know what is an array and such. $game_party.actors is an array variable containing the hero present in your party. Remember that an array index start at 0, not at 1, which means that the first hero in your party doesn't have the party ID#1, it have the party ID#0. So, this for loop actually iterate itself starting at 0, and finish at the amount of hero present in your party, excluding the last number. (Remember the range rules with the ... and .. points.) --> Why exclude the last number ? Here's why: (This example take into consideration that 4 hero are present in your party) [For Loop Start] - We check the size of game_party.actors - We have 4 party members, it thus equals 4 --> We will do 4 iteration in the for loop. [First Iteration - 1/4] - i=0 - refers to the game_party actor ID#0 (the first one) [Second Iteration - 2/4] - i=1 - refers to the game_party actor ID#1 (the second one) [Third Iteration - 3/4] - i=2 - refers to the game_party actor ID#2 (the third one) [Forth Iteration - 4/4] - i=3 - refers to the game_party actor ID#3 (the forth and last one) As you can see, ID0 is your first hero in the party. If we would have used 2 points in our range to include the last number, it would have given a loop that does 1 iteration that should not be done. (i.e: The array index start at 0, so look at this:) index 0 = Hilda index 1 = Arshes index 2 = Eliette index 3 = Dubealex We thus have an array with a size that equals 4. (I hope you got it.) Line 2 and 3: x = 0 -- y = i * 90 Remember that we are still inside the for loop body, which means we will do what is there multiple times. The first one is easy, x=0, this create a local variable and set it to 0. We will use that x variable later to place all our text at coordinate x (which is 0). If you change that 0 by another value, you will see that all the names will appears elsewhere in the window. The second one, y = i * 90, again create a local variable y that we will again use to place the text in the y coordinates. The trick in that part is that we want each name to appears above another, not in the same spot ! Since we now know that our variable i contains the iteration value (as I said earlier), we can thus use that. We multiply it by 90, if you put another value in place of 90, you will simply see more space between each name, or less space, depending on which value you put there. So, here's an explanation of this process: [First Iteration] - i=0 - x=0 - y= i * 90 --> i equals 0, so 0 * 90 equals 0. - We will draw the first name at coordinates [0,0] ([x,y]) [Second Iteration] - i=1 - x=0 - y= i * 90 --> i equals 1, so 1 * 90 equals 90. - We will draw the second name at coordinates [0,90] ([x,y]) [Third Iteration] - i=2 - x=0 - y= i * 90 --> i equals 2, so 2 * 90 equals 180. - We will draw the third name at coordinates [0,180] ([x,y]) [Forth Iteration] - i=3 - x=0 - y= i * 90 --> i equals 3, so 3 * 90 equals 270. - We will draw the forth name at coordinates [0,270] ([x,y]) Line 4: actor = $game_party.actors[ i] This line is to save space below, it wasn't a "necessary" line. But it's useful as it makes the line below smaller and more easy to understand. We also do not have to repeat the full variable name over and over again. Here's what it do: It create a local variable name actor, and set it as being $game_party.actors[ i]. (Remember that i is the party hero ID.) --> Then, in later lines, you can just use line like actor.name to refer to $game_party.actors[ID].name, which is a long line to type, isn't ? Line 6: self.contents.draw_text(x, y, 200, 32, actor.name) As explained earlier, we now draw the text of our hero's at coordinates x (which is 0), and coordinates y (that is calculated at each new iteration). And we can use actor.name instead of the full variable name, to save time and space in the script.
|
|
|
|
||
Nov 7 2005, 09:43 PM
Post
#2
|
||
![]() Administrator of this Asylum AdminMember No.: 1 Posts Liked: 48 * Joined: 8-November 04 Posts: 2,704 --> From: Longueuil, Canada RPG Maker Level: Master Class Title: Writer, Scripter & Designer Last.fm ID: Dubealex Country: ![]() |
Line 8: self.contents.draw_text(x, y+32, 200, 32, actor.class_name)
This line is similar to line 6, except for our y coordinates. We do y+32 because we want the class names to be written below the hero's name. (Remember, to go higher in the Y coordinate, you must lower the value, and to get lower, you must augment the value... I know it can be confusing at first.) We set 32 since we have text height of 32 everywhere, and it fits right. If you customize your script, you will have to put values that fits with your fonts and menus. Ok, that's it for this window. It wasn't that complicated, once you get the hang of it, isn't so ? Creating Window #3 The third and last window is the window to the right, the one that contains the heros attributes. This one looks like the window #2, but with a twist... We will use an if statement inside the for loop to make the hero appears in 2 column instead of all above another. So, just add another page in the script editor, and name it Window_3: CODE class Window_3 < Window_Base #BLOCK 1 def initialize super(0, 0, 440,380) self.contents = Bitmap.new(width-32, height-32) self.contents.font.name = "Arial" self.contents.font.size = 24 #BLOCK 2 for i in 0...$game_party.actors.size x = 0 y = i * 150 if i >= 2 x=250 y -= 300 end actor = $game_party.actors[i] self.contents.font.color = text_color(6) self.contents.draw_text(x, y, 200, 32, actor.name) offset_x=contents.text_size(actor.name).width+10 self.contents.font.color = text_color(4) self.contents.draw_text(x+offset_x, y, 200, 32, "Lv: " + actor.level.to_s) draw_actor_hp(actor, x, y+32) draw_actor_sp(actor, x, y+64) draw_actor_exp(actor, x, y+96) end end end Information about block 1 was explained in previous lessons. So I will skip to block 2: Line 1: for i in 0...$game_party.actors.size This will make a "for loop" starting at 0 and stoping at the size of our current game party, which is a max of 4 by default. THe game party info are stored as an array and thus start at 0, this is why the first hero in the party is known as 0, and the last as 3. Line 2: x = 0 Here we define x as being 0 so the listing can start at the far left of the screen. Line 3: y = i * 150 This line define the vertical position, and since we are doing a for loop, Y is defined as being the value of our loop (where we are at in the cycle) multiplied by 150 to let enough space to put the info we want for our hero. Line 4: if i >= 2 This line is the If Statement. This is only this little if statement that allows us to have 2 column of stats instead of one. To better explain it, I will show you the complete If body, not just the first line: 4 if i >= 2 5 x=250 6 y -= 300 7 end So, line 4 check if our i variable is bigger or equal than 2, and if it does, it will do what is inside the If body. Remember, when our i value is equal to 2 (or bigger) it's because 2 hero's where processed already. We wanted 2 hero in one column, and another 2 heros in another column. So when i equals 0 or 1, it is the 2 first hero to draw. When it's equals to 2 or 3, it the 2 last one. Line 5: x=250 So, if 2 hero were already processed, we don't want the 2 other to be drawn at the same spot, so we change the X cooridnate to 250, which will draw our 2 last hero to the right of the first. Line 6: y-=300 This line does almost the same thing as line 5. It modify the y value, but the fact is that we want the hero to have the exact same spacing between them, but since our i value is already at 2 when we do this, we must subtract the extra 300 that we got so we can draw the 2 other hero at the top of the new column. Here's a process sample for those who did not get that right: [First Iteration] - i=0 - x=0 - y= i * 150 --> i equals 0, thus 0 * 150 = 0 (y=0) - Check the if statement, it return false, i isn't bigger or equal to 2. --> New coordinates to draw text are [0,0] [etc] [Second Iteration] - i=1 - x=0 - y= i * 150 --> i equals 1, thus 1 * 150 = 150 (y=150) - Check the if statement, it return false, i isn't bigger or equal to 2. --> New coordinates to draw text are [0,150] [etc] [Third Iteration] - i=2 - x=0 - y= i * 150 --> i equals 2, thus 2 * 150 = 300 (y=300) - Check the if statement, it return true, i IS bigger or equal to 2. --> We enter the If Statement body and execute the actions in it... - x=250 (Change the value inside x to 250) - y-=300 --> y equals 300, thus 300-300=0 (y=0) --> New coordinates to draw text are [250,0] [etc] [Forth Iteration] - i=3 - x=0 - y= i * 150 --> i equals 3, thus 3 * 150 = 450 (y=450) - Check the if statement, it return true, i IS bigger or equal to 2. --> We enter the If Statement body and execute the actions in it... - x=250 (Change the value inside x to 250) - y-=300 --> y equals 450, thus 450-300=150 (y=150) --> New coordinates to draw text are [250,150] [etc] So, as you can see, we just create 2 aligned columns ! Let's jump to the other lines. Line 8 to 10 were already explained earlier... Line 11: offset_x=contents.text_size(actor.name).width+10 This line create a local variable named "offset_x", that will be equals to the width of the name of the hero that we have drawn plus 10 (so there a bit of space between what we will write there...) This will be used when drawing the Level of the hero. Basically, we wants the Level to be drawn just aside of the hero's name, but since hero's name can be of many different sizes, we must use a variable to set the x position of the level text. contents.text_size(actor.name).width is a command that allow you to know the width of a text. We specify which text between the parenthesis, and we choose a attribute after the last point. To know the height, we just replace width by height. Line 13: self.contents.draw_text(x+offset_x, y, 200, 32, "Lv: " + actor.level.to_s) This is the line that write the Level of the heros. So, as you can see, we have set it's x position by adding our "offset_x" value to the existing x position. That way, the level is always aside the names. Remember the .to_s command... The level is an integer, we must convert it to a string before writing it. Line 14: draw_actor_hp(actor, x, y+32) Ok, if you are asking yourself where the "variable" draw_actor_hp come from, you are mistaken. draw_actor_hp is in fact a method name, since we have argument between parenthesis aisde it. But wait a minute... Where is that method ? It's not in our Window_3 code ? Well... Remember inheritance ? We have set Window_Base as the SuperClass of Window_3, so that method is bound to be inside Window_Base, isn't ? Let's check it out ! Let's open Window_Base, and run a search for "draw_actor_hp" ... Found it ? Here it is: (I hate those jap giberrish comments.... anyway...) Window_Base -> draw_actor_hp method code: CODE def draw_actor_hp(actor, x, y, width = 144) # ??? "HP" ??? self.contents.font.color = system_color self.contents.draw_text(x, y, 32, 32, $data_system.words.hp) # MaxHP ??????????????? if width - 32 >= 108 hp_x = x + width - 108 flag = true elsif width - 32 >= 48 hp_x = x + width - 48 flag = false end # HP ??? self.contents.font.color = actor.hp == 0 ? knockout_color : actor.hp <= actor.maxhp / 4 ? crisis_color : normal_color self.contents.draw_text(hp_x, y, 48, 32, actor.hp.to_s, 2) # MaxHP ??? if flag self.contents.font.color = normal_color self.contents.draw_text(hp_x + 48, y, 12, 32, "/", 1) self.contents.draw_text(hp_x + 60, y, 48, 32, actor.maxhp.to_s) end end This is where all is coded... well, this code actually set the colors of the HP, set all the formatting. So, if you need to adjust stuff in your game, go there and have fun with the customization ! Back to our window now: All the other lines actually calls method from Window_Base to draw the HP, SP and Exp of our heros on the screen. There's really nothing more to it. We simply add some value to our y position, so they can be all above the others. It's now the time to create our magnificent scene... :clap: Creating Our Scene Now that we have 3 window working right, we need a scene to show them on screen. Remember when I was talking about a table and blocks... The table is your scene, and you can arrange your blocks as you please on that table. If you look at your window code, you will notice that we only set their width and height, we never specified any X and Y position. i.e: CODE def initialize super(0, 0, 440,380) #(x position, y position, width size, height size) It's because we will place those window where we desire in our scene. That way, if you wanted to have the Window_1 at the bottom, you can by modifying the scene, not the window. It's better that way, it's a better development habit. Ok, with that said, let's create our table... arg... our scene ! Just add a page in your script editor, and name it Scene_Chapter_2. Scene_Chapter_2 code: CODE class Scene_Chapter_2 #BLOCK 1 def main @window_1=Window_1.new @window_2=Window_2.new @window_2.y=100 @window_3=Window_3.new @window_3.x=200 @window_3.y=100 #BLOCK 2 Graphics.transition loop do Graphics.update Input.update update if $scene != self break end end #BLOCK 3 Graphics.freeze @window_1.dispose @window_2.dispose @window_3.dispose end #BLOCK 4 def update @window_1.update if Input.trigger?(Input::B) $game_system.se_play($data_system.cancel_se) $scene = Scene_Map.new end end end BLOCK 1: 1 def main 2 @window_1=Window_1.new 3 @window_2=Window_2.new 4 @window_2.y=100 5 @window_3=Window_3.new 6 @window_3.x=200 7 @window_3.y=100 This the begining of our main method for our scene. Ok... Why isn't there a method named initialize as in almost all other class... Why do a scene have a method called main instead of initialize ? Well, it's all up to Entrebrain, look in the MAIN script (to the very bottom), you will see that code around line #18: CODE while $scene != nil $scene.main end As you can see, they check for .main (method main), so if you just play with it, and write "pepsi" instead of "main", it would give you "$scene.pepsi". Of course, now all your scene would not work anymore. You would need to go in all of them, and change their method main by pepsi, and voil? ®? But let's stick to what's there by default, main is pretty descriptive of what it does... Line 2: @window_1=Window_1.new Remember Chapter 1 ? We talk about objects and stuff like that, so you should know by now that we just created a new object name @window_1 that is of class Window_1. So, now we can manipulate our window_1 as we want, without affecting the real window. Line 3 and 5 just does the same thing, but they "spawn" window 2 and 3 instead. Then we have lines 4, 6 and 7. Those lines specify our x and y position for the window we want. Wait a sec there... If you remember correctly chapter 1, we have said that to use something like @object.method, we need that method defined in the class of that object... And @window_2.x calls a method named x; this method isn't in our Window class. Let's look in Window_Base, it's SuperClass... Nope, it's not there. Let's then look in the SuperClass of Window_Base, which is Window...Oups, we don't have access to this class. The Window class is the class that built the in-game interface of RPG Maker XP. There is a lot of low-level code in there, thus Enterbrain just implemented it into RPG Maker, and we don't have access to it. But the method x is inside that Window class. You can simply open the help file of RMXP and go to the right section to see all the method inside Window. Just open it, and go in the SEARCH tool, type in Window, and choose the relevant section. The list is right there. You can translate it with Babel Fish. With all that said, we simply configured our window where we want them, and that's all. BLOCK 2: 1 Graphics.transition 2 loop do 3 Graphics.update 4 Input.update 5 update 6 if $scene != self 7 break 8 end 9 end Line 1: Graphics.transition This line make the scene appears. Once again, it's all interpreted by stuff already coded. This is why RGSS is simpler than Ruby, it's a scripting language. You can use already maded components. If you omit that line, the scene still works, you will just not see it on screen. Line 2: loop do This line start a loop, somewhat like a for loop, but it will repeat itself until the keyword "break" is met. In this case, we break the loop if the scene isn't the same as the scene you are viewing. This is done by the If Statement on line #6. This loop will start when you open the scene, and will always repeats itself. Line 3: Graphics.update This will update the graphics on screen, if you omit that line, you won't see any modification made to the window after the scene was first drawn. This mean that if you delete that line, you won't see the Playing Time running. Line 4: Input.update This update the input command the player can do in the game. This make sure that RMXP is always looking for a keypress made by the player. If you omit that line, you won't be able to use any interactivity in your scene. Line 6, 7 and 8 were explained above, it's our If Statement checking if the scene is changed. If it's changed, we must stop that loop. BLOCK 3: 1 Graphics.freeze 2 @window_1.dispose 3 @window_2.dispose 4 @window_3.dispose This part is still inside our main method, this part take care of getting rid of our window when we exit the scene. You may be wondering why the window are disposed only when we exit, even if the main method is the first to be executed when you open a scene ? Well, it's because of the Loop. Just like a for loop, what comes after the loop in the code will be executed only when the loop is completed or stopped. So, all that code after the loop will be executed only when we will break that loop in the If Statement; as explained above. Line 1: Graphics.freeze This line take care of making a "transition" between both scene. Because in RMXP, while you play, you are always in a scene or in another. So, when you exit a scene, that line makes sure that the scene you were in actually fade out and do not dissapear instateneously (Did I write that word well ??). If you delete that line, you will see what I mean. Line 2,3 and 4 actually take care of disposing of the window, so they aren't there anymore when you exit the scene. It will destroy the object we have created. That's why you may get errors if you try to access a window that have been previously disposed... You can't access an object that doesn't exist... It's purely logical. This time we can found the method "dispose" in Window_Base, here it is: CODE def dispose # Jap Comments if self.contents != nil self.contents.dispose end super end As you can see, that method only take care of getting rid of the content of the window, and there should be more stuff going on. So, once again, the code that is really responsible for disposing a window is in Window, not accesible by us. And you can clearly see that this dispose method call "super", meaning it's calling the method "dispode" in it's SuperClass, which is Window... The dark and mysterious class of RMXP. BLOCK 4: 1 def update 2 @window_1.update 3 if Input.trigger?(Input:: 4 $game_system.se_play($data_system.cancel_se) 5 $scene = Scene_Map.new 6 end 7 end 8 end This block is our update method, which is called in our main loop as explained above. That's is what makes the update method repeats itself over and over again. Line 2: @window_1.update As explained in chapter 1, this will execute the update method of our class Window_1... Simply because we have defined @window_1 as being an object of class Window_1 in our main method. Now you know why we coded an update method in our Window_1 earlier. So, to refresh your memory, we add an if statement in this method, that check if the total second has changed. If it does changes, it then calls refresh and re-draw the time in the window. Since the update method of our scene is looping, the update method of our Window_1 is also looping... and so on. Pretty cool isn't ? As you can see, we don't need any update for the 2 other window, we don't plan on modifying their content while the scene is open. Line 3: if Input.trigger?(Input:: This is another If Statement, in all it's glory, that is checking the input made by the player. Know that Input:: is in fact a module implemented inside RMXP, we still don't have access to it. If that If Statement becomes true, meaning that IF the playing press the B key (Which is the Escape, X or the NumPad 0 key on the keyboard by default. You can change that in the menu while you play by pressing F1.) Line 4: $game_system.se_play($data_system.cancel_se) This line will play an SE (Sound Effect) when you leave the scene. This is purely for aesthetic purposes. But I will explain how it's working anyway, as almost everything in RMXP works the same, if you understand that, you will understand almost everything else. $game_system is an object created when you start a game. It's created in Scene_Title, in the main method, here it is: CODE $game_system = Game_System.new So, everything that you can do with that object is defined in it's class, which is Game_System, as I explained in my Chapter 1. So, by filtering all the method inside Game_System, you can have a broader idea of what you can with it. So, in that particular line, we are invoking the se_play method, that is requiering an argument, which we specified in the parenthesis. (All of this was in Chapter 1 anyway.) So, if we search in Game_System to found that method, we will found that: CODE def se_play(se) if se != nil and se.name != "" Audio.se_play("Audio/SE/" + se.name, se.volume, se.pitch) end end This will play the SE. Take a look at how it's working, and you may have to follow the traces given by the objects/class names. You can thus try to understand anything by yourself. Become a "code hunter". Everything leave a trace, just follow it. Example: You see se.name in the If Statement... where does it come from ? Well, you can tell that it's a local variable by the way it's written, and since there is a point and a command after it, it should means it's an object, isn't ? Well, you aren't that far off, but in this very case, it's a bit darker. To know what is se.name and how it's working, you must first know that se is actualy the argument receiver of our method se_play. So, we need to check what we sent as argument... Let's see: CODE $game_system.se_play($data_system.cancel_se) Okay, we sent $data_system.cancel_se as argument. What is $data_system ? Once again, it's an object, it's followed by a point. So check in Scene Title, you will see it's definition once again, and you will be able to know what it is. Here: CODE $data_system = load_data("Data/System.rxdata") Oh boy, now we are going far far away. $data_system refer to the System.rxdata file found in your Data directory of your project. WHat does this file contains ? Well, when you open your datase in RMXP, the last tab is named System, well, that file stores all the stuff you set in that section. Which means that each tab in the database has it's rxdata file... So that's it, se.name is inside System.rxdata, our search ends here. (Well, to be honest, I just improvised all this little "code hunt" section, and I think it's cool to learn, so I will do another tutorial called "Code Hunt" that will give tricks like that.) Line 5: $scene = Scene_Map.new This line actually change the scene. Once again, $scene is an object, the first occurance of it's definition is in MAIN, it define $scene as being of class Scene_Title. So, now, to conclude this chapter, you just have to test play that scene to test it out. Make sure all your 3 Window and your Scene are in your Script Editor, and make a call script in an event with that in it: CODE $scene=Scene_Chapter_2.new That will start the scene. To exit the scene, you press Escape. In chapter 3 we will tackle some more advanced stuff. We will learn how to add a selection menu, and how to work with multiple selection menu in the same scene. We will also learn important component of Ruby, like how to do Alias and more advanced stuff, so your script can be more powerful. I hope you like that tutorial, it took a hell lot of time to do... lol (I'm tired... I'm exhausted. Let's post that on the board, and relax for a while... by !)
|
|
|
|
||
Nov 8 2005, 05:19 AM
Post
#3
|
|
![]() Version 2.0 I'm Awesome !!Member No.: 88 Posts Liked: 0 * Joined: 13-December 04 Posts: 7,175 --> From: Canada™ RPG Maker Level: Expert Country: ![]() |
Wow...that's nice!
Good job as always! |
|
|
|
Nov 8 2005, 05:21 AM
Post
#4
|
|
![]() God GodMember No.: 1,693 Posts Liked: 5 * Joined: 24-September 05 Posts: 1,514 --> From: Leeds, United Kingdom RPG Maker Level: Not Applicable Class Title: First Knight of the Order of the Pie Country: ![]() |
OMG, this must be like the longest tutorial ever created!
Thanks again for another lesson of greatness and stuff. Wait a sec....I read this ages ago....why am I replying to it now.....wierd..... This post has been edited by datriot: Nov 8 2005, 05:21 AM |
|
|
|
Nov 8 2005, 09:40 PM
Post
#5
|
||
![]() Administrator of this Asylum AdminMember No.: 1 Posts Liked: 48 * Joined: 8-November 04 Posts: 2,704 --> From: Longueuil, Canada RPG Maker Level: Master Class Title: Writer, Scripter & Designer Last.fm ID: Dubealex Country: ![]() |
lol, this isn't a new tutorial, it's the RGSS lessons chapter 2 -- The other topic was corrupted and I could not fit all the text in the post... :eusa_whistle:
And by the way, it took a long time, but I fixed all my tutorials to remove the weird characters (A) and stuff that occured because of the transfer to the new server. C ya !
|
|
|
|
||
Nov 9 2005, 04:20 PM
Post
#6
|
||
![]() X-Treme MasterMember No.: 660 Posts Liked: 0 * Joined: 18-May 05 Posts: 238 --> From: Massachusetts RPG Maker Level: Expert Class Title: Artist, Mapper, Writer, other stuff. |
Well that definitly gonna be fun readin through that.
And wasnt that last part in the 3rd tutorial last time? |
|
|
|
||
Nov 9 2005, 06:57 PM
Post
#7
|
||
![]() Administrator of this Asylum AdminMember No.: 1 Posts Liked: 48 * Joined: 8-November 04 Posts: 2,704 --> From: Longueuil, Canada RPG Maker Level: Master Class Title: Writer, Scripter & Designer Last.fm ID: Dubealex Country: ![]() |
Nope, chapter 3 is about understanding menus.
|
|
|
|
||
Nov 15 2005, 09:45 AM
Post
#8
|
|
|
Newbie NewbieMember No.: 1,993 Posts Liked: 0 * Joined: 15-November 05 Posts: 1 --> RPG Maker Level: Good |
Great tutorial!
I'm just wondering, i found parts of chapter 3 on google, but not the whole chapter. Are you going to post it in the forums, or is it allready posted here? Edit: Forget it. I Found Chapter 3.. This post has been edited by mazey: Nov 15 2005, 09:50 AM |
|
|
|
Feb 18 2006, 03:30 PM
Post
#9
|
||
![]() Kristof von Metal GodMember No.: 2,295 Posts Liked: 2 * Joined: 7-January 06 Posts: 1,286 --> From: Austin, Texas RPG Maker Level: Novice Class Title: Music Video Master Country: ![]() |
Thanks again for this tut. It rocks!
|
|
|
|
||
Mar 1 2006, 09:33 PM
Post
#10
|
||
![]() Newbie NewbieMember No.: 2,676 Posts Liked: 0 * Joined: 28-February 06 Posts: 27 --> RPG Maker Level: Fair |
I can't find the Ruby Syntax topic and the link in the tut. is missing. Where can I find it? :strach:
|
|
|
|
||
Mar 5 2006, 08:18 PM
Post
#11
|
||
![]() Administrator of this Asylum AdminMember No.: 1 Posts Liked: 48 * Joined: 8-November 04 Posts: 2,704 --> From: Longueuil, Canada RPG Maker Level: Master Class Title: Writer, Scripter & Designer Last.fm ID: Dubealex Country: ![]() |
its in the Main SIte menu at the top-right of the forum, it's called "RGS reference"
|
|
|
|
||
May 1 2006, 05:57 AM
Post
#12
|
|
|
Newbie NewbieMember No.: 3,061 Posts Liked: 0 * Joined: 1-May 06 Posts: 1 --> RPG Maker Level: Good |
I just read your scripting tutaorial, both chapters, and I kinda understood most of it, but i have a more specific question. How would you write the line of a sript so you can change the character graphic? I know how to do it in events, you just go 'Move Event', then 'Change Graphic'm but I want to do it in a script. Can you please tell me?
|
|
|
|
Jul 3 2006, 02:40 AM
Post
#13
|
||
![]() Newbie NewbieMember No.: 3,674 Posts Liked: 0 * Joined: 25-June 06 Posts: 26 --> From: San Antonio, TX RPG Maker Level: Good Class Title: writer, eventer, & mapper |
Very awesome set of tutorials!!! I've been wanting to learn how to script with ruby for RMXP for a while now but it's been hard to find any good tutorials for it. After reading these two, I'm getting the hang of it big time! I really appreciate these tutorials.
|
|
|
|
||
Jul 11 2006, 11:29 AM
Post
#14
|
||
![]() Newbie NewbieMember No.: 3,674 Posts Liked: 0 * Joined: 25-June 06 Posts: 26 --> From: San Antonio, TX RPG Maker Level: Good Class Title: writer, eventer, & mapper |
I never really understood how to make the window stay up for more than a split second. And how do you make it to where it won't close until you press a button??? I know it has something to do with scene map.
This post has been edited by RPG_GameDesigner: Jul 12 2006, 04:56 PM |
|
|
|
||
Oct 12 2006, 10:26 AM
Post
#15
|
||
|
One of the Returned CelestialMember No.: 4,646 Posts Liked: 3 * Joined: 6-September 06 Posts: 3,316 --> From: Life RPG Maker Level: Fair Class Title: Mother of a Beautiful Girl Last.fm ID: gemini8859 Country: ![]() |
I can't find the RGSS reference you're talking about. I found an RGSS Reference section in the script archive, but it's not the way you describe. It's just a few lists of syntaxes to cahnge some system things suck as armor, weapons, items, etc...
|
|
|
|
||
Nov 4 2006, 01:28 AM
Post
#16
|
||
![]() Expert ExpertMember No.: 3,056 Posts Liked: 0 * Joined: 30-April 06 Posts: 108 --> From: Malaysia RPG Maker Level: Good Class Title: Story maker, Database n Event maker, Mapper. |
A little bit confuze, but still.. it is a good tutorial.
I just want to know if it is posible to make the window appear by pressing esc?
|
|
|
|
||
Nov 9 2006, 08:43 PM
Mood: Annoyed
Post
#17
|
|
|
Newbie NewbieMember No.: 5,228 Posts Liked: 0 * Joined: 9-November 06 Posts: 5 --> RPG Maker Level: Good |
Alright, I copied your code for the basic 200x200 window and it wouldn't work.
I placed it at the bottom page and I copied and pasted directly. whenever I try and call the window I got: "?????? Name Error ?????? uninitialized constant interpreter:: [classname]" (in this case My_Window) So instead I called Window_Base directly like this: Window_Base.new(0,0,200,200) and that worked fine. Does anybody have any idea why I am getting that error message in the first instance. and if not can anyone tell me what it means? It's kind of hard to debug when I can't understand those error messages. This post has been edited by Unessential: Nov 9 2006, 08:46 PM |
|
|
|
Nov 10 2006, 07:14 AM
Post
#18
|
||
![]() Spider-Mod ModeratorMember No.: 1,136 Posts Liked: 7 * Joined: 13-July 05 Posts: 5,175 --> From: Israel RPG Maker Level: Master Class Title: Eventer/Scripter Country: ![]() |
What's the code exactly?
|
|
|
|
||
Nov 11 2006, 04:17 PM
Post
#19
|
|
|
Newbie NewbieMember No.: 5,228 Posts Liked: 0 * Joined: 9-November 06 Posts: 5 --> RPG Maker Level: Good |
this code
QUOTE class My_Window < Window_Base
def initialize super(0, 0, 200, 200) end end |
|
|
|
Nov 12 2006, 12:24 PM
Post
#20
|
|
![]() God GodMember No.: 1,130 Posts Liked: 0 * Joined: 12-July 05 Posts: 1,375 --> RPG Maker Level: Good Country: ![]() |
I think you pasted your code after Main, when it must be before Main.
|
|
|
|
![]() ![]() |
The Staff Team |
Lo-Fi Version | Time is now: 5th December 2020 - 10:33 AM |