设为首页收藏本站同能贴吧 切换语言 繁体中文
开启辅助访问 切换到窄版
扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 52|回复: 0

[制作教程] Advanced guide to script calls - no script required

[复制链接]
累计送礼:
0 个
累计收礼:
1 个
  • TA的每日心情
    开心
    3 天前
  • 签到天数: 209 天

    连续签到: 2 天

    [LV.7]常住居民III

    4544

    主题

    864

    回帖

    2万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    7
    卡币
    23095
    OK点
    16
    推广点
    0
    同能卷
    50
    积分
    28533

    灌水之王

    发表于 3 天前 | 显示全部楼层 |阅读模式
    Hello guys! In this tutorial I would like to give few words of advice on how to get the most out of your script calls. That includes using multiple script calls as a single one, creating your own classes inside a script call and other advanced things that people might not know being possible.

    Required scripts:none.

    Table of contents:

    • Pros and Cons of using script calls instead of Event Commands
    • What is a script call?
    • Overcoming lines limit
    • Class creation in a script call
    • Multiple script call class creation
    Level: Advanced

    This guide is about achieving things using script calls so that you can write what you need on your own.

    First of all let's analyze pro and cons of using script calls.

    PROS

    • More freedom than Event Commands
    • You can be very specific when writing them
    • Fast to set up
    • Can be extremely compact
    • Make handling complex events much easier
    CONS

    • Need ruby syntax (programming language)
    • The lower your knowledge of RMVXAce classes, the slower you are
    • No syntax highlighting when writing them
    To have a better understanding of those pro and cons let's see what a script call is and why things are like this. If you already know what script calls are you can skip this part but if you do not then I strongly recommend reading it.

    Spoiler: What are script calls?
    First of all a Script Call is an Event Command accessible from the 3rd page of your event commands list.

    Spoiler: Where to find Script Call



    Then how can a script call give more freedom than event commands when being an event command itself? The answer to this question lies in HOW script calls handle what you write.

    Let's take a look at how the engine handles script calls. Line 1402 of Game_Interpreter contains command_355 (the method that handles script calls). That said method is this:                                      Code:        
    1.   #--------------------------------------------------------------------------
    2.   # * Script
    3.   #--------------------------------------------------------------------------
    4.   def command_355
    5.     script = @list[@index].parameters[0] + "\n"
    6.     while next_event_code == 655
    7.       @index += 1
    8.       script += @list[@index].parameters[0] + "\n"
    9.     end
    10.     eval(script)
    11.   end
    复制代码

    What does it do? It basically converts what you wrote in the script box into a string and then uses the method eval. Tho make it short that method is used to read a string as part of code. It can be dangerous if you do not write your string properly and can even make your game crash but it is very useful.

    I do not plan on going deeper on how the eval method works but here is a link to ruby documentation so that you can go and take a look if you are interested. Methods are listed in alphabetical order so you can either scroll down until you find eval or just look for it using the search function.

    So basically a script call is just a string written using ruby syntax so that it can be evaluated and read as part of the code.

    This part is important, very important. It hides very useful informations.
    1) You can create local/instance/global variables inside a script call. Depending on their scope you can access them from different locations.
    2) You can use ruby syntax to make things faster (e.g.: no need to put 4 conditional branches to simulate a switch statement)
    3) If you need a new class just for a single event you can add it there instead of having to write a whole script for it.
    4) You can have access to variables unaccessible when using event commands (like events self switches).
    Now that you know what a script call is let's see what you can actually do. Of course you can do anything you can do with normal event commands. If you take a look into Game_Interpreter you'll see a lot of different methods used for event commands.  I am not going to tell what to write for each event command because this forum already has a script call collection thread for that purpose. You can go and take a look there or find what you need in the Game_Interpreter class, either way is fine.

    Once you start using script calls you find that many things are faster to achieve and you have a better control over what you are doing. You can use just the part of code you need, you can avoid using those you don't need. You can write everything in a text editor and just copy/paste it in a single script call instead of having to paste it in different event commands. As you can see there are many advantages if you use script calls.

    When using them, however, you will sooner or later face the fact that the number of lines you can add to each single script call is limited. This is not a big trouble in the greatest amount of cases but what if you have an if statement, a loop or any other kind of block and you don't have enough space to write everything you need? Of course there are scripts to allow you to read consecutive scripts calls as a single one but what if you don't want to use or don't know about them?

    Spoiler: Overcoming Script Calls maximum lines limit
    As you probably know at this point script calls are just strings evaluated as part of the code itself using the eval method. So why should you have a limit to what you can put in your script call? Can't you just use a string, add more text in the next script call and then evaluate it as a whole?

    The answer is: yes you can.

    Spoiler: Let's see an example of what I mean
    The first script call might be just this:
                    Code:        
    1. @this_is_an_instance_string = "
    2. unless $game_player.moving?
    3.   $game_player.jump(0, 0)
    4.   90.times { Fiber.yield }
    5. " # I am not using blank lines just for show here.
    6. # They make the code much easier to allign
    7. # so it is easier to read.
    8. # And since you are going to add more to this
    9. # string later on, having a blank line helps you
    10. # avoiding mistakes.
    复制代码

    As you can see this block is quite incomplete. There is no "end" keyword. Usually this throws an error message. Anyway since that is a string I can write anything I want there. There is no way I am going to get such an error because that is just a string content and it is not yet a block to run.

    To complete it the second script call can be something like this:
                    Code:        
    1. @this_is_an_instance_string += "
    2.   $game_player.jump(0, 0)
    3.   90.times { Fiber.yield }
    4. end #here is the end of our block
    5. "
    复制代码

    Now this part contains the end of our block. Our block is now written using proper ruby syntax and can finally be evaluated without throwing errors. Let's test it out calling the eval method for that string. You can do it in the second script call or in a new script call, it makes no difference. Anyway, regardless of where you want to put it, just add this:
                    Code:        
    1. eval(@this_is_an_instance_string)
    复制代码


    Now run your event and...the magic is done! Our character jumped twice!

    Of course you can do it using even more script calls. You can use as many as you want as long as you do not forget to add new lines. As I said I didn't use them just for show. Since you are creating a string you have to add new lines manually or the beginning of what you are going to add is going to be attached to the last thing you wrote!

    What do I mean with this? Well, try running this script call and find it yourselves.
                    Code:        
    1. sample_string = "unless $game_player.moving?
    2.   $game_player.jump(0, 0)"
    3. sample_string += "90.times { Fiber.yield }
    4. end"
    5. another_sample_string = "unless $game_player.moving?
    6.   $game_player.jump(0, 0)90.times { Fiber.yield }
    7. end"
    8. if (sample_string == another_sample_string)
    9.   $game_message.add("You made a mistake!")
    10.   Fiber.yield while $game_message.busy?
    11. else
    12.   eval(sample_string)
    13. end
    复制代码


    Why is that so? Simple enough: when you append the next part to sample_string there is just no new line in neither the previous sample_string nor the part you are going to add. For that reason you have a single line containing "$game_player.jump(0, 0)90.times { Fiber.yield }" and this is incorrect.
    Spoiler: Always be careful[quote]Once you know you can use strings to create longer script calls you can open your text editor, create some dialogue and add it to multiple script calls like this:
                    Code:        
    1. @my_string = "
    2. $game_message.add("Hello new player, welcome to this world.")
    3. Fiber.yield while $game_message.busy?
    4. " # this goes in the 1st script call
    5. # what follows goes in the 2nd script call
    6. @my_string += "
    7. $game_message.add("Are you ready to start a new adventure?")
    8. "
    9. eval(@my_string)
    复制代码

    You try running your game and...error message!

    What's wrong with it?! Multiple script calls were working just fine with the previous example, why is this happening? This tutorial is just useless then! (long list of curses directed toward the author for writing a useless tutorial)

    Ok, you cursed me, are you feeling better? Now take a deep breath and analyze the situation. What's different between this and the previous example? Here we passed a string to $game_message.add and we did it the wrong way.

    Wrong way?! We just used the exact same pattern used in the thread you linked! (more curses toward the author for saying something like that)

    Unfortunately that's exactly why it is wrong. Since we are using a string to use multiple script calls as one we have to remember that a string is included between quotation marks. That can bite you (and a lot). If you want to insert a string in your string you cannot just use quotation marks otherwise they tell the engine that your string ends there. To properly add a string in such a string you have to use \" instead of ". This is the same way you add quotation marks to normal strings, not in your code, but you have to remember that you are writing your code here as you write a string. For that reason you use quotation marks at the beginning and at the end of your string and every time you want to use them inside your string you have to use \" instead.

    So the correct way to write the previous script call would be this one:
                    Code:        
    1. @my_string = "
    2. $game_message.add("Hello new player, welcome to this world.")
    3. Fiber.yield while $game_message.busy?
    4. " # this goes in the 1st script call
    5. # what follows goes in the 2nd script call
    6. @my_string += "
    7. $game_message.add("Are you ready to start a new adventure?")
    8. "
    9. eval(@my_string)
    复制代码


    As you can see it now runs just fine. Remember this when you when you add strings in your string or it will come and bite you later.
    [/quote]
    Everything I had to say about using strings to overcome script call limits has been said. What's next? Is that the only way of overcoming script calls limits?

    They are not.

    As I mentioned you can use script calls to create classes you only need in a particular event. That can be done on multiple script calls too. First of all let's see how to create a class in a script call.

    Spoiler: Creating new classes in script calls
    In a script calls you have two ways of creating a new class:
    1) Creating a new class with a name and its methods
    2) Creating an anonymous class with its own methods
    Which one is better? We are talking about a class you only need for a single event so in my opinion it makes no difference at all. You can just use the one you like the most.

    A class is written this way:
                    Code:        
    1. class MyClass
    2.   #here you put your class methods
    3.   def initialize
    4.     @myc_value = "Hello!\nThis is my new class"
    5.   def my_method
    6.     $game_message.add(@myc_value)
    7.   end
    8. end
    复制代码


    Once you created your class and every method you need you can create a new instance of that class and use that method.

                    Code:        
    1. @my_var = MyClass.new
    2. @my_var.my_method
    3. Fiber.yield while $game_message.busy?
    复制代码


    Using those two codes together should print the message stored in @myc_value inside my_var. This is the first way of creating your class. To do it using anonymous classes you have to change the code in this example to something like this:

                    Code:        
    1. @my_var2 = Class.new do
    2.   #here you put your class methods
    3.   def initialize
    4.     @myc_value = "Hello!\nThis is my new class"
    5.   def my_method
    6.     $game_message.add(@myc_value)
    7.   end
    8. end.new
    复制代码


    Then you can use my_var2.my_method to display the message. The main difference here is that you have to declare my_var2 before defining the class itself and you have to create it using "Class.new" instead of using the class you created. Another difference is that the block which starts with "Class.new" ends with "end.new" instead of just "end". If you only need a single instance of that class and you only need it for that particular event using the former or the latter does not matter. It is a different story if you need more than one instance of that class, in which case you  should avoid using anonymous classes.
    Unfortunately the lines limit applies to class creation as well so this might be a little annoying. When creating classes and methods you probably want more lines and your class will most likely not fit.

    So can you create just classes with very few methods? Absolutely no. You are free to use multiple script calls to add more methods to an already existing instance of a certain class.

    Spoiler: how to add more methods to your class
    I said "add more methods to an already existing instance of a certain class" because to add more methods to your class you have to create a new instance of that class first. For that purpose I will be using the same my_var used in the previous example assuming we already created it.

    Ruby objects have a very powerful method called "instance_eval" (check the documentation for more info). This method is extremely useful and can be used in many different ways. You can use it to access instance variables, to evaluate strings or you can use it to evaluate a whole block. This last part is the one we will be using. A block is just a piece of code you can ass to instance_eval. Let's explain it with an example:

                    Code:        
    1. @my_var.instance_eval do
    2.   def my_method2
    3.     $game_message.add("We are in my_method2")
    4.   end
    5. end
    复制代码


    If after this you use
                    Code:        
    1. @my_var.my_method2
    2. Fiber.yield while $game_message.busy?
    复制代码

    The message displayed is the new one we just wrote. So we successfully created a class, then used a new script call to add more methods to it. This way you can create classes with many methods just by using script calls.
    In conclusion I wanted to show you how multiple script calls can be used as a whole in many different ways. Of course being able to use multiple script calls this way means you have to understand ruby to a certain degree. Probably many people with that much knowledge are able to write a script on their own to use multiple script calls as one without having to overcome that limit with strings or anything else. Even more, they could be able to write everything they need in a script and then use a single method in a script call that contains everything they need.

    Even so for everyone who does not want to use scripts and for those who don't know how powerful the engine is I hope this can be an eye opener and I hope they find it useful.

    Thank you for reading.


    本贴来自国际rpgmaker官方论坛作者:Heirukichi处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/advanced-guide-to-script-calls-no-script-required.97021/

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    简体中文
    繁體中文
    English(英语)
    日本語(日语)
    Deutsch(德语)
    Русский язык(俄语)
    بالعربية(阿拉伯语)
    Türkçe(土耳其语)
    Português(葡萄牙语)
    ภาษาไทย(泰国语)
    한어(朝鲜语/韩语)
    Français(法语)
    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2026-7-15 16:52 , Processed in 0.149260 second(s), 52 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表