Fonction fragment
Cette fonction s'execute à chacune des tuiles qui composent
l'affichage définissant le visuel en sortie de programme.
Pour être appliquée en sortie une fonction fragment
doit
être définie précédée de l'instruction export
et doit
retourner une valeur décimale via l'instruction return
.
Les valeurs envoyées de cette manière seront interprétées en formes
et en couleurs sur chaque tuile de la grille qui compose l'affichage
(voir encodage). L'envoie de la valeur 35 par
exemple remplira la grille d'affichage d'un '#'.
export function fragment(){
return 35;
}
Objet contexte de
fragment
Lorsqu'une fonction fragment
est traitée, un objet
contenant des propriétées spécifiques à son contexte d'execution lui est
envoyé en premier argument. Pour récupérer cet objet il suffit
d'attribuer un nom de variable en premier argument lors de la définition
de la function fragment
décrite précédement.
export function fragment(context){
var text = context.write(Object.keys(context));
return text ? text : 32;
}
Cet objet contient différents types d'informations et d'outils; il
apporte des données sur la position de la tuile en cours de traitement,
sur les dimensions et le contenu de la grille d'affichage en sortie
ainsi sur le set de tuiles (voir tileSet
) et la palette de couleur (voir
palette
) en cours d'utilisation. Il
contient également des fonctions se servant du système d'encodage pour
modifier les couleurs des tuiles ou convertir du texte ou des valeurs
hexadecimales en valeur décimales.
Il contient par exemple la méthode write
permettant
d'écrire du texte en sortie.
export function fragment(fragmentContext){
var text = fragmentContext.write("Sortie du fragment");
return text ? text : 35;
}
À noté qu'il est possible de nommer librement l'argument et de créer
des raccourcis vers ses propriétées.
export function fragment(ctx){
var {write,y} = ctx;
var text = write("Ligne "+y,0,y);
return text ? text : 32;
}
Index des
propritées du contexte de fragment
fragmentContext.write(str,x,y,fg,bg)
Converti une chaine de caractères en valeur decimales et les placent
aux coordonées indiquées en appliquant une la couleur de forme et de
fond. Les arguments de coordonées (x,y) et de couleur (fg,bg) sont
optionnels. Par défaut le text se place en 0,0 sans couleur définie.
export function fragment(fragmentContext) {
var text = fragmentContext.write("hello world");
return text ? text : 32;
}
fragmentContext.i
index
Renvoie la valeur d'index de la tuile en cours de traitement.
export function fragment(fragmentContext) {
var {i,y,write} = fragmentContext;
var text = fragmentContext.write(
i+" index du debut de ligne "+y,0,y
);
return text ? text : 32;
}
fragmentContext.x
x
Renvoie la position sur l'axe horizontal de la tuile en cours de
traitement.
export function fragment(fragmentContext) {
return !(fragmentContext.x%4) ? 35 : 32;
}
fragmentContext.y
y
Renvoie la position sur l'axe vertical de la tuile en cours de
traitement.
export function fragment(fragmentContext) {
return !(fragmentContext.y%4) ? 35 : 32;
}
fragmentContext.w
width
Renvoie le nombre de colonnes de l'affichage.
export function fragment(fragmentContext) {
var {x,w} = fragmentContext;
return x > w/2 ? 35 : 32;
}
fragmentContext.h
height
Renvoie le nombre de lignes de l'affichage.
export function fragment(fragmentContext) {
var {y,h} = fragmentContext;
return y > h/2 ? 35 : 32;
}
fragmentContext.di
data index
Renvoie la valeur actuelle de la tuile en cours de traitement.
export function fragment(fragmentContext) {
return fragmentContext.di + 1;
}
fragmentContext.d
data
Renvoie la liste du total des valeurs de tuiles.
export function fragment(fragmentContext) {
var {i,di,d} = fragmentContext;
return (
!i
? di
: d[i-1]+1
);
}
fragmentContext.t
tiles
Renvoie la taille du set de tuiles.
export function fragment(fragmentContext) {
var {i,t} = fragmentContext;
return i < t ? i : 32;
}
fragmentContext.tw
tile width
Renvoie la largeur en pixel des tuiles du set de tuiles.
fragmentContext.th
tile height
Renvoie la hauteur en pixel des tuiles du set de tuiles.
fragmentContext.c
colors
Renvoie le nombre de couleurs de la palette.
import {base4} from "textor/assets/palettes.mjs"
var {random,floor} = Math;
export var palette = base4;
export var freeColor = 1;
export function fragment(fragmentContext) {
var {t,c} = fragmentContext;
return floor(random()*t*c*c);
}
fragmentContext.cp(str)
code point
Converti une chaine de caractères en valeur decimales. Renvoi une
valeur seule ou une liste selon si la chaine comporte un ou plusieurs
caractères.
export function fragment(fragmentContext) {
return fragmentContext.cp('A');
}
fragmentContext.hex(str)
hexadecimal
Converti une chaine de caractères composées de valeurs hexadecimales
séparées un esapce en valeur decimales. Renvoi une valeur seule ou une
liste selon si la chaine comporte une ou plusieurs valeurs
hexadecimales.
À savoir qu'il est possible d'afficher ou cacher un tableau des
valeurs hexadecimales correspondant aux tuiles du tileSet
en cours d'utilisation via la touche F1
.
export function fragment(fragmentContext) {
return fragmentContext.hex('41');
}
fragmentContext.fg(value)
foreground
Retourne l'index d'encodage de la couleur de forme correspondant à la
valeur donnée. Cet index, ajouté à une valeur de forme de tuile permet
de définir sa couleur de forme.
import {base3} from "textor/assets/palettes.mjs"
export var palette = base3;
export var freeColor = 1;
export function fragment(fragmentContext) {
var {cp,fg} = fragmentContext;
return cp('A')+fg(1);
}
fragmentContext.bg(value)
background
Retourne l'index d'encodage de la couleur de fond correspondant à la
valeur donnée. Cet index, ajouté à une valeur de forme de tuile permet
de définir sa couleur de fond.
import {base3} from "textor/assets/palettes.mjs"
export var palette = base3;
export var freeColor = 1;
export function fragment(fragmentContext) {
var {cp,fg,bg} = fragmentContext;
return cp('A')+fg(1)+bg(2);
}
fragmentContext.gt(value)
get tile
Retourne la forme de tuile correspondante à la valeur donnée.
var {random,floor} = Math;
var tile = floor(random()*128);
export function fragment(fragmentContext) {
var {write,d,gt,di,cp} = fragmentContext;
var text = write(
gt(d[0])+" est la couleur de forme choisie au hasard",
1,
0
);
return (
text
? text
: !di
? tile
: di
);
}
fragmentContext.gfg(value)
get foreground
Retourne la couleur de forme correspondant à la valeur donnée.
import {base4} from "textor/assets/palettes.mjs"
var {random,floor} = Math;
export var palette = base4;
export var freeColor = 1;
var color = floor(random()*palette.length);
export function fragment(fragmentContext) {
var {write,di,d,c,cp,fg,gfg} = fragmentContext;
var text = write(
gfg(d[0])+" est la couleur de forme choisie au hasard",
1,
0
);
return (
text
? text+fg(c-1)
: !di
? cp('A') + fg(color)
: di
);
}
fragmentContext.gbg(value)
get background
Retourne la couleur de fond correspondant à la valeur donnée.
import {base4} from "textor/assets/palettes.mjs"
var {random,floor} = Math;
export var palette = base4;
export var freeColor = 1;
var color = floor(random()*palette.length);
export function fragment(fragmentContext) {
var {write,di,d,c,cp,fg,gfg} = fragmentContext;
var text = write(
gbg(d[0])+" est la couleur de forme choisie au hasard",
1,
0
);
return (
text
? text+bg(c-1)
: !di
? cp('A') + bg(color)
: di
);
}
Encodage des tuiles
La manière dont Textor encode les tuiles est similaire à l'encodage
de caractères. Le principe est d'assigner une valeur numérique à une
combinaison de forme, de couleur de forme et de couleur de fond de
tuile.
Exemple de tuile avec comme forme 'A',
noir comme couleur de fond et blanc comme couleur de forme
Les valeurs de tuiles sont rangées par forme puis par combinaisons de
couleur de forme et de couleur de fond. Le système d'encodage de Textor
varie selon le nombre de formes et de couleurs de tuiles définies par
les classes TileSet
et Palette
selon la
formule suivante:
valeur de tuile = (
forme de tuile
+ nombre de tuiles * couleur de fond
+ nombre de tuiles * nombre de couleurs * couleur de forme
)
Exemple
Prenons l'exemple de l'encodage obtenu par le TileSet
ascii8x16
combiné avec la Palette
base1
:
Ordre des tuiles encodées par la
combinaison ascii8x16
- base1
disposé par
lignes de 32 tuiles.
ascii8x16
contient 128 formes de tuiles correspondant à
l'encodage ASCII.
Les 32 premiers caractères ASCII correspondent à des caractères
de contrôle. Ces derniers n'étant pas censés être affichés ils n'ont
pas de forme et se confondent ici avec la forme d'un espace. Ils sont
dans l'image ces bandes vides au début de chaque changement de
couleur.
base1
contient 2 couleurs, le noir et le blanc,
correspondant à une profondeur
de couleur 1-bit.
La combinaison des deux produit 128*2*2
tuiles pour un
total de 512.
On peux observer dans l'image la manière dont sont rangées les tuiles
par le système d'encodage. D'abord 128 tuiles noir sur fond noir, le
noir étant la première couleur de la palette, produisant un rectangle
noir sur 4 lignes. Ensuite 128 tuiles noir sur fond blanc, le blanc
étant la deuxième couleur de la palette. Puis 128 tuiles blanc sur fond
noir, les combinaisons de couleur de fond étant épuisées c'est la
couleur de forme qui change tandis le fond retourne à la valeur
initiale. Viens enfin 128 tuiles en blanc sur fond blanc marquant la fin
des combinaisons possibles et produisant un rectangle blanc sur 4
lignes.
Pour retrouver la valeur d'un 'A' noir sur fond blanc nous pouvons
reprendre la formule citée plus haut.
valeur de tuile = (
65
+ 128 * 1
+ 128 * 1 * 0
)
65 étant la valeur de la forme de la tuile, la 65e forme sur les 128
stockées dans ascii8x16
.
128 étant le total des formes de tuiles.
1 étant la valeur de couleur de fond de la tuile, correspondant au
blanc, deuxième valeur de couleur sur les 2 stockées dans
base1
. (Il faut compter à partir de 0)
1 étant le total de couleurs stockées dans base1
.
0 étant la valeur de couleur de forme de la tuile, correspondant au
noir, première valeur de couleur sur les 2 stockées dans
base1
.
Le résultat étant 193 nous pouvons retrouver dans l'image le 'A' noir
sur fond blanc en 193e position. Il est possible de vérifier en s'aidant
des lignes, 'A' noir sur fond blanc étant à la 6e ligne après la tuile
'@' soit 6*32+1 = 192
.
Changer le tileSet
ou la palette
fait
varier l'encodage selon le nombre de tuiles et de couleurs.
Conservons le TileSet
ascii8x16
mais
changeons de Palette
avec base3
aura comme
resultat l'encodage suivant:
Ordre des tuiles encodées par la
combinaison ascii8x16
- base3
disposé par
lignes de 64 tuiles.
base3
contient 4 couleurs, correspondant à une profondeur
de couleur 3-bit.
Combiné avec ascii8x16
ont obtient 128*4*4
tuiles pour un total de 2048.
Avec ce changement de Palette
la valeur 193 ne tombe
plus sur 'A' noir sur fond blanc mais sur 'A' noir sur fond gris sombre,
le nouveau calcul étant:
valeur de tuile = (
65
+ 128 * 3
+ 128 * 3 * 0
)
Le premier 3 étant la valeur de couleur de fond de la tuile,
correspondant au blanc, 4e valeur de couleur sur les 4 stockées dans
base3
.
Le deuxième 3 étant le nombre total de couleur stockées dans
base3
.
Le résultat étant 449 nous pouvons retrouver dans l'image le 'A' noir
sur fond blanc en 449e position. Il est possible de vérifier en s'aidant
des lignes, 'A' noir sur fond blanc étant à la 7e ligne après la tuile
'@' soit 7*64+1 = 449
.
Changer la taille des pixels
export var scale = 3 // définir une taille de pixel de 3 pixels
Changer la vitesse de
l'animation
export var fps = 24 // définir 24 frames par seconde
Travailler librement
avec les couleurs
Par défaut, Textor Playground contraint les couleurs. Il fixe un
rendu en blanc sur fond noir. Pour pouvoir définir librement le rendu
coloré il faut exporter la variable freeColor
avec une
valeur positive.
export var freeColor = 1;
Changer le tilset
Instances tileSets
disponibles par défaut :
tileSets.ascii4x8
tileSets.liblab4x8
tileSets.ascii6x12
tileSets.ascii8x16
tileSets.semigraphRegular8x8
tileSets.semigraphBold8x8
tileSets.semigraphHeavy8x8
tileSets.creaturesHV
tileSets.amuryPerrotPixel
tileSets.jumpStyle
tileSets.newPiskel
tileSets.dragon
tileSets.canardPissenlit
tileSets.canardBouingBouing
tileSets.frog7x48
Exemple :
import {ascii4x8} from "textor/assets/tileSets.mjs";
export var tileSet = ascii4x8;
Changer de palette
Instances palettes
disponibles par défaut
palettes.base1 // 2 couleurs
palettes.base2 // 4 couleurs
palettes.base3 // 8 couleurs
palettes.base4 // 16 couleurs
palettes.resurrect64 // 64 couleurs
Exemple :
import {base3} from "textor/assets/palettes.mjs";
export var palette = base3;
Fonction frame
Cette fonction s'execute avant le rendu de chaque image de
l'animation.
Pour être appliquée une fonction frame
doit être définie
précédée de l'instruction export
et doit retourner une
valeur décimale via l'instruction return
.
Les valeurs envoyées de cette manière définiront si l'animation
s'arrête ou se poursuit. Une valeur vraie ou positive poursuit
l'animation tandis qu'une valeur fausse (false ou 0) stop
l'animation.
export function frame(){
return 1;
}
Objet contexte de
frame
Lorsqu'une fonction frame
est traitée, un objet
contenant des propriétées spécifiques à son contexte d'execution lui est
envoyé en premier argument. Pour récupérer cet objet il suffit
d'attribuer un nom de variable en premier argument lors de la définition
de la function frame
décrite précédement.
export function frame(frameContext){
console.log(context.write(Object.keys(frameContext)));
return 1;
}
Cet objet apporte des données sur l'état en temps réel de l'animation
mais également sur l'interface de sortie, instance de la classe
EndInterface
, notamment son format et les interactions à la
souris et au clavier de l'utilisateur.
Il contient par exemple la méthode write
permettant
d'écrire du texte en sortie.
Index des propritées
du contexte de frame
frameContext.at
animation time
Renvoie la valeur du temps passé en millisecondes depuis le début de
l'animation.
export function frame(frameContext) {
var {at} = fragmentContext;
// Stop l'animation au bout de 3 secondes selon la valeur at
return at/1000 < 3 ? 1 : 0;
}
frameContext.f
frame
Renvoie la valeur du nombre d'images rendues depuis le début de
l'animation.
export function frame(frameContext) {
var {f} = fragmentContext;
// Stop l'animation après 100 images
return f < 100 ? 1 : 0;
}
frameContext.fps
frames per second
Renvoie la valeur du nombre d'images rendues par seconde.
export function frame(frameContext) {
var {f,fps} = fragmentContext;
// Stop l'animation après 10 secondes adaptées selon le nombre d'images rendues par seconde
return f < fps*10 ? 1 : 0;
}
frameContext.ew
end interface width
Renvoie la valeur en pixels de la largeur de l'interface de
rendu.
export function frame(frameContext) {
var {ew} = fragmentContext;
// Stop l'animation si la largeur de l'interface de rendu est inférieure à 320px
return ew < 320 ? 0 : 1;
}
frameContext.eh
end interface height
Renvoie la valeur en pixels de la hauteur de l'interface de
rendu.
export function frame(frameContext) {
var {eh} = fragmentContext;
// Stop l'animation si la hauteur de l'interface de rendu est inférieure à 240px
return ew < 240 ? 0 : 1;
}
frameContext.m
mouse down
Renvoie une valeur positive ou négative selon si le bouton de la
souris est appuyé ou non.
export function frame(frameContext) {
var {m} = fragmentContext;
// Stop l'animation au clic
return m ? 0 : 1;
}
frameContext.mx
mouse x
Renvoie la valeur de la coordonnée de l'axe X de la souris vis-à-vis
de l'interface de sortie.
export function frame(frameContext) {
var {mx,ew} = fragmentContext;
// Stop l'animation si la souris en X est supérieure à la moitiée de la
// largeur de l'interface de sortie
return mx > ew/2 ? 0 : 1;
}
frameContext.my
mouse y
Renvoie la valeur de la coordonnée de l'axe Y de la souris vis-à-vis
de l'interface de sortie.
export function frame(frameContext) {
var {my,eh} = fragmentContext;
// Stop l'animation si la souris en Y est supérieure à la moitiée de la
// hauteur de l'interface de sortie
return my > eh/2 ? 0 : 1;
}
frameContext.k
Renvoie sous forme de liste de valeurs positives ou negatives (1 ou
0) les touches pressées ou non par l'utilisateur.
La liste incorpore 128 entrées correpondant qui correspondent dans la
mesure du possible aux caractères ASCII triées dans le même ordre.
Certaines entrées correspondantes aux caractères
de contrôle n'ayant aucune équivalence au clavier ont été remplacées
de manière arbitraire afin d'inclure le maximum de touches.
Ci après la liste des 128 entrées et le nom des touches
correspondantes.
0 Unidentified
1 Dead
2 Home
3 En
4 Alt
5 AltGraph
6 Control
7 NumLock
8 Backspace
9 Tab
10 Meta
11 PageUp
12 PageDown
13 Enter
14 CapsLock
15 Shift
16 PrintScreen
17 ArrowUp
18 ArrowRight
19 ArrowDown
20 ArrowLeft
21 F1
22 F2
23 F3
24 F4
25 F5
26 Insert
27 Escape
28 F6
29 F7
30 F8
31 F9
32
33 !
34 "
35 #
36 $
37 %
38 &
39 \'
40 (
41 )
42 *
43 +
44 ,
45 -
46 .
47 /
48 0
49 1
50 2
51 3
52 4
53 5
54 6
55 7
56 8
57 9
58 :
59 ;
60 <
61 =
62 >
63 ?
64 @
65 A
66 B
67 C
68 D
69 E
70 F
71 G
72 H
73 I
74 J
75 K
76 L
77 M
78 N
79 O
80 P
81 Q
82 R
83 S
84 T
85 U
86 V
87 W
88 X
89 Y
90 Z
91 [
92 \
93 ]
94 ^
95 _
96 `
97 a
98 b
99 c
100 d
101 e
102 f
103 g
104 h
105 i
106 j
107 k
108 l
109 m
110 n
111 o
112 p
113 q
114 r
115 s
116 t
117 u
118 v
119 w
120 x
121 y
122 z
123 {
124 |
125 }
126 ~
127 Delete
export function frame(frameContext) {
var {k} = fragmentContext;
// Stop l'animation avec la touche "Enter"
return k[13] ? 0 : 1;
}
frameContext.key(str)
Renvoie une valeur positive ou negative (1 ou 0) correspondant au nom
d'une touche donée en argument.
export function frame(frameContext) {
var {key} = fragmentContext;
// Stop l'animation avec la touche "Enter"
return key("Enter") ? 0 : 1;
}
frameContext.cp(str)
code point
Converti une chaine de caractères en valeur decimales. Renvoi une
valeur seule ou une liste selon si la chaine comporte un ou plusieurs
caractères.
frameContext.hex(str)
hexadecimal
Converti une chaine de caractères composées de valeurs hexadecimales
séparées un esapce en valeur decimales. Renvoi une valeur seule ou une
liste selon si la chaine comporte une ou plusieurs valeurs
hexadecimales.
À savoir qu'il est possible d'afficher ou cacher un tableau des
valeurs hexadecimales correspondant aux tuiles du tileSet
en cours d'utilisation via la touche F1
.
Cycles et instruments
Les cycles sont des objets contenant des valeurs qui évoluent et se
répétent dans le temps, indiquent leur changement en cours et qui
peuvent s'imbriquer les uns dans les autres.
Instances time, measure,
sheet et loop
Par défaut il existe 4 instances de cycles : time
,
measure
, sheet
et loop
. Ensemble
ils forment une sorte de métaphore d'une partition de musique.
time
représente l'unité temporelle de base de la
partition, la durée d'une noire et son
nombre de répétitions dans une mesure (4 par défaut).
measure
représente une mesure, qui
par défaut dure de 4 time
et qui se répéte 4 fois par
sheet
.
sheet
représente une feuille de partition,
par défaut dure 4 measure
et qui se répéte 4 fois par
loop
.
loop
représente l'ensemble de la partition, contient 4
sheet
par défaut.
Méthode play
de l'instance instrument
Pour jouer une note il faut utiliser la méthode play
de
l'instance instrument
.
Celle-ci nécéssite deux fonctions en arguments, une première pour
définir quand l'instrument doit-il jouer une note dans la frame en cours
et une deuxième pour définir quoi doit-il jouer (voir les exemples plus
bas).
Import des cycles et
instrument
Pour être utilisés ils doivent être importés via l'instance live de
playground/playground.mjs
.
import {live} from "playground/playground.mjs";
const {time,measure,sheet,loop,instrument} = live;
Propritées d'une instance de
cycle
cycle.sharp
Renvoie une valeur positive ou négative selon si le cycle est entrain
de changer de valeur dans la frame en cours d'execution.
import {live} from "playground/playground.mjs";
const {time,measure,sheet,loop,instrument} = live;
function when(){
return time.sharp
}
function what(){
return {
freq:200
}
}
export function frame(frameContext) {
instrument.play(when,what);
return 1;
}
cycle.index
Renvoie l'index de progression du cycle avant sa répétition.
import {live} from "playground/playground.mjs";
const {time,measure,sheet,loop,instrument} = live;
function when(){
return (
time.sharp
&& (
// joue tout les premier(0) et deuxième temps(1)
time.index == 0
|| time.index == 1
)
)
}
function what(){
return {
freq:(
(time.index+1) * 150
)
}
}
export function frame(frameContext) {
instrument.play(when,what);
return 1;
}
cycle.cycle
Renvoie la valeur du nombre de répétitions du cycle
import {live} from "playground/playground.mjs";
const {time,measure,sheet,loop,instrument} = live;
function when(){
return (
time.sharp
&& (
// joue tout les premier(0) et deuxième temps(1)
time.index == 0
|| time.index == 1
// un cycle sur deux, joue à tout les temps
|| time.cycle%2
)
)
}
function what(){
return {
freq:(
(time.index+1) * 100
// un cycle sur deux multiplie la fréquence par 2
* (time.cycle%2+1)
)
}
}
export function frame(frameContext) {
instrument.play(when,what);
return 1;
}
Propriétées de définition
d'une note
{
gain : 0.1 // volume, valeur à définir entre 0 et 1
freq : 200, // note définie en fréquence voir https://fr.wikipedia.org/wiki/Fr%C3%A9quences_des_touches_du_piano
shape : 0 // 0 sinusoid, 1 triangle, 2 square ou 3 sawtooth pour le type de timbre de l'instrument, triangle, square, sinusoide, sawtooth
noise: 0.01 // niveau de bruit entre 0 et 1
vibAmt: 0.001 // intensité du vibrato, entre 0 et 1
vibFreq: 400 // fréquence du vibrato
inDur: 0.01 // durée d'entrée du son en secondes ( plus c'est bas plus le son est percussif)
midDur: 0 // durée de maintient du son en secondes (plus c'est haut plus la note dure)
outDur: 0.25 // durée de fin du son en secondes (plus c'est haut plus le son met du temps à s'arrêter en diminuant lentement
echoLimit: 7, // nombre de répétition de l'écho
echoLatency: 300, // temps en millisecondes entre chaque écho
echoModifier: 0.7 // modifieur de l'écho, entre 0 et 1, plus c'est bas plus le volume de l'écho diminue vite
}