lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Sean Middleditch wrote:
 >> run a PORTION of that script, halt, run some other code, then return 

   First, search the message archive or e-group list for previous posts by
Bret Mogilefsky - he posted some interesting ideas on modifying the Lua
internals to do this.  Otherwise, I think the answer is "no", not without
modifying the Lua source.

   Second, you CAN do this with "plain" Lua if you're willing to suffer
some performance penalty.  The setup is to store those scripts as text and
then do the line-by-line code stepping yourself.  So you execute a script
that executes scripts - the performance penalty being the extra parsing of
the manual dostring() calls.  Following is some old code that I was playing
with after reading Bret's posts.  The "driver" script is runbob.lua and the
"actor" script is bob.lua, you'll need to manually snip them apart from
this message to try it.  It isn't elegant as is but may give you some
ideas, the guts are in _ACTOR:runScript().  You can extrapolate to figure
out how you'd set up multiple actors running asynchronously.

  Cheers,

  Dave

<--cut here-->
-- runbob.lua
$debug

--
-- global pointer to current actor, used in "actor" scripts
--
currentActor = {}

--
-- base class for actor
--
_ACTOR = {}

function _ACTOR:loadScript(filename)
  self.script = { n=0 }
  readfrom(filename)
  local s = read()
  while (s) do
    tinsert(self.script, s)
    s = read()
  end
  readfrom()
end

-- runs until break or actor not alive or out of code
function _ACTOR:runScript()
  breakFlag = nil
  while (self.alive) and (not breakFlag) do
    local s = self.script[self.codeptr]
    if (s) then
      -- increment code pointer
      self.codeptr = self.codeptr + 1
      -- set global actor pointer
      currentActor = self
      -- execute script snippet
      dostring(s)
      -- check if end of script
      if (self.codeptr > self.script.n) then
        self.alive = nil
      end
    end
  end
end

function _ACTOR:move()
  self.x = self.x + self.dx
  self.y = self.y + self.dy
end


--
-- constructor for actor
--
function ACTOR(filename)
  local t = {}
  t.script = { n=0 }
  t.alive = 1
  t.codeptr = 1
  t.x = 0
  t.y = 0
  t.dx = 0
  t.dy = 0
  t.loadScript = _ACTOR.loadScript
  t.runScript = _ACTOR.runScript
  t.move = _ACTOR.move
  if (filename) then
    t:loadScript(filename)
  end
  return t
end


--
-- utility functions
--
function isMoving()
  if (currentActor.dx ~= 0) or (currentActor.dy ~= 0) then
    print("  ..moving..")
    currentActor:move()
    return (currentActor.x ~= currentActor.targetx) -- and y's
  else
    return nil
  end
end

function break()
  breakFlag = 1
end

function waitTill(func)
  if (not func()) then
    -- decrement code pointer
    currentActor.codeptr = currentActor.codeptr - 1
    break()
  end
end

function waitWhile(func)
  if (func()) then
    -- decrement code pointer
    currentActor.codeptr = currentActor.codeptr - 1
    break()
  end
end


--
-- testing
--
bob = ACTOR("bob.lua")
-- this loop would be in host program
frame=1
while (bob.alive) do
  print("FRAME =",frame)  frame=frame+1
  bob:runScript()
end

<--cut here-->
-- bob.lua
--
-- will execute on frame 1...
--
print("  Start..")
currentActor.x = 0
currentActor.dx = 1
break() -- prove break() works
--
-- will execute on frame 2
--
print("  frame = 2?")
currentActor.targetx = 10
--
-- will execute at end of frame 2, then 3-11...
--
waitWhile( isMoving )
--
-- will execute at end of frame 11...
--
print("  Done.")
print("  x =", currentActor.x)
currentActor.alive = nil
<--cut here-->