Le Glitch

Un glitch désigne une défaillance technique ou électronique temporaire

Log in to post a comment.

// --- Paramètres des Lignes ---
const nb_lignes = 150; // min=50, max=300, step=1 (Nombre de lignes)
const desordre = 1.5; // min=0, max=5, step=0.1 (Variation d'espacement)

// --- Paramètres de l'illusion (Décalage du Masque) ---
const decalage_x = -7; // min=-40, max=40, step=1
const decalage_y = 7; // min=-40, max=40, step=1

// --- Forme 1 (Principale) ---
const forme1 = 0; // min=0, max=1, step=1 (0 = Rectangle, 1 = Cercle)
const taille_x1 = 45; // min=5, max=90, step=1
const taille_y1 = 45; // min=5, max=90, step=1
const rotation1 = 45; // min=0, max=360, step=1

// --- Forme 2 (Optionnelle, permet de faire un trou dans la Forme 1) ---
const active2 = 0; // min=0, max=1, step=1 (0 = Désactivé, 1 = Activé)
const forme2 = 1; // min=0, max=1, step=1 (0 = Rectangle, 1 = Cercle)
const taille_x2 = 20; // min=5, max=90, step=1
const taille_y2 = 20; // min=5, max=90, step=1
const rotation2 = 0; // min=0, max=360, step=1
const offset_x2 = 0; // min=-50, max=50, step=1
const offset_y2 = 0; // min=-50, max=50, step=1

Canvas.setpenopacity(1);
const turtle = new Turtle();

// Génération des lignes de base avec leur espacement chaotique figé
function pseudoRandom(seed) {
    return Math.abs(Math.sin(seed * 12.9898 + 78.233) * 43758.5453) % 1;
}

const lignes = [];
const espacement_moyen = 190 / nb_lignes;
for (let i = 0; i < nb_lignes; i++) {
    let y_base = -95 + (i * espacement_moyen);
    let y_final = y_base + (pseudoRandom(i) * desordre * espacement_moyen);
    lignes.push(y_final);
}

// Mathématiques de rotation pour aligner les lignes avec la forme 1
const rad1 = rotation1 * Math.PI / 180;
const cos1 = Math.cos(rad1);
const sin1 = Math.sin(rad1);

function testShape(x, y, f_type, tx, ty, rot, ox, oy) {
    let dx = x - ox;
    let dy = y - oy;
    const rad = -rot * Math.PI / 180;
    const nx = dx * Math.cos(rad) - dy * Math.sin(rad);
    const ny = dx * Math.sin(rad) + dy * Math.cos(rad);

    if (f_type === 0) {
        return Math.abs(nx) <= tx && Math.abs(ny) <= ty; // Rectangle
    } else {
        return (nx * nx) / (tx * tx) + (ny * ny) / (ty * ty) <= 1; // Ellipse
    }
}

function isInsideBaseMask(x, y) {
    let in1 = testShape(x, y, forme1, taille_x1, taille_y1, rotation1, 0, 0);
    if (active2 === 1) {
        let in2 = testShape(x, y, forme2, taille_x2, taille_y2, rotation2, offset_x2, offset_y2);
        return in1 !== in2; // XOR : Exclut la forme 2 de la forme 1
    }
    return in1;
}

function isInsideShiftedMask(x, y) {
    return isInsideBaseMask(x - decalage_x, y - decalage_y);
}

// Le test pour la Phase 2 : On simule l'espace local pour y chercher les limites du masque
function phase2MaskLocal(x_local, y_local) {
    let wx = x_local * cos1 - y_local * sin1 + decalage_x;
    let wy = x_local * sin1 + y_local * cos1 + decalage_y;
    return isInsideShiftedMask(wx, wy);
}

function findBoundary(x1, x2, y, maskFunc) {
    let left = x1;
    let right = x2;
    let state = maskFunc(left, y);
    for (let i = 0; i < 12; i++) { 
        let mid = (left + right) / 2;
        if (maskFunc(mid, y) === state) left = mid;
        else right = mid;
    }
    return (left + right) / 2;
}

function getSegments(y, maskFunc, wantInside, minX, maxX) {
    let crossings = [minX];
    let wasInside = maskFunc(minX, y);
    
    for (let x = minX + 1; x <= maxX; x += 1) {
        let inside = maskFunc(x, y);
        if (inside !== wasInside) {
            crossings.push(findBoundary(x - 1, x, y, maskFunc));
            wasInside = inside;
        }
    }
    crossings.push(maxX);

    let segments = [];
    for (let i = 0; i < crossings.length - 1; i++) {
        let mid = (crossings[i] + crossings[i+1]) / 2;
        if (maskFunc(mid, y) === wantInside) {
            segments.push([crossings[i], crossings[i+1]]);
        }
    }
    return segments;
}

let index = 0;
let phase = 0; 

function walk(i) {
    // --- PHASE 1 : Fond horizontal, contourne le masque ---
    if (phase === 0) { 
        if (index >= lignes.length) {
            phase = 1;
            index = 0;
            return true;
        }
        let y = lignes[index];
        let segments = getSegments(y, isInsideBaseMask, false, -105, 105);
        for (let seg of segments) {
            turtle.jump(seg[0], y);
            turtle.goto(seg[1], y);
        }
        index++;
        return true;
        
    } 
    // --- PHASE 2 : Lignes internes pivotées avec la forme ---
    else if (phase === 1) { 
        if (index >= lignes.length) {
            return false;
        }
        let y_local = lignes[index]; 
        // On cherche les limites dans l'espace "non pivoté" de la forme
        let segments = getSegments(y_local, phase2MaskLocal, true, -150, 150);
        
        for (let seg of segments) {
            // On applique la matrice de rotation pour tracer de vraies lignes inclinées
            let wx1 = seg[0] * cos1 - y_local * sin1 + decalage_x;
            let wy1 = seg[0] * sin1 + y_local * cos1 + decalage_y;
            let wx2 = seg[1] * cos1 - y_local * sin1 + decalage_x;
            let wy2 = seg[1] * sin1 + y_local * cos1 + decalage_y;
            
            turtle.jump(wx1, wy1);
            turtle.goto(wx2, wy2);
        }
        index++;
        return true;
    }
}