tutorial

Unblocked AI:https://gemini.google.com/app

DONT USE IT FOR CHEATS AT SCHOOL DO UR HOMEWORK YES IM TALKING TO U uhhh who am I talking to….

Drift V8

(function(){

if(window.driftEditorActive) return;

window.driftEditorActive = true;

console.log("🏎️ Drift Sandbox v10 β€” Area Paint, Ball Mode, Rotate & Explosives!");


// === Basic page setup ===

document.body.innerHTML = '';

document.body.style.margin = '0';

document.body.style.overflow = 'hidden';

document.body.style.background = 'white';


// === Canvas ===

const canvas = document.createElement('canvas');

canvas.width = innerWidth;

canvas.height = innerHeight;

canvas.style.position = 'fixed';

canvas.style.left = '150px';

canvas.style.top = '0';

canvas.style.zIndex = 10;

document.body.appendChild(canvas);

const ctx = canvas.getContext('2d');


// === Sidebar UI ===

const sidebar = document.createElement('div');

sidebar.style.position = 'fixed';

sidebar.style.left = 0;

sidebar.style.top = 0;

sidebar.style.width = '150px';

sidebar.style.height = '100vh';

sidebar.style.background = '#f4f4f4';

sidebar.style.borderRight = '2px solid #ccc';

sidebar.style.display = 'flex';

sidebar.style.flexDirection = 'column';

sidebar.style.alignItems = 'center';

sidebar.style.paddingTop = '12px';

sidebar.style.fontFamily = 'sans-serif';

sidebar.style.zIndex = 20;

document.body.appendChild(sidebar);


function makeButton(label){

  const b = document.createElement('button');

  b.innerHTML = label;

  b.style.margin = '6px';

  b.style.padding = '6px 8px';

  b.style.width = '120px';

  b.style.cursor = 'pointer';

  b.style.borderRadius = '8px';

  b.style.border = '1px solid #888';

  b.style.background = '#fff';

  b.style.fontWeight = 'bold';

  sidebar.appendChild(b);

  return b;

}


// Tool buttons

const wallBtn  = makeButton('🧱 Wall');

const boostBtn = makeButton('⚑ Boost');

const mudBtn   = makeButton('🟀 Mud');

const iceBtn   = makeButton('🧊 Ice');

const slowBtn  = makeButton('🐒 Slower');

const boomBtn  = makeButton('πŸ’₯ Explosive');

const stopBtn  = makeButton('β›” Stopper');

const delBtn   = makeButton('πŸ—‘οΈ Delete');


// Mode toggle (ball / area)

const modeBtn = makeButton('Mode: Ball');

let placementMode = 'ball'; // 'ball' or 'area'


// Help text

const help = document.createElement('div');

help.style.fontSize = '12px';

help.style.textAlign = 'center';

help.style.padding = '6px';

help.style.width = '130px';

help.innerHTML = 'Click tool β†’ click to place.<br>Area mode: click corner A β†’ click corner B.<br>Press <b>R</b> to rotate ghost.';

sidebar.appendChild(help);


// Nitro bar

const nitroBar = document.createElement('div');

nitroBar.style.position='fixed';

nitroBar.style.bottom='18px';

nitroBar.style.left='180px';

nitroBar.style.width='220px';

nitroBar.style.height='18px';

nitroBar.style.background='#ccc';

nitroBar.style.borderRadius='9px';

nitroBar.style.overflow='hidden';

nitroBar.style.border='2px solid #444';

nitroBar.style.zIndex = 30;

document.body.appendChild(nitroBar);

const nitroFill = document.createElement('div');

nitroFill.style.height='100%';

nitroFill.style.width='100%';

nitroFill.style.background='#00bfff';

nitroFill.style.transition='width 0.08s linear';

nitroBar.appendChild(nitroFill);


// === State ===

const placed = []; // placed objects {type,x,y,w?,h?,angle?}

let placingType = null;

let ghost = null; // {type,x,y,angle}

let areaStart = null; // for area mode first corner

let mouse = {x:0,y:0};

const explosions = []; // {x,y,radius,life,maxR}

const mudTrail = [];


// button handlers

function startPlacing(type){

  placingType = type;

  ghost = {type, x: mouse.x, y: mouse.y, angle: 0};

  areaStart = null;

}

wallBtn.onclick = ()=> startPlacing('wall');

boostBtn.onclick = ()=> startPlacing('boost');

mudBtn.onclick = ()=> startPlacing('mud');

iceBtn.onclick = ()=> startPlacing('ice');

slowBtn.onclick = ()=> startPlacing('slow');

boomBtn.onclick = ()=> startPlacing('boom');

stopBtn.onclick = ()=> startPlacing('stop');

delBtn.onclick = ()=> { placingType = 'delete'; ghost = {type:'delete',x:mouse.x,y:mouse.y,angle:0}; areaStart=null; };


modeBtn.onclick = ()=>{

  placementMode = placementMode === 'ball' ? 'area' : 'ball';

  modeBtn.innerHTML = 'Mode: ' + (placementMode==='ball'? 'Ball' : 'Area');

  areaStart = null;

};


// === Mouse events on canvas ===

canvas.addEventListener('mousemove', e=>{

  mouse.x = e.clientX - 150;

  mouse.y = e.clientY;

  if(ghost) { ghost.x = mouse.x; ghost.y = mouse.y; }

});

canvas.addEventListener('click', e=>{

  if(!placingType) return;

  // delete mode single click: remove nearest

  if(placingType === 'delete'){

    const idx = placed.findIndex(o => Math.hypot(o.x - mouse.x, o.y - mouse.y) < (o.w||20) + 12);

    if(idx !== -1) placed.splice(idx,1);

    return;

  }


  if(placementMode === 'ball'){

    // place a single object

    placeObject(placingType, mouse.x, mouse.y, ghost && ghost.angle || 0);

    if(placingType !== 'wall') { placingType = null; ghost = null; } // keep wall selected for convenience

    return;

  }


  // area mode

  if(!areaStart){

    areaStart = {x: mouse.x, y: mouse.y, angle: ghost ? ghost.angle : 0};

  } else {

    // finalize rectangle from areaStart to current mouse

    const x1 = Math.min(areaStart.x, mouse.x);

    const y1 = Math.min(areaStart.y, mouse.y);

    const x2 = Math.max(areaStart.x, mouse.x);

    const y2 = Math.max(areaStart.y, mouse.y);


    // fill grid with objects spaced by cell size

    const cell = placementCellSizeFor(placingType);

    const offsetX = cell/2;

    const offsetY = cell/2;

    for(let px = x1 + offsetX; px <= x2; px += cell){

      for(let py = y1 + offsetY; py <= y2; py += cell){

        placeObject(placingType, Math.round(px), Math.round(py), ghost ? ghost.angle : 0);

      }

    }

    areaStart = null;

    // keep placingType selected for repeat painting

  }

});


// helper: choose a sensible cell size depending on type

function placementCellSizeFor(type){

  switch(type){

    case 'wall': return 44;

    case 'boost': return 46;

    case 'mud': return 52;

    case 'ice': return 52;

    case 'slow': return 46;

    case 'boom': return 50;

    case 'stop': return 44;

    default: return 44;

  }

}


// place single object helper

function placeObject(type, x, y, angle = 0){

  // for walls we allow rotated rectangles (angle multiple of 90)

  const obj = {type, x, y, angle: angle || 0};

  // dimension presets (for collision checks & drawing)

  if(type === 'wall'){

    obj.w = 40; obj.h = 12;

    // if angle is 90 or 270 swap w/h

    const a = ((obj.angle % (Math.PI*2)) + Math.PI*2) % (Math.PI*2);

    if(Math.abs(a - Math.PI/2) < 0.01 || Math.abs(a - 3*Math.PI/2) < 0.01){

      [obj.w, obj.h] = [obj.h, obj.w];

    }

  } else if(type === 'boost'){ obj.r = 20; }

  else if(type === 'mud'){ obj.r = 26; }

  else if(type === 'ice'){ obj.r = 26; }

  else if(type === 'slow'){ obj.r = 20; }

  else if(type === 'boom'){ obj.r = 20; obj.explosive = true; obj.broken = false; }

  else if(type === 'stop'){ obj.r = 18; }

  placed.push(obj);

}


// rotate ghost with R

window.addEventListener('keydown', e=>{

  if(e.key === 'r' || e.key === 'R'){

    if(ghost){

      // rotate by 90deg

      ghost.angle = (ghost.angle || 0) + Math.PI/2;

      // normalize

      ghost.angle = ((ghost.angle % (Math.PI*2)) + Math.PI*2) % (Math.PI*2);

    }

  }

});


// === Car & physics ===

const car = {

  x: canvas.width/2,

  y: canvas.height/2,

  angle: 0,

  speed: 0,

  accel: 0.22,

  friction: 0.02,

  turnFriction: 0.05,

  turnRate: 0.07,

  driftFactor: 0.86,

  maxSpeed: 10.5,

  boostTime: 0,

  nitro: 100

};

const keys = {};

const trails = [];


window.addEventListener('keydown', e=>{

  if(["ArrowUp","ArrowDown","ArrowLeft","ArrowRight"," "].includes(e.key)) e.preventDefault();

  keys[e.key] = true;

});

window.addEventListener('keyup', e=> keys[e.key] = false);


// place explosion when boom breaks

function spawnExplosion(x,y){

  explosions.push({x,y,life:1,maxR:140,r:8});

}


// === Update car each frame ===

function updateCar(){

  const isBoosting = car.boostTime > 0;

  const isNitro = keys[' '] && car.nitro > 0;


  let accel = car.accel;

  let max = car.maxSpeed;

  let currentFriction = car.friction;

  let turnF = car.turnFriction;


  if(isBoosting){ car.boostTime--; accel *= 2; max *= 1.8; }

  if(isNitro){ accel *= 3; max *= 2.5; car.nitro -= 0.9; }

  else car.nitro = Math.min(100, car.nitro + 0.35);


  nitroFill.style.width = car.nitro + "%";


  if(keys['ArrowUp']) car.speed += accel;

  if(keys['ArrowDown']) car.speed -= accel;


  const turning = keys['ArrowLeft'] || keys['ArrowRight'];

  if(keys['ArrowLeft']) car.angle -= car.turnRate * (car.speed > 0 ? 1 : -1);

  if(keys['ArrowRight']) car.angle += car.turnRate * (car.speed > 0 ? 1 : -1);


  // Terrain detection & interactions

  let onMud = false, onIce = false, onSlow = false;

  for(let i = placed.length - 1; i >= 0; i--){

    const o = placed[i];

    // approximate hit tests:

    if(o.type === 'wall'){

      // axis-aligned rotated rectangle check (simple bounding box because walls small)

      const dx = Math.abs(car.x - o.x);

      const dy = Math.abs(car.y - o.y);

      const rw = (o.w||40)/2 + 12, rh = (o.h||12)/2 + 12;

      if(dx < rw && dy < rh){

        // bounce off

        car.speed *= -0.45;

        car.x -= Math.cos(car.angle) * 12;

        car.y -= Math.sin(car.angle) * 12;

      }

    } else {

      const dx = car.x - o.x, dy = car.y - o.y;

      const dist = Math.hypot(dx,dy);

      const radius = (o.r||20) + 12;

      if(dist < radius){

        if(o.type === 'boost'){ car.boostTime = Math.max(car.boostTime, 160); }

        if(o.type === 'mud'){ onMud = true; }

        if(o.type === 'ice'){ onIce = true; }

        if(o.type === 'slow'){ onSlow = true; }

        if(o.type === 'stop'){ car.speed = 0; }

        if(o.type === 'boom' && !o.broken){

          // explode: remove explosive and spawn explosion

          o.broken = true;

          // remove object

          placed.splice(i,1);

          // compute direction from explosion center to car, push car away

          const vx = car.x - o.x, vy = car.y - o.y;

          const ang = Math.atan2(vy, vx);

          car.angle = ang;

          car.speed = Math.min(18, 8 + Math.hypot(vx,vy) * 0.06);

          spawnExplosion(o.x, o.y);

        }

      }

    }

  }


  // terrain modifications

  if(onIce){ currentFriction = 0; turnF = 0.005; }

  if(onMud){ currentFriction = Math.max(currentFriction, 0.04); max *= 0.65; }

  if(onSlow){ currentFriction += 0.03; max *= 0.6; }


  // More sliding when turning: reduce speed a bit when steering to create slide feeling

  if(turning) car.speed *= (1 - turnF);

  else car.speed *= (1 - currentFriction);


  if(car.speed > max) car.speed = max;

  if(car.speed < -max/2) car.speed = -max/2;


  car.x += Math.cos(car.angle) * car.speed;

  car.y += Math.sin(car.angle) * car.speed;


  // wrap

  if(car.x < 0) car.x = canvas.width;

  if(car.x > canvas.width) car.x = 0;

  if(car.y < 0) car.y = canvas.height;

  if(car.y > canvas.height) car.y = 0;


  // trails + mud trail

  const backOffset = 20;

  const isHot = isBoosting || isNitro;

  const leftTrail = {

    x: car.x - Math.cos(car.angle) * backOffset + Math.sin(car.angle) * 6,

    y: car.y - Math.sin(car.angle) * backOffset - Math.cos(car.angle) * 6,

    life: 1, heat: isHot ? 1 : 0,

    color: isHot ? '#ff0000' : '#000'

  };

  const rightTrail = {

    x: car.x - Math.cos(car.angle) * backOffset - Math.sin(car.angle) * 6,

    y: car.y - Math.sin(car.angle) * backOffset + Math.cos(car.angle) * 6,

    life: 1, heat: isHot ? 1 : 0,

    color: isHot ? '#ff0000' : '#000'

  };

  trails.push(leftTrail, rightTrail);

  if(onMud) mudTrail.push({x:car.x, y:car.y, life:1});

  if(trails.length > 1200) trails.splice(0, 2);

  if(mudTrail.length > 800) mudTrail.splice(0, 4);

}


// === Draw routines ===

function drawCar(x,y,a){

  ctx.save();

  ctx.translate(x,y);

  ctx.rotate(a);

  // body

  ctx.fillStyle = '#ff4d4d';

  ctx.strokeStyle = '#222';

  ctx.lineWidth = 3;

  roundRect(ctx, -15, -10, 30, 20, 5, true, true);

  // window

  ctx.fillStyle = '#66ccff';

  roundRect(ctx, -10, -7, 20, 7, 2, true, false);

  ctx.restore();

}


function roundRect(ctx, x, y, w, h, r, fill, stroke){

  if (typeof r === 'undefined') r = 5;

  ctx.beginPath();

  ctx.moveTo(x + r, y);

  ctx.arcTo(x + w, y, x + w, y + h, r);

  ctx.arcTo(x + w, y + h, x, y + h, r);

  ctx.arcTo(x, y + h, x, y, r);

  ctx.arcTo(x, y, x + w, y, r);

  ctx.closePath();

  if(fill) ctx.fill();

  if(stroke) ctx.stroke();

}


// draw placed objects, ghost, explosions, trails

function drawObjects(){

  // placed

  for(const o of placed){

    ctx.save();

    if(o.type === 'wall'){

      ctx.translate(o.x, o.y);

      ctx.rotate(o.angle || 0);

      ctx.fillStyle = '#444';

      ctx.fillRect(-(o.w||40)/2, -(o.h||12)/2, o.w||40, o.h||12);

    } else if(o.type === 'boost'){

      ctx.fillStyle = '#00ff88';

      ctx.beginPath(); ctx.arc(o.x, o.y, o.r||20, 0, Math.PI*2); ctx.fill();

    } else if(o.type === 'mud'){

      ctx.fillStyle = '#6b4b2a';

      ctx.beginPath(); ctx.arc(o.x, o.y, o.r||26, 0, Math.PI*2); ctx.fill();

    } else if(o.type === 'ice'){

      ctx.fillStyle = '#bfe8ff';

      ctx.beginPath(); ctx.arc(o.x, o.y, o.r||26, 0, Math.PI*2); ctx.fill();

    } else if(o.type === 'slow'){

      ctx.fillStyle = '#fdd835';

      ctx.beginPath(); ctx.arc(o.x, o.y, o.r||20, 0, Math.PI*2); ctx.fill();

    } else if(o.type === 'boom'){

      ctx.fillStyle = '#ff3333';

      ctx.beginPath(); ctx.arc(o.x, o.y, o.r||20, 0, Math.PI*2); ctx.fill();

      // little center

      ctx.fillStyle = '#fff';

      ctx.beginPath(); ctx.arc(o.x, o.y, 4, 0, Math.PI*2); ctx.fill();

    } else if(o.type === 'stop'){

      ctx.fillStyle = '#000';

      ctx.beginPath(); ctx.arc(o.x, o.y, o.r||18, 0, Math.PI*2); ctx.fill();

    }

    ctx.restore();

  }


  // ghost preview

  if(ghost){

    ctx.save();

    ctx.globalAlpha = 0.45;

    if(placementMode === 'area' && areaStart){

      // draw rectangle area between areaStart and current mouse

      const x1 = Math.min(areaStart.x, mouse.x);

      const y1 = Math.min(areaStart.y, mouse.y);

      const x2 = Math.max(areaStart.x, mouse.x);

      const y2 = Math.max(areaStart.y, mouse.y);

      ctx.fillStyle = '#b0b0b0';

      ctx.fillRect(x1, y1, x2 - x1, y2 - y1);

    } else {

      if(ghost.type === 'wall'){

        ctx.translate(ghost.x, ghost.y);

        ctx.rotate(ghost.angle || 0);

        ctx.fillStyle = '#888';

        ctx.fillRect(-20, -6, 40, 12);

      } else {

        ctx.fillStyle = '#888';

        ctx.beginPath(); ctx.arc(ghost.x, ghost.y, placementCellSizeFor(ghost.type)/2 - 4, 0, Math.PI*2); ctx.fill();

      }

    }

    ctx.restore();

  }


  // explosions

  for(const ex of explosions){

    ctx.save();

    const alpha = ex.life;

    const r = ex.r;

    // expanding ring

    ctx.globalAlpha = Math.min(0.6, alpha*0.6);

    ctx.fillStyle = 'rgba(255,140,0,0.9)';

    ctx.beginPath();

    ctx.arc(ex.x, ex.y, r/2, 0, Math.PI*2);

    ctx.fill();

    // ring

    ctx.globalAlpha = Math.max(0, alpha);

    ctx.strokeStyle = `rgba(255,120,0,${alpha})`;

    ctx.lineWidth = 6 * alpha;

    ctx.beginPath();

    ctx.arc(ex.x, ex.y, r, 0, Math.PI*2);

    ctx.stroke();

    ctx.restore();

  }

}


// draw trails and mud trail

function drawTrails(){

  for(const t of trails){

    if(t.heat > 0){

      let c = '#ff0000';

      if(t.heat < 0.66 && t.heat >= 0.33) c = '#ff7f00';

      if(t.heat < 0.33) c = '#ffff00';

      ctx.fillStyle = c;

    } else ctx.fillStyle = t.color;

    ctx.globalAlpha = t.life * 0.28;

    ctx.beginPath();

    ctx.arc(t.x, t.y, 2.2, 0, Math.PI*2);

    ctx.fill();

    ctx.globalAlpha = 1;

    t.life -= 0.014;

    if(t.heat > 0) t.heat -= 0.02;

  }

  for(const m of mudTrail){

    ctx.fillStyle = '#6b4b2a';

    ctx.globalAlpha = Math.min(0.6, m.life * 0.9);

    ctx.beginPath();

    ctx.arc(m.x, m.y, 3.5, 0, Math.PI*2);

    ctx.fill();

    ctx.globalAlpha = 1;

    m.life -= 0.008;

  }

}


// === Main loop ===

function loop(){

  ctx.clearRect(0,0,canvas.width,canvas.height);

  updateCar();

  drawTrails();

  drawObjects();

  drawCar(car.x, car.y, car.angle);


  // update explosions

  for(let i = explosions.length - 1; i >= 0; i--){

    const ex = explosions[i];

    ex.r += (ex.maxR / 30);

    ex.life -= 0.04;

    if(ex.life <= 0) explosions.splice(i,1);

  }


  requestAnimationFrame(loop);

}

loop();


// === Helpers & resize ===

window.addEventListener('resize', ()=>{ canvas.width = innerWidth; canvas.height = innerHeight; });


// utility: approx point in rect (used earlier maybe)

/* nothing extra */


// End script

})();