[Ohrrpgce] Slice tutorial

James Paige Bob at HamsterRepublic.com
Mon Jan 19 09:12:10 PST 2009


On Sat, Jan 17, 2009 at 10:30:32AM -0800, Adam Perry wrote:
>    James,
> 
>    I see the documentation for the new slice commands in the xml plotdict.
>    Two things, though:
> 
>    - The business of containers, slices, and such isn't intuitive. Could you
>    (or someone) create a short tutorial explaining, minimally, how to get a
>    sprite on the screen and manipulate it?
>    - All of these commands need to find their way into the wiki as well.
>
>    I'm sure I'm not the only one who's excited about slices but doesn't know
>    where to start.


Well, lets start here.

A slice is a rectangular thing. It has an X/Y position, a Width and a 
height, and it can be attached to the screen (root) or it can be 
attached to any other slice.

A great way to get used to what slices are capable of is to try out the 
"Screen Layout Editor" in custom. Right now it is not yet actually 
capable of being used to lay out screens, but it does let you connect 
slices together and see what happens when you move them around or resize 
them.

Anyway, on to coding examples. Suppose you want to put a large enemy 
sprite on the screen.

  variable(sl)
  sl := load large enemy sprite(0)

We have now added a slice containing a copy of large enemy sprite #0 to 
the slice tree. The slice tree gets redrawn automatically, all we need 
to do is add things to it, and move them around. Here is how we move a 
slice:

  set slice x(sl, slice x(sl) + 10)

That moves the sprite 10 pixels to the right.

You may notice in the plotscripting dictionary that there are two sets 
of functions for working with slice x and y

 "slice x" "set slice x"
 "slice y" "set slice y"
 "slice screen x" "set slice screen x"
 "slice screen y" "set slice screen y"

At first glance these might seem to be totally redundant. Indeed, if you 
check out the values for our newly loaded large enemy sprite, you will 
notice that the x/y and screen x/screen y are the same.

The difference is, the slixe x/y values are relative to the slice's 
parent. Every slice has a parent. When we first load a sprite, the 
default parent for it is "sprite layer" which is a "special" slice. the 
sprite layer slice has an x/y of 0,0 and a width/height of 320,200 just 
the same size as the screen.

One of the really cool things about slices is that you can attach them 
to parents. For example, lets load a small enemy sprite that resembles a 
top-hat and put it on the large enemy sprite we loaded before.

  variable(hat)
  hat := load small enemy sprite(0)
  set parent(hat, sl)
  set slice x(hat, 23)
  set slice y(hat, -28)

I'm just guessin on the x/y here, because I don't know  exactly where 
the head of your large enemy sprite will be, but the point is that we 
have detached the hat sprite from the screen, and attached it to the 
large enemy sprite. Now if we say:

  set slice y(sl, slice y(sl) + 5)

then BOTH the enemy sprite AND his hat will move together.

Now suppose that in this way we have set up 5 different enemy sprites, 
each of them wearing a hat. That makes a total of 10 slices on screen. 
Does that mean that we need to keep 10 variables to store their handles? 
Well, not really. Sure, you could be tucking the slice handles away in 
a fake array using "write global", but you don't really need to.

The fact is, the children of a parent slice are already kinda like an 
array. SO lets see how you loop through them without needing to know 
their handles in advance.

  variable(handle)
  handle := first child(sprite layer)
  while(handle) do, begin
    #do something to each handle here
    handle := next sibling(handle)
  end

So first we use the "first child" command. This takes any slice and 
gives us the handle to its first child, or 0 if there are no children.

Slice handles are always non-zero, so then we can say "while(handle)" 
for our loop.

At the end of the loop, we use the "next sibling" command to get the 
next slice handle, or 0 if there are no more (and as you know, a 0 will 
cause the "while" loop to stop)

Now if we loop through our hat-wearing enemy sprites in this way, the 
while loop is going to loop through 5 times, once for each enemy.

Why not for the hats? The hats are NOT children of the "sprite layer" 
anymore. Remember? we re-parented them with the "set parent" command. 
The hats are now childrewn of the enemy sprites (and thusly they are 
grandchildren of the sprite layer)

So what if we want to loop through all the hats and manipulate them?

  variable(handle, hat)
  handle := first child(sprite layer)
  while(handle) do, begin
    hat := first child(handle)
    if(hat) then, begin
      #do something to each hat here
    end
    handle := next sibling(handle)
  end

See? We can use the "first child" command on the enemy sprite's slice 
handle and get the hat. Now suppose we wanted to allow enemies to maybe 
wear more than one hat... or glasses... or gloves or something.

  variable(handle, clothing)
  handle := first child(sprite layer)
  while(handle) do, begin
    clothing := first child(handle)
    while(clothing) do, begin
      # do something with each article of clothing here
      clothing := next sibling(clothing)
    end
    handle := next sibling(handle)
  end

And yes, children can have children which can have children, and so-on, 
until you create a family tree of slices that is so big you run out of 
memory.

One other thing to note is that if you delete a slice using "free slice" 
(or "free sprite") then all of its children will be deleted too, as if 
you are chopping the whole branch off of the family tree.

Okay. Does all of the above make sense? If not, let me know what I need 
to clarify, and if so we can move on to talking about containers and 
rects.

---
James


More information about the Ohrrpgce mailing list