Game Development Community

T2D Tutorial - Mouse Object Selection

by Matthew Langley · 04/15/2005 (5:40 pm) · 12 comments

A Simple and a Complex way in doing Object Selection with the Mouse Moving the Object

Ok, so you want to do object selection and allow your mouse to move the object, whether this is for in game mouse moving or even for sort of editor for your game(s). Well here I will go step by step through two different methods of doing this (at least these are the two methods I've used, I ended up using the more complex one in the end). One is simple and one is more complex... the simple one will work when theres less of a requirement for the objects to affect their surrounds, it will use the .setPosition() method so theres a chance collision/physics will slip while moving objects with this method, the next one uses a fxSceneObject2D that constantly follows the mouse (not using setPosition) and then you can mount whatever you want to this object... and even apply a force to it. I did this in my second release of the Physics Demo and thought about extending that tutorial to add this, though figured I'd do a fresh one so people who haven't done the Creating the Physics Demo Tutorial (which I highly recommend) can still do this :) I hope you enjoy

Matthew "King BoB" Langley


Ok

Part 1: The Simple Way

Getting Started:

Ok, first method, lets start simple... we want to be able to attach an objects movement to the mouse, we will need some way of keeping track where the mouse is... (you can find all these functions in the T2D Reference Documentation) so we will utilize the following script functions



function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
}

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
}

function sceneWindow2D::onMouseUp( %this, %mod, %worldPos, %mouseClicks )
{
}

function sceneWindow2D::onMouseEnter( %this, %mod, %worldPos, %mouseClicks )
{
}

function sceneWindow2D::onMouseLeave( %this, %mod, %worldPos, %mouseClicks )
{
}

Now we might not need all of these, but I figured I'd throw all of them up there... These are what we call "Callbacks"...

basically a Callback is just the engine (the T2D C++ side) "calling back" to the scripting language... normally we wouldn't be able to know when the mouse moves, or drags, but since the callbacks were placed in the source code we now have helpful function that automatically get called on these actions :) Its how the C++ interacts back to the script... we utilize functions in script that send data to the C++ side and the C++ side sends "callbacks" to script functions, this is how we handle events, like the mouse events like these, as well as the onCollision event (and many others, just search for "Callbacks" in the Reference documentation, Melv organized it nice and neat for us).

Ok, back to the task at hand... ok so we have these functions that we can create in script that get called when the appropriate action happens,

What we will ant to do is store the mouse position on the onMove and onDragged functions

ok lets start off with something simple, a little fun, and teaches some basic debugging practice... I'm a big fan of echo statements lol, they can be immensely helpful to figure out problems... so lets add some echo statements...

create a new .cs file (just like creating any text file) in the T2D/client folder (same folder as client.cs)...call it "simpleMouse.cs" and format it like this so you have proper echos

function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
	echo("Mouse Moving");
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
	echo("Mouse Dragging");
}

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	echo("Mouse Down");
}

function sceneWindow2D::onMouseUp( %this, %mod, %worldPos, %mouseClicks )
{
	echo("Mouse Up");
}

function sceneWindow2D::onMouseEnter( %this, %mod, %worldPos, %mouseClicks )
{
	echo("Mouse Entered... Knew it would come crawling back");
}

function sceneWindow2D::onMouseLeave( %this, %mod, %worldPos, %mouseClicks )
{
	echo("Mouse Left... Go Get It!");
}

save the .cs file... and create a new .cs file in the same folder called "exec.cs"...
in here put this line of code

exec("./simpleMouse.cs");

now save it and open up your client.cs... find the area (towards the beginning) where it has multiple exec( statements
at the end add this
exec("./exec.cs");

that way if you have to exec any new files you can simple add them to the exec.cs and not dig through your client.cs :) Its a good idea to start seperating your files like this, it helps not only in debugging but in making changes... ok save off the exec.cs and client.cs files, you can close them for now also... fire up T2D.exe and move your mouse arround, now press the "~" tilde key to bring up the console, you should see something like this

www.razedskyz.com/games/torque/tutorials/T2D/mouseTut/mouseTut1.JPG
now you can see all the "Mouse Moving" calls, so the onMove code works... and you also see an ending onLeave call? This is because you opened the console and it technically left the T2D window... quite nifty actually :)

now close the console with the tilde key and click and drag then let go and hit the console button again

www.razedskyz.com/games/torque/tutorials/T2D/mouseTut/mouseTut2.JPG
now you can see the onDragged getting called, the onMouseUp for when you let it go and the onLeave again... close the console... click around your T2D window and hit the console and you should see a lot of move dragged and down calls

www.razedskyz.com/games/torque/tutorials/T2D/mouseTut/mouseTut3.JPG
as you can see it works quite well... these debug message are great for checking things like this without having to set up complex systems... though we don't want them spamming our console anymore... instead of have you delete or comment them I'm going to have you do something a bit different, we're going to more or less "toggle them off." What do I mean by that? Glad you asked! lol (so I'm a bit weird) let me show you

we're going to put this line of code
if($debugMsg::mouse::callBacks)
before every echo statement

like this

function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Moving");
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Dragging");
}

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Down");
}

function sceneWindow2D::onMouseUp( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Up");
}

function sceneWindow2D::onMouseEnter( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Entered... Knew it would come crawling back");
}

function sceneWindow2D::onMouseLeave( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Left... Go Get It!");
}

now save and fire up T2D, move the mouse around and bring up the console, you shouldn't see any of those echo statements... now type this in the console
$debugMsg::mouse::callbacks = true;
hit enter and close the console, move your mouse around and bring up the console again, now you should see the echo statements again... to turn them off type
$debugMsg::mouse::callbacks = false;


if we organize all our echo statements like this then later if we need to debug these aspects again we can toggle them with simple commands (and even make a nifty little function to do this for us)

ok so we set up some mouse callbacks, tested them, and we even set up some debug messages that can be toggled. Now we want to get back to our goal... we were wanting to get the position of the mouse... if you remember when you click and drag onMouseDragged gets called and onMouseMove stops getting called... so we will want to store its position on both of those functions so we know where its at when its draged and when its moving, as you might have guessed the %worldPos variable that gets passed to these functions is the location... so lets add something to those functions

%this.mousePos = %worldPos;

so it should look like this

function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Moving");

	//lets store the mouses position
	%this.mousePos = %worldPos;
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Dragging");

	//lets store the mouses position
	%this.mousePos = %worldPos;
}

so now we can access the mouse position... now we need an object to set to this position... add this function to the end of your "simpleMouse.cs"

function simpleMouse()
{

	$test = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$test.setImageMap( tileMapImageMap );
	$test.setSize( "5 5" );
	$test.setPosition( "0 0" );
	$test.isSelectable = true;
	$test.objectName = "test box";

}

now go to your client.cs and add a call to this function where it says

// ************************************************************************
	//
	// Add your custom code here...
	//
	// ************************************************************************

so add this

simpleMouse();

save it then run T2D.exe... you should see something like this (a box in the center of the screen)

www.razedskyz.com/games/torque/tutorials/T2D/mouseTut/mouseTut4.JPG
if it doesnt compare your entire "simpleMouse.cs" file to this... and make sure you have the "simpleMouse();" call in your client.cs

function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Moving");

	//lets store the mouses position
	%this.mousePos = %worldPos;
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Dragging");

	//lets store the mouses position
	%this.mousePos = %worldPos;
}

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Down");
}

function sceneWindow2D::onMouseUp( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Up");
}

function sceneWindow2D::onMouseEnter( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Entered... Knew it would come crawling back");
}

function sceneWindow2D::onMouseLeave( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Left... Go Get It!");
}

function simpleMouse()
{

	$test = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$test.setImageMap( tileMapImageMap );
	$test.setSize( "5 5" );
	$test.setPosition( "0 0" );
	$test.isSelectable = true;
	$test.objectName = "test box";

}



Ok so we are storing the mouse position and we have an object, we also added a property that says it is selectable, this will help in the object selection... now we want to select it... do this by adding this code to onMouseDown

//lets get a list of all the objects at the clicked point in the t2dSceneGraph
	%objList = t2dSceneGraph.pickPoint(%worldPos);
	//lets get a count of how many objects in the list
	%objCount = getWordCount(%objList);
	
	//we will start looping through the list
	for(%i=0;%i<%objCount;%i++)
	{
		//grabing the entry corresponding to the loop
		%obj = getWord(%objList, %i);
		
		//if we find an object in the list that "isSelectable = true"
		if(%obj.isSelectable)
		{
			//we toggle a value so we know we found an object that "isSelectable"
			%selected = true;
			//we kick out of the loop
			%i = %objCount;
		}	
	}
	
	//if we found an "isSelectable" object
	if(%selected)
	{
		//we then store that object as the selectedObj
		%this.selectedObj = %obj;
	}

ok this is a lot of code to digest at first... though the comments explain it pretty accurately...
we do these steps

get a list of all the objects we clicked
loop through that list until we find one that we have set to isSelectable (in this case we only have set the box to this)
then we kick out of the loop and check if we found a valid object, if we have we then store that as the selected object

now lets add in a debug message to check this without having to complete the system... your entire onMouseDown function should look like this

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Down");

	//lets get a list of all the objects at the clicked point in the t2dSceneGraph
	%objList = t2dSceneGraph.pickPoint(%worldPos);
	//lets get a count of how many objects in the list
	%objCount = getWordCount(%objList);
	
	//we will start looping through the list
	for(%i=0;%i<%objCount;%i++)
	{
		//grabing the entry corresponding to the loop
		%obj = getWord(%objList, %i);
		
		//if we find an object in the list that "isSelectable = true"
		if(%obj.isSelectable)
		{
			//we toggle a value so we know we found an object that "isSelectable"
			%selected = true;
			//we kick out of the loop
			%i = %objCount;
		}	
	}
	
	//if we found an "isSelectable" object
	if(%selected)
	{
		//we then store that object as the selectedObj
		%this.selectedObj = %obj;
	
		if($debugMsg::mouse::selection)
			echo("You have selected:" SPC %obj SPC "with the name:" SPC %obj.objectName);
	}
}


now fire up T2D and type this in the console
$debugMsg::mouse::selection = true;

then click on the box and bring up the console... you should see this

www.razedskyz.com/games/torque/tutorials/T2D/mouseTut/mouseTut5.JPG
Ok, now we got some basic object selection working! We set .isSelectable = true; on an object and it will be selectable, though its good to keep in mind this only will select a single object, multiple object selection is for another tutorial lol :)

ok now we got that part done, lets do the fun part, lets move the object upon selection

ok this is where the simple and complex methods differ... I will first show you the simple method... this method will be using a lot of setPosition() calls... the idea is that when you click an object it stores that object (we already have that) then it toggles a value, something like objectSelected... then we want to check if this is true every time we move the mouse, if its true then we want to grab that stored object and set its position to the mouse position... its a fairly simple concept and it helps to think something out in programming before you actually try and code it... if you need to re-read this paragraph a couple of times untill your comfortable with the idea...

first lets add that toggle value "objectSelected" into the mouseDown, so it toggles correctly...

add it in the end "if(%selected if statement)" so your entire onMouseDown function should now look like this

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Down");

	//lets get a list of all the objects at the clicked point in the t2dSceneGraph
	%objList = t2dSceneGraph.pickPoint(%worldPos);
	//lets get a count of how many objects in the list
	%objCount = getWordCount(%objList);
	
	//we will start looping through the list
	for(%i=0;%i<%objCount;%i++)
	{
		//grabing the entry corresponding to the loop
		%obj = getWord(%objList, %i);
		
		//if we find an object in the list that "isSelectable = true"
		if(%obj.isSelectable)
		{
			//we toggle a value so we know we found an object that "isSelectable"
			%selected = true;
			//we kick out of the loop
			%i = %objCount;
		}	
	}
	
	//if we found an "isSelectable" object
	if(%selected)
	{
		//we then store that object as the selectedObj
		%this.selectedObj = %obj;
	
		if($debugMsg::mouse::selection)
			echo("You have selected:" SPC %obj SPC "with the name:" SPC %obj.objectName);

		%this.objectSelected = true;
	}
}

now we will create new function... add it to the end... and call it

function fxSceneWindow2D::objectFollowCheck()
{

}

now first thing we want to do is check if an object is selected... so add this into the objectFollowCheck() function

if(%this.objectSelected)
	{

	}

if something is selected then we want to update its position to the mouse position... so we grab the value we stored the object in
%this.selectedObj and we set its position... add this into the if statement

%obj = %this.selectedObj;
		%mousePos = %this.mousePos;	
		%obj.setPosition(%mousePos);

so the whole objectFollowCheck function should look like this

function fxSceneWindow2D::objectFollowCheck(%this)
{
	if(%this.objectSelected)
	{
		%obj = %this.selectedObj;
		%mousePos = %this.mousePos;	
		%obj.setPosition(%mousePos);
	}
}

now add a call to this in the onMove and onDrag function

like this

function fxSceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Moving");

	//lets store the mouses position
	%this.mousePos = %worldPos;
	%this.objectFollowCheck();
}

function fxSceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Dragging");

	//lets store the mouses position
	%this.mousePos = %worldPos;
	%this.objectFollowCheck();
}

to keep our debug messages consistent lets add a debug msg like this

function fxSceneWindow2D::objectFollowCheck(%this)
{
	if(%this.objectSelected)
	{
		%obj = %this.selectedObj;
		%mousePos = %this.mousePos;	
		%obj.setPosition(%mousePos);
	
		if($debugMsg::mouse::follow)
			echo("this object:" SPC %obj SPC "is following the mouse at this position:" SPC %mousePos);
	}
}

now fire up T2D and give this a whirl... click on the box and move, very cool it moves around!

www.razedskyz.com/games/torque/tutorials/T2D/mouseTut/mouseTut6.JPG
if yours doesn't work compare your entire simpleMouse.cs to this

function sceneWindow2D::onMouseMove( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Moving");

	//lets store the mouses position
	%this.mousePos = %worldPos;
	%this.objectFollowCheck();
}

function sceneWindow2D::onMouseDragged( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Dragging");

	//lets store the mouses position
	%this.mousePos = %worldPos;
	%this.objectFollowCheck();
}

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Down");

	//lets get a list of all the objects at the clicked point in the t2dSceneGraph
	%objList = t2dSceneGraph.pickPoint(%worldPos);
	//lets get a count of how many objects in the list
	%objCount = getWordCount(%objList);
	
	//we will start looping through the list
	for(%i=0;%i<%objCount;%i++)
	{
		//grabing the entry corresponding to the loop
		%obj = getWord(%objList, %i);
		
		//if we find an object in the list that "isSelectable = true"
		if(%obj.isSelectable)
		{
			//we toggle a value so we know we found an object that "isSelectable"
			%selected = true;
			//we kick out of the loop
			%i = %objCount;
		}	
	}
	
	//if we found an "isSelectable" object
	if(%selected)
	{
		//we then store that object as the selectedObj
		%this.selectedObj = %obj;
	
		if($debugMsg::mouse::selection)
			echo("You have selected:" SPC %obj SPC "with the name:" SPC %obj.objectName);

		%this.objectSelected = true;
	}
}

function sceneWindow2D::onMouseUp( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Up");
}

function sceneWindow2D::onMouseEnter( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Entered... Knew it would come crawling back");
}

function sceneWindow2D::onMouseLeave( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Left... Go Get It!");
}

function simpleMouse()
{

	$test = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$test.setImageMap( tileMapImageMap );
	$test.setSize( "5 5" );
	$test.setPosition( "0 0" );
 	$test.isSelectable = true;
	$test.objectName = "test box";

}

function fxSceneWindow2D::objectFollowCheck(%this)
{
	if(%this.objectSelected)
	{
		%obj = %this.selectedObj;
		%mousePos = %this.mousePos;	
		%obj.setPosition(%mousePos);
	
		if($debugMsg::mouse::follow)
			echo("this object:" SPC %obj SPC "is following the mouse at this position:" SPC %mousePos);
	}
}

ok... now that we got it to moving we need to get it to stop moving lol, gets a little annoying with a little box stuck to your mouse.

for this we will simply edit the onMouseDown function a little

in fact we can help efficiency some if we do this right... when we click again we want it to stop following... well when we do this click we don't need to be searching for objects, or getting the list of objects in fact... so lets encompass most of this function in an if statement, checking if(%this.objectSelected)... like this

function sceneWindow2D::onMouseDown( %this, %mod, %worldPos, %mouseClicks )
{
	if($debugMsg::mouse::callBacks)
		echo("Mouse Down");

	//check to see if we have an object already selected, if so we don't want to do anything expect set it to false so it doesn't follow anymore
	if(%this.objectSelected)
	{
		if($debugMsg::mouse::selection)
			echo("unselecting");

			%this.objectSelected = false;
	} else
	{
		//lets get a list of all the objects at the clicked point in the t2dSceneGraph
		%objList = t2dSceneGraph.pickPoint(%worldPos);
		//lets get a count of how many objects in the list
		%objCount = getWordCount(%objList);
	
		//we will start looping through the list
		for(%i=0;%i<%objCount;%i++)
		{
			//grabing the entry corresponding to the loop
			%obj = getWord(%objList, %i);
		
			//if we find an object in the list that "isSelectable = true"
	
			if(%obj.isSelectable)
			{
				//we toggle a value so we know we found an object that "isSelectable"
				%selected = true;
				//we kick out of the loop
				%i = %objCount;
			}	
		}
	
		//if we found an "isSelectable" object
		if(%selected)
		{
			//we then store that object as the selectedObj
			%this.selectedObj = %obj;
		
			if($debugMsg::mouse::selection)
				echo("You have selected:" SPC %obj SPC "with the name:" SPC %obj.objectName);

			%this.objectSelected = true;
		}
	}
}

this way (as the comment says) the first thing we do is check if we already have something selected, if so we simply set it to false so the movement wont set the position of the object, if something isn't selected then we go through all that process

fire up T2D and move your box around! Now its very cool... should look like this

www.razedskyz.com/games/torque/tutorials/T2D/mouseTut/mouseTut7.JPG
ok now this was the simple way, this should work for level editing, pretty much anything that doesn't require more precise following of the object, if you move this object over another one that it is set to collide with it will collide unless you do it quickly... that is where the next method comes in handy

since I got this done quicker than expected I am releasing this as part 1 and will release the second part later

#1
04/06/2005 (8:43 pm)
Very cool!
Good work, I imagine this would be handy as a base for inventory management.
#2
04/07/2005 (11:15 am)
Glad you enjoyed this

Part 2
#3
04/16/2005 (3:22 pm)
Heya Matt, I'd like to make a suggestion, if you don't mind. Instead of a flag for selectable objects, it may be easier (and tidier, possible) to keep selectable objects in their own group or layer (or both), since all of the pick commands allow you to specify a group and layer mask.
#4
04/17/2005 (12:34 am)
Very good point and I 'almost' set it up like that... though for the original purpose (which I used for my GID) I wanted a lot of different things to be selectable, and since you can only set one group (I think?) that could get messy if I organized other things by groups... things that I wouldn't want selected would, etc...

though what would have been more efficient is to do what you say, search restricting by layer and group as well as keeping the isSelectable Flag... that way It won't have to filter through as many results
#5
04/17/2005 (9:28 am)
Actually you can specify more than one layer/group in the bitmasks for the pick commands. IIRC you'd use the || operator to separate them.
#6
04/17/2005 (10:05 am)
Your completely right... using the | (the bit or operator... || is the scripting or)... though I was basically referring to only setting one group per object...

say I set a player group, enemy group, building group, map layer group (for water terrain etc)...

I then make a whole group selectable... say I wanted to be able to select a waterfall, but nothing else in the map layer group, I would have to put it in its own group... quickly 31 groups can be filled up like this (especially in an RTS when you have multiple unit types that will need there own seperate groups for collision reasons), plus it also make it hard to keep the bitMasks organized like this...

Though I do think your suggestion is good because at least I could slim it down to only the groups I would want to select at all.. (like a logo group could be left out completely, etc)... btw don't take this the wrong way, if you have any suggestions for steps to go beyond any of my tutorials feel free :) I'm always up for finding the most efficient way
#7
04/17/2005 (10:11 am)
Ah, I see what you mean. Sorry, misunderstood that part. :) You're probably right, in that a combination of the bitmasks and an isSelectable flag would probably be the way to go. That'll provide for the most flexibility as well as performance.
#8
04/17/2005 (10:17 am)
I know what you meant though, in fact I probably went down the exact process (great minds think alike ;)... lol thinking "there must be some way to make this work off the groups and layers"... though as I looked at how I had collision groups and masks set up in my GID (had it failrly organized)

function startGame()
{
	

	$objBorder = new fxStaticSprite2D() {sceneGraph = t2dSceneGraph;};

	$AI = new ScriptObject(AI);
	$AI.workerNum = 5;
	$AI.thinkTime = 10000;	

	$gameData = new ScriptObject(gameData);
	$gameData.circles = new ScriptObject();
	$gameData.circles.team = "circles";	
	$gameData.squares = new ScriptObject();
	$gameData.squares.team = "squares";

	$costs::worker = 50;
	$costs::workerUpgrade = 300;
	$costs::soldier = 100;

	$gameData.circles.workerHealth = 50;
	$gameData.circles.workerPower = 5;
	$gameData.circles.soldierHealth = 100;
	$gameData.circles.soldierPower =15;

	$gameData.circles.workerDelay = 800;
	$gameData.circles.soldierDelay = 600;

	$gameData.squares.workerHealth = 50;
	$gameData.squares.workerPower = 5;
	$gameData.squares.soldierHealth = 100;
	$gameData.squares.soldierPower =15;

	$gameData.squares.workerDelay = 800;
	$gameData.squares.soldierDelay = 600;

	$gameData.circles.workerCount = 0;
	$gameData.circles.soldierCount = 0;	
	$gameData.circles.createCount = 0;
	$gameData.circles.isCreating = false;

	$gameData.squares.workerCount = 0;
	$gameData.squares.soldierCount = 0;
	$gameData.squares.createCount = 0;
	$gameData.squares.isCreating = false;

	$collision::circleGroup = 1;
	$collision::squareGroup = 1;

	$collision::circleLayer = 1;
	$collision::squareLayer = 1;

	$collision::baseLayer = 5;
	$collision::baseGroup = 5;

	$collision::goldLayer = 6;
	$collision::goldGroup = 6;

	$collision::farmLayer = 7;
	$collision::farmGroup = 7;	

	$collision::goldMineLayer = 8;
	$collision::goldMineGroup = 8;	

	$collision::sets::mapGroupMask = BIT($collision::circleGroup) | BIT($collision::squareGroup);
	$collision::sets::mapLayerMask = BIT($collision::circleLayer) | BIT($collision::squareLayer);

	$collision::sets::circleGroupMask = BIT($collision::squareGroup) | BIT($collision::goldGroup) | BIT($collision::farmGroup) | BIT($collision::baseGroup) | BIT($collision::goldMineLayer);
	$collision::sets::circleLayerMask = BIT($collision::squareLayer) | BIT($collision::goldLayer) | BIT($collision::farmLayer) | BIT($collision::baseLayer) | BIT($collision::goldMineGroup);


	$collision::sets::squareGroupMask = BIT($collision::circleGroup) | BIT($collision::goldGroup) | BIT($collision::farmGroup) | BIT($collision::baseGroup) | BIT($collision::goldMineLayer);
	$collision::sets::squareLayerMask = BIT($collision::circleLayer) | BIT($collision::goldLayer) | BIT($collision::farmLayer) | BIT($collision::baseLayer) | BIT($collision::goldMineGroup);

	new ActionMap(playerMap);
	playerMap.bindCmd(keyboard, "a", "panLeft();", "");
      playerMap.bindCmd(keyboard, "d", "panRight();", "");
      playerMap.bindCmd(keyboard, "w", "panUp();", "");
      playerMap.bindCmd(keyboard, "s", "panDown();", "");
 
	playerMap.bindCmd(keyboard, "e", "rightClick($mouseObj::pos);", "");

	playerMap.bindCmd(keyboard, "]", "sceneWindow2D.setCurrentCameraZoom(sceneWindow2D.getcurrentCameraZoom() + 1);", "");
	playerMap.bindCmd(keyboard, "[", "sceneWindow2D.setCurrentCameraZoom(sceneWindow2D.getcurrentCameraZoom() - 1);", "");
	playerMap.push();

	loadGameMap();	

	
}

function loadGameMap()
{
	$mapLayer = new ScriptObject();

	echo("trying to load map");
      $mapLayer.map = new fxTileMap2D() { scenegraph = t2dSceneGraph; };   
      $mapLayer.map.loadTileMap("~/client/maps/grassyMap.map");
      $mapLayer.waterMap = new fxTileMap2D() { scenegraph = t2dSceneGraph; };   
      $mapLayer.waterMap.loadTileMap("~/client/maps/water.map");
  	
	
	$mapLayer.grassLayer = addLayer($mapLayer.map, 0);		
   	$mapLayer.grassOver = addLayer($mapLayer.map, 1);
		$mapLayer.grassOver.setBlendColour("255 255 255 155");
		
   	$mapLayer.water = addLayer($mapLayer.waterMap, 0);
   	$mapLayer.water.setCollisionMasks( $collision::sets::mapGroupMask, $collision::sets::mapLayerMask );
	$mapLayer.water.setCollisionActive(true, true);
	$mapLayer.water.setCollisionPhysics(true, true);
	
	$mapLayer.mud = addLayer($mapLayer.waterMap, 1);
		$mapLayer.mud.setBlendColour("255 255 255 155");
   
			
		  
	$mapLayer.bridge = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$mapLayer.bridge.setImageMap(Bridge_hor1ImageMap);
	$mapLayer.bridge.setSize("14 7");
	$mapLayer.bridge.setPosition("2 63.5");
	$mapLayer.bridge.setLayer( 30 );
	$mapLayer.bridge.setGroup( 30 );    	
	$mapLayer.bridge.type = "bridge";    

	$gameData.goldValue = 20;
	$gameData.circles.gold = 200;
	$gameData.squares.gold = 200;

	createGoldMine(0, "-85 30");
	createGoldMine(1, "50 0");

	$gameData.squares.goldMine = $mapLayer.goldMine[0];
      
	$gameData.circles.base = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$gameData.circles.base.setImageMap(CityImageMap);
	$gameData.circles.base.setSize("25 25");
	$gameData.circles.base.setPosition("75 -77");
	$gameData.circles.base.setLayer( $collision::baseLayer );
	$gameData.circles.base.setGroup( $collision::baseGroup );    	
	$gameData.circles.base.type = "circleBase"; 
	$gameData.circles.base.setCollisionActive( true, true); 	
	$gameData.circles.base.isSelectable = true; 
	$gameData.circles.base.isRightClickable = true; 
	$gameData.circles.base.health = 1000; 
	$gameData.circles.base.team = $gameData.circles; 
	$gameData.circles.base.setBlendColour("155 155 255 255"); 	 

	$gameData.squares.base = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$gameData.squares.base.setImageMap(CityImageMap);
	$gameData.squares.base.setSize("25 25");
	$gameData.squares.base.setPosition("-75 -80");
	$gameData.squares.base.setLayer( $collision::baseLayer );
	$gameData.squares.base.setGroup( $collision::baseGroup );    	
	$gameData.squares.base.type = "squareBase";
	$gameData.squares.base.setCollisionActive( true, true);
	$gameData.squares.base.isSelectable = true;
	$gameData.squares.base.isRightClickable = true;
	$gameData.squares.base.health = 1000;
	$gameData.squares.base.team = $gameData.squares;
	$gameData.squares.base.setBlendColour("255 155 155 255");

	$gameData.circles.spawn = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$gameData.circles.spawn.setImageMap(CityImageMap);
	$gameData.circles.spawn.setSize("3 3");
	$gameData.circles.spawn.setPosition("75 -53");
	$gameData.circles.spawn.setLayer( $collision::baseLayer );
	$gameData.circles.spawn.setGroup( $collision::baseGroup );    	
	$gameData.circles.spawn.type = "spawn"; 
	$gameData.circles.spawn.setCollisionActive( true, true); 

	$gameData.squares.spawn = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$gameData.squares.spawn.setImageMap(CityImageMap);
	$gameData.squares.spawn.setSize("3 3");
	$gameData.squares.spawn.setPosition("-75 -53");
	$gameData.squares.spawn.setLayer( $collision::baseLayer );
	$gameData.squares.spawn.setGroup( $collision::baseGroup );    	
	$gameData.squares.spawn.type = "spawn"; 
	$gameData.squares.spawn.setCollisionActive( true, true); 




}

function createGoldMine(%num, %pos)
{

			  
	$mapLayer.goldMine[%num] = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };
	$mapLayer.goldMine[%num].setImageMap(Desert_Mountain2ImageMap);
	$mapLayer.goldMine[%num].setSize("15 15");
	$mapLayer.goldMine[%num].setPosition(%pos);
	$mapLayer.goldMine[%num].setLayer( $collision::goldMineLayer );
	$mapLayer.goldMine[%num].setGroup( $collision::goldMineGroup );    	
	$mapLayer.goldMine[%num].type = "goldMine";  
	$mapLayer.goldMine[%num].isRightClickable = true;  

	
}

after I looked back at that I realized setting an isSelectable and isRightClickable flag was probably my best bet lol...

again a combined method seems the most efficient so it probably would have been a good idea for me to set it up like that... then again there might be a better way to do it
#10
09/09/2005 (9:26 am)
You can now get this tutorial along with 9 others in a T2D "Tutorial Pack"... in this pack each tutorial is an external html file so you can use them offline :)
#11
12/12/2005 (11:15 am)
Matt... I'm not sure what's wrong. I was going through the tutorial fine, until the part where you have to put the box on-screen. The box just simply will not show up. I have "simpleMouse();" in the client.cs where I'm to put my own code. I typed everything exactly as you said. In the end, I even copied and pasted the entirety of your code up to that point into simpleMouse.cs. That should have ensured that everything was exact and perfect to your specifications. However, it still didn't display a box. I deleted the dso files to make sure it was actually recompiling the scripts. It did in fact recompile them. No error is displayed in the console. I feel stupid for messing up this early in this simple tutorial, but I just simply don't know where I messed up. Again, I copied and pasted all of your code (I typed it out at first), and the mouse tracking worked fine. I'm using T2D 1.1a. Is this code compatable with it? (I used the version of the tutorial in TDN)
#12
12/13/2005 (10:58 pm)
Ok, so everyone knows, there was a 1.1a error in the tutorial that used to be correct in version 1.0.2 of T2D.

$test = new fxStaticSprite2D() { sceneGraph = t2dSceneGraph; };

should be:

$test = new fxStaticSprite2D() { sceneGraph = t2dScene; };

I'm sure this will be fixed soon after I make this post, but in case any of you failed at this tutorial in the past using the new version of Torque, that may be the issue you ran into. Thank you Matt, for helping me with this.