Lab 2 Exercises
Today's lab will involve constructing a model of a lift. Again we will be working almost entirely in DASM with the cloning and construction of objects as well as animation being the key focus.
Begin by loading up a blank environment with a window to work in:
~empublic/teaching/cs405/run lab2
Objects, Prototypes and Cloning
The first thing you might wish to do when making a lift model is make a lift and place it on the screen. The best way to do this is to take some existing object that is similar to what we want and then change it a bit. For this purpose there are some prototype objects that are incomplete but provide a template. Prototypes already exist for image objects and we have provided an image called 'lift.png' so all we need to do is make a clone of that prototype and make a few changes. Remember to select %dasm as the notation to use.
@lift = (new union (@prototypes image)
filename = "lift.png"
x = 100
y = 100
width = 100
height = 100
);
What we have done here is make a new object, combine that with an existing image object and then change a few parameters. 'union' is what does the copy of everything in the object on the right-hand-side to the object on the left. You can chain several unions together to combine lots of objects. x and y give the position on the screen of the top left corner of the image in pixels. Now let's put this on the screen:
@screen mylift = (@lift);
We have also provided an image called 'floor.png'. It is possible to clone the lift to make a floor:
@screen floor1 = (new union (@lift)
filename = "floor.png"
x = 200
width = 400
);
Now clone this floor and change y to make 4 other floors. It would be a good idea to give y a definition such that each floor is always below the other.
Making the Lift Act Like A Lift: Animation
Since we are making a lift we would like it to be controlled and behave like a lift. So instead of having to worry about its pixel position we simply want to control which floor it is on. This can be done by giving y a definition that depends on some floor observable by converting a floor into pixels. There are a few ways to do this but try the following first and see if you can think of a better way:
@lift offsety = 100;
@lift floor = 0;
@lift y is {
select (.floor) {
0: { .offsety + 400 }
1: { .offsety + 300 }
2: { .offsety + 200 }
3: { .offsety + 100 }
4: { .offsety }
}
};
offsety is used to give the distance the top floor is from the top of the screen (you could give this a definition to actually link it with the top floors position). Now try changing the value of floor to check that the lift jumps around correctly. Let's try and get this more realistic before adding buttons and doors. What we really need is for the lift to move smoothly at a certain speed between floors instead of teleporting.
So when floor is changed the lift will need to move up or down at a certain speed until it reaches that floor. Eventually this will involve modifying the definition of y but first we need to know things like desired speed, direction and whether it has arrived at the floor or not:
@lift speed = 20.0;
Has it arrived at the floor?:
@lift atfloor is {
.y < (.floor_pix + 2) and (.y > (.floor_pix -2))
};
To work this out we needed to know the pixel location of the floor:
@lift floor_pix is { 400 - (.floor * 100) + (.offsety) };
Something else we need to know is the direction the lift should move in:
@lift direction is {
if (.y < (.floor_pix)) 1.0 else -1.0
};
Finally, we can now re-define y using the above to make it move smoothly between floors:
@lift y is {
if (.atfloor not) {
.y + (.direction * (.speed) * (@root itime))
} else {
.y
}
};
Try this out by changing the floor observable. Also try changing floor before it has reached the floor you last sent it to and see what happens. Each individual definition above has been kept small because of the way it has been split up into several smaller and meaningful observables. The similarity to spreadsheet modelling can be seen with this example. The most important definition to understand is the final one for y. This definition refers to itself but what it is actually doing is refering to the last known value of itself and then using that in a formula to calculate its next value. Such a definition will update constantly as fast as the machine can do it because one of the things it depends on will always change (itself). For this reason we use itime which is the time in seconds between each update cycle so that we can control how fast it appears to move independent of how fast the machine is.
Advanced: Extend the Model
Extend the model to include buttons on each floor and 5 buttons in the lift. Come up with definitions for 'floor' which decide, based upon which buttons have been pressed, which floor to go to next. You may also want to add doors and people.
Experiment and ask questions.