JustPaste
HomeCategoriesAboutDonateContactTerms of UsePrivacy Policy
JustPaste

Free online notepad — write and share instantly

Navigate

  • Home
  • Timeline
  • Categories

Info

  • About
  • Donate
  • Contact

Legal

  • Terms of Use
  • Privacy Policy

© 2026 JustPaste.app. All rights reserved.

Made with ♥ by JustPaste

prova | JustPaste.app
15 days ago6 views
💻Technology

prova

<!doctype html>
<html lang="ca">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Mini Joc Multiacció</title>
<style>
  :root{--bg:#0f172a;--ground:#0ea5a4;--panel:#0b1220}
  body{margin:0;font-family:Inter,Arial;background:var(--bg);color:#e6eef8;display:flex;flex-direction:column;align-items:center;gap:12px;padding:12px}
  canvas{background:linear-gradient(#071029,#0b1220);border-radius:8px;box-shadow:0 8px 30px rgba(2,6,23,0.6)}
  .hud{width:900px;display:flex;justify-content:space-between;align-items:center;gap:12px}
  .panel{background:var(--panel);padding:8px;border-radius:8px;font-size:14px}
  .controls{font-size:13px;color:#cbd5e1}
  button{background:#06b6d4;border:0;padding:8px 10px;border-radius:6px;color:#042027;cursor:pointer}
  @media(max-width:960px){canvas{width:100%;height:auto}}
</style>
</head>
<body>
<div class="hud">
  <div class="panel">Vida: <span id="hp">100</span></div>
  <div class="panel controls">
    Controls: ← → moure | Shift córrer | Space saltar | Z atacar | X esquivar | E recollir
  </div>
  <div class="panel"><button id="restart">Reinicia</button></div>
</div>

<canvas id="game" width="900" height="420"></canvas>

<script>
// Joc multiacció bàsic en Canvas
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

const keys = {};
window.addEventListener('keydown', e => keys[e.key.toLowerCase()] = true);
window.addEventListener('keyup', e => keys[e.key.toLowerCase()] = false);

document.getElementById('restart').onclick = () => init();

// Estat del jugador
const player = {
  x: 100, y: 0, w: 36, h: 48,
  vx: 0, vy: 0,
  speed: 1.6, runMult: 1.8,
  onGround: false,
  facing: 1, // 1 dreta, -1 esquerra
  hp: 100,
  invulnerable: 0,
  inventory: [],
  state: 'idle', // idle, run, jump, attack, dash
  dashTimer: 0,
  attackTimer: 0
};

// Entorn
const gravity = 0.45;
const groundY = 360;
let lastTime = 0;
let items = [];
let enemies = [];

// Inicialitza nivell, objectes i enemics
function init(){
  player.x = 100; player.y = 0; player.vx = 0; player.vy = 0;
  player.hp = 100; player.inventory = []; player.invulnerable = 0;
  items = [
    {x: 420, y: groundY-18, w:18, h:18, type:'gem'},
    {x: 700, y: groundY-18, w:18, h:18, type:'potion'}
  ];
  enemies = [
    {x: 520, y: groundY-48, w:36, h:48, vx:-0.6, hp:30},
    {x: 760, y: groundY-48, w:36, h:48, vx:-0.4, hp:20}
  ];
}
init();

// Colisió AABB
function collide(a,b){
  return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
}

// Lògica del jugador
function updatePlayer(dt){
  // Invulnerabilitat countdown
  if(player.invulnerable>0) player.invulnerable = Math.max(0, player.invulnerable - dt);

  // Moviment horitzontal
  let move = 0;
  if(keys['arrowleft'] || keys['a']) move -= 1;
  if(keys['arrowright'] || keys['d']) move += 1;

  const running = keys['shift'];
  const spd = player.speed * (running ? player.runMult : 1);

  // Dash (esquivar) amb X
  if(keys['x'] && player.dashTimer <= 0 && player.onGround){
    player.dashTimer = 0.22; // durada dash en segons
    player.vx = 10 * (player.facing || 1);
    player.state = 'dash';
  }

  // Si dash actiu, decrementa i aplica fricció
  if(player.dashTimer > 0){
    player.dashTimer -= dt;
    player.vx *= 0.92;
  } else {
    // Aplicar moviment normal
    player.vx = move * spd;
    if(move !== 0) player.facing = move > 0 ? 1 : -1;
  }

  // Saltar
  if((keys[' '] || keys['space']) && player.onGround){
    player.vy = -10.5;
    player.onGround = false;
    player.state = 'jump';
  }

  // Atac amb Z
  if(keys['z'] && player.attackTimer <= 0){
    player.attackTimer = 0.28;
    player.state = 'attack';
  }

  // Aplicar gravetat
  player.vy += gravity;
  player.x += player.vx;
  player.y += player.vy;

  // Col·lisió amb terra
  if(player.y + player.h >= groundY){
    player.y = groundY - player.h;
    player.vy = 0;
    player.onGround = true;
    if(player.dashTimer <= 0 && player.attackTimer <= 0){
      player.state = Math.abs(player.vx) > 0.1 ? 'run' : 'idle';
    }
  } else {
    player.onGround = false;
  }

  // Atac: comprovar col·lisions amb enemics
  if(player.attackTimer > 0){
    player.attackTimer -= dt;
    // hitbox frontal
    const hit = {
      x: player.x + (player.facing>0 ? player.w : -30),
      y: player.y + 8,
      w: 30, h: player.h - 16
    };
    enemies.forEach(e=>{
      if(e.hp>0 && collide(hit,e)){
        e.hp -= 20;
      }
    });
  }

  // Recollir amb E
  if(keys['e']){
    items = items.filter(it=>{
      if(collide(player, it)){
        player.inventory.push(it.type);
        return false;
      }
      return true;
    });
  }

  // Limitar posicions dins canvas
  player.x = Math.max(0, Math.min(canvas.width - player.w, player.x));
}

// Lògica enemics simple
function updateEnemies(dt){
  enemies.forEach(e=>{
    if(e.hp <= 0) return;
    e.x += e.vx;
    // girar en límits
    if(e.x < 300 || e.x > 860) e.vx *= -1;
    // col·lisió amb jugador
    if(collide(e, player) && player.invulnerable <= 0){
      player.hp -= 10;
      player.invulnerable = 0.8;
      player.vx = -player.facing * 4;
    }
  });
  // eliminar enemics morts
  enemies = enemies.filter(e=>e.hp>0);
}

// Render
function draw(){
  // fons
  ctx.clearRect(0,0,canvas.width,canvas.height);
  // cel
  const g = ctx.createLinearGradient(0,0,0,canvas.height);
  g.addColorStop(0,'#071029'); g.addColorStop(1,'#071a2a');
  ctx.fillStyle = g; ctx.fillRect(0,0,canvas.width,canvas.height);

  // terra
  ctx.fillStyle = '#0ea5a4'; ctx.fillRect(0, groundY, canvas.width, canvas.height-groundY);

  // items
  items.forEach(it=>{
    ctx.fillStyle = it.type === 'gem' ? '#f472b6' : '#60a5fa';
    ctx.fillRect(it.x, it.y, it.w, it.h);
    ctx.fillStyle = '#021124'; ctx.font='12px Arial'; ctx.fillText(it.type, it.x-6, it.y-6);
  });

  // enemics
  enemies.forEach(e=>{
    ctx.fillStyle = '#ef4444';
    ctx.fillRect(e.x, e.y, e.w, e.h);
    ctx.fillStyle = '#fff'; ctx.font='12px Arial'; ctx.fillText('HP:'+e.hp, e.x, e.y-6);
  });

  // jugador (simple sprite rectangle)
  ctx.save();
  // parpelleig si invulnerable
  if(player.invulnerable > 0 && Math.floor(player.invulnerable*10)%2===0) ctx.globalAlpha = 0.4;
  ctx.fillStyle = '#fbbf24';
  ctx.fillRect(player.x, player.y, player.w, player.h);
  // cap per indicar direcció
  ctx.fillStyle = '#0b1220';
  if(player.facing>0) ctx.fillRect(player.x+player.w-6, player.y+8, 6, 8);
  else ctx.fillRect(player.x, player.y+8, 6, 8);
  ctx.restore();

  // HUD inventari i vida
  document.getElementById('hp').textContent = player.hp;
  ctx.fillStyle = '#e6eef8'; ctx.font='13px Arial';
  ctx.fillText('Inventari: ' + (player.inventory.join(', ') || 'buit'), 12, 18);

  // Indicador d'estat
  ctx.fillStyle = '#cbd5e1'; ctx.fillText('Estat: ' + player.state, 12, 36);
}

// Bucle principal
function loop(ts){
  const dt = Math.min(0.033, (ts - lastTime) / 1000 || 0.016);
  lastTime = ts;

  updatePlayer(dt);
  updateEnemies(dt);
  draw();

  // condició de final
  if(player.hp <= 0){
    ctx.fillStyle = 'rgba(0,0,0,0.6)'; ctx.fillRect(0,0,canvas.width,canvas.height);
    ctx.fillStyle = '#fff'; ctx.font='36px Arial'; ctx.fillText('Has perdut', canvas.width/2 - 80, canvas.height/2);
    return;
  }

  requestAnimationFrame(loop);
}

requestAnimationFrame(loop);
</script>
</body>
</html>
← Back to timeline