<?xml version="1.0" encoding="UTF-16"?>
<rss version="2.0"><channel><title>SoftXML | DIRECTOR Tutorials</title><link>http://www.softxml.com/rss/tutorials/director.xml</link><description>Tutorials</description><pubDate>Sun, 11 Jan 2009 14:27:50 EST</pubDate><language>en-us</language><image><title>SoftXML | DIRECTOR Tutorials</title><url>http://www.softxml.com/images/rsscategory.gif</url><link>http://www.softxml.com/rss/tutorials/director.xml</link><width>80</width><height>73</height></image><item><title>Introduction to Games with Director 8.5</title><link>http://www.softxml.com/LearnTutorial.asp?id=46184132387&amp;f=director&amp;fo=tutorials</link><description>&lt;P&gt;This is a tutorial about the use of Director and &lt;B&gt;3ds max&lt;/B&gt;
to create 1st person 3D worlds.
&lt;P&gt;It's not a tutorial for beginners. You need to know the basics of Director, &lt;B&gt;3ds 
		max&lt;/B&gt;
and programming with Lingo.
&lt;P&gt;
3D web design is a new-old world. Or: a "rediscovered" world.
&lt;P&gt;
In the beginings of the Web (1995), Mark Pesce did some experiments, trying to 
create VRML. But (better not to talk about the reasons) he was not successful. 
Now, the big players of the SW market (ADOBE, Macromedia, Microsoft etc.) are 
begining the 2d round. Who knows the future... We like digital 3D and we hope 
3D web will have its chance.
&lt;P&gt;&lt;BR&gt;
	&lt;FONT face="Arial" color="red" size="2"&gt;DON'T READ THIS TUTORIAL!&lt;/FONT&gt;
&lt;P&gt;This tutorial is not only to be readed. You need, at each lesson, &lt;B&gt;to make&lt;/B&gt;
the exercice/demo. This is the right way to really learn.
&lt;P&gt;&lt;BR&gt;
	&lt;FONT face="Arial" color="red" size="2"&gt;
		&lt;P&gt;
		DOUBTS? USE THE FORUMS.&lt;/FONT&gt;
&lt;P&gt;We know that it's not the &lt;B&gt;ideal&lt;/B&gt; tutorial for &lt;B&gt;your level&lt;/B&gt;. This &lt;B&gt;ideal&lt;/B&gt;
tutorial doesn't exist.
&lt;P&gt;If you have some doubt, try the User to Users Forums from &lt;A href="http://www.macromedia.com/support/director/"&gt;
		Macromedia&lt;/A&gt;
. There are many qualified people that can help you. We also read the Forums 
and can help sometimes.
&lt;P&gt;&lt;BR&gt;
	&lt;FONT face="Arial" color="red" size="2"&gt;THE &lt;B&gt;3dD WORLD&lt;/B&gt; SITE STYLE&lt;/FONT&gt;
&lt;P&gt;
I'm not an english speaker/writer. I'm not a designer. I am only a programmer 
trying to have fun with 3D web. So: our site has a style: bad english and ugly 
design. But I hope you will have fun too. Thanks and stay with us.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=46184132387&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>CREATING AN AVATAR </title><link>http://www.softxml.com/LearnTutorial.asp?id=34892700484&amp;f=director&amp;fo=tutorials</link><description>&lt;FONT face="Arial" color="blue" size="3"&gt;CREATING AN AVATAR&lt;/FONT&gt;
&lt;br/&gt;&lt;br/&gt;The code of the next three lessons is based (we made some modifications)in 
	studies from&lt;br/&gt; Anthony Rowe and Gareth Bushell from the design group: &lt;B&gt;squid soup&lt;/B&gt;
.
&lt;br/&gt;&lt;br/&gt;
	Our basic idea (a little different from their ideas - they are creating a car 
	running) is to create 1st person web worlds. Funny games... Or art galleries... 
	Or virtual malls...

&lt;br/&gt;&lt;br/&gt;
	In this kind of world the "point-of-view" is the eye of the user, the eye of 
	the player - if we have a game.

&lt;br/&gt;&lt;br/&gt;In multiuser 3D worlds we have the &lt;B&gt;avatar&lt;/B&gt;&lt;br/&gt; that represents the player. In 
	the future we will try to create multiuser worlds but now, we will create an 
	invisible avatar and put a &lt;B&gt;camera&lt;/B&gt; in his eyes.

&lt;br/&gt;&lt;br/&gt;
	In this lesson we will only create the avatar and try to learn how to move him. 
	The camera will stay fixed, looking for the world. In the next lesson, the 
	camera will go to the eyes of the avatar.

&lt;br/&gt;&lt;br/&gt;
	I hope you have readed the Help of 3ds max. We will not talk about the basics.

&lt;br/&gt;&lt;br/&gt;
	I hope you have readed also the Help of Director.

&lt;br/&gt;&lt;br/&gt;If you did this things it's possible that you discover a terrible fact:&lt;br/&gt; &lt;FONT color="red"&gt;
		in Director, the positive Y axis points up; in 3ds max the positive axis points &lt;I&gt;away&lt;/I&gt;
		from you and the positive Z points up!&lt;/FONT&gt; .

&lt;br/&gt;&lt;br/&gt;We choose the traditional Cartesian standard and we will need to make some 
	"magic", transforming the &lt;B&gt;max&lt;/B&gt; views.

&lt;br/&gt;&lt;br/&gt;
	&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd1-1.jpg" width=300/&gt;&lt;/CENTER&gt;

&lt;br/&gt;&lt;br/&gt;
	It&amp;#8216;s not easy to do this every project and our sugestion is: the creation of a 
	basic world that will be open and re-saved in the begining of each project.

&lt;br/&gt;&lt;br/&gt;
	My sugestion also is that: in every lesson of this tutorial you try to make the 
	exercice that is our 3D demo. In this lesson, the world is only a floor, and 
	something that you can imagine like a primitive, basic avatar (a red box).

&lt;br/&gt;&lt;br/&gt;Important: the avatar needs to have a name: &lt;B&gt;avatar&lt;/B&gt;
, that will be used inside Director.
&lt;br/&gt;&lt;br/&gt;We need to export the &lt;B&gt;3ds max&lt;/B&gt; world to a format&lt;br/&gt; that Director can import, 
	a &lt;I&gt;.W3D&lt;/I&gt; file. In the &lt;A href="http://www.discreet.com/products/3dsmax/exporter/register/" target="_blank"&gt;
		Discreet site&lt;/A&gt; we can download (it&amp;#8216;s free) a plugin that do it. It&amp;#8216;s 
	very easy to install and you need to read the documentation.

&lt;br/&gt;&lt;br/&gt;When we import a &lt;I&gt;.W3D&lt;/I&gt; file, it goes to the &lt;B&gt;cast&lt;/B&gt;. In our case we 
	will change its name to: &lt;B&gt;world&lt;/B&gt; .
&lt;br/&gt;&lt;br/&gt;A 3D world in Director is a &lt;B&gt;sprite&lt;/B&gt; of a normal Director "movie", but the 
	movie is in &lt;B&gt;loop&lt;/B&gt; repeating the same frame forever :-)

&lt;br/&gt;&lt;br/&gt;
	We can glue a script to the world/movie. This script will run when the movie 
	starts.

&lt;br/&gt;&lt;br/&gt;
	Scripts not glued to frames or to the world can be created and need to be 
	called by one of this scripts.

&lt;br/&gt;&lt;br/&gt;To create a script we can open a window selecting &lt;B&gt;Window | Script&lt;/B&gt; . To 
	create another script we use the + button.

&lt;br/&gt;&lt;br/&gt;
	&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dir5-2.jpg" width=300/&gt;
	&lt;/CENTER&gt;
	The script that will run when the world is "loaded" needs to have the name: &lt;B&gt;setupscript&lt;/B&gt;:
	&lt;PRE&gt;global myworld
global avatarobj, cameraobj 

on preparemovie me
 setupobjects &lt;B&gt;-- look  how we put comments in the script&lt;/B&gt;

end

on setupobjects
 clearglobals 
 member("world").resetworld()
 myworld = member("world")
  
 avatarobj = new(member("avatarobj").script)
  
 cameraobj = new(member("cameraobj").script) 
  
end 
&lt;/PRE&gt;

&lt;br/&gt;&lt;br/&gt;The name of the imported world will be &lt;B&gt;myworld&lt;/B&gt; in the script - could be 
	another....

&lt;br/&gt;&lt;br/&gt;We are creating two external scripts: &lt;B&gt;avatarobj&lt;/B&gt; and &lt;B&gt;cameraobj&lt;/B&gt; that 
	is called here.
&lt;br/&gt;&lt;br/&gt;The &lt;B&gt;cameraobj&lt;/B&gt; script:
	&lt;PRE&gt;property mycam  --the camera  
 
global avatarobj,myworld

on new me
 
  mycam = myworld.camera[1]
  mycam.projectionangle = 40 
  mycam.transform.position=vector(-2.88,-150.0, 41.20) - position of the camera 
  mycam.transform.rotation=vector(80.00,0.43, -3.61)
 return me
  
end
&lt;/PRE&gt;

&lt;br/&gt;&lt;br/&gt;A block &lt;B&gt;new&lt;/B&gt;
is executed in the first time when the script is called.
&lt;br/&gt;&lt;br/&gt;Here we define &lt;B&gt;mycam&lt;/B&gt; using a basic object/array of Director.
&lt;br/&gt;&lt;br/&gt;We said that a 3D world is a sprite in a frame in loop. The script glued to this 
	frame (can be the frame 10 if we create an 2D introduction) .
	&lt;PRE&gt;global avatarobj

on exitFrame me
  go the frame
end

on prepareframe me
 control avatarobj - go to method control of script avatarobj 
end 

&lt;/PRE&gt;

&lt;br/&gt;&lt;br/&gt;
The statement in the first method/event creates the loop.
&lt;br/&gt;&lt;br/&gt;When the frame is "beginning" the part &lt;B&gt;control&lt;/B&gt;&lt;br/&gt; - we will see it soon - of 
	the script &lt;B&gt;avatarobj&lt;/B&gt; is executed. This is the more important part of our 
	application.
&lt;br/&gt;&lt;br/&gt;The &lt;B&gt;avatarobj&lt;/B&gt; script:
	&lt;PRE&gt;property fwvect, upvect, distanceforward, steer
global myworld

on new me
  upvect = vector(0,1,0) -- up is Y  
  fwvect = vector(1,0,0)  
  distanceforward = 0
  steer = 0
 return me
end


on control me
  if keypressed(126) then  --uparrow
    acc = 0.025
  else
    acc = 0
   end if 
  
  if keypressed(124) then  --rightarrow
    turn = 2    
  else
    if keypressed(123) then  --leftarrow
      turn = -2
    else
      turn = 0
    end if
  end if 
  
  distanceforward = distanceforward + acc - 0.015
  
  if distanceforward &amp;lt; 0 then distanceforward = 0
  if keypressed(125) then  distanceforward = - 0.8
  if distanceforward &amp;gt; 0.8 then distanceforward = 0.8
  
  steer = (steer + turn)*0.8
  if steer &amp;lt; -5.0 then steer = -5.0
  if steer &amp;gt; 5.0 then steer = 5.0  
  
  &lt;FONT color="blue"&gt;--  turning  the avatar
  myworld.model("avatar").transform.rotate(myworld.model("avatar").worldposition, upvect, steer, #self)&lt;/FONT&gt;

  &lt;FONT color="green"&gt;--  translating the avatar
  rotator = transform()
  rotator.rotate(vector(0,0,0), upvect, steer) 
  fwvect = rotator*fwvect
  movement = ( fwvect*distanceforward )
  myworld.model("avatar").translate(movement ,#world)&lt;/FONT&gt;

end
&lt;/PRE&gt;

&lt;br/&gt;&lt;br/&gt;Our target is: &lt;B&gt;when the player press one arrow key (123 or 124 or 125 or 126) the 
		avatar makes a translation or a rotation.&lt;/B&gt;
&lt;br/&gt;&lt;br/&gt;Director has two methods for this:
	&lt;PRE&gt;&lt;B&gt;
  &lt;I&gt;obj&lt;/I&gt;.transform.rotate(&lt;I&gt;position,axis,angle&lt;/I&gt;,#self)
 
  &lt;I&gt;obj&lt;/I&gt;.translate(&lt;I&gt;fwvect*distancefoward&lt;/I&gt;, #world)&lt;/B&gt;

&lt;/PRE&gt;

&lt;br/&gt;&lt;br/&gt;&lt;B&gt;self&lt;/B&gt; and/or &lt;B&gt;world&lt;/B&gt; are&lt;br/&gt; the referenced system of coordinates.
&lt;br/&gt;&lt;br/&gt;The basic axis : Y, for rotation is defined by a vector: &lt;B&gt;vector(0,1,0)&lt;/B&gt; .
&lt;br/&gt;&lt;br/&gt;&lt;B&gt;translate&lt;/B&gt; needs a vector that defines the&lt;br/&gt; direction (&lt;B&gt;vector(1,0,0)&lt;/B&gt; 
	), multipled by the increment in distance.
&lt;br/&gt;&lt;br/&gt;The &lt;B&gt;world&lt;/B&gt; needs to be draged from the cast to the stage (to the frame 
	that has the loop script). Only this :-)
&lt;br/&gt;&lt;br/&gt;&lt;FONT color="red"&gt;We can change the background color and the ambient light in the 
		world, using the &lt;B&gt;Property Inspector&lt;/B&gt;&lt;/FONT&gt;
&lt;br/&gt;&lt;br/&gt;
	&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dir5-3.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=34892700484&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>THE AVATAR AND THE THE CAMERA </title><link>http://www.softxml.com/LearnTutorial.asp?id=32160184539&amp;f=director&amp;fo=tutorials</link><description>&lt;P&gt;In this lesson we will glue the camera to the "avatar". 
&lt;P&gt;First thing: we build an object (we call it &lt;B&gt;aux&lt;/B&gt;) and glue the camera 
to it. It&amp;#8216;s created using: &lt;PRE&gt;aux.myworld.new model("aux")
&lt;/PRE&gt;
&lt;P&gt;We make it invisible: &lt;PRE&gt;aux.visibility = #none
&lt;/PRE&gt;In the loop, we glue &lt;B&gt;aux&lt;/B&gt; to the avatar. And the camera to 
&lt;B&gt;aux&lt;/B&gt;. When the player moves the avatar (we saw how to do this in the 
previous lesson) he moves the camera. 
&lt;P&gt;&lt;FONT color=red&gt;It&amp;#8216;s important to note that we are talking about "avatar" but 
our world is not multiplayer and doesn&amp;#8216;t exist an avatar : only a camera.&lt;/FONT&gt; 

&lt;P&gt;To make the glues we use a Director method: &lt;PRE&gt;&lt;B&gt;&lt;I&gt;obj1&lt;/I&gt;.interpolate(obj2.getworldtransform(),&lt;I&gt;lag&lt;/I&gt;)&lt;/B&gt;
&lt;/PRE&gt;
&lt;P&gt;This method moves a model (obj1) from its current position to the position of 
another object (obj2). &lt;B&gt;lag&lt;/B&gt; is the time to move. If we use lag=100 the 
obj1 seems to be strongly glued. If we use lag=10 this gives a fluity to the 
movement of the camera. 
&lt;P&gt;We make the avatar invisible too. 
&lt;P&gt;In the new world of this lesson, the graphic part is similar and the script 
&lt;B&gt;setupscript&lt;/B&gt; is the same of the previous lesson. 
&lt;P&gt;The difference in the script &lt;B&gt;avatarobj&lt;/B&gt; is a line to make the "avatar" 
invisible: &lt;PRE&gt;&lt;B&gt;myworld.model("avatar").visibility = #none &lt;/PRE&gt;&lt;/B&gt;
&lt;P&gt;The script of the loop runs a new part of the script &lt;B&gt;cameraobj&lt;/B&gt;: &lt;PRE&gt;on prepareframe me
  global avatarobj, cameraobj 
  
  control avatarobj
  &lt;B&gt;control cameraobj&lt;/B&gt;
end

on exitFrame me
  go the frame
end 
&lt;/PRE&gt;
&lt;P&gt;And the script &lt;B&gt;cameraobj&lt;/B&gt; has many new lines: &lt;PRE&gt;property mycam   
property aux  
property cameraoffset  

global avatarobj,myworld

on new me
  aux = myworld.newmodel("aux")
  mycam = myworld.camera[1]
  
  aux.visibility = #none
  mycam.projectionangle = 65 
  cameraoffset = [5,-50]
   
  return me  
end


on control me 
   
  aux.transform.interpolateto(myworld.model("avatar").getworldtransform(), 100)
  camvect = (avatarobj.upvect*cameraoffset[1]+   avatarobj.fwvect*cameraoffset[2])
  aux.translate(camvect, #world)
  
   
  aux.pointat(myworld.model("avatar").worldposition ) 
  lag = 100
   mycam.transform.interpolateto(aux.getworldtransform(), lag)  
end
&lt;/PRE&gt;
&lt;P&gt;Save, publish etc. etc. You can play the demo using the arrow keys. 
&lt;P&gt;The height (defined by &lt;B&gt;cameraoffset = [5,-50]&lt;/B&gt;) and velocity of 
avatar/camera can be changed.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=32160184539&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>COLLISION AGAINST THE TERRAIN </title><link>http://www.softxml.com/LearnTutorial.asp?id=18862567650&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;The secret tool to define collision of the avatar against anything is the method &lt;B&gt;modelsUnderRay&lt;/B&gt;
	of the Director API. Its declaration is:
	&lt;PRE&gt;alist = myworld.modelsUnderRay(&lt;I&gt;locationVector , directionVector &lt;/I&gt; , 5, #detailed)
&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;
	&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dir9-1.jpg" width=300/&gt;
	&lt;/CENTER&gt;
	The method returns a array of arrays. Each line of the main array has details 
	of the objects found under a ray drawn from the position specified by &lt;I&gt;locationVector&lt;/I&gt;
	and pointing in the direction of &lt;I&gt;directionVector&lt;/I&gt;
. The max number of objects/models to be found is 5 in our declaration but can 
be changed.
&lt;br/&gt;&lt;br/&gt;For each object found we have a array with properties that can be called by 
	name:
	&lt;PRE&gt;&lt;B&gt;
      alist[i].name  -         the name of the object found 
      alist[i].distance -      the distance from the  position 
                               of the avatar to the point of 
                               intersection with the object.
      alist[i].isectposition - is a vector representing the  
                               position of the  intersection.
      alist[i].isectNormal -   is the  &lt;B&gt;normal&lt;/B&gt; vector to the mesh 
  &lt;/B&gt;                             at the point of intersection.
&lt;/PRE&gt;

&lt;br/&gt;&lt;br/&gt;Do you remember what is a &lt;B&gt;normal&lt;/B&gt;
to a surface? OK. Congratulations. Good hight school :-)
&lt;br/&gt;&lt;br/&gt;The idea is to create a method &lt;B&gt;seekfloor&lt;/B&gt; that has the parameters:
	&lt;UL&gt;
		&lt;LI&gt;
			the avatar name (defined in &lt;B&gt;3ds max&lt;/B&gt;);
		&lt;/LI&gt;
		&lt;LI&gt;
			the name of the object that is "the floor" (defined in &lt;B&gt;3ds max&lt;/B&gt;);
		&lt;/LI&gt;
		&lt;LI&gt;
			the height of the camera (eye of the avatar).&lt;/LI&gt;&lt;/UL&gt;
&lt;br/&gt;&lt;br/&gt;This method returns an array with 3 elements:
	&lt;UL&gt;
		&lt;LI&gt;
		a flag=1 if a point-of-intersection was found - the floor ends in some place 
		:-)&lt;/LI&gt;
		&lt;LI&gt;
		the angle of the slope;&lt;/LI&gt;
		&lt;LI&gt;
			the vector of the &lt;B&gt;normal&lt;/B&gt; in this point.&lt;/LI&gt;&lt;/UL&gt;
&lt;br/&gt;&lt;br/&gt;
This "return" is received at each loop and we need to translate and rotate the 
avatar.
&lt;br/&gt;&lt;br/&gt;Play the demo. All the codes are after the demo. Walking, look back to see that 
	you are &lt;B&gt;on&lt;/B&gt;
the floor, going up or down.
&lt;br/&gt;&lt;br/&gt;OK.Play the demo (remember: the code is in this page, after the demo)

&lt;FONT face="Arial" color="red" size="2"&gt;THE CODE:&lt;/FONT&gt;
&lt;br/&gt;&lt;br/&gt;The &lt;B&gt;setupscript&lt;/B&gt;
is the same.
&lt;br/&gt;&lt;br/&gt;In the &lt;B&gt;avatarobj&lt;/B&gt; script we have the new method:
	&lt;PRE&gt; 
property fwvect
property upvect  

property distanceforward 
property steer  
property ang, xvect,avatarheight  
global myworld 

on new me
   
  upvect = vector(0, 1,0)
  fwvect = vector(0,0,1)
  xvect = vector(1,0,0)
  distanceforward = 0
  steer = 0
  myworld.model("avatar").visibility = #none
  myworld.model("avatar").translate(vector(0,0,0),#world) -- put it at a height above the ground
  
  &lt;B&gt;--for collision versus terrain
  xvect = vector(1,0,0)
  ang = 0 
  avatarheight = 15
  --&lt;/B&gt;
  
  return me
  
end


on control me
  if keypressed(126) then   
    acc = 0.025
  else
    acc = 0
   end if 
  
  if keypressed(123) then   
    turn = 2
    
  else
    if keypressed(124) then   
      turn = -2
      
    else
      turn = 0
    end if
  end if 
  
  distanceforward = distanceforward + acc - 0.015
  
  if distanceforward &amp;lt; 0 then distanceforward = 0 
  if keypressed(125) then  distanceforward = - 0.8 
  if distanceforward &amp;gt; 0.8 then distanceforward = 0.8
  
  steer = (steer + turn)*0.8
  if steer &amp;lt; -5.0 then steer = -5.0
  if steer &amp;gt; 5.0 then steer = 5.0  
  
  myworld.model("avatar").transform.rotate(myworld.model("avatar").worldposition, upvect, steer)
  
  rotator = transform()
  rotator.rotate(vector(0,0,0), upvect, steer) 
  fwvect = rotator*fwvect
  movement = ( fwvect*distanceforward )
  myworld.model("avatar").translate(movement ,#world)
  
  &lt;B&gt;--for collision versus  terrain
   
  floordetails = seekfloor("avatar", "land", "world", avatarheight, upvect) 
  
  ang = 0
  
  if floordetails[1] = 0 then
   myworld.model("avatar").translate(-movement ,#world)
  else
    if floordetails[2] &amp;lt;&amp;gt; 0 then
      xvect = floordetails[2]
      ang = floordetails[3] 
    end if
  end if  
  myworld.model("avatar").transform.rotate(myworld.model("avatar").worldposition, xvect, ang)
  
end

&lt;FONT color="red"&gt;on seekfloor modelname, floorname, worldname, modelheight, directionvector
   
  flag = 0
  tiltangle = 0
  tiltvector = 0
  
  alist = myworld.modelsUnderRay(myworld.model(modelname).worldposition - directionvector*100  ,directionvector,5, #detailed)  
  
  repeat with i = 1 to count(alist)
    if alist[i].model.name contains floorname  then
       
      a = alist[i].isectposition
      
      av = vector(0,(-myworld.model(modelname).worldposition.y + alist[i].isectposition.y +modelheight ), 0)
      myworld.model(modelname).</description><guid>http://www.softxml.com/LearnTutorial.asp?id=18862567650&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>COLLISION: AVATAR x WALLS AND OTHER COLLISIONS </title><link>http://www.softxml.com/LearnTutorial.asp?id=11909391704&amp;f=director&amp;fo=tutorials</link><description>&lt;P&gt;Director has the usual system of "spheres of collision" for detection of the 
moment when two objects collide. We will talk a little about this in the lesson. 

&lt;P&gt;But first: we need to review a little "who is our avatar": 
&lt;P&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd6-1.jpg" width="300"&gt; &lt;/CENTER&gt;
&lt;P&gt;The values of: &lt;B&gt;avatarheight&lt;/B&gt;, &lt;B&gt;cameraoffset&lt;/B&gt; (2 values) and 
&lt;B&gt;projectionangle&lt;/B&gt; need sometimes to be redefined in a new project for the 
best precision of collisions of the avatar. 
&lt;P&gt;When we work detecting collision, the ideal values of &lt;B&gt;cameraoffset&lt;/B&gt; are 
something like: 0.001 and -0.003. The proportion between this values define the 
basic angle of the camera. If they are little, the camera and the object 
&lt;B&gt;aux&lt;/B&gt; (used to glue the camera to the avatar) are inside the avatar and the 
precision of the collision is better. 
&lt;P&gt;The collison between two objects are detected (there are some other 
techniques but this is the cheaper in machine cicles and is the Director 
default) using an sphere that is around the object. 
&lt;P&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd6-2.jpg" width="300"&gt; &lt;/CENTER&gt;. It's not a very precise method but 
works. 
&lt;P&gt;All the basic lines of code to work with the collision of an avatar are in 
the &lt;B&gt;avatarobj script/new&lt;/B&gt; 
&lt;P&gt;To an object, in a Director world be available for collision it needs to be 
declared in the lines of code: &lt;PRE&gt;  myworld.model("avatar").addmodifier(#collision)
  myworld.model("avatar").collision.enabled = true
  myworld.model("avatar").collision.resolve = true
&lt;/PRE&gt;
&lt;P&gt;If we are trying to administrate the collision of the avatar against the 
object/model: "ball", by example, this object needs also to be declared: &lt;PRE&gt; myworld.model("ball").addmodifier(#collision)
 myworld.model("ball").collision.enabled = true
 myworld.model("ball").collision.resolve = true
&lt;/PRE&gt;
&lt;P&gt;When an avatar collides with another model that has the #collision modifier 
attached, it will stop moving. 
&lt;P&gt;Sometimes this method of colliding "spheres" - the Director default - is 
inviable because the object is not like a sphere and we need to have an 
acceptable precision . In this case you need to add another line in the group 
(for each object and for the avatar): &lt;PRE&gt;myworld.model("avatar").collision.mode = #mesh
&lt;/PRE&gt;
&lt;P&gt;This technique spend lots of CPU time if the object is very complex (many 
polygons in the mesh). 
&lt;P&gt;There are the option #box if your object is near the box format. 
&lt;P&gt;We can capture some data in the moment of the collision if we define for an 
object (the avatar in our case): &lt;PRE&gt;  
  myworld.model("avatar").collision.setCollisionCallBack(#mydata,me) 
 &lt;/PRE&gt;
&lt;P&gt;&lt;B&gt;mydata&lt;/B&gt; is the name of a method that we need to create to use the data 
- could be another name: &lt;PRE&gt;on mydata me , collisionData
 -- we can use the properties of the collision to many things.
 put collisionData.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=11909391704&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>LIGHTS - SPOT </title><link>http://www.softxml.com/LearnTutorial.asp?id=46495281277&amp;f=director&amp;fo=tutorials</link><description>&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd8-1.jpg" width="300"&gt; &lt;/CENTER&gt;
&lt;P&gt;WOW! It's beautiful! 
&lt;P&gt;This lesson is the first of a serie about: lights in Director. 
&lt;P&gt;Director doesn&amp;#8216;t respect all the lights that you install in &lt;B&gt;3ds max&lt;/B&gt; 
like you are thinking that it does. Better to create a new system of lights by 
program, in Director. 
&lt;P&gt;There are many types of lights. We will talk, in this lesson about a 
"charming" type: the &lt;B&gt;spot&lt;/B&gt;. Lights of this type cast their light from a 
particular point and within the cone defined by the light&amp;#8216;s forward direction 
and the &lt;B&gt;spotAngle&lt;/B&gt; property. 
&lt;P&gt;To create a spot it&amp;#8216;s easy. In the method &lt;B&gt;setupobjects&lt;/B&gt; of the 
&lt;B&gt;setupscript&lt;/B&gt; put the lines: &lt;PRE&gt;  
-- Creating spot light
  myworld.newLight("spot1", #spot)
  sp1 = myworld.light("spot1")
  sp1.color = rgb(255, 255, 192)
  sp1.spotangle=80
  sp1.transform.position = vector(47, 10, 536)
&lt;/PRE&gt;
&lt;P&gt;The name of the spot is &lt;B&gt;spot1&lt;/B&gt;. But, defining properties, we will need 
to use the "complete-reference-of-the-object": &lt;B&gt;myworld.light("spot1")&lt;/B&gt;. 
So: we create a variable: &lt;B&gt;sp1&lt;/B&gt; to simplify. 
&lt;P&gt;We can&amp;#8216;t define the intensity of the light. But a funny resource is: we can 
put the cone-of-light in the direction of an object. 
&lt;P&gt;In our exercice, first: in &lt;B&gt;3ds max&lt;/B&gt; we create two "3D stars" with the 
names, defined inside &lt;B&gt;3ds max&lt;/B&gt;: &lt;B&gt;star1&lt;/B&gt; - the red and &lt;B&gt;star2&lt;/B&gt; - 
the yellow. 
&lt;P&gt;To put the cone-of-light in direction of &lt;B&gt;star1&lt;/B&gt; we use the lines of 
code: &lt;PRE&gt; 
 pstar1=myworld.model("star1").worldposition
 sp1.pointAt(pstar1)
&lt;/PRE&gt;&lt;BR&gt;&lt;FONT face=Arial color=red size=2&gt;TRICKS&lt;/FONT&gt; 
&lt;P&gt;It&amp;#8216;s not easy to discover the position (coordinates) where to "install" the 
spot. The trick is: use the avatar walking. In the &lt;B&gt;timestep&lt;/B&gt; script we 
write the statement:&lt;PRE&gt;put myworld.model("avatar").worldposition
&lt;/PRE&gt;
&lt;P&gt;Opening the window: &lt;B&gt;Message&lt;/B&gt; we , using the avatar walking to the point 
that we like to know, we can read the coordinates in the Message window. 
&lt;P&gt;Another trick that I use are the "auxiliary spheres". 
&lt;P&gt;Lights are not visible objects. I create a sphere only to help to define its 
position and effects. You can do it in &lt;B&gt;3 ds max&lt;/B&gt; - it&amp;#8216;s easyer - but I 
create it using Director comands and put it in the world - look in the figure: 
it&amp;#8216;s between the stars - the little one. And after this we can define the 
position of the spot using the sphere: The code to create an auxiliary sphere 
(in the &lt;B&gt;setupscript&lt;/B&gt;) is: &lt;PRE&gt;  --create aux-sphere
  myworld.newModelResource("ls", #sphere, #front)
  as = myworld.modelResource("ls")
  as.radius = 10.0
  myworld.newModel("ls", as)
  asm = myworld.model("ls")
  --using the aux-sphere like a reference
  asm.transform.position = vector(47, 10, 536)
  sp1.transform.position = asm.transform.position
&lt;/PRE&gt;
&lt;P&gt;There are another auxiliary sphere (the big one) in the point (0,0,0) - a 
very important point. Look in the figure. 
&lt;P&gt;&lt;BR&gt;&lt;FONT face=Arial color=red size=2&gt;CHANGING THE FOCUS&lt;/FONT&gt; 
&lt;P&gt;Only for fun, in the demo we can change the focus of the spot to each one of 
the stars. It&amp;#8216;s a code created in the &lt;B&gt;control&lt;/B&gt; method of the 
&lt;B&gt;avatarobj&lt;/B&gt; script : &lt;PRE&gt; 
 if keypressed("2") then 
    pstar2=myworld.model("star2").worldposition
    myworld.light("spot1").</description><guid>http://www.softxml.com/LearnTutorial.asp?id=46495281277&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>LIGHTS - POINT</title><link>http://www.softxml.com/LearnTutorial.asp?id=15757172465&amp;f=director&amp;fo=tutorials</link><description>&lt;P&gt;If you have a room or a cave etc. in your world, you need to install a light 
(or lights) inside it. There are the type: &lt;B&gt;point&lt;/B&gt;. This lights shine in 
all directions from a specific location in the 3D world. The effect is similar 
to a bare light bulb hanging in a room. 
&lt;P&gt;In our exercice/demo we have used auxiliary-spheres created in &lt;B&gt;3ds 
max&lt;/B&gt;. 
&lt;P&gt;The code is similar: &lt;PRE&gt;-- Create point lights
  l1=myworld.model("light1") --light1 is the name of aux-sphere in max
  l1.visibility = #none
  myworld.newLight("pt1", #point)
  pt1Light = myworld.light("pt1")
  pt1Light.color = rgb(4, 155, 176)
  pt1Light.transform.position = l1.transform.position
&lt;/PRE&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face=Arial color=red size=2&gt;AVATAR DRIVING A CAR&lt;/FONT&gt; 
&lt;P&gt;A &lt;B&gt;bonus&lt;/B&gt; in this lesson: 
&lt;P&gt;If you have some large terrain, walk is not a good option. You can put your 
avatar in a car! 
&lt;P&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd9-1.jpg" width="300"&gt; &lt;/CENTER&gt;
&lt;P&gt;Realy we only change the variable &lt;B&gt;avatarheight&lt;/B&gt; and the value of the 
acceleration added when the player press the up-arrow-key. 
&lt;P&gt;In this case, the &lt;B&gt;inercia&lt;/B&gt; doesn't stops the "car" if the player is not 
pressing the key. He needs to press the down-arrow key to stop or go back. 
&lt;P&gt;&lt;FONT face=Arial color=red size=2&gt;CHANGING THE AVATAR VELOCITY&lt;/FONT&gt; 
&lt;P&gt;A "human being" has a limit of walk velocity. But in the 3D worlds you can 
make the avatar to run sometimes irreally. 
&lt;P&gt;How the velocity of the avatar is defined? 
&lt;P&gt;In the &lt;B&gt;avatarobj&lt;/B&gt; script we have the variable: &lt;PRE&gt;                       acc = 0.025
&lt;/PRE&gt;
&lt;P&gt;Each time the player press the up/down arrow keys &lt;B&gt;0.025&lt;/B&gt; is &lt;FONT 
color=red&gt;added&lt;/FONT&gt; to the avatar&amp;#8216;s velocity. 
&lt;P&gt;But, in the line of code; &lt;PRE&gt;distanceforward = distanceforward + acc - 0.015
&lt;/PRE&gt;we can imagine that &lt;B&gt;0.015&lt;/B&gt; is an &lt;B&gt;inertia factor&lt;/B&gt; against the 
aceleration, subtracted every loop-timestep.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=15757172465&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>STAIRS AND THE 3dD BASIC KIT </title><link>http://www.softxml.com/LearnTutorial.asp?id=33292566150&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;In previous demo (lesson about spot lights) there was a stair and you saw 
that our code that covers collisions against the terrain is good enough to our 
avatar goes up in the stair. Why? 
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd7-3.jpg" width="300"/&gt; &lt;/CENTER&gt;
&lt;br/&gt;&lt;br/&gt;Because the avatar sends rays continualy to redefine his position in the Y 
axis. Look at the figure. At moment &lt;B&gt;2&lt;/B&gt; the point of contact changes up. 
So: the avatar jumps to a new position. Realy the avatar does not collide 
against the floor. His position is recalculed every loop-timestep to be just 
"flying" over the floor. Very funny :-) 
&lt;br/&gt;&lt;br/&gt;But realy important in this lesson is that we will make a total review of all 
we have seeing in out tutorial until now, presenting the complete code of an 
standard/basic application. Is the &lt;FONT color="red"&gt;3dD Basic Kit&lt;/FONT&gt;, a group 
of code that you can use like a first step in all projects. Because we have in 
the kit: 
&lt;br/&gt;&lt;br/&gt;
&lt;UL&gt;
&lt;LI&gt;the creation of an avatar;&lt;/LI&gt; 
&lt;LI&gt;how to move him;&lt;/LI&gt; 
&lt;LI&gt;the instalation of the camera in the avatar's eyes;&lt;/LI&gt; 
&lt;LI&gt;control of his collision against the terrain;&lt;/LI&gt; 
&lt;LI&gt;control of his collision against walls; and general collision; &lt;/LI&gt;&lt;/UL&gt;
&lt;br/&gt;&lt;br/&gt;It&amp;#8216;s usual that, if you are making a 1st person world, you will need this 
things in your project. 
&lt;br/&gt;&lt;br/&gt;The general schema of the &lt;B&gt;3dD Basic Kit&lt;/B&gt; is: 
&lt;br/&gt;&lt;br/&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd7-2.jpg" width="300"/&gt; &lt;/CENTER&gt;
&lt;br/&gt;&lt;br/&gt;1 - We have first of all a &lt;B&gt;SETUPSCRIPT&lt;/B&gt; where we declare the 
&lt;B&gt;world&lt;/B&gt; and call two sub-scripts: &lt;B&gt;avatarobj&lt;/B&gt; and &lt;B&gt;cameraobj&lt;/B&gt;: &lt;PRE&gt;&lt;FONT color="magenta"&gt;
global myworld
global avatarobj, cameraobj 
on preparemovie me
 setupobjects
end

on setupobjects
 clearglobals 
 member("world").resetworld()
 myworld = member("world")
  
 avatarobj = new(member("avatarobj").script)
  
 cameraobj = new(member("cameraobj").script) 
  
end 
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;In the &lt;B&gt;AVATAROBJ&lt;/B&gt; sub-script we define: 
&lt;UL&gt;
&lt;LI&gt;the main loop (control) that is called by the &lt;B&gt;timestep&lt;/B&gt; script -in the 
frame where is the world;&lt;/LI&gt; 
&lt;LI&gt;the translation and rotation of the avatar using arrow keys;&lt;/LI&gt; 
&lt;LI&gt;the collision of avatar against the terrain using the &lt;B&gt;seekfloor&lt;/B&gt; 
method;&lt;/LI&gt; 
&lt;LI&gt;the colision of the avatar against walls and other objects&lt;/LI&gt;&lt;/UL&gt;
&lt;br/&gt;&lt;br/&gt;&lt;PRE&gt;&lt;FONT color="green"&gt;
 
property fwvect
property upvect  

property distanceforward 
property steer  
property ang, xvect,avatarheight  
global myworld 

on new me
  upvect = vector(0, 1,0)
  fwvect = vector(0,0,1)
  distanceforward = 0
  steer = 0
  myworld.model("avatar").visibility = #none
    
  --for collision
  xvect = vector(1,0,0)
  ang = 0 
  avatarheight = 40 
  --
  
  --for wall collision
  myworld.model("avatar").addmodifier(#collision)
  myworld.model("avatar").collision.enabled = true
  myworld.model("avatar").collision.resolve = true
  myworld.model("avatar").collision.mode = #mesh 

  myworld.model("logo").addmodifier(#collision)
  myworld.model("logo").collision.enabled = true
  myworld.model("logo").collision.resolve = true 
  myworld.model("logo").collision.mode = #mesh 
  return me
  
end


 
on control me
  
 
  --avatar movements
  if keypressed(126) then   
    acc = 0.025
  else
    acc = 0
  end if 
  
  if keypressed(123) then   
    turn = 2
    
  else
    if keypressed(124) then   
      turn = -2
      
    else
      turn = 0
    end if
  end if 
  
  distanceforward = distanceforward + acc - 0.015
  
  if distanceforward &amp;lt; 0 then distanceforward = 0  
  if keypressed(125) then  distanceforward = - 0.8
  if distanceforward &amp;gt; 0.8 then distanceforward = 0.8
  
  --rotation of the avatar
  steer = (steer + turn)*0.8
  if steer &amp;lt; -5.0 then steer = -5.0
  if steer &amp;gt; 5.0 then steer = 5.0  
  myworld.model("avatar").transform.rotate(myworld.model("avatar").worldposition, upvect, steer)
  
  --translation of the avatar 
  rotator = transform()
  rotator.rotate(vector(0,0,0), upvect, steer) 
  fwvect = rotator*fwvect
  movement = ( fwvect*distanceforward )
  myworld.model("avatar").translate(movement ,#world)
  
   
  -- puting the avatar in the floor using data returned by seekfloor method 
  floordetails = seekfloor("avatar", "land", "world", avatarheight, upvect) 
  
  ang = 0
  
  if floordetails[1] = 0 then
    myworld.model("avatar").translate(-movement ,#world)
  else
     
  if floordetails[2] &amp;lt;&amp;gt; 0 then
     xvect = floordetails[2]
     ang = floordetails[3] 
    end if
  end if  
  
  myworld.model("avatar").transform.rotate(myworld.model("avatar").worldposition, xvect, ang)
  
end

--seekfloor method
on seekfloor modelname, floorname, worldname, modelheight, directionvector
  flag = 0
  tiltangle = 0
  tiltvector = 0
  
  alist = myworld.modelsUnderRay(myworld.model(modelname).worldposition - directionvector*100  ,directionvector,5, #detailed)  
  
   repeat with i = 1 to count(alist)
   
    if alist[i].model.name contains floorname  then
      a = alist[i].isectposition
      av = vector(0,(-myworld.model(modelname).worldposition.y + alist[i].isectposition.y +modelheight ), 0)
      myworld.model(modelname).translate(av, #world)
      ay = -directionvector
      tiltangle = -ay.anglebetween(alist[i].isectnormal)
      tiltvector = alist[i].isectnormal.perpendicularto(ay)
      flag = 1
      
      exit repeat     
    end if
  end repeat
  
  return [flag, tiltvector, tiltangle]  
end
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;In the sub-script &lt;B&gt;CAMERAOBJ&lt;/B&gt; we define: 
&lt;UL&gt;
&lt;LI&gt;an auxiliar object (aux) to glue the camera to the avatar;&lt;/LI&gt; 
&lt;LI&gt;another main loop - called also by &lt;B&gt;timestep&lt;/B&gt; - to translation of the 
camera like the avatar.&lt;/LI&gt;&lt;/UL&gt;&lt;PRE&gt;&lt;FONT color="#b000"&gt;
property mycam   
property aux  
property cameraoffset  

global avatarobj,myworld

on new me
  
  aux = myworld.newmodel("aux")
  mycam = myworld.camera[1]
  
  aux.visibility = #none
  mycam.projectionangle = 75 -- read about this properties in previous lesson
  cameraoffset = [0.0001, -0.0003]
 
  return me  
end

on control me 
   
  aux.transform.interpolateto(myworld.model("avatar").getworldtransform(),  100.0)
  camvect = (avatarobj.upvect*cameraoffset[1]+ avatarobj.fwvect*cameraoffset[2])
  aux.translate(camvect, #world)
  
   aux.pointat(myworld.model("avatar").worldposition ) 
  lag = 100
   mycam.transform.interpolateto(aux.getworldtransform(), lag)  
end
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;In the &lt;B&gt;TIMESTEP&lt;/B&gt; script installed in the frame where the world is 
&lt;UL&gt;
&lt;LI&gt;we create the loop and we call the &lt;B&gt;controls&lt;/B&gt; methods every 
loop-timestep;&lt;/LI&gt; 
&lt;LI&gt;we execute other actions started by triggers.&lt;/LI&gt;&lt;/UL&gt;
&lt;br/&gt;&lt;br/&gt;&lt;PRE&gt;&lt;FONT color="blue"&gt;
global avatarobj, cameraobj, myworld, trigger
 
on prepareframe me
  control avatarobj
  control cameraobj
    
end 

on exitFrame me
  go the frame

end
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;To start an action trigerred we have sometimes the Macromedia standard 
&lt;B&gt;behaviors&lt;/B&gt;: by example: 
&lt;UL&gt;
&lt;LI&gt;one &lt;B&gt;trigger behavior&lt;/B&gt; that detects the click ;&lt;/LI&gt; 
&lt;LI&gt;one &lt;B&gt;action behavior&lt;/B&gt; that jumps the movie to the marker whose name is 
&lt;B&gt;trigger&lt;/B&gt; where we have an script that sets some flag.&lt;/LI&gt;&lt;/UL&gt;
&lt;br/&gt;&lt;br/&gt;We will talk about this soon. 
&lt;br/&gt;&lt;br/&gt;The script &lt;B&gt;TRIGGER&lt;/B&gt; (there are not included in the kit) could be:&lt;PRE&gt;&lt;FONT color="red"&gt;
global avatarobj

on exitFrame me
  avatarobj.flagd=1
  go to "play"
  
end
&lt;/FONT&gt;&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;You need to understand very well this group of scripts that are the "soul" of 
the inteligence of all the &lt;B&gt;1st person worlds&lt;/B&gt; that you will make. 
&lt;br/&gt;&lt;br/&gt;&lt;BR&gt;&lt;FONT face="Arial" color="red" size="2"&gt;DOWNLOAD OF THE 3dD BASIC KIT&lt;/FONT&gt; 
&lt;br/&gt;&lt;br/&gt;The &lt;B&gt;3dD Basic Kit&lt;/B&gt; is the basic scenery where you can make the 
exercices of our tutorial. 
&lt;br/&gt;&lt;br/&gt;We have a basic &lt;B&gt;3ds max&lt;/B&gt; world: &lt;B&gt;kitb.max&lt;/B&gt; that is only a floor 
with an &lt;B&gt;auxiliary sphere&lt;/B&gt; to be used to put the spot-light to iluminate 
the logo. 
&lt;br/&gt;&lt;br/&gt;The Director world is: &lt;B&gt;kitb.dir&lt;/B&gt;. It has the four scripts that we are 
talking about: 
&lt;UL&gt;
&lt;LI&gt;setupscript&lt;/LI&gt; 
&lt;LI&gt;avatarobj&lt;/LI&gt; 
&lt;LI&gt;cameraobj and&lt;/LI&gt; 
&lt;LI&gt;timestep&lt;/LI&gt;&lt;/UL&gt;
&lt;br/&gt;&lt;br/&gt;Normaly you will put YOUR code in the &lt;B&gt;avatarobj&lt;/B&gt; script using one of 
the two methods: &lt;B&gt;new&lt;/B&gt; - for one-time execution code or &lt;B&gt;control&lt;/B&gt; - 
for code inside the timestep-loop. 
&lt;br/&gt;&lt;br/&gt;In our lessons we will use the &lt;B&gt;3dD Basic Kit&lt;/B&gt; like a pre-requirement 
for the exercices and make references to it.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=33292566150&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>AN AUTOMATIC DOOR - DISTANCETO AND INTERPOLATETO</title><link>http://www.softxml.com/LearnTutorial.asp?id=44108127362&amp;f=director&amp;fo=tutorials</link><description>&lt;P&gt;When you are near some automatic door, it opens.This fact has two parts: 
&lt;UL&gt;
&lt;LI&gt;"you are near": a &lt;B&gt;trigger&lt;/B&gt; 
&lt;LI&gt;"the door opens": an &lt;B&gt;action&lt;/B&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The usual triggers &lt;B&gt;in the 3D virtual life&lt;/B&gt; are:
&lt;UL&gt;
&lt;LI&gt;click or pointer-over an object 
&lt;LI&gt;press some key&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;But &lt;B&gt;Lingo&lt;/B&gt; has a method that let us know (returns) how far is the 
&lt;B&gt;distance&lt;/B&gt; between the avatar an some object; is the method: 
&lt;B&gt;distanceTo&lt;/B&gt;. 
&lt;P&gt;Better to say: &lt;B&gt;false distance&lt;/B&gt;. Look at the figure (the avatar and 
world are from out tutorial about ADOBE's Atmosphere that has the same method): 
&lt;P&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/falsedist0.jpg" width="300"&gt;&lt;/CENTER&gt;
&lt;P&gt;or more schematicaly: 
&lt;P&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/falsedist0a.jpg" width="300"&gt;&lt;/CENTER&gt;
&lt;P&gt;But this doesn't matter. The important is that we can capture the "distance" 
(&lt;B&gt;proximity&lt;/B&gt;) between two objects A and B using the lines of code: &lt;PRE&gt;  posA = myworld.model("A").worldposition 
  posB = myworld.model("B").worldposition
  dist = posA.distanceTo(posB)
&lt;/PRE&gt;
&lt;P&gt;In our exercice we will open a door using the &lt;B&gt;proximity&lt;/B&gt; from the 
avatar to a door. 
&lt;P&gt;But how to open the door? 
&lt;P&gt;Lingo has another method that we can use to do this: &lt;B&gt;interpolateTo&lt;/B&gt; 
&lt;P&gt;If we have two objects A and B, using the lines of code: &lt;PRE&gt; 
    tA = myworld.model("A").transform
    tB = myworld.model("B").transform
    tA.interpolateTo(tB, n)
     
&lt;/PRE&gt;inside a loop, A will go to the B transform (position + rotation) runing 
n% of the distance from A to B in each timestep. 
&lt;P&gt;Using the &lt;FONT color=red&gt;3dD Basic Kit&lt;/FONT&gt; we create in &lt;B&gt;3ds max&lt;/B&gt; a 
house and &lt;B&gt;two doors&lt;/B&gt;: a real, in the closed position, and a "ghost" in the 
open position. 
&lt;P&gt;The "distance" tested is between the avatar and the door. 
&lt;P&gt;Using the &lt;B&gt;3dD Basic Kit&lt;/B&gt; you need to add some lines of code in the 
&lt;B&gt;avatatobj&lt;/B&gt; script. In the &lt;B&gt;new&lt;/B&gt; method: &lt;PRE&gt;  
  myworld.model("house").addmodifier(#collision)
  myworld.model("house").collision.enabled = true
  myworld.model("house").collision.resolve = true
  myworld.model("house").collision.mode = #mesh
  
  
  myworld.model("door").addmodifier(#collision)
  myworld.model("door").collision.enabled = true
  myworld.model("door").collision.resolve = true
  myworld.model("door").collision.mode = #mesh 
  
  doorg = myworld.model("doorg") -- the ghost door
  doorg.visibility = #none
 &lt;/PRE&gt;
&lt;P&gt;In the &lt;B&gt;control&lt;/B&gt; method: &lt;PRE&gt;  
  pav = myworld.model("avatar").</description><guid>http://www.softxml.com/LearnTutorial.asp?id=44108127362&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>ROTATION - PART 1 </title><link>http://www.softxml.com/LearnTutorial.asp?id=35176903117&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;Why every tutorial about 3D has this infamous "rotating boxes"? I don&amp;#8216;t know. 
Perhaps because they are an easy example of rotation. 
&lt;br/&gt;&lt;br/&gt;In Director we have, for rotation: &lt;PRE&gt;&lt;I&gt;myworld&lt;/I&gt;.model("&lt;I&gt;object&lt;/I&gt;").transform.rotate(&lt;I&gt;myworld&lt;/I&gt;.model("&lt;I&gt;object&lt;/I&gt;"), upvect, r)&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;&lt;B&gt;upvect&lt;/B&gt; is the vector that defines the base axis of rotation. 
&lt;br/&gt;&lt;br/&gt;The important resource that Director has is that we can define the &lt;B&gt;pivot 
axis&lt;/B&gt; of the rotation. In our general statement above we used: 
&lt;I&gt;myworld&lt;/I&gt;.model("&lt;I&gt;object&lt;/I&gt;") like an argument defining that , the 
&lt;B&gt;pivot axis&lt;/B&gt; is in the center of &lt;I&gt;object&lt;/I&gt;. But think about a 
&lt;B&gt;pivoting door&lt;/B&gt;: the &lt;B&gt;pivot axis&lt;/B&gt; is not in the center of the door! We 
can create a &lt;B&gt;hinge&lt;/B&gt;. The center of the hinge will be the pivot axis. 
&lt;br/&gt;&lt;br/&gt;The most correct general statement for rotation is: &lt;B&gt;&lt;PRE&gt;&lt;I&gt;myworld&lt;/I&gt;.model("&lt;I&gt;object&lt;/I&gt;").transform.rotate(&lt;I&gt;myworld&lt;/I&gt;.model("&lt;I&gt;object of the axis of rotation&lt;/I&gt;"), upvect, r)&lt;/PRE&gt;&lt;/B&gt;
&lt;br/&gt;&lt;br/&gt;We will make a demo of a &lt;B&gt;pivoting door&lt;/B&gt; in the next lesson. Now, lets 
go to create our infamous "dancing cube". Really will be not a cube. We will 
rotate our plaque with logo. 
&lt;br/&gt;&lt;br/&gt;In our &lt;B&gt;3dD Basic Kit&lt;/B&gt; we have a script glued to the frame where is the 
sprite of the world. The &lt;B&gt;timestep&lt;/B&gt; script. We will put the code there: &lt;PRE&gt;on prepareframe me
 global avatarobj, cameraobj, &lt;FONT color="red"&gt;myworld&lt;/FONT&gt; 
  
 control avatarobj
 control cameraobj

  
   &lt;FONT color="red"&gt;myworld.model("logo").transform.rotate(myworld.model("logo").worldposition, avatarobj.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=35176903117&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>ROTATING OBJECTS - PART 2</title><link>http://www.softxml.com/LearnTutorial.asp?id=49603728571&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;Everybody likes to open doors in games. And this is a "pivoting door"!It has 
a &lt;B&gt;hinge&lt;/B&gt; and will be open by a click in the red button. 
&lt;br/&gt;&lt;br/&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd4-1.jpg" width="300"/&gt; &lt;/CENTER&gt;&lt;BR/&gt;&lt;FONT face="Arial" color="red" 
size="2"&gt;CLICKS IN 3D OBJECTS&lt;/FONT&gt; 
&lt;br/&gt;&lt;br/&gt;The first thing we need to learn is how to detect a click in a 3D object. 
&lt;br/&gt;&lt;br/&gt;Lingo has a powerful method to do this: &lt;B&gt;modelsUnderLoc&lt;/B&gt; 
&lt;br/&gt;&lt;br/&gt;We need to create a &lt;B&gt;sprite-script&lt;/B&gt; in the sprite that is "the world" 
(click in the score is an option to open a sprite-script). We will call this 
script:&lt;B&gt;trigger&lt;/B&gt;: &lt;PRE&gt;global avatarobj

on mouseUp me
 set=point(sprite(1).left,sprite(1).top)
 pt = the mouseLoc - set
  
  m = sprite(1).camera.modelsUnderLoc(pt, 3, #detailed)
  if m.count&amp;gt;2 then
   if  m[2].model.name ="but"  then 
    avatarobj.open=1 
   end if
  end if
  
end
&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;To understand how &lt;B&gt;modelsUnderLoc &lt;/B&gt;works you imagine a &lt;B&gt;ray&lt;/B&gt; 
(Macromedia loves rays and array of arrays...)that goes, from the camera to the 
point that was clicked in a "virtual window" in front of the 3D world and goes 
ahead to the infinitum. 
&lt;br/&gt;&lt;br/&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd4-2.jpg" width="300"/&gt; &lt;/CENTER&gt;
&lt;br/&gt;&lt;br/&gt;It returns all the objects it bores in an array of arrays (&lt;B&gt;m&lt;/B&gt;). Each 
array is for each object bored. 
&lt;br/&gt;&lt;br/&gt;Our camera is inside the avatar. The "avatar" will be the first object/model. 
The second array is for the object clicked. 
&lt;br/&gt;&lt;br/&gt;We test if the name of the object clicked is "but" (and set a flag) using: &lt;PRE&gt; if  m[2].model.name ="but"  then 
    avatarobj.open=1 
&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;We need to create the flag &lt;B&gt;open&lt;/B&gt; in the &lt;B&gt;avatarobj/new&lt;/B&gt; script. A 
good place to create flags and counters. 
&lt;br/&gt;&lt;br/&gt;And what happens if the flag &lt;B&gt;avatarobj.open&lt;/B&gt; is set to 1? Look to the 
new &lt;B&gt;timestep&lt;/B&gt; script: &lt;PRE&gt;global avatarobj, cameraobj, myworld 

on prepareframe me
  control avatarobj
  control cameraobj
  
   --to open the door
  if(avatarobj.open=0) then 
    sound(1).pause()
  else
    sound(1).play()
  end if
  
end 


on exitFrame me
   
  if( avatarobj.open=1 AND avatarobj.t&amp;lt;50) then      
    myworld.model("door").transform.rotate(myworld.model("hin").worldposition, avatarobj.upvect, 2)  
  if( avatarobj.open=1 AND avatarobj.t&amp;lt;51) then 
    set avatarobj.t = avatarobj.t + 1
  
  go the frame
  
end
&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;We rotate the door using the hinge like the basic axis. 
&lt;br/&gt;&lt;br/&gt;In the &lt;B&gt;avatarobj/new&lt;/B&gt; script we define the collision and the flag and 
counter. The added code is: &lt;PRE&gt;  myworld.model("house").addmodifier(#collision)
  myworld.model("house").collision.enabled = true
  myworld.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=49603728571&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>ART GALLERY 1 - LOOKING UP/DOWN</title><link>http://www.softxml.com/LearnTutorial.asp?id=42660802010&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;If you are an artist (and who is not?) you have some hidden works that now 
you can show to &lt;B&gt;the world&lt;/B&gt; creating your own 3D gallery. The visit can 
walk looking your works and, clicking, can go to a detailed description of it in 
other web page. 
&lt;br/&gt;&lt;br/&gt;In the first lesson of this serie we will learn how to make &lt;B&gt;the avatar&lt;/B&gt; 
to look up and down - to see all your beautiful work :-) 
&lt;br/&gt;&lt;br/&gt;Do you remember &lt;B&gt;who&lt;/B&gt; is the avatar? 
&lt;br/&gt;&lt;br/&gt;
&lt;CENTER&gt;&lt;IMG src="http://www.dmu.com/3dd/dd12a-1.jpg" width="300"/&gt;&lt;/CENTER&gt;
&lt;br/&gt;&lt;br/&gt;There are the variable: &lt;B&gt;cameraoffset&lt;/B&gt; that represents the position of 
the camera related to &lt;B&gt;aux&lt;/B&gt; and to the &lt;B&gt;avatar&lt;/B&gt; object. 
&lt;br/&gt;&lt;br/&gt;If we vary the elements of the array we can change the camera angle &lt;B&gt;and 
the vision of the avatar-player&lt;/B&gt;. 
&lt;br/&gt;&lt;br/&gt;We will use two keyboard keys to control this movement: &lt;B&gt;a&lt;/B&gt; and &lt;B&gt;z&lt;/B&gt; 
but you can choose another if you like. 
&lt;br/&gt;&lt;br/&gt;We will change the &lt;B&gt;cameraobj&lt;/B&gt; script of our &lt;B&gt;3dD Basic Kit&lt;/B&gt; (the 
new lines are bolded): &lt;PRE&gt;property mycam   
property aux  
property cameraoffset 
global avatarobj,myworld 
&lt;B&gt;property camy
property camx&lt;/B&gt;

on new me
  &lt;B&gt;camx = -0.002 
  camy = 0.001&lt;/B&gt;

  aux = myworld.newmodel("aux")
  mycam = myworld.camera[1]
  aux.visibility = #none
  mycam.projectionangle = 95 
  
  return me  
end

on control me
  
  &lt;B&gt;cameraoffset = [camx,camy]
  if keypressed("a") then
    camx = camx - 0.0015 
    camy = camy + 0.001
  end if 
  
  if keypressed("z") then
    camx = camx - 0.0015 
    camy = camy - 0.001
  end if&lt;/B&gt;   
  
  
  -- the same
  aux.transform.interpolateto(myworld.model("avatar").getworldtransform(),  100.0)
  camvect = (avatarobj.upvect*cameraoffset[1]+ avatarobj.fwvect*cameraoffset[2])
  aux.translate(camvect, #world)
  aux.pointat(myworld.model("avatar").worldposition ) 
  lag = 100
  mycam.transform.interpolateto(aux.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=42660802010&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>ART GALLERY 2 - CLICKING TO PAGE LINK </title><link>http://www.softxml.com/LearnTutorial.asp?id=19569152781&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;OK. I know that &lt;B&gt;Half-Life&lt;/B&gt; is great and &lt;B&gt;Warcraft&lt;/B&gt; is a nice tool 
to create new maps to play in the Internet. 
&lt;br/&gt;&lt;br/&gt;If you are only a teenager trying to have fun playing games using the 
Internet, Director looks like a poor tool to create games. 
&lt;br/&gt;&lt;br/&gt;For this teenager doesn&amp;#8216;t matter that, to play his new Half-Life map, the 
player needs to have a CD-ROM drive and the basic CD of the game. The game will 
not work in the future wireless web devices without CD-ROM players . 
&lt;br/&gt;&lt;br/&gt;This teenager doesn&amp;#8216;t know that &lt;FONT color="red"&gt;Internet is not Web!&lt;/FONT&gt;. 
Internet uses the TCP/IP protocol and Web uses the HTTP protocol (over TCP/IP). 
This means: &lt;B&gt;browser, web pages, links, e-commerce&lt;/B&gt; etc. 
&lt;br/&gt;&lt;br/&gt;The &lt;B&gt;Half-Life&lt;/B&gt; map can&amp;#8216;t be embedded in a Web page. The player can&amp;#8216;t 
click in a gun and go to a page where he can buy a gun like that :-) 
&lt;br/&gt;&lt;br/&gt;There are some methods in the Lingo language to make this interaction between 
&lt;B&gt;a Director movie and the Web&lt;/B&gt;. We will use: &lt;PRE&gt;            goToNetPage &lt;/PRE&gt;to go to a new web page if the internaut 
clicks "the painting in 3D gallery". This page can have details about the 
painting, a better image, how to buy it etc. etc. 
&lt;br/&gt;&lt;br/&gt;We have seen in &lt;A href="dd4.html" target="_blank"&gt;previous lesson&lt;/A&gt; how to 
capture the click in a 3D object using the method:&lt;B&gt;modelsUnderLoc&lt;/B&gt;. We will 
not re-explain the details. We will have a sprite-script &lt;B&gt;trigger&lt;/B&gt; that 
sets a flag: &lt;PRE&gt;global avatarobj

on mouseUp me
 set=point(sprite(1).left,sprite(1).top)
 pt = the mouseLoc - set
 m = sprite(1).camera.modelsUnderLoc(pt, 3, #detailed)
 if m.count&amp;gt;1 then
  if  m[1].model.name ="pic"  OR  m[2].model.name ="pic" then
  &lt;B&gt;avatarobj.link=1&lt;/B&gt; 
  end if
 end if

end
&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;The flag &lt;B&gt;link&lt;/B&gt; is created in the &lt;B&gt;avatarobj&lt;/B&gt; script but the action 
is in new lines of the &lt;B&gt;timestep&lt;/B&gt; script: &lt;PRE&gt;on exitFrame me
  &lt;B&gt;if(avatarobj.link=1)   then
    goToNetPage "http://www.moma.org", "_new"
   avatarobj.link= 0  
   end if &lt;/B&gt;
  
  go the frame
  
end
&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;The &lt;I&gt;targetName&lt;/I&gt; argument - &lt;B&gt;new&lt;/B&gt; in our case - is an optional HTML 
parameter that identifies the frame or window in which the page is loaded. 
&lt;br/&gt;&lt;br/&gt;If &lt;I&gt;targetName&lt;/I&gt; is a window or frame in the browser, gotoNetPage 
replaces the contents of that window or frame.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=19569152781&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>ART GALLERY 3 - CHANGING THE POINTER IMAGE </title><link>http://www.softxml.com/LearnTutorial.asp?id=28018319973&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;To change the pointer image you will make the player spend lots of CPU 
because the program will use the method/event:&lt;B&gt;on mouseWithin&lt;/B&gt; in the 
sprite script &lt;B&gt;trigger&lt;/B&gt; and the mouse is always over the world (that is the 
sprite). 
&lt;br/&gt;&lt;br/&gt;We will use the trick of &lt;B&gt;the ray&lt;/B&gt; of the &lt;B&gt;modelsUnderLoc&lt;/B&gt; method 
(the same used to capture clicks). 
&lt;br/&gt;&lt;br/&gt;The &lt;B&gt;trigger&lt;/B&gt; script now has two methods: &lt;PRE&gt;global avatarobj

&lt;B&gt;on mouseWithin me --to  capture the mouseover
  cursor(-1) -- the normal image

  set0=point(sprite(1).left,sprite(1).top)
  pt0 = the mouseLoc - set0
  m0 = sprite(1).camera.modelsUnderLoc(pt0, 3, #detailed)
  if m0.count&amp;gt;1 then
   if  m0[1].model.name ="pic"  OR  m0[2].model.name ="pic"  then
    cursor (280) -- the "finger" image
   end if
  end if

end&lt;/B&gt;

on mouseUp me --to capture the click 
 set=point(sprite(1).left,sprite(1).top)
  pt = the mouseLoc - set

  m = sprite(1).camera.modelsUnderLoc(pt, 3, #detailed)
  if m.count&amp;gt;1 then
   if  m[1].model.name ="pic"  OR  m[2].model.name ="pic" then
    avatarobj.link=1 
   end if
  end if

end
&lt;/PRE&gt;There are many pointer images numbers: &lt;PRE&gt;    0     No cursor set
 
   -1     Arrow (pointer) cursor
 
    1     I-beam cursor
 
    2     Crosshair cursor
 
    3     Crossbar cursor
 
    200   Blank cursor (hides cursor)

    254   Help

    256   Pencil

    280   Finger

    290   Closed hand

    291   No-drop closed hand

    292   Copy closed hand

    302   Zoom in

    303   Zoom out

    etc. etc.

&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;You can create a new image.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=28018319973&amp;f=director&amp;fo=tutorials</guid><category>director</category></item><item><title>LINKING 3D WORLDS </title><link>http://www.softxml.com/LearnTutorial.asp?id=21023232815&amp;f=director&amp;fo=tutorials</link><description>&lt;br/&gt;&lt;br/&gt;One of the problems of web 3D is: a "good" world will have many Mbs and the 
velocity of the Internet (until we have 2Mbps broadband) is not good enough to 
make the download in a confortable time. So: we need to break our game (or 
another kind of world) in many parts and to create a link between this levels 
(or &lt;B&gt;websodes&lt;/B&gt; - this is a new word :-) 
&lt;br/&gt;&lt;br/&gt;We have the method: &lt;PRE&gt;        gotoNetMovie "http://www.dmu.com/3dd/someworld.dcr"
&lt;/PRE&gt;to do this link. 
&lt;br/&gt;&lt;br/&gt;We cam design a "portal" (look in the demo) with a auxiliary-sphere that will 
be a target to a &lt;B&gt;distance&lt;/B&gt; method (we saw this technique in previous 
lesson of this tutorial): &lt;PRE&gt; 
 dist=myworld.model("avatar").worldposition.distanceTo(myworld.model("auxs1").worldposition)
 if dist&amp;lt;40 AND cross = 0 then 
  gotoNetMovie "http://www.dmu.com/3dd/redw.dcr" 
  cross = 1
 end if
&lt;/PRE&gt;
&lt;br/&gt;&lt;br/&gt;If we don&amp;#8216;t define a flag (&lt;B&gt;cross&lt;/B&gt; in our sample) we will have a bad 
loop an the link will not work well. 
&lt;br/&gt;&lt;br/&gt;&lt;BR/&gt;&lt;FONT face="Arial" color="red" size="2"&gt;ANOTHER FLOOR&lt;/FONT&gt; 
&lt;br/&gt;&lt;br/&gt;In our demo we have a gate (click the red button) to cross the chasm - a hole 
inside the "land". It is a new floor and we need to change the &lt;B&gt;seekfloor&lt;/B&gt; 
method to test it like a "new land". The changed part of the method is: &lt;PRE&gt;on seekfloor modelname, floorname, worldname, modelheight, directionvector
  flag = 0
  tiltangle = 0
  tiltvector = 0
  
  alist = myworld.modelsUnderRay(myworld.model(modelname).worldposition - directionvector*100  ,directionvector,5, #detailed)  
  
  repeat with i = 1 to count(alist)
     if alist[i].model.name contains floorname  &lt;FONT color="red"&gt;OR "gate"&lt;/FONT&gt; then
      a = alist[i].isectposition
      av = vector(0,(-myworld.model(modelname ...etc etc. etc.</description><guid>http://www.softxml.com/LearnTutorial.asp?id=21023232815&amp;f=director&amp;fo=tutorials</guid><category>director</category></item></channel></rss>
