403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /var/www/arni-solutions.de/web/slots/js/engine/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/arni-solutions.de/web/slots/js/engine/WheelEngine.js
/* Reel Royale – WheelEngine: animierter Roulette-Kessel + Kugel.
   Rad und Kugel drehen gegenläufig, beschleunigen/laufen aus, Kugel fällt ins
   serverbestimmte Fach (top = Zeiger). Reine Canvas-Grafik. */
export class WheelEngine {
  constructor(canvas, config, audio) {
    this.canvas = canvas;
    this.ctx = canvas.getContext('2d');
    this.wheel = config.wheel;          // [0,32,15,...]
    this.colors = config.colors;        // {n: color}
    this.audio = audio;
    this.n = this.wheel.length;         // 37
    this.seg = (Math.PI * 2) / this.n;
    this.wheelAngle = 0;
    this.ballAngle = 0;
    this.ballR = 1;
    this._dpr = Math.min(window.devicePixelRatio || 1, 2);
    this._setup();
    this.draw(0, 0, 0.86);
  }

  _setup() {
    const size = this.canvas.clientWidth || 380;
    this.canvas.width = size * this._dpr;
    this.canvas.height = size * this._dpr;
    this.ctx.setTransform(this._dpr, 0, 0, this._dpr, 0, 0);
    this.size = size;
    this.cx = size / 2; this.cy = size / 2;
    this.R = size / 2 - 4;
  }

  _segColor(n) {
    const c = this.colors[n];
    return c === 'green' ? '#0a8a4f' : c === 'red' ? '#d4332f' : '#1a1a20';
  }

  // canvas-Winkel: top = -PI/2, im Uhrzeigersinn wachsend
  draw(wheelAngle, ballAngle, ballR) {
    const { ctx, cx, cy, R } = this;
    ctx.clearRect(0, 0, this.size, this.size);

    // Außenring (Holz)
    ctx.save(); ctx.translate(cx, cy);
    ctx.beginPath(); ctx.arc(0, 0, R, 0, 7);
    const ring = ctx.createRadialGradient(0, 0, R * 0.7, 0, 0, R);
    ring.addColorStop(0, '#6b3f1d'); ring.addColorStop(1, '#2c1809');
    ctx.fillStyle = ring; ctx.fill();
    ctx.lineWidth = 2; ctx.strokeStyle = 'rgba(255,215,140,.5)'; ctx.stroke();

    // Fächer (im gedrehten Rad-Frame)
    ctx.save();
    ctx.rotate(wheelAngle);
    const rOuter = R * 0.9, rInner = R * 0.55;
    for (let i = 0; i < this.n; i++) {
      const a0 = i * this.seg - Math.PI / 2;
      const a1 = a0 + this.seg;
      ctx.beginPath();
      ctx.arc(0, 0, rOuter, a0, a1);
      ctx.arc(0, 0, rInner, a1, a0, true);
      ctx.closePath();
      ctx.fillStyle = this._segColor(this.wheel[i]);
      ctx.fill();
      ctx.lineWidth = 1; ctx.strokeStyle = 'rgba(255,255,255,.18)'; ctx.stroke();
    }
    // Nabe
    ctx.beginPath(); ctx.arc(0, 0, rInner, 0, 7);
    const hub = ctx.createRadialGradient(0, 0, 4, 0, 0, rInner);
    hub.addColorStop(0, '#caa92e'); hub.addColorStop(.6, '#8a6b1d'); hub.addColorStop(1, '#3a2c0c');
    ctx.fillStyle = hub; ctx.fill();
    ctx.strokeStyle = 'rgba(0,0,0,.4)'; ctx.stroke();
    // Kreuz-Speichen
    ctx.strokeStyle = 'rgba(255,240,200,.5)'; ctx.lineWidth = 3;
    for (let k = 0; k < 4; k++) {
      ctx.beginPath(); ctx.moveTo(0, 0);
      ctx.lineTo(Math.cos(k * Math.PI / 2) * rInner, Math.sin(k * Math.PI / 2) * rInner); ctx.stroke();
    }
    ctx.restore(); // zurück in den (cx,cy)-Frame ohne Rad-Rotation

    // Zahlen als eigene Ebene – saubere Einzel-Transformation, garantiert alle 37 sichtbar
    ctx.font = `800 ${Math.max(9, Math.round(R * 0.062))}px Inter, Arial, sans-serif`;
    ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
    ctx.lineJoin = 'round'; ctx.lineWidth = Math.max(2, R * 0.018);
    const rNum = rOuter - R * 0.085;
    for (let i = 0; i < this.n; i++) {
      const phi = wheelAngle + i * this.seg + this.seg / 2; // im Uhrzeigersinn ab oben
      const label = String(this.wheel[i]);
      ctx.save();
      ctx.translate(Math.sin(phi) * rNum, -Math.cos(phi) * rNum);
      ctx.rotate(phi); // radial, dreht mit dem Rad (wie echtes Roulette)
      ctx.strokeStyle = 'rgba(0,0,0,.7)'; ctx.strokeText(label, 0, 0);
      ctx.fillStyle = '#fff'; ctx.fillText(label, 0, 0);
      ctx.restore();
    }
    ctx.restore(); // outer (translate cx,cy)

    // Kugel (absolute Lage, top=-PI/2)
    const br = R * ballR;
    const ba = ballAngle - Math.PI / 2;
    const bx = cx + Math.cos(ba) * br;
    const by = cy + Math.sin(ba) * br;
    ctx.beginPath(); ctx.arc(bx, by, Math.max(4, R * 0.035), 0, 7);
    const bg = ctx.createRadialGradient(bx - 2, by - 2, 1, bx, by, R * 0.04);
    bg.addColorStop(0, '#fff'); bg.addColorStop(1, '#bcbcbc');
    ctx.fillStyle = bg; ctx.fill();

    // Zeiger oben
    ctx.beginPath(); ctx.moveTo(cx - 8, 2); ctx.lineTo(cx + 8, 2); ctx.lineTo(cx, 20); ctx.closePath();
    ctx.fillStyle = '#ffce53'; ctx.fill();
  }

  /** Dreht zum gegebenen Gewinn-Index (Position in this.wheel). Promise nach Stopp. */
  spin(number) {
    const idx = this.wheel.indexOf(number);
    this.audio.play('rlStart');

    // Endwinkel des Rades, sodass Fach idx oben (top) liegt
    const targetMod = -(idx * this.seg + this.seg / 2);
    const wheelStart = this.wheelAngle % (Math.PI * 2);
    const wheelTurns = 5;
    let wheelEnd = wheelTurns * Math.PI * 2 + targetMod;
    while (wheelEnd < wheelStart + 3 * Math.PI * 2) wheelEnd += Math.PI * 2;

    const ballTurns = 9;
    const ballStart = 0;
    const ballEnd = -ballTurns * Math.PI * 2;     // endet bei top (0 mod 2π)

    const dur = 5200;
    const t0 = performance.now();
    let lastTick = -1;

    const easeWheel = (t) => 1 - Math.pow(1 - t, 3);
    const easeBall = (t) => 1 - Math.pow(1 - t, 4);

    return new Promise((resolve) => {
      const anim = (now) => {
        const t = Math.min(1, (now - t0) / dur);
        this.wheelAngle = wheelStart + (wheelEnd - wheelStart) * easeWheel(t);
        this.ballAngle = ballStart + (ballEnd - ballStart) * easeBall(t);
        // Kugel fällt in den letzten 22% nach innen
        if (t < 0.78) this.ballR = 0.86;
        else this.ballR = 0.86 - (0.86 - 0.72) * ((t - 0.78) / 0.22);
        this.draw(this.wheelAngle, this.ballAngle, this.ballR);

        // Tick-Sound abhängig von Geschwindigkeit
        const tickN = Math.floor((1 - t) * 60 * (1 - t));
        if (tickN !== lastTick && t < 0.92) { lastTick = tickN; if (Math.random() < 0.6) this.audio.play('ballRoll'); }
        if (t >= 1) { this.audio.play('ballDrop'); resolve(); return; }
        requestAnimationFrame(anim);
      };
      requestAnimationFrame(anim);
    });
  }

  resize() { this._setup(); this.draw(this.wheelAngle, this.ballAngle, 0.86); }
}

Youez - 2016 - github.com/yon3zu
LinuXploit