Game Scripting with Lua in Ogre

Today, we will play more with Lua scripting in Ogre. Download the file:

Note that this is an updated version of the OgreScripting project that we used last week, so redownload this one, don't use the old one.

Get the project compiling and running. If you run the program, you get a little cube that you can control with the arrow keys (hold space to move the cube faster). As before, you can bring up the lua console with the ~, and type in commands. One helpful command is print, which displays text on a seconday overlay -- try it out!

Also, there is now a help function, that prints out C++ functions that are exposed to lua

Exposed Functions

ScriptManager.lua

We've modified ScriptManager.lua a little since last lecture:

-- Our quick and dirty script system.  We maintain a global array of scripts.  
-- The Ogre Frame Listener calls our ScriptManagerThink function, which in turn
-- calls the Think methods on all active scripts.

-- A more robust scripting system would have an eaiser way of indexing scripts, and
-- activating / deactivating / removing scripts.  This is just quick and dirty enough
-- to work for now.


-- Our table of running scripts
GlobalScripts = { }

-- Method to add a script.

function addScript(script, name)
    if name == nil then
		table.insert(GlobalScripts, script)
	else
		GlobalScripts[name] = script
	end
end

function removeScript(name)
	GlobalScripts[name] = nil
end

function ScriptManagerThink(time)
    for i, v in pairs(GlobalScripts) do	   
	   if v:Active() then
			v:Think(time)
	   end
    end
end


-- Handy print method.  Use print instead of debugOutput, to avoid crashes 
-- for nil values and non-string values.
function print(x)
    debugOutput(tostring(x))
end



----------------------------
-- Script "Class" -- pretty straighforward for now, scripts have a Think method
-- and an Active method by default, and nothing else
-----------------------------
Script = {}

function Script.Active(this)
	return this.isActive
end

function Script.Think(this, time)

end

function Script.create()
	local s  = {}
	s.isActive = true	
	s.Active = Script.Active;
	s.Think = Script.Think
	return s
end

Sample Scripts

File Level1.lua

function destroySeeker(name)
	removeObject(name)
	removeScript(name .. "_script")

end



function createSeekerTrigger(name, x, y, z)
    x = x or 0
	y = y or z
	z = z or 30
	createTriggerArea(name, x, y, z)
	setTriggerSize(name, 10, 10, 10)
	setOnEnter(name, "if triggerObject == 'player' then  createSeeker('" .. name .. "_seeker', 50, 0, 50)  end")
	setOnExit(name, "if triggerObject == 'player' then  destroySeeker('" .. name .. "_seeker') end")
end

function createSeeker(name, x, y, z) 
	if name == nil then
		print("createSeeker:  name required!")
		return
	end
	x = x or 0
	y = y or 0
	z = z or 0
	
	print("Creating Seeker: ID = " .. name .. ",  Location: " .. tostring(x) .. ", " .. tostring(y) .. ",  " .. tostring(z))
	createObject("MyCube.mesh", name)
	setPosition(name, x, y, z)
	setObjectSize(name, 5,1,1)
	local seekerScript = Script.create()
	seekerScript.Think = function(this, time)
		local pX, pY, pZ = getPosition("player")
		local mX, mY, mZ =  getPosition(name)
		local deltaX, deltaY, deltaZ = pX-mX, pY-mY, pZ - mZ
		setVelocity(name, deltaX , deltaY, deltaZ)
	end	
	-- We are using the 
	addScript(seekerScript, name .. "_script")
end

createSeekerTrigger("testSeekerTrigger")

In-Class Exercise

Now to work! In the Content/Scripts folder, open up the level1.lua file, and extend it in the following ways