🎮ArcadeLab

Pizzería Simulador 2D 🇦🇷

by MegaGalaxy31
716 lines19.7 KB
▶ Play
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pizzería Simulador 2D 🇦🇷</title>
<style>
* {box-sizing: border-box; margin: 0; padding: 0;}
body {
  font-family: 'Segoe UI', Roboto, Arial, sans-serif;
  background: #2c1810;
  color: #f8f4e9;
  display: flex;
  justify-content: center;
  line-height: 1.5;
}
#app {
  width: 100%;
  max-width: 980px;
  padding: 12px;
}
h1 {
  text-align: center;
  margin: 8px 0 16px;
  font-size: 24px;
  color: #ffcc44;
  text-shadow: 2px 2px 0 #884400;
}

/* Panel Superior */
#top {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px;
  background: #442614;
  padding: 12px;
  border-radius: 8px;
  border: 3px solid #884400;
  font-size: 11px;
}
.top-block {
  background: #5a331a;
  padding: 8px;
  border-radius: 6px;
  border: 2px solid #995511;
  text-align: center;
}
.top-label {
  font-size: 9px;
  color: #e0c8a0;
  display: block;
}
.top-value {
  font-weight: bold;
  color: #fff8e6;
  font-size: 13px;
}
.neg { color: #ff6666; }
.pos { color: #88ff88; }

/* Botones Principales */
.btn-row {
  display: flex;
  gap: 8px;
  margin: 12px 0;
  flex-wrap: wrap;
}
.btn-row button {
  flex: 1;
  padding: 9px;
  border: 3px solid #663300;
  border-radius: 6px;
  font-weight: bold;
  cursor: pointer;
  background: #b36b24;
  color: #fff;
  font-size: 12px;
  transition: all 0.15s;
}
.btn-row button:hover { transform: scale(1.03); background: #cc8033; }
.btn-row button:active { transform: scale(0.98); }

/* Cocina 2D */
#kitchen-2d {
  background: #5a331a;
  border: 4px solid #884400;
  border-radius: 8px;
  padding: 16px;
  position: relative;
  height: 400px;
  margin-bottom: 12px;
  overflow: hidden;
  background-image: 
    linear-gradient(90deg, #6b3e20 20px, transparent 20px),
    linear-gradient(#6b3e20 20px, transparent 20px);
  background-size: 40px 40px;
}
.zone {
  position: absolute;
  border: 3px solid #995511;
  border-radius: 6px;
  background: #7a4522;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  color: #fff8e6;
  box-shadow: inset 0 0 10px rgba(0,0,0,0.3);
}
#ingredients-table { width: 220px; height: 200px; top: 20px; left: 20px; font-size: 12px; }
#oven { width: 160px; height: 220px; top: 20px; right: 20px; font-size: 14px; }
#counter { width: 340px; height: 100px; bottom: 20px; left: 50%; transform: translateX(-50%); font-size: 12px; }

/* Pizza */
#pizza-2d {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background: #f9d076;
  border: 4px solid #b87a3e;
  position: relative;
  margin: 8px auto;
  box-shadow: inset 0 0 10px rgba(0,0,0,0.4);
  transition: all 0.4s ease;
}
#pizza-2d.fresh { box-shadow: inset 0 0 10px rgba(0,0,0,0.4), 0 0 10px #ffdd44; }
#pizza-2d.regular { filter: brightness(0.92); }
#pizza-2d.dry { filter: brightness(0.78) saturate(0.85); }
#pizza-2d.overcooked { filter: brightness(0.65) saturate(0.7); }
#pizza-2d.burnt { background: #5a280e; border-color: #3a1808; filter: brightness(0.5); }
.ing-2d {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  box-shadow: 0 0 2px rgba(0,0,0,0.7);
}
.tomato { background: #dc2626; }
.cheese { background: #ffdd44; }
.pepper { background: #22aa44; }
.ham { background: #994411; }
.mushroom { background: #774422; }
.onion { background: #e8e0f0; }
.olive { background: #111122; }
.oregano { background: #559922; }

/* Lista Ingredientes */
#ing-list {
  width: 100%;
  height: 150px;
  overflow-y: auto;
  padding: 4px;
  font-size: 10px;
}
.ing-btn {
  background: #995522;
  border: 2px solid #cc8833;
  border-radius: 4px;
  padding: 3px 5px;
  margin: 2px 0;
  cursor: pointer;
  color: #fff;
  text-align: left;
  transition: all 0.2s;
}
.ing-btn.out { opacity: 0.35; cursor: not-allowed; }
.ing-btn:hover:not(.out) { background: #b36b24; }

/* Cliente y Pedido */
#client-bar {
  background: #442614;
  border: 3px solid #884400;
  border-radius: 8px;
  padding: 10px;
  margin-bottom: 12px;
  font-size: 12px;
}
#bar-wrap {
  height: 16px;
  background: #663311;
  border-radius: 8px;
  overflow: hidden;
  margin-top: 6px;
  border: 2px solid #995511;
}
#bar {
  height: 100%;
  width: 100%;
  background: linear-gradient(90deg, #ff4422 0%, #ffcc22 50%, #22cc44 100%);
  transition: width 0.2s ease;
}
#ticket {
  background: #442614;
  border: 3px solid #884400;
  border-radius: 8px;
  padding: 12px;
  margin-bottom: 12px;
  font-family: 'Courier New', monospace;
  font-size: 12px;
}

/* Botones de Acción */
.action-btn {
  width: 100%;
  padding: 9px;
  margin: 5px 0;
  border: 3px solid #662200;
  border-radius: 6px;
  font-weight: bold;
  cursor: pointer;
  font-size: 12px;
}
#cook-btn { background: #cc3311; color: white; }
#serve-btn { background: #229933; color: white; }
#reset-btn { background: #775533; color: white; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

/* Modales */
.modal {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,0.85);
  justify-content: center;
  align-items: center;
  z-index: 200;
}
.modal-content {
  background: #442614;
  border: 4px solid #ffaa22;
  border-radius: 10px;
  padding: 20px;
  width: 92%;
  max-width: 580px;
  max-height: 90vh;
  overflow-y: auto;
}
.modal h3 {
  text-align: center;
  margin-bottom: 15px;
  color: #ffdd44;
}
.store-item, .inv-item, .loan-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px;
  margin: 6px 0;
  background: #5a331a;
  border-radius: 6px;
  border: 2px solid #995522;
  font-size: 12px;
}
.fresh { border-color: #44aa44; background: #335522; }
.close-modal {
  width: 100%;
  background: #cc3311;
  border: 2px solid #882200;
  color: white;
  margin-top: 12px;
  padding: 8px;
  border-radius: 6px;
  cursor: pointer;
}
#resumen {
  display: none;
  background: #442614;
  border: 3px solid #ffaa22;
  border-radius: 8px;
  padding: 16px;
  margin: 12px 0;
  font-size: 12px;
}
#msg {
  text-align: center;
  padding: 8px;
  background: #442614;
  border-radius: 6px;
  margin-top: 8px;
  border: 2px solid #884400;
  min-height: 36px;
  font-size: 12px;
}
</style>
</head>
<body>
<div id="app">
<h1>🍕 Pizzería Simulador 2D 🇦🇷</h1>

<!-- Panel Superior -->
<div id="top">
  <div class="top-block"><span class="top-label">Caja</span><span class="top-value">$<span id="money">8500</span></span></div>
  <div class="top-block"><span class="top-label">Día</span><span class="top-value"><span id="day">1</span></span></div>
  <div class="top-block"><span class="top-label">Pedidos</span><span class="top-value"><span id="ordersDone">0</span>/<span id="ordersGoal">3</span></span></div>
  <div class="top-block"><span class="top-label">Horno</span><span class="top-value" id="ovenStatus">100%</span></div>
  <div class="top-block"><span class="top-label">Heladera</span><span class="top-value" id="fridgeStatus">✅</span></div>
  <div class="top-block"><span class="top-label">Clima</span><span class="top-value" id="weather">☀️</span></div>
  <div class="top-block"><span class="top-label">Temp</span><span class="top-value" id="temp">22°C</span></div>
  <div class="top-block"><span class="top-label">Inflación</span><span class="top-value" id="inflation">3.8%</span></div>
  <div class="top-block"><span class="top-label">Deuda</span><span class="top-value neg" id="debt">$0</span></div>
</div>

<!-- Botones Principales -->
<div class="btn-row">
  <button onclick="openStore()">🛒 Comprar</button>
  <button onclick="openInventory()">📦 Stock</button>
  <button onclick="openMaintenance()">🔧 Equipos</button>
  <button onclick="openFinances()">📊 Finanzas</button>
  <button onclick="openLoans()">💸 Préstamos</button>
</div>

<!-- Barra de Cliente -->
<div id="client-bar">
  <span>👤 Cliente: <span id="clientName">-</span> | <span id="clientType"></span></span>
  <div id="bar-wrap"><div id="bar"></div></div>
</div>

<!-- Pedido Actual -->
<div id="ticket">📝 Pedido: <span id="orderText">Esperando...</span></div>

<!-- Cocina -->
<div id="kitchen-2d">
  <div id="ingredients-table" class="zone">
    🧺 Ingredientes
    <div id="ing-list"></div>
  </div>

  <div id="oven" class="zone">
    🔥 Horno
    <div id="pizza-2d" class="fresh"></div>
    <div id="ovenInfo">Listo</div>
    <button id="cook-btn" class="action-btn" onclick="startCooking()">Cocinar</button>
  </div>

  <div id="counter" class="zone">
    🛎️ Mostrador
    <button id="serve-btn" class="action-btn" onclick="serveOrder()" disabled>Entregar</button>
    <button id="reset-btn" class="action-btn" onclick="resetPizza()">Deshacer ($30)</button>
  </div>
</div>

<!-- Modales -->
<div id="storeModal" class="modal">
  <div class="modal-content">
    <h3>🛒 Proveedor Mayorista</h3>
    <p>💰 Efectivo: $<span id="storeMoney">0</span></p>
    <div id="storeList"></div>
    <button class="close-modal" onclick="closeStore()">Cerrar</button>
  </div>
</div>

<div id="inventoryModal" class="modal">
  <div class="modal-content">
    <h3>📦 Control de Stock</h3>
    <p>🔴 Vencido | 🟡 Por vencer | 🟢 Buen estado</p>
    <div id="inventoryList"></div>
    <button class="close-modal" onclick="closeInventory()">Cerrar</button>
  </div>
</div>

<div id="maintenanceModal" class="modal">
  <div class="modal-content">
    <h3>🔧 Mantenimiento</h3>
    <p>Horno: <span id="ovenStatusText"></span></p>
    <p>Heladera: <span id="fridgeStatusText"></span></p>
    <div class="store-item"><span>🔧 Reparar horno</span><span>$2500</span><button onclick="repairOven()">Hacer</button></div>
    <div class="store-item"><span>❄️ Reparar heladera</span><span>$950</span><button onclick="repairFridge()">Hacer</button></div>
    <button class="close-modal" onclick="closeMaintenance()">Cerrar</button>
  </div>
</div>

<div id="financesModal" class="modal">
  <div class="modal-content">
    <h3>📊 Finanzas</h3>
    <div id="financesContent"></div>
    <button class="close-modal" onclick="closeFinances()">Cerrar</button>
  </div>
</div>

<div id="loansModal" class="modal">
  <div class="modal-content">
    <h3>💸 Préstamos</h3>
    <p>Deuda actual: $<span id="currentDebt">0</span></p>
    <div id="loansList"></div>
    <button class="close-modal" onclick="closeLoans()">Cerrar</button>
  </div>
</div>

<div id="resumen">
  <h3>📊 Cierre del Día <span id="resDay"></span></h3>
  <p>✅ Pedidos: <span id="resOrders"></span> / <span id="resGoal"></span></p>
  <p>💵 Ventas: +$<span id="resIncome"></span></p>
  <p>🛒 Gastos: -$<span id="resExpenses"></span></p>
  <p><strong>📈 Ganancia: $<span id="resNet"></span></strong></p>
  <button onclick="startNewDay()" style="width:100%; margin-top:15px; padding:10px; background:#ffaa22; border:none; border-radius:6px; font-weight:bold;">➡️ Siguiente día</button>
</div>

<div id="msg">¡Empezá comprando insumos!</div>
</div>

<script>
// --------------------------
// VARIABLES
// --------------------------
let money = 8500;
let day = 1;
let ordersDone = 0;
let ordersGoal = 3;
let dailyIncome = 0;
let dailyExpenses = 0;
let debt = 0;

let ovenCondition = 100;
let fridgeCondition = 100;

let inventory = [];
let currentOrder = [];
let pizzaBuild = [];
let isCooked = false;
let isCooking = false;
let isBurnt = false;

const names = ["Luca","Mia","Sofia","Nico","Emma","Tomas","Julia","Bruno","Ana","Pablo","Martina"];
const ingNames = {
  dough:"Masa", tomato:"Salsa", cheese:"Queso", pepper:"Pimiento", ham:"Jamón",
  mushroom:"Champiñón", onion:"Cebolla", olive:"Aceituna", oregano:"Orégano"
};
const basePrices = {
  dough:1600, tomato:1250, cheese:2350, pepper:800, ham:2800, mushroom:1800,
  onion:900, olive:1350, oregano:450
};
const recipes = {
  1: [["dough","tomato","cheese"], ["dough","tomato","cheese","pepper"]],
  2: [["dough","tomato","cheese","ham"], ["dough","tomato","cheese","oregano"]],
  3: [["dough","tomato","cheese","ham","mushroom"]]
};

// --------------------------
// INICIO
// --------------------------
window.onload = startGame;

function startGame() {
  updateUI();
  newClientOrder();
  updateAvailableStock();
  updateOvenUI();
  updateFridgeUI();
}

// --------------------------
// ACTUALIZAR INTERFAZ GENERAL
// --------------------------
function updateUI() {
  document.getElementById("money").textContent = money;
  document.getElementById("day").textContent = day;
  document.getElementById("ordersDone").textContent = ordersDone;
  document.getElementById("debt").textContent = debt;
}

function setMessage(text) {
  document.getElementById("msg").textContent = text;
}

// --------------------------
// CLIENTES Y PEDIDOS
// --------------------------
function newClientOrder() {
  if(ordersDone >= ordersGoal) { endDay(); return; }

  const dayRecipes = recipes[Math.min(day,3)];
  currentOrder = dayRecipes[Math.floor(Math.random() * dayRecipes.length)];

  document.getElementById("orderText").textContent = currentOrder.map(i => ingNames[i]).join(" + ");
  document.getElementById("clientName").textContent = names[Math.floor(Math.random() * names.length)];
  document.getElementById("clientType").textContent = "Cliente habitual";

  pizzaBuild = [];
  isCooked = false;
  isCooking = false;
  isBurnt = false;
  document.getElementById("serve-btn").disabled = true;
  document.getElementById("pizza-2d").className = "fresh";
  document.getElementById("ovenInfo").textContent = "Listo";
  renderPizza();
}

// --------------------------
// INGREDIENTES
// --------------------------
function addIngredient(type) {
  if(isCooking || isCooked) return;
  if(!hasIngredient(type)) {
    setMessage(`❌ No hay ${ingNames[type]}`);
    return;
  }

  consumeIngredient(type);
  pizzaBuild.push(type);
  renderPizza();
  updateAvailableStock();
  setMessage(`✔ Agregado: ${ingNames[type]}`);
}

function hasIngredient(type) {
  return inventory.some(i => i.type === type && i.quantity > 0);
}

function consumeIngredient(type) {
  for(let i=0; i<inventory.length; i++) {
    if(inventory[i].type === type && inventory[i].quantity > 0) {
      inventory[i].quantity--;
      if(inventory[i].quantity <= 0) inventory.splice(i,1);
      break;
    }
  }
}

function renderPizza() {
  const pizza = document.getElementById("pizza-2d");
  pizza.innerHTML = "";
  pizzaBuild.forEach((ing, i) => {
    const el = document.createElement("div");
    el.className = `ing-2d ${ing}`;
    el.style.left = `${20 + (i % 4) * 20}px`;
    el.style.top = `${20 + Math.floor(i / 4) * 20}px`;
    pizza.appendChild(el);
  });
}

function updateAvailableStock() {
  const list = document.getElementById("ing-list");
  list.innerHTML = "";
  const total = {};
  for(const ing of Object.keys(ingNames)) total[ing] = 0;
  inventory.forEach(i => total[i.type] += i.quantity);

  for(const ing of Object.keys(total)) {
    const cls = total[ing] > 0 ? "ing-btn" : "ing-btn out";
    list.innerHTML += `<div class="${cls}" onclick="addIngredient('${ing}')">${ingNames[ing]}: ${total[ing]}</div>`;
  }
}

// --------------------------
// COCCIÓN
// --------------------------
function startCooking() {
  if(isCooking || pizzaBuild.length === 0 || ovenCondition < 20) {
    setMessage(ovenCondition < 20 ? "⚠️ El horno está muy dañado" : "⚠️ No se puede cocinar");
    return;
  }
  isCooking = true;
  let time = 0;

  const timer = setInterval(() => {
    time++;
    document.getElementById("ovenInfo").textContent = `Cocinando... ${time}s`;

    if(time >= 6) {
      clearInterval(timer);
      isCooking = false;
      isCooked = true;
      ovenCondition = Math.max(0, ovenCondition - 5);
      updateOvenUI();

      if(time > 9) {
        isBurnt = true;
        document.getElementById("pizza-2d").className = "burnt";
        setMessage("🔥 Se quemó la pizza");
      } else if(time > 7) {
        document.getElementById("pizza-2d").className = "overcooked";
        setMessage("⚠️ Un poco pasada");
      } else {
        document.getElementById("pizza-2d").className = "regular";
        setMessage("🍕 Lista para servir");
      }
      document.getElementById("serve-btn").disabled = false;
    }
  }, 1000);
}

// --------------------------
// SERVIR
// --------------------------
function serveOrder() {
  if(!isCooked) return;
  let correct = JSON.stringify([...pizzaBuild].sort()) === JSON.stringify([...currentOrder].sort());
  let earn = correct ? 1200 : 400;
  if(isBurnt) earn = 100;

  money += earn;
  dailyIncome += earn;
  ordersDone++;
  updateUI();
  setMessage(correct ? "😎 Pedido perfecto!" : "😅 Pedido incompleto o mal armado");

  setTimeout(newClientOrder, 1500);
}

// --------------------------
// REINICIAR
// --------------------------
function resetPizza() {
  if(money < 30 || isCooking) return setMessage("❌ No se puede deshacer");
  money -= 30;
  dailyExpenses += 30;

  // Devolver ingredientes
  pizzaBuild.forEach(ing => {
    const exists = inventory.find(i => i.type === ing);
    if(exists) exists.quantity++;
    else inventory.push({type:ing, quantity:1});
  });

  pizzaBuild = [];
  isCooked = false;
  isBurnt = false;
  document.getElementById("serve-btn").disabled = true;
  renderPizza();
  updateAvailableStock();
  updateUI();
  setMessage("🔄 Deshecho, ingredientes devueltos");
}

// --------------------------
// TIENDA
// --------------------------
function openStore() {
  document.getElementById("storeMoney").textContent = money;
  const list = document.getElementById("storeList");
  list.innerHTML = "";
  for(const ing of Object.keys(basePrices)) {
    list.innerHTML += `<div class="store-item">
      <span>${ingNames[ing]} (10u)</span>
      <span>$${basePrices[ing]}</span>
      <button onclick="buy('${ing}')">Comprar</button>
    </div>`;
  }
  document.getElementById("storeModal").style.display = "flex";
}
function closeStore() { document.getElementById("storeModal").style.display = "none"; }

function buy(type) {
  const price = basePrices[type];
  if(money < price) { setMessage("❌ No alcanza el dinero"); return; }
  money -= price;
  dailyExpenses += price;
  const item = inventory.find(i => i.type === type);
  if(item) item.quantity += 10;
  else inventory.push({type, quantity:10});
  updateAvailableStock();
  updateUI();
  closeStore();
  setMessage(`✅ Comprado: ${ingNames[type]}`);
}

// --------------------------
// STOCK
// --------------------------
function openInventory() {
  const list = document.getElementById("inventoryList");
  list.innerHTML = "";
  if(inventory.length === 0) {
    list.innerHTML = "<p>No hay ingredientes en stock</p>";
  } else {
    inventory.forEach(i => {
      list.innerHTML += `<div class="inv-item fresh">
        <span>${ingNames[i.type]}</span>
        <span>${i.quantity} unidades</span>
      </div>`;
    });
  }
  document.getElementById("inventoryModal").style.display = "flex";
}
function closeInventory() { document.getElementById("inventoryModal").style.display = "none"; }

// --------------------------
// MANTENIMIENTO
// --------------------------
function openMaintenance() {
  updateOvenUI();
  updateFridgeUI();
  document.getElementById("maintenanceModal").style.display = "flex";
}
function closeMaintenance() { document.getElementById("maintenanceModal").style.display = "none"; }

function repairOven() {
  if(money < 2500) return setMessage("❌ No alcanza para reparar");
  money -= 2500;
  dailyExpenses += 2500;
  ovenCondition = 100;
  updateOvenUI();
  closeMaintenance();
  setMessage("✅ Horno reparado al 100%");
}
function repairFridge() {
  if(money < 950) return setMessage("❌ No alcanza para reparar");
  money -= 950;
  dailyExpenses += 950;
  fridgeCondition = 100;
  updateFridgeUI();
  closeMaintenance();
  setMessage("✅ Heladera reparada al 100%");
}

function updateOvenUI() {
  document.getElementById("ovenStatus").textContent = `${ovenCondition}%`;
  document.getElementById("ovenStatusText").textContent = `${ovenCondition}%`;
}

function updateFridgeUI() {
  document.getEl

Game Source: Pizzería Simulador 2D 🇦🇷

Creator: MegaGalaxy31

Libraries: none

Complexity: complex (716 lines, 19.7 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: pizzer-a-simulador-2d-megagalaxy31" to link back to the original. Then publish at arcadelab.ai/publish.