
At this lesson we will work with two "pieces" that are walls for a virtual house creation.
You know that, for each piece, you need to create a folder having the name of the piece and a subfolder Textures. So: please download these files:
After this you need to create a new Class for each piece: Wall12x7x1 and WallWindow12x7x1 - capitalized.
Here we have something new! We are defining two "instanceVariableNames": inControl and tframe. A variable defined inside a method is valid only for this method. An "instance variable" can receive a value in some method of the Class and this value will be valid at any other method of an instance of this Class.
TIP: To define a variable valid at ALL THE INSTANCES of a Class we put its name at: "classVariableNames".
We need to define - like ever - for each Class, 3 methods - we call them the "3-basic-methods" :
handlesKeyboard: pointer ^ true.
The 2nd method:
handlesPointerDown: pointer ^ true.
The 3th method:
isComponent ^ true.
ATTENTION: We will not repeat this in the next lessons. Remember to define this 3 methods for each piece!!!
For the first piece the "initialize" method will be:
initialize
super initialize.
tframe := (TLoad3DSMax new initializeWithFileName:
(FileDirectory pathFrom:
{FileDirectory default pathName. 'Content'. 'wall12x7x1'. 'wall12x7x1.ase'})
scale: 0.1 shadeAngle: 90.1 textureMode: GLReplace) frame.
tframe collapse.
tframe boundsDepth: 3.
tframe initBounds.
self addChild: tframe.
tframe objectOwner: self.
inControl := false.
CODE COMMENTS
The "initialize" for the other piece is similar:
initialize
super initialize.
tframe := (TLoad3DSMax new initializeWithFileName:
(FileDirectory pathFrom:
{FileDirectory default pathName. 'Content'. 'wallWindow12x7x1'. 'wallWindow12x7x1.ase'})
scale: 0.1 shadeAngle: 90.1 textureMode: GLReplace) frame.
tframe collapse.
tframe boundsDepth: 3.
tframe initBounds.
self addChild: tframe.
tframe objectOwner: self.
inControl := false.
Now, the action begins!
Each one of our pieces can be moved in the space, in "execution time" to be placed in the adequate position : "pointing" (mouse-over, not click) it and pressing a keyboard keys. We are defining a covention for these keys:
If the piece has an "action" the basic key to press is "P". By example, imagine a wall having a door; this door can be opened and closed "mouse-overing" it and pressing "P". If a piece has many actions we will define other keys ("O", "K", "L" etc.)
The key "R" is to create, "on the fly", a copy of this piece .
IMPORTANT:
To add this interactivity for each piece, we need to define, for each, the method keyDown: pointer:
keyDown: pointer | c | c := pointer event2D keyCharacter. "To move X+" c = $w ifTrue:[ tframe translation: tframe translation+( tframe localTransform column1*0.5). inControl := true. ]. "To move X-" c = $s ifTrue:[ tframe translation: tframe translation-( tframe localTransform column1*0.5). inControl := true. ]. "To turn left" c = $a ifTrue:[ tframe addRotationAroundY:-1. inControl := true. ]. "To turn right" c = $d ifTrue:[ tframe addRotationAroundY: 1. inControl :=true. ]. "To go up:Y+" c = $z ifTrue:[ tframe translation: tframe translation+( tframe localTransform column2*0.5). inControl := true. ]. "To go down (oops!):Y-" c = $x ifTrue:[ tframe translation: tframe translation-( tframe localTransform column2*0.5). inControl := true. ]. "To move Z+" c = $c ifTrue:[ tframe translation: tframe translation+( tframe localTransform column3*0.5). inControl:= true. ]. "To move Z-" c = $v ifTrue:[ "Z-" tframe translation: tframe translation-( tframe localTransform column3*0.5). inControl := true. ]. "To create a clone". (c = $r) ifTrue:[ tframe:=Wall12x7x1 new. self addChild:tframe. tframe translationX: 50 y: 0 z: -50. inControl := true. ].
CODE COMMENTS
When we refer to "column2", we are talking about one unit of distance in the Y axis. And "column3" is for the Z axis. The statements using these methods will move the piece 0.5 of one unit - half "croq-foot".
We need to write an IDENTICAL method in the Class of the other piece. Like the movement depends also of the "pointing" (mouse-over) over the piece, the keys are the same for any piece, or copy of a piece, because we have local variables and methods .
TIP: Creating a clone, press the "r" key very quickly or you will create many clones!
OK. We have now the 2 pieces defined here and "the base" defined in the previous lesson. We need to put all these pieces inside the Private space/area, using the method initializeDefaultSpace of the Class Private. Look the code to do this:
| space base w1 wW1 | "Create a new space" space := TSpace new. "Make a light" self makeLight: space. "Adding the base - position defined inside the piece" base:=BasePlate70x3x70 new. space addChild:base. "Adding the pieces - positions defined here" w1:=Wall12x7x1 new. space addChild:w1. w1 translationX: 5 y: 0 z: 10. wW1:=WallWindow12x7x1new. space addChild:wW1. wW1 translationX: 20 y: 0 z: -10. ^space.
CODE COMMENTS
And here usual "script-for-Workspace" that "do-itize" the 2D window etc. etc. This doesn't change...
pV:= Private new. win:= SystemWindow new. lf:= LayoutFrame new. lf leftFraction:0. lf rightFraction:1. lf topFraction:0. lf bottomFraction:1. win setLabel: 'PRIVE'. win addMorph: pV fullFrame:lf. win openInWorldExtent: 500@500. pV requestInitialSpace.
Doing the exercice, you can move the 2 pieces in the space. Really, at this lesson you don't have any orientation about the "adequate" positions of these 2 pieces. It's only an exercice... The "general idea" presented in this course is the creation of sceneries having a set of pieces downloaded and a map having the adequate positions of them , like you receive in a LEGO box for the construction of a LEGO set. At this moment you have only 2 pieces, 2 types of walls. You don't have yet a wall-having-a-door and any piece to be the ceiling of a room. We will see in the next lesson how we can create a door that opens and closes using the "action" key (P).
Look some figures of our walls in the space:
PREVIOUS LESSON NEXT LESSON T. CONTENTS HOMEPAGE
