View this PageEdit this PageAttachments to this PageHistory of this PageHomeRecent ChangesSearch the SwikiHelp Guide
Hotspots: Admin Pages | Turn-in Site |
Current Links: Cases Final Project Summer 2007

Team MOUSE: Through the Looking Glass

Ali Ihsan gtg846f
Jawwad Ahmad
Imran Chowdhury


Welcome to our Cases page in which we shall attempt to go over our project and attempt to give useful advice from a point when we have hindsight working for us.

The class project for Fall 2004 was designing a game much like Sims called Simtech which would allow you to simulate and control the live's of students at tech. The project by its description sounds rather open-ended and indeed it is meant to be so. However, it is essential that you come up with a good design when working with Wonderland (The 3D graphics world withing Squeak) otherwise prepare yourself for a world of trouble getting this at times moody environment to work with you.

This is meant to be a tutorial in design and general help in how to integrate with wonderland. But before that I think I shall start with pros and cons of whether to use wonderland in the first place. Keep in mind this is a choice you have to make relatively further on in the semester however if you don't design for it, it will provide serious integration issues.

Why do I Wonder?

The decision to use wonderland proved to be a bit like a double-edged sword. I will go over why we thought it would be useful and which of our thoughts ultimtely proved to be false.

We thought...

Turns out...

e.g. If say you have a student who has to leave a room. He should ideally walk towards the door, go through it. Then your code can change the room he is in. One would expect that is the order it would follow. However, wonderland scheduling is taking care in its own sweet time so you might find lines of your code executing when the animation hasn't arrived yet. Have no fear...doInOrder is your friend.

So you've read through the pros and cons and you like a good challenge. Then get ready, because this is about to get really challenging.

Enter the Dragon

So here's what our project finally looked like.

External Image

The doors would lead to different buildings or rooms depending on where you were...and would respond to clicks which as you shall soon see is easier said than done.

First things first, how'd we get the Wonderland to drop into the System Window. Here's the code:

sceneMorph _ BorderedMorph new.
sceneMorph color: Color yellow.
sceneMorph height: 400.
sceneMorph hResizing: #spaceFill.
camera _ wonder getDefaultCamera.
camMorph _ camera getMorph.
camMorph hResizing: #spaceFill.
camMorph vResizing: #spaceFill.

Where scene morph is the window you see with the Wonderland in it.

sceneMorph addMorph: camMorph.
window openInWorld extent: 800.0 @ 620.0.

And you're done. This was simple enough to do and provides a good idea on who any interaction with wonderland will take place. By using the provided API for it. It seems like an obvious enough point but just take our word for it, spend a lot of time getting familiar with the API because you will be using it a lot.

One major design issue with Wonderland is how to integrate it with your metadata for students and other actors. We made every student have_a WonderlandActor. So whenever you see a reference to model, it is a a getter for that students WonderlandActor. This might not have been the best idea in retrpspect. We should've extended the WonderlandActor class in the first place and associated all the data with it instead. But hindsight is 20/20 and we wanted to reuse the code from our previous submissions, design with that in mind from the beginning and you should be good.

Also, very very important word of caution (or two). Never modify the Wonderland class on its own, always extend it and make changes to it. The reasons for this are many but most importantly the Wonderland classes has a shared dictionary which for some inane reason will not be filed-out (even though it says it will) and without it any changes you make to the scene or ground actors will get lost.

How to....

Make the actors clickable and execute code:

addResponse: [:event | model getWonderland currentPerson: model asString]
to: 'leftMouseUp'.

Interesting thing to note is that you'll need to extend WonderLand (we called ours SimLand) to have a currentPerson model before you can do this. Even though the code will compile there is no way for a WonderlandActor to edit objects which it doesn't have a handle on.

addResponse: [:event | Transcript show: model getName , ' selected.';
to: 'leftMouseUp'.

Make sure to associate functions with MouseUp events because press events and click events are already predefined and at times the hashing will create issues in dynamic binding (only one or the other method associated will get executed).

This code is from our Person class which had a model (WonderlandActor). Also make sure that if you wish to set the name of a certain Actor (you should ideally name them the same name as the metadata) then use the setName: Method for the actor.

Hide the editor:

I know it was annoying for us to.

editor _ wonder getEditor.
editor hide.

Update statistics:

Make sure you all the String Morphs are accesible from the GUI and the metadata. After that it is as simple as changing the String contents of the String Morph. We used a method called refreshStatus to update all the morphs whenever a change was made.

nameStr contents: 'Name: ' , currentPerson name.
genderStr contents: 'Gender: ' , currentPerson gender.
locStr contents: 'Location: ' , currentPerson location.
cashStr contents: 'Cash: ' , currentPerson wallet asString.
majorStr contents: 'Major: '
, (currentPerson attribute: 'Major').
ageStr contents: 'Age: ' , (currentPerson attribute: 'Age') asString.
happyStr contents: 'Happiness: ' , (currentPerson factor: 'happiness') asString.
hungerStr contents: 'Hunger: ' , (currentPerson factor: 'hunger') asString.
stressStr contents: 'Stress: ' , (currentPerson factor: 'stress') asString.
knStr contents: 'Knowledge: ' , (currentPerson factor: 'knowledge') asString.
socialStr contents: 'Social Skills: ' , (currentPerson factor: 'social') asString.
gameStr contents: 'Game: ' , (currentPerson factor: 'game') asString

Make actors walk up to each other using Alarms:

Use alarms and schedulers to avoid having synchronization issues I talked about earlier.

| person lookAt goTo door otherDoor |
person _ currentPerson model.
world currentDoor = 'left'
ifTrue: [door _ world leftDoor model.
otherDoor _ world rightDoor model].
world currentDoor = 'right'
ifTrue: [door _ world rightDoor model.
otherDoor _ world leftDoor model].
world currentDoor = 'center'
ifTrue: [door _ world centerDoor model.
otherDoor _ world centerDoor model].
lookAt _ person pointAt: door duration: 1.
goTo _ person
place: #inFrontOf
object: door
duration: 1.
world wonder doInOrder: {lookAt. goTo}.
Transcript show: 'Walking to ' , door getName;
do: [self move]
at: world wonder getScheduler getTime + 2.1
inScheduler: world wonder getScheduler.
do: [person
place: #inFrontOf
object: otherDoor
duration: #rightNow]
at: world wonder getScheduler getTime + 2.1
inScheduler: world wonder getScheduler

This was a particularly tricky piece of code because in our design (and in Wonderland in general) you have to load all actors up and then hide and show them depending on the metadata. We achieved that as follows:

room _ world findLocation: aRoom.
people _ room persons.
things _ room items.
self hideAll.
do: [:aPerson | aPerson model show].
do: [:anItem | anItem model show].

Where persons and items were a bag containing all the person and items in that room. And the room was well...a room.

So back to the alarms, when we exited a door to the right we wanted the actor to appear back on the left (as would make sense). The Alarms helped us time things out (and yes required a lot of manual tweaking) so that the animation and the messages appeared at its alloted time.

The Achilles Heel

So enough nice talk, time to explain where we really got ourselves in over our heads. Don't expect to find models online which can be used easily. Wonderland is picky NAY bratty about which models it will use and what it will reject (as seen by the models appearing in white...yayyy!!!). Roaming around using the camera keys seems like a great idea but here's the issue. You have to manually postion every item/actor in the world from an origin point and short of pulling your hair out I suggest that you just leave the camera functions alone.

Saving and Loading was the single biggest issue we ran into. We tried everything from SmartRefStreams to SIXX and every other Object writer that we could. The problems lay in savind and loading the Wonderland Models which despite our best efforts we were not able to disassociate from one bag or the other. Be scared, be very scared. What you should it by hand. Make wrapper objects which contain only the date you wish to save, save them. Load them back and populate you game objects. Hack? maybe. Functional? you bet.

Lastly, the performance of Wonderland is kindof appalling whenever you run it with too many models. So for quick testing make sure you make a newTest initializer along with your new initializer. This will save you a ton of time, trust me.

Here's how we did it.

^ super new buildGUI: SimWorld newTest

where buildGUI was our initializer for our interface window.

and in newTest only define the models that you need to load to test a certain functionality.

wonder _ SimLand new.
self initLocations.
self initItems.
persons _ Bag new.
newFor: self
model: 'dragon.mdl'
named: 'Ali'
size: 1.6
moveTo: {0. 0. 0}.
Transcript clear

Only intializes the model which was my namesake as opposed to everyone in the world. If you don't to this get ready to fall in love with this screen...

External Image

There is no "I have another project" in Team

I could tell you the tragic tale of how team members will be your worst enemy at times. But to tell the truth its tricky to work with teams in general at times. People will find new and innovative ways to test your patience so make sure you have a good plan heading into this class. Get a team early, get to know them early so that you can be sure that they are reliable. And learn to work around unreliable members because like it or not you're gonna be seeing them a lot.

In our design, saving and loading proved to be our undoing. Simply, because of the way our references for Actors were associated with the metadate. It proved difficult to uncouple that relationship using any object writer which saves references to other objects. We'd probably have been better off extracting and saving the data as text ourselves and then parsing it in (yes, it really got that ugly) but you can't do all the work.

Here is a good discussion on how some good planning and organization by YOU can save you a migraine later in the semester.

Team work and Team roles

Teamwork plays a crucial role towards a successful implementation of SimTech incorporating Wonderland. Every team member has to be responsible for their function as the project continues to scale. We had 4 team members having 2 group members focusing on the user interface and overall functionality of the system including the various data structures and interactions. The other 2 group members went through the Wonderland tutorial and learned how to use the environment to come up with creative commands for game functionality such as positioning models (people, things, etc.) and various movements. The 2 members working on the basic system would incorporate the Wonderland commands into their code and integrate the two systems for launch. As one may notice 2 members are doing the same thing. Why have 2 group members focus on Wonderland and the other 2 focus on game functionality? We leveraged the concept of “Peer Programming” as one member would code as the other watched for errors. This helps reduce coding time as two members can come up with the idea and get to work. It allows less time to be unproductive as well as smaller chances of future error. By having two members being experts in the “core” system and having two Wonderland experts, the game was built with greater ease and scaled well with every upcoming Milestone.

Finally, our Final Turnin

Link to this Page