This tutorial assumes you have a copy of 3D Studio Max installed in your system, and you have downloaded Starting Tutorial File and extracted it to folder, which we refer with (Dage)\
Also these tutorials assumes you have basic knowledge how to find things in 3D Studio Max, like property editor, material editor, etc.
It is recommended you have already took the previous tutorials.
Let's look at the starting tutorial file.
There is our lonely guy in a room, where there is a door and a crate. You can do nothing much, but to walk around.
First we want to create a way for player to identify objects in game.
We use TDummy objects to create invisible boxes. If user hovers mouse or clicks inside the boxes, we want to give feedback of players actions.
Place in roomscripts.txt file following lines in the end of file.
function onRoom01Load() mtDoor = TDummy.Create(); mtDoor.SetPosition(1.6,9.7,6); mtDoor.SetScale(9,1.2,13); mtDoor.onMouseDown = 'onDoorMouseDown'; mtDoor.onMouseMove = 'onDoorMouseMove'; end
This code creates new TDummy object and repositions and scales it so that it is around the door. Then it adds mousedown and mousemove function handlers to it.
Press F8 to debug TDummys.
Next we want to define what happens when user hovers mouse over the mousetarget.
Add new function.
function onDoorMouseMove() MouseText.Text = 'door'; end
Now if we test the game, we can hover over the mouse and the text changes to 'door'. However the text doesn't change back to '[none]' when we hover off from the door.
function onRoom01MouseMove() MouseText.Text = '[none]'; end
This simple function does the trick. Note that you don't have to assign the event to Room01, it does it automatically.
Next we do the same for the crate:
function onRoom01Load() mtDoor = TDummy.Create(); -- ..... -- ..... mtCrate = TDummy.Create(); mtCrate.SetPosition(-4.8,-5.4,2.2); mtCrate.SetScale(5,5,5); mtCrate.onMouseDown = 'onCrateMouseDown'; mtCrate.onMouseMove = 'onCrateMouseMove'; end function onCrateMouseMove() MouseText.Text = 'crate'; end
When changing rooms, we want that our objects destroy when we unload the room, so we script this:
function onRoom01Unload() mtDoor.Destroy(); -- This destroys object in Engine Core side. mtCrate.Destroy(); mtDoor = nil; -- This removes any reference from LUA mtCrate = nil; end
Now that we have our room identified, we want to change to Room02 when clicking door.
First we need to create our second room. Insert the following to onGameLoad.txt file.
Room02 = TRoom.Create(); Room02.Name = 'Room02'; Room02.Filename = 'Room01/Room02.3ds'; Room02.WalkArea = 'Room01/Room02.3ds'; Room02.scriptfile = 'roomscripts.txt';
Note that we share the same scriptfile here. It is recommended to place the room scripts in separate scriptfiles. We have so small game it doesn't matter.
Then we assign mousedown event so that the Room02 is loaded:
function onDoorMouseDown() Room02.Load(); end
We already assigned onDoorMouseDown event to our mtDoor object, so now when we click we jump to the next room. Little adjustments on camera angle should be in place. Write this in roomscripts.txt file:
function onRoom02Load() Camera.SetPosition(20,20,-20,1); end
Now when we click we end up having camera angle changed smoothly. Few more adjustments for actor and light position.
function onRoom02Load() Camera.SetPosition(20,20,-20,1); MainActor.SetPosition(5,5,5); Light.SetPosition(20,50,-20); end
As with Room01, we will create TDummy for door, add little mouse-events. Here is full script. Note that we re-use door mousemove event. Also we clear actors walkpoints and position him according to the room entrance.
function onRoom01Progress() if MainActor.Y < -40 then MainActor.SetPosition(0,10,0); MainActor.ClearWalkPoints(); end end function onRoom01Load() MainActor.ClearWalkPoints(); Camera.SetPosition(20,20,20,1); MainActor.SetPosition(5,5,-4); MainActor.PointTo(0,5,100); Light.SetPosition(20,50,20); mtDoor = TDummy.Create(); mtDoor.SetPosition(1.6,9.7,6); mtDoor.SetScale(9,1.2,13); mtDoor.onMouseDown = 'onDoorMouseDown'; mtDoor.onMouseMove = 'onDoorMouseMove'; mtCrate = TDummy.Create(); mtCrate.SetPosition(-4.8,-5.4,2.2); mtCrate.SetScale(5,5,5); mtCrate.onMouseDown = 'onCrateMouseDown'; mtCrate.onMouseMove = 'onCrateMouseMove'; end function onCrateMouseMove() MouseText.Text = 'crate'; end function onDoorMouseMove() MouseText.Text = 'door'; end function onDoorMouseDown() Room02.Load(); end function onRoom01MouseMove() MouseText.Text = '[none]'; end function onRoom01Unload() mtDoor.Destroy(); -- This destroys object in Engine Core side. mtCrate.Destroy(); mtDoor = nil; -- This removes any reference from LUA mtCrate = nil; end -- ROOM 02!!! ... function onRoom02Progress() if MainActor.Y < -40 then MainActor.SetPosition(0,10,0); MainActor.ClearWalkPoints(); end end function onRoom02Load() MainActor.ClearWalkPoints(); Camera.SetPosition(20,20,-20,1); MainActor.SetPosition(5,5,4); MainActor.PointTo(0,5,-100); Light.SetPosition(20,50,-20); mtDoor2 = TDummy.Create(); mtDoor2.SetPosition(5.6,-9.7,6); mtDoor2.SetScale(9,1.2,13); mtDoor2.onMouseDown = 'onDoor2MouseDown'; mtDoor2.onMouseMove = 'onDoorMouseMove'; end function onDoor2MouseDown() Room01.Load(); end function onRoom02MouseMove() MouseText.Text = '[none]'; end function onRoom02Unload() mtDoor2.Destroy(); mtDoor2 = nil; end
Next we create a key to our game. We don't want to create this specifically in room scriptfile, because we want to carry this through our game (to the next room also).
Note: Make sure your inventory mesh objects are located and centered in origo. Otherwise they will not get mouse-events and might look funny in inventory.
Put this in onGameLoad.txt before Room01.Load();
obKey = TMesh.Create(); obKey.Load('Room01/key.3ds'); obKey.SetPosition(-4.65,4.1,5); obKey.onMouseMove = 'onKeyMouseMove'; obKey.onMouseDown = 'onKeyMouseDown'; obKey.CastShadows = 1;
Okay, it's little pixel hunting to find the key. We could make another TDummy for the object, but to keep it simple, we won't.
Next we will say that the door is locked, unless we have the key. So change the onDoorMouseDown function to following:
function onDoorMouseDown()
if obKey.InInventory == -1 then
MainActor.Say("It is locked");
else
Room02.Load();
end
end
InInventory gives the id of inventory where the key is located. If it is in room, it is -1.
Inventory? We don't have inventory to put the key on. So let's create one.
Inventory = TInventory.Create(); Inventory.SetPosition(-0.65,-1.0);
Now we have inventory. Next we want to add the key to the inventory, when player clicks the key.
function onKeyMouseDown() if obKey.InInventory == -1 then MainActor.Say("That looks useful, I'll take it"); obKey.MoveToInventory(Inventory.ID); obKey.SetScale(1.5,1.5,1.5); end end
Once again, if the key is not in inventory, take it.
Now when we have taken the key, we can go freely through the door.
Remember, when creating your own inventories and objects, inventory mouse-events are found in current room scriptfile. So basically you have to have in all room scriptfiles mouse events for objects in your inventory.
That wraps our Room changing and Inventory handling tutorial.