Vapid
Vapid

Reputation: 816

Running Lua scripts line per line

I'm making a game where you code your own robot using Lua inside the game. I'm using the C# Lua library called NLua, which basically works just like the offical C library.

If the user enters the following code:

for i=0,10 do -- Repeat 10 times
    if (robot:check_clear(0.1)) then -- Check if clear up to 10cm in front
        robot:go_foward(0.1) -- Go foward 10cm
    else then
        robot:turn_right(45) -- Turn 45 degrees
    end
end

I want it to run the entire code 10 times, as you can see. It will move on to check robot:check_clear(), let's say it returns false. So it will now run robot:turn_right(45) and wait for the action to finish, because rotation might take 3 seconds or so. Same with go_forward(0.1). How would I make it wait before moving on?

Right now I use lua.DoString(code); to execute all of the code. The problem is that it doesn't wait before moving on.

The robot in the code refers to a C# class I have called LRobot. It is assigned by doing this lua["robot"] = new LRobot();

I'm a bit of a newcommer to Lua and the Lua C/C# library, so I'd be thankful for detailed answers. I don't want someone to code this for me, just want to know of key commands and how to structure it all.

Thanks in advance!

Upvotes: 0

Views: 673

Answers (2)

Niccolo M.
Niccolo M.

Reputation: 3413

A relatively easy solution (IMO) is to do it with coroutines. Eventually, your code would look like:

robot:go_foward(0.1)
wait_till_robot_stops()
robot:turn_left()
wait_till_robot_stops()
robot:go_foward(0.1)
wait_till_robot_stops()
alert("I'm home!")

The "wait_till_robot_stops()" would freeze your function till the robot rests. How to implement this? It's easy. This wait() function is simply a call to coroutine.yield(). This makes your function (your coroutine) go to sleep.

Now, how do you wake up your coroutine? It's easy. When the robot movement stops, your game should invoke some function on the Lua side. Let's call it on_robot_stop(). This function will call coroutine.resume() on the dormant coroutine.

You can later make your system a bit more complicated (but much more fun) by having a wait() function that waits for certain events:

robot:go_foward(4)
wait_for("robot rests")
robot:go_foward(2)
wait_for("incomming missile")
robot:raise_shield()

Upvotes: 3

Tom Blodget
Tom Blodget

Reputation: 20802

One option would be to have the robot class's commands not return until the command is carried out. That would probably mean running the user's Lua state on a separate thread. If can't check for completion then you can estimate the time and use something like:

System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10));

Upvotes: 1

Related Questions