I am learning morphic with the intent of using it to teach my SO's son how to program. He REALLY wants to program games, but he doesn't have a clue about it at all, and I thought using morphic in an OO-logo fashion would be a very nice start...
I'm not familiar w/ morphic at all, so I was happy to see that there is finally some documentation for beginners out there. Very cool. But I have some further questions.... (some of these may be obvious to those more experienced w/ morphic... I'd be happy to collect the results and put them on someone's swiki)
1) I wrote a method called touches: which is based on some of the logic in moveTowards: in order to have a test for collisions (which has obvious value to a 9 year old programmer-wannabe). I am now able to create a cat and mouse simulation where the cat can catch the mouse and make it attack (the mouse turns red when touched, the cat makes a noise when it touches). But the mouse code would be better if he could detect if ANY cat is touching him... Can it?
checkBleeding | blood normal | blood _ (Color r: 1.0 g: 0 b: 0). normal _ (Color r: 0 g: 0 b: 1.0).
(self touches: (self class refPlayer61)) " <--- here is the problem" ifTrue: [ self setColor: blood ] ifFalse: [ self setColor: normal ]! !
2) I don't understand the model too well... From the debug menu, I learn that the mouse is an instance of StarMorph. But when I edit one of his methods it is an instance of a subclass of Player... Is this an analog to View and Controller?
3) Is there a registry of known players in a given morph? (possibly a shorter version of #1).
4) I assume that the costumes are akin to sprites? That way I could have several different costumes for a spaceship or car and have it rotate through them??? How?
5) Is there some clean way to get all my changes saved to a text file? I found the save morph, but they are at least partial binary files...
6) Any way to automatically clean or not generate these:
!Player5 methodsFor: 'anonymous scripts'! xxxScript7 ^ self! !
7) I can name a player in the debug menu, can I have something rename the class?
Ryan Davis -=- Zen Spider Software -=- mailto:zss@ZenSpider.com -=- http://www.ZenSpider.com/ -=- I know that you believe you understand what you think I said but, I'm not sure you realize that what you heard is not what I meant.
At 12:00 AM -0800 11/9/98, Ryan Davis zss@ZenSpider.com wrote:
- I wrote a method called touches: which is based on some of the logic in
moveTowards: in order to have a test for collisions (which has obvious value to a 9 year old programmer-wannabe). I am now able to create a cat and mouse simulation where the cat can catch the mouse and make it attack (the mouse turns red when touched, the cat makes a noise when it touches). But the mouse code would be better if he could detect if ANY cat is touching him... Can it?
checkBleeding (self touches: (self class refPlayer61)) " <--- here is the problem" ifTrue: [self setColor: blood] ifFalse: [ [self setColor: normal]
If you make every cat be a monochrome object of the same distinguished color, then the method #seesColor: will do exactly what you want, and, even better, it will do it not by comparing bounding boxes but by actually looking for pigment overlap.
Moreover, you can do this script entirely within the tile-scripting regime, if you prefer. The script would be:
TEST mouse isOverColor catColor YES mouse's color <- bloodColor NO mouse's color <- normalColor
(however, sketches don't have a single "color", so the "mouse's color <- bloodColor" assignment will only work if your mouse is *not* costumed as a SketchMorph; you could use a Polygon or curve instead).
Aside: general collision-detection will be coming soon.
------
- I don't understand the model too well... From the debug menu, I learn
that the mouse is an instance of StarMorph. But when I edit one of his methods it is an instance of a subclass of Player... Is this an analog to View and Controller?
The same Player can at various times wear various different costumes. Each costume can belong to a different subclass of Morph. The Player abstraction allows code and identity to be borne by something that remains the same amidst the potential swirl of changing costumes.
As long as your're simply constructing surface graphics, you'll operate entirely in a world of morphs. Whenever you wish to script a morph, a Player subclass is created for you, and it's that Player subclass that bears all the scripting code.
(The Player is somewhat analogous to Model, the Morph (aka Costume) to View/Controller.)
-----
- Is there a registry of known players in a given morph? (possibly a
shorter version of #1).
Yes, but it's maintained under the covers. When you construct scripts for a given Player, every other Player that is referenced by the those scripts is kept track of; that's what the refPlayerxxx things are about.
You can also define your own instance variables, of type "player", which hold on to references to specific other objects, and you can set their values by direct manipulation if desired. If it's not obvious how to do all of this, please holler.
-----
- I assume that the costumes are akin to sprites? That way I could have
several different costumes for a spaceship or car and have it rotate through them??? How?
The standard technique for doing this at present is to have the collection of variant costumes reside in a PasteUpMorph that you're using as a "holder". To do this, get a PasteUpMorph (playfield) and choose "behave like a holder" from its "playfield options" submenu. Place the variant costumes within it.
To get an object (e.g. a "spaceShip") to animate by switching from one to another of the variant costumes, use a script patterned after the following:
holder's cursor <- holder's cursor + 1. spaceShip look like holder's valueAtCursor
The idea is that the "cursor" is an index into the holder's collection of subparts; holders's "valueAtCursor" is a reference to the element in the holder that is currently "selected". The "look like" script says for its receiver to wear a costume that resembles the costume worn by that selected element of the holder.
-----
- Is there some clean way to get all my changes saved to a text file? I
found the save morph, but they are at least partial binary files...
The short answer here is no -- not yet, anyway. The scripts often refer to specific objects (e.g. "car move toward trafficLight") and this is not very straightforward to represent in a naked fileout. The morphic "save files" are in essence persistent objects.
------
- Any way to automatically clean or not generate these:
!Player5 methodsFor: 'anonymous scripts'! xxxScript7 ^ self! !
An "anonymous script" is a script created on your behalf (through your work with tiles) which has not been "named and saved", and has not yet deleted.
Our idea here is that it's just too blocking to the imagination if you have to think up a name for a script before you can play with it and see how it behaves. So we support the idea of constructing scripts without names. Internally, of course, they have to have *some* name, since they're represented by actual Smalltalk methods. Thus the xxxScriptn methods.
To get rid of such methods, just delete the corresponding Scriptors (by hitting their pink "X" dismiss buttons). If you're seeing scripts like the one you mention, they're obviously empty, which means that graphically they are script shells that currently have no tiles in them.
If you're seeing such vacuous methods lingering in your image even though you thought you'd deleted the scripts, it's probably because you didn't delete the scripts using the pink "X" on the Scriptor. A lingering bug in the system is that if you delete a script-editor by any other technique (e.g. hitting its "dismiss" halo handle or dragging it to the trash), the corresponding method is not deleted. This is obviously something that we need to fix!
------
- I can name a player in the debug menu, can I have something rename the
class?
No, sorry. For the moment, the "reality" is the actual objects on the screen and their palpable state and behavior. The oddly-named classes are privately maintained under the covers to support that external reality. As we move forward with our scripting experiments, we are conscious of the need for a convergence between the user-illusion reality and the under-the-covers reality.
(Incidentally, note that to name a player, you should either do it in a Viewer [click on the player's name at the top of the viewer, backspace to delete unwanted characters, and type the name you want] or in the object's halo [click on the name at the base of the halo, etc]. I believe that the ability to name the object in the "debug" menu is a throwback to earlier times that operates outside the scripting regime and probably will not do everything you hope it will.)
------
Thanks for your interest in our early experiments in morphic scripting. Obviously, this work is in a preliminary state; it does a few things well and many other things not-so-well or not-at-all. At the moment, it's much more suited for the presentation of suggestive demos in the hands of people who already know precisely what they're doing, and not really well-suited at all to the true novice user, nor to the accomplished Smalltalk programmer who wants to be able to remain in complete control of everything. As time goes on, we intend to evolve this facility outward in both of these directions.
-- Scott
[major snip]
Thanks for your interest in our early experiments in morphic scripting. Obviously, this work is in a preliminary state; it does a few things well and many other things not-so-well or not-at-all. At the moment, it's much more suited for the presentation of suggestive demos in the hands of people who already know precisely what they're doing, and not really well-suited at all to the true novice user, nor to the accomplished Smalltalk programmer who wants to be able to remain in complete control of everything. As time goes on, we intend to evolve this facility outward in both of these directions.
Very cool. Thanks for the very complete reply... Yes collision detection would be very nice. I will soon require something more complete than the current facilities allow (detecting one color only, or based on color alone, is not sufficient for a 9 year old (for more than 10 minutes)).
The demo/doc was very easy to go through and helped a lot. W/O it, I have simply been avoiding morphic... (and downloading very boring ports of logo for the mac). I assume that a couple more features and I can do everything _I_ can think of that a 9 yo would want initially... Noises, color, custom graphics, movement and interaction. If I can get collision detection (incl. knowledge of WHAT I touched), and possibly a more complete physics model (mass and velocity!!!), I can rock this kid's world...
Ryan Davis -=- Zen Spider Software -=- mailto:zss@ZenSpider.com -=- http://www.ZenSpider.com/ -=- I know that you believe you understand what you think I said but, I'm not sure you realize that what you heard is not what I meant.
scottw@wdi.disney.com wrote:
At 12:00 AM -0800 11/9/98, Ryan Davis zss@ZenSpider.com wrote:
- Is there a registry of known players in a given morph? (possibly a
shorter version of #1).
Yes, but it's maintained under the covers. When you construct scripts for a given Player, every other Player that is referenced by the those scripts is kept track of; that's what the refPlayerxxx things are about.
You can also define your own instance variables, of type "player", which hold on to references to specific other objects, and you can set their values by direct manipulation if desired. If it's not obvious how to do all of this, please holler.
HOLLER!!!!
I have a PasteUpMorph which has within it some buttons (RectangleMorphs with embedded and locked editable text) and a single "label" (StringMorph). I want the act of clicking on a button to change the value (contents) of the StringMorph. I gave the StringMorph a new instance variable called "value" and I've browsed the StringMorph and determined that it has a method called contents: which should be used to set its value but what I can't for the life of me figure out is how to reference the StringMorph.
I suspect this is becauase you're managing so much of the model "under the covers" as you said in your earlier message to Ryan Davis. But I do notice that it has an instance variable called contents which contains its displayed value. If I edit this value in an inspector and accept the change, though, the displayed value of the StringMorph doesn't change. (That didn't particularly _surprise_ me but it kept me in my quandary.)
While I'm at it, how, if at all, can I take a custom morph and put it into a Parts Bin so that I can later instantiate it anew? Or has morphic proceeded that far yet?
At 8:40 AM -0800 11/17/98, Dan Shafer wrote:
I have a PasteUpMorph which has within it some buttons (RectangleMorphs with embedded and locked editable text) and a single "label" (StringMorph). I want the act of clicking on a button to change the value (contents) of the StringMorph. I gave the StringMorph a new instance variable called "value" and I've browsed the StringMorph and determined that it has a method called contents: which should be used to set its value but what I can't for the life of me figure out is how to reference the StringMorph.
You can't (yet) do this directly using just tile scripts, but if you wish to edit your script textually, you need to be aware that in scripts, "self" is always a *player* and that all references to other objects are to other *players*; if you want to talk directly to a Morph, you get at it by sending the message "costume" to its associated player.
That's probably the lone missing piece of information you need to complete your example.
For completeness, I tried out two different ways to implement your example, and they both worked fine:
Suppose your button is named myButton and that it has one submorph inside it, namely that StringMorph, which you've named myLabel. Suppose further that the Player associated with your button has a string-valued instance variable named 'value' that you've already defined.
Then you could create a script for myButton, and tell it to be triggered on mouseUp, and name-and-save it. Now proceed to use either of the following two alternative techniques...
Technique One:
Make the script be "textually edited" and edit its script to say just
self costume submorphs first contents: value
(That'll do it. self is the player. "self costume" is the rectangleMorph; its first submorph is the label morph. value is the player's own string-valued instance variable defined by you, and #contents: sets the contents and does the change notification.)
Technique Two:
From the viewer of myLabel, drag a phrase -- any phrase, let's say "myLabel forward by 5", into the scriptor for your new myButton script. The point of this is just so that you can see how to refer to the myLabel guy in the script of the myButton guy, if you don't want to use the "submorphs first" circumlocution of technique one.
Having dragged such a phrase into the scriptor for your button script, now "edit it textually". You'll see in the textual version something like self class refPlayer3 forward: 5 The point of this is that it indicates that "self class refPlayer3" is the way the reference to the label player is encoded.
Using this knowledge, now you can edit the script so that it reads, instead,
self class refPlayer3 costume contents: value
Unlike the first technique, this one does not rely on the label being the first submorph of the button -- or indeed on its being a submorph of it at all.
Down the road -- hopefully not too *far* down the road -- we want to have a smoother way that you can transition from the point-and-click, drag-and-drop immediacy of the tile-scripting to the full power of smalltalk scripting without the awkwardnesses required in the above two examples.
------
...But I do notice that it has an instance variable called contents which contains its displayed value. If I edit this value in an inspector and accept the change, though, the displayed value of the StringMorph doesn't change. (That didn't particularly _surprise_ me but it kept me in my quandary.)
This is just a matter of change notification not taking place when you smash a new value into an instance variable in an Inspector. If, in that same Inspector, after you've submitted a new value for the StringMorph's contents, you evaluate "self changed", you'll immediately see the StringMorph change as you were expecting. This will not a problem programatically, because you'd send a message like "aStringMorph contents: 'xxx'", and StringMorph's #contents: method issues the change notification.
------
While I'm at it, how, if at all, can I take a custom morph and put it into a Parts Bin so that I can later instantiate it anew? Or has morphic proceeded that far yet?
Yes, it's altogether possible (that's the point of the "custom parts bin") but in 2.2 it's still rather awkward to do -- among other things, you have first to tell the parts-bin-page in question to stop being a parts-bin-page, then add the thing you want, then tell it to resume being a parts-bin-page, etc. In 2.3, coming out soon now, it will be very much more straightforward to add any objects to a parts bin, so I suggest you wait for that.
-- Scott
squeak-dev@lists.squeakfoundation.org