Created: around 09-07-2001
Last update: 12-07-2021
Back Previous Next

Beginners howto 4 - colour cycling - refinements

This howto expands a bit on tea's colour-cycling tutorial. Her method can be used to cycle colour, shape (like raising and lowering a hood) or whatever you can think of, but I'm going to concentrate on the colour-changing function, and instead of a head with three hairstyles, I'm going to use a flower with six colours of petals. There are two basic cels, a stalk cel and a flowerhead cel; the flowerhead cel can be copied and filled in with different colours to make differently coloured petals.

refinement 1: using layer order

In tea's tutorial, only one of the cycling cels is mapped at a time. But for cels that exactly cover each other, only the topmost mapped cel will be visible anyway, so you can have them all mapped and "click away" each cel until you get to the bottom cel, and clicking that one remaps all the cels.

The object and cel declarations will look like this:

#1   	petals.cel  *0 :0           ; red petals
#1      petpink.cel *0 :0           ; pink petals
#1      petorng.cel *0 :0           ; orange petals
#1      petblue.cel *0 :0           ; blue petals
#1      petyelw.cel *0 :0           ; yellow petals
#1      petpurp.cel *0 :0           ; purple petals
#1   	stalk.cel   *0 :0           ; flower stalk
And the code looks like this:
;@   unmap("petals.cel")  ; exposes pink petals
;@   unmap("petpink.cel") ; exposes orange petals
(etc. - repeat for all but last cel)
;@press("petpurp.cel")    ; bottom-most petals
;@   map(#1)              ; a quick way to remap all the flowerheads

Note that object #1 includes all parts of the flower, so you can freely drag it around.

refinement 2: putting all cycling cels into their own object

This makes for easy coding when you can't use layer order, and know that the object won't be moved around. The object declarations are:

#1.999	petals.cel  *0 :0           ; red petals
#1.999	petpink.cel *0 :0           ; pink petals
#1.999	petorng.cel *0 :0           ; orange petals
#1.999	petblue.cel *0 :0           ; blue petals
#1.999	petyelw.cel *0 :0           ; yellow petals
#1.999	petpurp.cel *0 :0           ; purple petals
#2.999	stalk.cel   *0 :0           ; flower stalk
And the code goes:
;@   unmap(#1) map("petpink.cel")
;@   unmap(#1) map("petorng.cel")
and so on, up to and including the purple petals.

Note that flowerheads and stalk are now two different objects. This flower has to be locked into place, or it and its petals will part company.

refinement 3: using the same cel with different palettes

This solution requires a basic knowledge of palettes. It uses the same cel six times with six different object numbers, which keeps down the size of the set but uses up much RAM, possibly making the set slow to load and play with. (I wrote this in the days when I was just getting used to 16MB of RAM, and 128MB RAM was seen as astronomical.) In the basic flower palette, colour number 5, which colours the petals, is red. Cels themselves are colourless, so if I make five more palettes in which colour 5 is respectively pink, orange, blue, yellow or purple, list these in the cnf header and define the objects as follows:

; **Palette files**

[playfield size and other stuff]

#1.999	petals.cel	*0 :    2       ; red palette
#2.999	petals.cel	*1 :    2       ; pink palette
#3.999	petals.cel	*2 :    2       ; orange palette
#4.999	petals.cel	*3 :    2       ; blue palette
#5.999	petals.cel	*4 :    2       ; yellow palette
#6.999	petals.cel	*5 :    2       ; purple palette
#7.999	stalk.cel	*0 :    2       ;
then I can colour-cycle by alternating objects, like this:
;@   unmap(#1) map(#2)
;@   unmap(#2) map(#3)
and so on, up to:
;@   unmap(#6) map(#1)

Note that this flower, like the one before, has to be locked in place or its petals will go flying off in all directions.

refinement 4: using merged palettes

This solution assumes a more in-depth knowledge of palettes. It is possible to pack up to ten palettes into a palette file. Each of these ten can be made visible by activating its "palette group", but this will also activate that palette group for any other palette used. Anyway, suppose you have one merged palette. This is how you define the flower object:

#1   	petals.cel	*0 :0           ; yes, only once!
#1   	stalk.cel	*0 :0           ;

This is a flower that can be dragged around without losing parts. The colour will change when the palette group does. This can't be done by clicking on the petals (unless you use FKiSS3, where you can have a variable to keep track of the palette group number) so it needs something like a button object to click:

#2   	cycle1.cel	*0 :0           ;
#2   	cycle2.cel	*0 :0           ;
#2   	cycle3.cel	*0 :0           ;
#2   	cycle4.cel	*0 :0           ;
#2   	cycle5.cel	*0 :0           ;
#2   	cycle6.cel	*0 :0           ;

;@     unmap("cycle1.cel") changecol(1) ; change palette group
;@     unmap("cycle2.cel") changecol(2)
and so on until the last button cel:
;@     map(#2) changecol(0)
which works like refinement 1, except the cels of the button object are being cycled instead of the petal cels. Or, instead of coding this cycling button, you can simply use the viewer's own palette group changing buttons, in which case no FKiSS is required whatsoever.

This method requires only one cel, one object and one palette, making it a big space-saver if you don't need more than ten different colours.

refinement 5: using transparent()

FKiSS1b, the first extension of FKiSS, implements the "%t" transparency tag and the action "transparent()", which makes a cel or object more or less see-through.

In this example, cels are not unmapped, but made transparent, allowing the cel beneath to shine through. This solution is clunky rather than refined, but it may allow for extra steps in the colour cycling if you make a cel semi-transparent, which blends its colour with the cel underneath, rather than making it fully see-through straight away. The object declarations may, but don't have to, look like that of the first method, with a transparency tag added:

#1   	petals.cel  *0 :0           ;      red petals
#1      petpink.cel *0 :0           ;%t255 pink petals
#1      petorng.cel *0 :0           ;%t255 orange petals
#1      petblue.cel *0 :0           ;%t255 blue petals
#1      petyelw.cel *0 :0           ;%t255 yellow petals
#1      petpurp.cel *0 :0           ;%t255 purple petals
#1   	stalk.cel   *0 :0           ;%t255 flower stalk

As you can see, this is again a flower that won't separate into components when moved around, although you could also make each ring of petals a different object, since transparent() works both with cels and objects. Since the cels are never unmapped, you can't cycle through them by clicking on them (unless you use FKiSS3 to count the number of clicks), so you have to add an extra button object as in the previous example. The code might look like:

;@   unmap("cycle1.cel")
;@   transparent("petals.cel",255)
;@   transparent("petpink.cel",-255)
;@   unmap("cycle2.cel")
;@   transparent("petpink.cel",255)
;@   transparent("petorng.cel",-255)
and so on. Or, you might try intermediate transparencies:
;@   unmap("cycle1.cel")
;@   transparent("petals.cel",128)
;@   transparent("petpink.cel",-128) ; colour between pink and red
;@   unmap("cycle2.cel")
;@   transparent("petals.cel",128)
;@   transparent("petpink.cel",-128) ; completely pink
since transparent() doesn't set an absolute transparency value, but adds or subtracts the given value from the transparency value, meaning that after the second cycling cel has been clicked away, the red petals are 0 + 128 + 128 = 255 which means totally transparent, while the pink petals are 255 - 128 - 128 = 0 which means totally opaque. (This looks like bad arithmetic, but computers start counting at 0.) This changing of transparency can be done in even smaller steps, or transparency-altering controls can be included in the KiSS set to let the users do a bit of colour-mixing themselves.

refinement 6: using frames (requires FKiSS4)

FKiSS4 introduces cel groups and frames. Note that these have not been implemented in the FKiSS4 version of PlayFKiSS, PKFS2; for this solution, you need a fully FKiSS4-capable viewer. The whole flower remains one single object, but the petals become frames in the cel group "!Petals". (Cel group names always start with an exclamation mark.)

#1   	petals.cel  *0 :0           ;!Petals:0            ;red petals
#1      petpink.cel *0 :0           ;!Petals:  1          ;pink petals
#1      petorng.cel *0 :0           ;!Petals:    2        ;orange petals
#1      petblue.cel *0 :0           ;!Petals:      3      ;blue petals
#1      petyelw.cel *0 :0           ;!Petals:        4    ;yellow petals
#1      petpurp.cel *0 :0           ;!Petals:          5  ;purple petals
#1   	stalk.cel   *0 :0           ; flower stalk

Frames are declared by putting a colon after a cel group name, and then adding the number of the frame in which each ring of petals should be mapped. The frame numbers don't have to be staggered the way I wrote them out, but it's more legible that way. Since every ring of petals is in a different frame, only one is mapped at a time, so if any of the petal rings is a bit transparent, there is no other ring underneath that will shine through. Only when the set is newly loaded, and a frame not yet set, all petal rings may be mapped; but that's solved by setting the active frame in this cel group to 0 under initialize(), or better yet, version().

As in the very first example, I cycle through the colours by clicking on the petals. Now that all petals are in the same cel group, I only need "press(!Celgroupname)" for the lot of them. That might not tell me which colour I clicked on, but now that every colour is a frame, I ask which frame is active, and put the frame number in a variable "FrameNo", using letframe(). Then, using add(), let() and the if-else-end block introduced in FKiSS3, I ask if FrameNo is less than 5, in which case I add 1 to move to the next frame; else, I set FrameNo back to 0. I then use setframe() with FrameNo to make the that frame active:

;@  setframe(!Petals,0) ; make first frame active
;@  letframe(FrameNo,!Petals)  ; note: variable comes first
;@  iflessthan(FrameNo,5)
;@    add(FrameNo,FrameNo,1)   ; move up one frame
;@  else()
;@    let(FrameNo,0)           ; back to first frame
;@  endif()
;@  setframe(!Petals,FrameNo)  ; note: variable comes second

Click on the image to download the demo set. demo set

Back Previous Next