Class : Gravity
L'idée est de simuler la chute d'un objet.
La chute ne doit pas être linéaire mais accélérée.
Physique
Équation
A chaque itération, il suffit d'appliquer les équations suivantes :
y += gravitySpeed;
Avec les valeurs de simulation suivantes, on voit clairement que durant :
- les dix premières itérations l'objet passe de la position 1 à 6
- les dix itérations suivantes l'objet passe de la position 6 à 22
- de l'itération 60 à 70 l'objet passe de la position de 183 à 249
Frame 1 : y = 1 (valeur tronquée)
(index):186 Frame 2 : y = 1
(index):186 Frame 3 : y = 1
(index):186 Frame 4 : y = 1
(index):186 Frame 5 : y = 2
(index):186 Frame 6 : y = 3
(index):186 Frame 7 : y = 3
(index):186 Frame 8 : y = 4
(index):186 Frame 9 : y = 5
(index):186 Frame 10 : y = 6
(index):186 Frame 11 : y = 7
(index):186 Frame 12 : y = 8
(index):186 Frame 13 : y = 10
(index):186 Frame 14 : y = 11
(index):186 Frame 15 : y = 12
(index):186 Frame 16 : y = 14
(index):186 Frame 17 : y = 16
(index):186 Frame 18 : y = 18
(index):186 Frame 19 : y = 20
(index):186 Frame 20 : y = 22
...
(index): 186Frame 60 : y = 183
(index):186 Frame 61 : y = 190
(index):186 Frame 62 : y = 196
(index):186 Frame 63 : y = 202
(index):186 Frame 64 : y = 208
(index):186 Frame 65 : y = 215
(index):186 Frame 66 : y = 222
(index):186 Frame 67 : y = 228
(index):186 Frame 68 : y = 235
(index):186 Frame 69 : y = 242
(index):186 Frame 70 : y = 249
L'objet chute :
- durant les dix premières itérations l'objet chute de ( 6 - 1) 5px,
- de l'itération 60, la chute sera de (249 - 183 ) 66px
- et à partir de l'itération 1000, l'objet chute à une très grande vitesse (or, nous savons qu'il existe une vitesse limite de chute qui est du au freinage des frottement)
Code
class GravityBloc extends AnimatedBloc {
constructor(elt, {
speed
}) {
super(elt, {
speed
});
this.gravity = 0.1;
this.gravitySpeed = 0;
}
static construct(elt, {
speed = 0
} = {}) {
return new GravityBloc( elt, speed );
}
update() {
super.update();
this.gravitySpeed +=this.gravity;
this.y += this.gravitySpeed;
}
}
Animation : class
Pour obtenir un temps écoulé :
let startTime = new Date().getTime();
function main() {
//pour avoir un temps de simu depuis le départ
let currTime = new Date().getTime(),
dt = ((currTime - startTime)/1000);
update(dt);
render();
requestId = window.requestAnimationFrame(main);
}
temps quasi constant
function main() {
let now = Date.now(),
dt = (now - lastTime) / 1000.0;
update(dt);
render();
lastTime = now;
requestId = window.requestAnimationFrame(main);
}
on pourra écrire la classe suivante :
class Oxilo extends AnimatedBloc {
constructor(elt, { speed }) {
super(elt, {
speed
});
}
static construct(elt, { speed = 1 } = {}) {
return new Oxilo(elt, { speed });
}
update(dt) {
this.x = Math.cos(2*Math.PI*(dt))*50;
this.y = Math.sin(Math.PI*(dt))*50;
}
}
on pourra écrire la classe suivante :
class Oxilo extends AnimatedBloc {
constructor(elt, { speed }) {
super(elt, {
speed
});
}
static construct(elt, { speed = 1 } = {}) {
return new Oxilo(elt, { speed });
}
update(dt) {
this.x = Math.cos(2*Math.PI*(dt))*50;
this.y = Math.sin(Math.PI*(dt))*50;
}
}
animation : class
Élément de base
class AnimatedBloc {
constructor(elt, {speed = 1} = {} ) {
this.elt = elt;
// initial CSS
this.initPosition( speed );
}
initPosition( speed ) {
if (this.elt) {
const {
left,
top
} = this.elt.getBoundingClientRect();
// CSS
this.cssX = left;
this.cssY = top;
this.x = 0;
this.y = 0;
this.speed = speed;
}
}
render() {
this.elt.style.cssText = `left:${this.x+this.cssX}px`;
//ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
}
update() {
this.x = this.x + this.speed;
}
}
Héritage
class BouncingBloc extends AnimatedBloc {
constructor(elt, {speed = 3, at = 300 } = {} ) {
super(elt, {speed});
this.boundary = at;
}
update() {
super.update();
if (this.x >= this.boundary || this.x == 0) {
this.speed *= -1;
this.elt.classList.toggle("bouncing");
}
}
}
Passage par défault
class Player {
constructor({
keysMap = new Map([
["up", "ArrowUp"],
["right", "ArrowRight"],
["down", "ArrowDown"],
["left", "ArrowLeft"],
]),
x = 20,
y = 20,
speed = 0.5,
} = {}) {
Object.assign(this, { touches, x, y, speed });
...
this.moveX = 0;
this.moveY = 0;
}
...
}
https://es6console.com/jpcwjhve/
constructor({
keysMap = new Map([
["up", "ArrowUp"],
["right", "ArrowRight"],
["down", "ArrowDown"],
["left", "ArrowLeft"],
]),
x = 20,
y = 20,
speed = 0.5,
} = {}) {
Object.assign(this, { touches, x, y, speed });
...
this.moveX = 0;
this.moveY = 0;
}
...
}
https://es6console.com/jpcwjhve/
------------ Amélioration du code
Méthode static !
class Player {
constructor( {keysMap, x, y, speed} ) {
Object.assign(this, {
keysMap,
x,
y,
speed
});
this.moveX = 0;
this.moveY = 0;
...
}
static create({
keysMap = new Map([
["ArrowUp", "up"],
["ArrowRight", "right"],
["ArrowDown", "down"],
["ArrowLeft", "left"],
]),
x = 100,
y = 100,
speed = 0.5,
} = {}) {
return new Player({keysMap, x, y, speed})
}
...
}
appel
Player.create();
Player.create({
keysMap: new Map([
["z", "up"],
["d", "right"],
["x", "down"],
["q", "left"],
]),
speed: 2
});
https://es6console.com/jpdtv6zx/
itérator
Ne marche pas si appellé deux fois
const dateRange = {
from: new Date(2018, 0, 23),
to: new Date(2018, 3, 28),
[Symbol.iterator]() {
this.current = this.from
return this
},
next() {
if (this.current <= this.to) {
this.current.setDate(this.current.getDate() + 1)
return {
done: false,
value: new Date(this.current)
}
}
return {
done: true
}
}
}
const dateList = Array.from(dateRange);
dateList.forEach(date => {
console.log(date.toString())
})
const dateRange = {
from: new Date(2018, 0, 23),
to: new Date(2018, 3, 28),
[Symbol.iterator]() {
this.current = this.from
return this
},
next() {
if (this.current <= this.to) {
this.current.setDate(this.current.getDate() + 1)
return {
done: false,
value: new Date(this.current)
}
}
return {
done: true
}
}
}
const dateList = Array.from(dateRange);
dateList.forEach(date => {
console.log(date.toString())
})
Getter et Setter d'une classe
La syntaxe
Exemple :
class CodeSecret {
constructor(num) {
// invokes the setter
this.code = num;
}
set code(num) {
if ( !/^ISBN/.test(num)) {
console.log("votre code doit commencer par ISBN");
return;
}
this._code = num;
}
get code() {
return this._code;
}
}
let t = new CodeSecret("dD1");
https://es6console.com/jpbn7x38/
set
permet de lier une propriété d'un objet à une fonction qui sera appelée à chaque tentative de modification de cette propriété.Exemple :
class CodeSecret {
constructor(num) {
// invokes the setter
this.code = num;
}
set code(num) {
if ( !/^ISBN/.test(num)) {
console.log("votre code doit commencer par ISBN");
return;
}
this._code = num;
}
get code() {
return this._code;
}
}
let t = new CodeSecret("dD1");
https://es6console.com/jpbn7x38/
class : Action
class Prefix {
constructor(pref) { // pas de fx arrow
this.pref= pref;
}
addPref(tab) {
return tab.map( ( {genre,nom} ) => {
let pref = genre =='m' ? `${this.pref}` : `${this.pref}e`;
return `${pref} ${this.upper(nom)}`
})
}
upper(s){
return s[0].toUpperCase() + s.slice(1);
}
}
pers = [
{nom: "Dupont",ville: "evry",genre: "f"},
{nom: "Brusel",ville: "belfort",genre: "m"}
];
let t = new Prefix("Cher");
console.log(t.addPref(pers));
Mélanger un tableau !
On veut mélanger les éléments d'un tableau :
["denis","gérard","nicolas","lolo"]
["nicolas","gérard","lolo","denis"]
idem en 1
["denis","gérard","nicolas","lolo"]
["denis","gérard","nicolas","lolo"]
idem en 0
["denis","gérard","nicolas","lolo"]
["nicolas","lolo","denis","gérard"]
TOP
Améliorer ce code :
test map !
const pers = [
{ nom: "Dupont", ville: "evry", sex: "f", born: 1903 },
{ nom: "Dupont", ville: "Paris", sex: "f", born: 2004 },
{ nom: "Brusel", ville: "belfort", sex: "h", born: 1930 }
];
const filles_callBack = pers.filter(function(p){
return (p.sex === "f");
});
const filles_callBackDest = pers.filter(function( {sex}){
return (sex === "f");
});
const filles_callBackArrowDestruc = pers.filter( ({sex} ) => sex == "f" );
filles.map(function annee( p, index ) {
return [p.nom,p.born]
});
filles.map(ajout);
filles.map(ajout_2);
filles.map(p=>p);
filles.map(p=>p["new"]="hallo");
filles.map(ageObj);
filles.map(ageVal);
filles.map(function({ born : annee }) {return { annee }});
filles.map(function({ born :annee, nom }) {return { nom,annee }});
filles.map(function ({ nom, ville }) {
return {
info: `${nom} habite ${ville}`
}
});
https://goo.gl/G6u1Cz
{ nom: "Dupont", ville: "evry", sex: "f", born: 1903 },
{ nom: "Dupont", ville: "Paris", sex: "f", born: 2004 },
{ nom: "Brusel", ville: "belfort", sex: "h", born: 1930 }
];
const filles_callBack = pers.filter(function(p){
return (p.sex === "f");
});
Comparer ces différentes écritures
const filles_callBackArrow = pers.filter(p => p.sex === "f");const filles_callBackDest = pers.filter(function( {sex}){
return (sex === "f");
});
const filles_callBackArrowDestruc = pers.filter( ({sex} ) => sex == "f" );
Pour chaque transformation donner le résultat sous forme graphique :
exemple
const filles= pers.filter(function(p){
return (p.sex === "f");
});
const dates = filles.map(function annee( p, index ) {
return {
num : index,
annee : p.born
};
});
en Action
function ageObj({ born }) {return { born }}
function ageVal({ born }) {return born}
function ajout(p) {p["new"] = "hallo";}
function ajout_2(p) {return p["new"] = "hallo";}
function ageObjDestruct({ born :annee }) {return { annee }};
function ageVal({ born }) {return born}
function ajout(p) {p["new"] = "hallo";}
function ajout_2(p) {return p["new"] = "hallo";}
function ageObjDestruct({ born :annee }) {return { annee }};
return [p.nom,p.born]
});
filles.map(ajout);
filles.map(ajout_2);
filles.map(p=>p);
filles.map(p=>p["new"]="hallo");
filles.map(ageObj);
filles.map(ageVal);
filles.map(function({ born : annee }) {return { annee }});
filles.map(function({ born :annee, nom }) {return { nom,annee }});
filles.map(function ({ nom, ville }) {
return {
info: `${nom} habite ${ville}`
}
});
https://goo.gl/G6u1Cz
Map en Action
Comment transformer :
[['eux', ' ', ' ' ],['A', 'B', 'C' ],['eux', ' ', ' ']]
en
[["eux", "A", "eux"],[" ", "B", " "],[" ", "C", " "]]
Aide
for of
let tabPers =
[
{
nom: "Dupont",
sex : "f"},
{
nom: "Brusel",
sex : "h"},
{
nom: "Dupont",
sex : "f"},
];
Cas des pointeurs
for (let pers of tabPers){
console.log(pers);
}
Cas de la déstructuration
for (let { nom } of tabPers){
console.log(nom);
}
A chaque itération, nous aurons :
{
let [ FORMAL_PARAMETERS ] = [ ACTUAL_PARAMETERS ];
{
CODE
}
}
ainsi
{
let [ { nom } ] = [ { nom: "Dupont",sex:"f" } ];
{
console.log( nom );
}
}
sera équivalent à
{
let [ { nom:nom } ] = [ { nom: "Dupont",sex:"f" } ];
{
console.log( nom );
}
}
et
{
let [ { nom } ] = [ { nom: "Dupont",sex:"f" } ];
{
console.log( nom );
}
}
Tu pointes ou tu tires ?
Que veux dire filtrer un tableau ?
La modification d'un élément filtré modifie-t-elle le tableau initial ?
La modification d'un élément filtré modifie-t-elle le tableau initial ?
Visualize : outil d'aide
Voici un lien pour comprendre le clonage d'objets avec :
Object.assign( objDestination, objSource)
Visualisation
this et la fonction flechée
function normalise(){
let normaliseT = this.valeurs.map(function(v){
return v / this.nb;
});
console.log(`valeurs normalisées ${normaliseT}`);
}
const obj = {valeurs:[3,6,12], nb:3};
normalise.call(obj);
Solution à ce problème classique :
function normalise(){
let normaliseT = this.valeurs.map(function(v){
return v / this.nb;
}.bind(this));
console.log(`valeurs normalisées ${normaliseT}`);
}
const obj = {valeurs:[3,6,12], nb:3};
normalise.call(obj);
Avec une fonction fléchée :
function normalise(){
let normaliseT = this.valeurs.map(v => v / this.nb);
console.log(`valeurs normalisées ${normaliseT}`);
}
const obj = {valeurs:[3,6,12], nb:3};
normalise.call(obj);
En action
lire un object !
Notez les différences d'affichage :
let u = {t:2,u:3};
console.log("u=" + u);
console.log(u);
let u = {t:2,u:3};
console.log("u=" + u);
console.log(u);
- "u=[object Object]"
- [object Object] {
t: 2,
u: 3
}
const propKeys = Reflect.ownKeys(res);
for (const propKey of propKeys) {
console.log([propKey, res[propKey]]);
}
itérator
function iterateOver(...args) {
let [from, to, step=1] = [...args];
const range = {
[Symbol.iterator]() {
this.current = from;
return this;
},
next() {
if (this.current <= to) {
let char = this.current;
this.current = String.fromCharCode(this.current.charCodeAt(0) + step);
return {
done: false,
value: char
};
} else {
return {
done: true
};
}
}
}
return range;
}
for (let num of iterateOver("A","W",5)) {
console.log(num);
}
let t = Array.from(iterateOver("A","J"), c => c.toLowerCase());
console.log(t);
fichier source
fichier source
JS Bin on jsbin.com
let [from, to, step=1] = [...args];
const range = {
[Symbol.iterator]() {
this.current = from;
return this;
},
next() {
if (this.current <= to) {
let char = this.current;
this.current = String.fromCharCode(this.current.charCodeAt(0) + step);
return {
done: false,
value: char
};
} else {
return {
done: true
};
}
}
}
return range;
}
for (let num of iterateOver("A","W",5)) {
console.log(num);
}
let t = Array.from(iterateOver("A","J"), c => c.toLowerCase());
console.log(t);
fichier source
fichier source
JS Bin on jsbin.com
Array.from + itérateur
let range = {
from: "A",
to: "W"
};
// 1. call to for..of initially calls this
range[Symbol.iterator] = function() {
// 2. ...it returns the iterator:
return {
current: this.from,
last: this.to,
// 3. next() is called on each iteration by the for..of loop
next() {
// 4. it should return the value as an object {done:.., value :...}
if (this.current <= this.last) {
let char = this.current;
this.current = String.fromCharCode(this.current.charCodeAt(0)+1);
return { done: false, value: char };
} else {
return { done: true };
}
}
};
};
for (let num of range) {
console.log(num);
}
let t = Array.from(range,c=>c.toLowerCase());
console.log(t);
JS Bin on jsbin.com
from: "A",
to: "W"
};
// 1. call to for..of initially calls this
range[Symbol.iterator] = function() {
// 2. ...it returns the iterator:
return {
current: this.from,
last: this.to,
// 3. next() is called on each iteration by the for..of loop
next() {
// 4. it should return the value as an object {done:.., value :...}
if (this.current <= this.last) {
let char = this.current;
this.current = String.fromCharCode(this.current.charCodeAt(0)+1);
return { done: false, value: char };
} else {
return { done: true };
}
}
};
};
for (let num of range) {
console.log(num);
}
let t = Array.from(range,c=>c.toLowerCase());
console.log(t);
code
JS Bin on jsbin.com
Array.from : magic
t = Array.from(Fib)
console.log(t);
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
fichier code
code
[Symbol.iterator]() {
let n1 = 1,
n2 = 1;
return {
[Symbol.iterator]() {
return this;
},
next() {
let current = n2;
n2 = n1;
n1 = n1 + current;
if (current <= 1000) { //sinon la boucle est infinie
return {
value: current,
done: false
};
} else {
return {
done: true
};
}
return {
value: current,
done: false
};
},
return () {
console.log(
`stop`
);
return {
done: true
};
}
};
}
};
t = Array.from(Fib)
console.log(t);
console.log(t);
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
fichier code
code
En action :
let Fib = {[Symbol.iterator]() {
let n1 = 1,
n2 = 1;
return {
[Symbol.iterator]() {
return this;
},
next() {
let current = n2;
n2 = n1;
n1 = n1 + current;
if (current <= 1000) { //sinon la boucle est infinie
return {
value: current,
done: false
};
} else {
return {
done: true
};
}
return {
value: current,
done: false
};
},
return () {
console.log(
`stop`
);
return {
done: true
};
}
};
}
};
t = Array.from(Fib)
console.log(t);
itérator :
Voici deux écritures de Fibonacci :
const Fibonacci = {
n1: 1,
n2: 1,
[Symbol.iterator]() {
return this;
},
next() {
let current = this.n2;
this.n2 = this.n1;
this.n1 = this.n1 + current;
return {
value: current,
done: false
};
},
return (v) {
return {
value: v,
done: true
};
}
};
let Fib = {
[Symbol.iterator]() {
let n1 = 1,
n2 = 1;
return {
[Symbol.iterator]() {
return this;
},
next() {
let current = n2;
n2 = n1;
n1 = n1 + current;
return {
value: current,
done: false
};
},
return () {
console.log(
`stop`
);
return {
value: v,
done: true
};
}
};
}
};
for (var v of Fib) {
console.log(v);
if (v > 50) break;
}
const Fibonacci = {
n1: 1,
n2: 1,
[Symbol.iterator]() {
return this;
},
next() {
let current = this.n2;
this.n2 = this.n1;
this.n1 = this.n1 + current;
return {
value: current,
done: false
};
},
return (v) {
return {
value: v,
done: true
};
}
};
let Fib = {
[Symbol.iterator]() {
let n1 = 1,
n2 = 1;
return {
[Symbol.iterator]() {
return this;
},
next() {
let current = n2;
n2 = n1;
n1 = n1 + current;
return {
value: current,
done: false
};
},
return () {
console.log(
`stop`
);
return {
value: v,
done: true
};
}
};
}
};
for (var v of Fib) {
console.log(v);
if (v > 50) break;
}
itérateur
let range = {
from: 65,
to: 90,
[Symbol.iterator]() {
return this;
},
next() {
if (this.from <= this.to) {
return {
done: false,
value: String.fromCharCode(this.from++)
};
} else {
return {
done: true
};
}
},
};
// A-W
for (let num of range) {
console.log(num);
}
from: 65,
to: 90,
[Symbol.iterator]() {
return this;
},
next() {
if (this.from <= this.to) {
return {
done: false,
value: String.fromCharCode(this.from++)
};
} else {
return {
done: true
};
}
},
};
// A-W
for (let num of range) {
console.log(num);
}
Inscription à :
Articles (Atom)