Lua Basics

Overview

To use Lua in a VB program is not exceptionally hard. Its just about half a dozen things that can go wrong and the error messages aren't all that friendly. The main issue with using Lua in a VB program is the fact that everything about Lua is designed for C languages (C++, C#). Thanks to the LuaInterface thingamabob, Lua is available to the CLR. That means that, in theory, any language using the CLR can use Lua.

Lots of people have been viewing this page lately, if you have any comments or suggestions, you can leave them at the bottom. I urge you to let me know if this helped you, and to provide me with any insight you might have on making this example better, or more robust. I would like to actually turn this from a sample snippet into a whole sample game.

Coding

To extend your program to use Lua Scripting is fairly straightforward, you'll need a copy of LuaInterface, and a copy of Lua. In these steps assume we have a form (Form1), a class (Humaniod) and two scripts (script.txt (our Main Script) and Human.txt (the script that creates the NPCs)). Since the most common use (that I can think of) to need to extend scripting functionality to a program is a game, this example will have a gamey kind of feel to it.

Class Humaniod
    Private _ID as Integer
    Private _FirstName as String
    Private _LastName as String

    Public Property ID() As Integer
    Get
        Return _ID
    End Get
    Set(ByVal value as Integer)
        _ID = value
    End Set
    End Property

    Public Property LastName() As String
        Get
            Return _LastName
        End Get
        Set(ByVal value As String)
            _LastName = value
        End Set
    End Property

    Public Property FirstName() As String
        Get
            Return _FirstName
        End Get
        Set(ByVal value As String)
            _FirstName = value
        End Set
    End Property

    Public Sub Speak(msg As String)
        Form1.TextBox1.Text += _FirstName + " says: " + msg + vbCrLf
    End Sub
End Class

Note:
I strongly recommend using Interfaces to control how you create NPCs, if you really are going to attempt to create a game.

What is doing what

Detailed breakdown of what exactly is happening, and where. This is an extremely over-simplified method of creating a few NPC type characters, giving them names, and making them talk when the player (you) interacts with them (double clicks their name in the listview)

clsHumaniod.vb

Here we create the Humaniod class, hopefully you know about classes, so this won't be to complicated. First things first, we declare some private variables to store the objects ID number, FirstName and LastName. Next we actually create the properties for the class, and finally we create a simple Method that takes a string and repeats it into a textbox on form1. Note this is all hardcoded and very much a bad idea, as it really shoots your modularity in the foot (well, with minor changes its fixable, but still not to great for production)

Form1.vb

This is also pretty straight forward, its a form with a listview, a button and a textbox, all assigned the default name. Make sure to set the Textbox to multiline and make sure the Listview is set to Details instead of Icons or anything else. Inside the code there are two Subs that are registered when the form loads. Registering a function with LuaInterface allows your scripts to use that function the same way you would in Vb. The button simply acts as the catalyst, starting this whole thing off, it starts LuaInterface on the file "Script.txt" which will be explained below. As the script finishes (note that the LuaInterface will block while it is processing a script) it will then take the list of humans and create a new line in the listview for each one. When a NPC is double clicked in the listview, the Speak function that is in "Script.txt" will be fired, and passed the ID of the selected NPC from the listview.

Script.txt

This script does quite a few things, the first thing it does is load the entire namespace of the application, in this case mine is called "LuaTest", change this to whatever your projects main namespace is. Then we create an object "HumanNPC" and set it to the Humaniod class, much as if we had done the following in Vb.Net:

Dim HumanNPC as New Humaniod()

Now that we have an Humaniod class object in our lua script, we could use it directly, but since we want multiple NPCs, and eventually there will be many many kinds of NPCs (right?), we should create a Table (Lua term for an array, basically) to hold all these NPCs. We then call the CreateNPC function (note that is actually a sub in our vb code) that we registered in Form1, which takes an NPC type as a string. In this case we want to create a Human, so we pass that along. The Vb code will use this to run correct script file (Human.txt) to create the NPC. We can call this as many times as we like, everytime it will run the script file again.

Human.txt

This script simply creates a new object in the NPCs table, then assigns the properties. I know that I did not give the code for the NextID() function, I am leaving that up to the reader to create and impliment. All this function does is generate and return the next ID. The reason I'm leaving it up to the reader is because there are many many ID schemes you can use, and I'd rather you find the one that works for you. The scheme I've used here is a simple numeric scheme where you just use the next number, but maybe you need letters in your ids, or are loading from a database, I don't know. Anyways, we set a variable, just a regular variable, to the value returned by NextID(), we then use this as our index for the NPC object in the table. Notice how we use the HumanNPC() object we set in the other script? Thats because everything in your Lua scripts is global. Well, not everything, variable scope does become a factor, but not at this level of the game (pardon the pun). So we have the ID, we use that as the index, we set that to the HumanNPC type, now we just assign the properties the values they should have (note, these values are hard coded, you could use a random name generator) then we use the AddNPC function, which was registered when Form1 loaded, to add the new NPC to the list we are tracking back in Vb. Also, notice that we registered the function as "AddNPC" when in Vb the Sub is named "AddPerson". When you register a function, you don't need to register it with the same name as you use in your code. If another name would improve the readability of your scripts, then I don't see the issue using it.

Conclusion

While this is an example of extending a program with Lua, it doesn't do a whole lot, and there are much much better ways to improve on the design. And as I mentioned before, if you really are planning on creating a game, use interfaces, it will help you keep track when you create 15 new types of NPC at the same time and forget to implement the attack function on type number 9, because Vb won't let it compile until you do.

Theory (Why would I use this?)

While it might not jump out to you why this would be beneficial to you at all (ok ok, maybe it did, sometimes it doesn't), there are plenty of reasons to implement this, or some other kind, method of scripting. I'm going to touch on this briefly here, maybe someday it'll get its own page with lots of extra details.

Basically, the biggest perk of this system is that once you design the basic program, you can extend it without recompiling your code. Lets say you were making a physics game and you wanted to allow players to create and share their own objects that they could use in the game. Well, if the objects are hard coded, the whole program would have to recompile. If the objects are stored as XML or some other descriptive file and read in by the game, the game would have to "reload". It might be possible to mitigate the time that takes, but it would require extensive coding. If the objects are shared as scripts, all you need to do is add the script to the objects directory and the next time the game displays a list of objects to be used to the player, it should be included (Note, this sounds like it just works automatically, but you would have to program the game to check for new scripts)

Another example, lets say your creating a RPG, your in the middle of creating an epic story line and you realize you want to change a few lines of dialogue, remove a quest and tweak a few weapons balance issues. You make those quick changes to the scripts, reload those particular objects and off you go. Now you realize you just left out that really great character you thought up last night, what is, that half crab half meatball guy, yeah, that's right. But you have no other NPCs quite like this guy, so you need to define him in a script, call it HalfCrabHalfMeatball.txt. Then, using whatever event you want to trigger the NPCs creation, you just call CreateNPC("HalfCrabHalfMeatball").

Any other questions? Feel free to ask. (I'm not an expert by any means, but if I can help, I will)

Comments

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License