FKiSS is a set of commands that lets the user directly manipulate the KiSS
viewer's abilities. Consider this: a KiSS viewer parses a cnf. In this cnf, object
#0 is present on page 0, absent on page 1 and all the way down in the lower right
corner on page 3. That means that the viewer has to "draw" the image referred to by the
object when you open the set, "erase" it when you switch to page 1, and move it to
another place when you switch to page 2. Now suppose you could tell it to move,
draw and erase the image at your command while the set is opened. To manipulate
the viewer this way, the pioneers of KiSS formulated a simple syntax consisting
of events and actions.
An event is something that happens, and is noticed by the viewer. An action is
something the viewer has to do when an event happens. The basic syntax for any
FKiSS code is:
(more actions as required)
For instance, the event press(#1) happens, when the user clicks on something; in this case, object #1. When a user clicks on any object, a FKiSS-enabled viewer will recall if there is anything the cnf told it to do in the event of a mouseclick on that object, and do it. The action might be move(#1,X,Y). Being moved by the viewer as ordered in the cnf, object #1 might touch object #2 and trigger a collision event; the actions of one event can spark off another event, whose actions are then also carried out. Strictly speaking, press(#1) is not the event itself, but an instruction to the viewer that it should react to this event: such an instruction is called an event handler, and the FKiSS section of the cnf starts with the statement ;@EventHandler, to let the FKiSS-capable viewer know that the following lines should be read as FKiSS code. Non-FKiSS viewers will only understand the semicolon, read the statement as a user-inserted comment, and ignore it; they will similarly treat the FKiSS code under it as comments. The ";@" that goes before each FKiSS command tells the FKiSS viewer that this is code, not comment.
I am not going to sum up all the FKiSS commands here; check out the list of
FKiSS documents on the Web. There are a few terms
and things every beginning FKiSS programmer should know, though.
The most basic events are press() and release(), two mouseclick
events. The most basic actions are map() and unmap(), which map
and unmap (make visible/invisible) the image referred to in the brackets.
All actions and events end on a pair of brackets; depending on the command,
these must be left empty or filled with something to apply the
command to. The mouseclick events and mapping actions can have either a cel
name or an object number in the brackets. Since coordinates can only be
assigned to objects, move() and all actions derived from it (I
sometimes call them the move..() commands, as they have names like
moveto(), movebyx() etc.) can only take an object number.
The argument in the brackets doesn't always have to be a cel name or object
number; there is a timer() action that sets off an alarm() event
after a given number of milliseconds, and a music() action that plays a
given midi file.
The images in a KiSS set are not just placed on one single screen; they
can be displayed, at different coordinates, on up to ten different pages,
between which the user can flip at will. This has consequences for the
FKiSS programmer. Suppose I start an animation sequence, which in FKiSS
is done mostly with mapping, unmapping and alarms, on page 4, but halfway
through I become bored and go to page 7. An alarm will fire no matter
what page I'm on, and so the animation will continue offscreen, using up
processor time, despite the fact that it's not even visible. Object coordinates
are a per-page thing, though, so if the animation involves moving an object
around, then as soon as I change page, this movement will stop; or, if
the object being moved is also displayed on page 7, it may start to
move there, which is not what I intended. So the FKiSS programmer
should know what commands work only on the present page, and what
commands will work across the whole set.
Mouse events will only happen on the current page. (Obviously. You
can't click on something that's on a page you haven't opened.) Moving
actions will also only happen on the current page.
Mapping actions, alarms and soundfile-playing actions work across the
whole set. Unmapping an object on page 0 unmaps it on all pages where
it was visible.
Collision events are an iffy matter. Four of the six collision events
are fired when there is a change in the situation; when two images that
didn't overlap before are moved over each other, or vice versa. In most
fact that images may be repositioned by a page change is not taken
into account, so if object #1 touches object #2 on page 5, and I
go to page 6 where the two objects aren't touching and drag them over
each other, this second collision goes undetected. Viewers are not
consistent in handling collision detection, which is not surprising
as it's a complicated subject.
Apart from the intricacies of collision detection, there are three
problem areas the FKiSS coder should be aware of, as FKiSS viewers are
not consistent in the way they handle these issues.
Firstly: moving images off the screen through FKiSS actions. John Stiles'
Mac viewer will allow this. Most viewers will not. Consequently,
sets made for this viewer will be broken (which means, they won't work
properly) in many other viewers. In general, expect a viewer not to
Secondly: multiple event handlers. A practical example: I use press(#1)
at the beginning of the FKiSS block with the action unmap(#3), and at
the end of the FKiSS block I add another press(#1) to start a timer.
Most viewers will execute the actions under both event handlers, but
it's always possible that they might ignore the second one. Whether it
works or not, it's sloppy coding and should be avoided. Every event
handler should be unique.
Thirdly: ambiguous cel names. On the previous page, I explained what
cels and objects are, and how a cnf can display more instances
of the same cel. This is tricky when you have three instances of the
file FLOWER.CEL, which shows as three flowers on the screen, and you
use the event "press("flower.cel")". Should the event be fired when
clicking on either of the three instances? If you put the action
"unmap("flower.cel")" under it, should all three flowers be unmapped?
Although ideally the event and the action should apply to all three
instances, and this is probably the way FKiSS4-capable viewers will
work, older viewers will typically affect only the first instance
in the object declaration block, and ignore the rest. In the case
of the flower cel, each instance needs a unique object number to be
displayed at all, so the problem is easily solved by putting the
object numbers in the brackets, rather than the cel name. But some
FKiSS commands specifically require a cel name; ifmapped()
will set a timer if a certain cel is mapped. In the case of
the three flowers, should the timer be set if the first instance
is mapped, the second instance is mapped, the third instance is
mapped or only if all three are mapped? The "flower.cel" in
this example is an ambiguous cel name, as it's not clear which
item it refers to. How FKiSS commands should react to ambiguous
cel names has been the subject of raging debates. Generally, the
best thing is to simply avoid them.
There are currently five known and implemented FKiSS levels: FKiSS, FKiSS2,
FKiSS2.1, FKiSS3, and FKiSS4. The higher the level, the more you can do with it.
Generally, every level is backwards compatible, so a viewer that can read
FKiSS2.1 should also be able to read FKiSS, but some commands are so
unstandard or obsolete that not every viewer recognizes them. And different
viewers interpret FKiSS code in different ways; the most difficult
thing about FKiSS isn't the code itself, but the fact that every viewer
may produce a slightly different result!
Hopefully, though, this won't discourage KiSS artists from experimenting
with FKiSS. The viewer page (currently,
a work in progress) lists known bugs in viewers, and offers possible FKiSS