XTaylorSpenceX

Glyph Garden Growth

Sep 19th, 2025
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 31.51 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>Glyph Garden Growth</title>
  7.     <style>
  8.         :root {
  9.             --fire-color: #ff4500;
  10.             --water-color: #1e90ff;
  11.             --earth-color: #228b22;
  12.             --air-color: #ffd700;
  13.             --steam-color: #9370db;
  14.             --wind-color: #00ced1;
  15.             --mud-color: #8b4513;
  16.             --smoke-color: #696969;
  17.             --lava-color: #ff8c00;
  18.             --storm-color: #4b0082;
  19.         }
  20.        
  21.         body {
  22.             font-family: 'Arial', sans-serif;
  23.             background: linear-gradient(135deg, #2c1810, #4a2c0b);
  24.             color: #fff;
  25.             display: flex;
  26.             flex-direction: column;
  27.             align-items: center;
  28.             margin: 0;
  29.             padding: 20px;
  30.             min-height: 100vh;
  31.             overflow-x: hidden;
  32.         }
  33.        
  34.         header {
  35.             text-align: center;
  36.             margin-bottom: 20px;
  37.             width: 100%;
  38.         }
  39.        
  40.         h1 {
  41.             text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
  42.             animation: glow 2s ease-in-out infinite alternate;
  43.             margin: 0;
  44.             font-size: 2.5rem;
  45.         }
  46.        
  47.         @keyframes glow {
  48.             from { text-shadow: 0 0 10px rgba(255, 255, 255, 0.5); }
  49.             to { text-shadow: 0 0 20px rgba(255, 255, 255, 1), 0 0 30px rgba(255, 255, 255, 0.7); }
  50.         }
  51.        
  52.         .subtitle {
  53.             font-style: italic;
  54.             margin-top: 5px;
  55.             opacity: 0.8;
  56.         }
  57.        
  58.         #game-container {
  59.             display: flex;
  60.             flex-direction: column;
  61.             align-items: center;
  62.             width: 100%;
  63.             max-width: 600px;
  64.         }
  65.        
  66.         #status-bar {
  67.             display: flex;
  68.             justify-content: space-around;
  69.             width: 100%;
  70.             margin-bottom: 20px;
  71.             background: rgba(0, 0, 0, 0.3);
  72.             padding: 10px;
  73.             border-radius: 10px;
  74.             box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
  75.         }
  76.        
  77.         .stat {
  78.             display: flex;
  79.             flex-direction: column;
  80.             align-items: center;
  81.         }
  82.        
  83.         .stat-value {
  84.             font-size: 1.2rem;
  85.             font-weight: bold;
  86.         }
  87.        
  88.         .stat-label {
  89.             font-size: 0.8rem;
  90.             opacity: 0.8;
  91.         }
  92.        
  93.         #garden {
  94.             display: grid;
  95.             grid-template-columns: repeat(5, 80px);
  96.             grid-gap: 10px;
  97.             background: #3d2b1f;
  98.             padding: 25px;
  99.             border-radius: 15px;
  100.             box-shadow: inset 0 0 20px rgba(0,0,0,0.5), 0 10px 20px rgba(0,0,0,0.5);
  101.             margin-bottom: 20px;
  102.             position: relative;
  103.             overflow: hidden;
  104.         }
  105.        
  106.         #garden::before {
  107.             content: '';
  108.             position: absolute;
  109.             top: 0;
  110.             left: 0;
  111.             right: 0;
  112.             height: 10px;
  113.             background: linear-gradient(to bottom, rgba(101, 67, 33, 0.7), transparent);
  114.             z-index: 1;
  115.             border-radius: 15px 15px 0 0;
  116.         }
  117.        
  118.         .plot {
  119.             width: 80px;
  120.             height: 80px;
  121.             background: linear-gradient(45deg, #8B4513, #A0522D);
  122.             border: 2px solid #654321;
  123.             border-radius: 8px;
  124.             position: relative;
  125.             cursor: pointer;
  126.             transition: all 0.3s ease;
  127.             overflow: hidden;
  128.             box-shadow: inset 0 0 10px rgba(0,0,0,0.3);
  129.         }
  130.        
  131.         .plot:hover {
  132.             transform: scale(1.05);
  133.             box-shadow: 0 0 15px rgba(255, 255, 255, 0.2);
  134.         }
  135.        
  136.         .plot::after {
  137.             content: '';
  138.             position: absolute;
  139.             top: 0;
  140.             left: 0;
  141.             right: 0;
  142.             bottom: 0;
  143.             background: radial-gradient(circle at center, transparent 30%, rgba(0,0,0,0.3) 100%);
  144.             pointer-events: none;
  145.         }
  146.        
  147.         .plant {
  148.             position: absolute;
  149.             bottom: 5px;
  150.             left: 50%;
  151.             transform: translateX(-50%);
  152.             width: 40px;
  153.             height: 40px;
  154.             border-radius: 50%;
  155.             animation: bloom 3s ease-in-out infinite;
  156.             transition: all 0.5s;
  157.             z-index: 2;
  158.         }
  159.        
  160.         .plant::before {
  161.             content: '';
  162.             position: absolute;
  163.             bottom: -5px;
  164.             left: 50%;
  165.             transform: translateX(-50%);
  166.             width: 10px;
  167.             height: 15px;
  168.             background: linear-gradient(to top, #5d4037, #8d6e63);
  169.             border-radius: 0 0 5px 5px;
  170.         }
  171.        
  172.         @keyframes bloom {
  173.             0%, 100% { transform: translateX(-50%) scale(0.9) rotate(0deg); }
  174.             50% { transform: translateX(-50%) scale(1.1) rotate(5deg); }
  175.         }
  176.        
  177.         .fire {
  178.             background: radial-gradient(circle at 30% 30%, #ff7b25, #ff4500);
  179.             box-shadow: 0 0 15px var(--fire-color);
  180.         }
  181.        
  182.         .water {
  183.             background: radial-gradient(circle at 30% 30%, #4fc3f7, #0288d1);
  184.             box-shadow: 0 0 15px var(--water-color);
  185.         }
  186.        
  187.         .earth {
  188.             background: radial-gradient(circle at 30% 30%, #66bb6a, #2e7d32);
  189.             box-shadow: 0 0 15px var(--earth-color);
  190.         }
  191.        
  192.         .air {
  193.             background: radial-gradient(circle at 30% 30%, #fff176, #ffd54f);
  194.             box-shadow: 0 0 15px var(--air-color);
  195.         }
  196.        
  197.         .hybrid-steam {
  198.             background: radial-gradient(circle at 30% 30%, #ba55d3, #9370db);
  199.             box-shadow: 0 0 20px var(--steam-color);
  200.             animation: pulse 2s ease-in-out infinite, float 4s ease-in-out infinite;
  201.         }
  202.        
  203.         .hybrid-wind {
  204.             background: radial-gradient(circle at 30% 30%, #7fffd4, #00ced1);
  205.             box-shadow: 0 0 15px var(--wind-color);
  206.             animation: swirl 3s linear infinite;
  207.         }
  208.        
  209.         .hybrid-mud {
  210.             background: radial-gradient(circle at 30% 30%, #a1887f, #6d4c41);
  211.             box-shadow: 0 0 10px var(--mud-color);
  212.             animation: mud-bubble 4s ease-in-out infinite;
  213.         }
  214.        
  215.         .hybrid-smoke {
  216.             background: radial-gradient(circle at 30% 30%, #bdbdbd, #616161);
  217.             box-shadow: 0 0 15px var(--smoke-color);
  218.             animation: smoke-float 5s ease-in-out infinite;
  219.         }
  220.        
  221.         .hybrid-lava {
  222.             background: radial-gradient(circle at 30% 30%, #ffa726, #ef6c00);
  223.             box-shadow: 0 0 20px var(--lava-color);
  224.             animation: lava-glow 2s ease-in-out infinite;
  225.         }
  226.        
  227.         .hybrid-storm {
  228.             background: radial-gradient(circle at 30% 30%, #7b1fa2, #4a148c);
  229.             box-shadow: 0 0 20px var(--storm-color);
  230.             animation: storm-pulse 1.5s ease-in-out infinite;
  231.         }
  232.        
  233.         @keyframes pulse {
  234.             0%, 100% { transform: translateX(-50%) scale(1); }
  235.             50% { transform: translateX(-50%) scale(1.2); }
  236.         }
  237.        
  238.         @keyframes float {
  239.             0%, 100% { bottom: 5px; }
  240.             50% { bottom: 15px; }
  241.         }
  242.        
  243.         @keyframes swirl {
  244.             0% { transform: translateX(-50%) rotate(0deg); }
  245.             100% { transform: translateX(-50%) rotate(360deg); }
  246.         }
  247.        
  248.         @keyframes mud-bubble {
  249.             0%, 100% { transform: translateX(-50%) scale(1); }
  250.             50% { transform: translateX(-50%) scale(1.1); }
  251.         }
  252.        
  253.         @keyframes smoke-float {
  254.             0% { transform: translateX(-50%) translateY(0) scale(1); opacity: 0.7; }
  255.             50% { transform: translateX(-50%) translateY(-20px) scale(1.2); opacity: 1; }
  256.             100% { transform: translateX(-50%) translateY(-40px) scale(1.5); opacity: 0; }
  257.         }
  258.        
  259.         @keyframes lava-glow {
  260.             0%, 100% { box-shadow: 0 0 20px var(--lava-color); }
  261.             50% { box-shadow: 0 0 30px var(--lava-color), 0 0 40px rgba(255, 140, 0, 0.6); }
  262.         }
  263.        
  264.         @keyframes storm-pulse {
  265.             0%, 100% { box-shadow: 0 0 20px var(--storm-color); transform: translateX(-50%) scale(1); }
  266.             50% { box-shadow: 0 0 30px var(--storm-color), 0 0 50px rgba(75, 0, 130, 0.6); transform: translateX(-50%) scale(1.1); }
  267.         }
  268.        
  269.         #controls {
  270.             display: flex;
  271.             flex-wrap: wrap;
  272.             justify-content: center;
  273.             gap: 15px;
  274.             margin: 20px 0;
  275.             width: 100%;
  276.         }
  277.        
  278.         .glyph-btn {
  279.             width: 60px;
  280.             height: 60px;
  281.             border-radius: 50%;
  282.             border: none;
  283.             cursor: pointer;
  284.             font-weight: bold;
  285.             transition: all 0.3s;
  286.             position: relative;
  287.             overflow: hidden;
  288.             box-shadow: 0 4px 8px rgba(0,0,0,0.3);
  289.         }
  290.        
  291.         .glyph-btn::after {
  292.             content: '';
  293.             position: absolute;
  294.             top: 0;
  295.             left: 0;
  296.             right: 0;
  297.             bottom: 0;
  298.             background: radial-gradient(circle at center, rgba(255,255,255,0.3) 0%, transparent 70%);
  299.             pointer-events: none;
  300.         }
  301.        
  302.         .glyph-btn:hover {
  303.             transform: scale(1.1) translateY(-5px);
  304.             box-shadow: 0 8px 15px rgba(0,0,0,0.4);
  305.         }
  306.        
  307.         .glyph-btn.selected {
  308.             transform: scale(1.1);
  309.             box-shadow: 0 0 20px 5px rgba(255, 255, 255, 0.7);
  310.         }
  311.        
  312.         #fire-btn {
  313.             background: linear-gradient(45deg, var(--fire-color), #ff8c00);
  314.         }
  315.        
  316.         #water-btn {
  317.             background: linear-gradient(45deg, var(--water-color), #00bcd4);
  318.         }
  319.        
  320.         #earth-btn {
  321.             background: linear-gradient(45deg, var(--earth-color), #8bc34a);
  322.         }
  323.        
  324.         #air-btn {
  325.             background: linear-gradient(45deg, var(--air-color), #ffeb3b);
  326.         }
  327.        
  328.         #prune-btn {
  329.             padding: 10px 20px;
  330.             background: linear-gradient(45deg, #78909c, #b0bec5);
  331.             border: none;
  332.             border-radius: 30px;
  333.             color: white;
  334.             cursor: pointer;
  335.             font-weight: bold;
  336.             transition: all 0.3s;
  337.             box-shadow: 0 4px 8px rgba(0,0,0,0.3);
  338.         }
  339.        
  340.         #prune-btn:hover, #prune-btn.active {
  341.             transform: scale(1.05);
  342.             box-shadow: 0 0 15px rgba(207, 216, 220, 0.8);
  343.         }
  344.        
  345.         #prune-btn.active {
  346.             background: linear-gradient(45deg, #f44336, #ef5350);
  347.         }
  348.        
  349.         #help-btn {
  350.             padding: 10px 20px;
  351.             background: linear-gradient(45deg, #9e9e9e, #607d8b);
  352.             border: none;
  353.             border-radius: 30px;
  354.             color: white;
  355.             cursor: pointer;
  356.             font-weight: bold;
  357.             transition: all 0.3s;
  358.             box-shadow: 0 4px 8px rgba(0,0,0,0.3);
  359.         }
  360.        
  361.         #help-btn:hover {
  362.             transform: scale(1.05);
  363.             box-shadow: 0 0 15px rgba(144, 164, 174, 0.8);
  364.         }
  365.        
  366.         .overgrown {
  367.             animation: shake 0.5s infinite;
  368.         }
  369.        
  370.         @keyframes shake {
  371.             0%, 100% { transform: translateX(0); }
  372.             25% { transform: translateX(-5px); }
  373.             75% { transform: translateX(5px); }
  374.         }
  375.        
  376.         #message {
  377.             position: fixed;
  378.             top: 20px;
  379.             left: 50%;
  380.             transform: translateX(-50%);
  381.             background: rgba(0, 0, 0, 0.8);
  382.             color: white;
  383.             padding: 15px 25px;
  384.             border-radius: 30px;
  385.             z-index: 100;
  386.             opacity: 0;
  387.             transition: opacity 0.5s;
  388.             pointer-events: none;
  389.         }
  390.        
  391.         #message.show {
  392.             opacity: 1;
  393.         }
  394.        
  395.         #game-over {
  396.             position: fixed;
  397.             top: 0;
  398.             left: 0;
  399.             right: 0;
  400.             bottom: 0;
  401.             background: rgba(0, 0, 0, 0.9);
  402.             display: flex;
  403.             flex-direction: column;
  404.             justify-content: center;
  405.             align-items: center;
  406.             z-index: 1000;
  407.             opacity: 0;
  408.             pointer-events: none;
  409.             transition: opacity 0.5s;
  410.         }
  411.        
  412.         #game-over.show {
  413.             opacity: 1;
  414.             pointer-events: all;
  415.         }
  416.        
  417.         #game-over h2 {
  418.             font-size: 3rem;
  419.             margin-bottom: 20px;
  420.             text-shadow: 0 0 10px rgba(255, 255, 255, 0.8);
  421.         }
  422.        
  423.         #game-over p {
  424.             font-size: 1.5rem;
  425.             margin-bottom: 30px;
  426.         }
  427.        
  428.         #restart-btn {
  429.             padding: 15px 30px;
  430.             background: linear-gradient(45deg, #ff69b4, #ff1493);
  431.             border: none;
  432.             border-radius: 30px;
  433.             color: white;
  434.             cursor: pointer;
  435.             font-weight: bold;
  436.             font-size: 1.2rem;
  437.             transition: all 0.3s;
  438.         }
  439.        
  440.         #restart-btn:hover {
  441.             transform: scale(1.1);
  442.             box-shadow: 0 0 20px rgba(255, 105, 180, 0.8);
  443.         }
  444.        
  445.         .particle {
  446.             position: absolute;
  447.             border-radius: 50%;
  448.             pointer-events: none;
  449.             z-index: 5;
  450.         }
  451.        
  452.         @media (max-width: 600px) {
  453.             #garden {
  454.                 grid-template-columns: repeat(5, 60px);
  455.                 padding: 15px;
  456.                 grid-gap: 8px;
  457.             }
  458.            
  459.             .plot {
  460.                 width: 60px;
  461.                 height: 60px;
  462.             }
  463.            
  464.             .plant {
  465.                 width: 30px;
  466.                 height: 30px;
  467.             }
  468.            
  469.             .glyph-btn {
  470.                 width: 50px;
  471.                 height: 50px;
  472.             }
  473.            
  474.             h1 {
  475.                 font-size: 2rem;
  476.             }
  477.         }
  478.     </style>
  479. </head>
  480. <body>
  481.     <header>
  482.         <h1>Glyph Garden Growth 🌱✨</h1>
  483.         <div class="subtitle">Cultivate elemental harmony in your mystical garden</div>
  484.     </header>
  485.    
  486.     <div id="game-container">
  487.         <div id="status-bar">
  488.             <div class="stat">
  489.                 <div class="stat-value" id="harmony">100</div>
  490.                 <div class="stat-label">Harmony</div>
  491.             </div>
  492.             <div class="stat">
  493.                 <div class="stat-value" id="yield">0</div>
  494.                 <div class="stat-label">Yield</div>
  495.             </div>
  496.             <div class="stat">
  497.                 <div class="stat-value" id="hazards">0</div>
  498.                 <div class="stat-label">Hazards</div>
  499.             </div>
  500.         </div>
  501.        
  502.         <div id="garden"></div>
  503.        
  504.         <div id="controls">
  505.             <button id="fire-btn" class="glyph-btn" title="Fire Glyph">🔥</button>
  506.             <button id="water-btn" class="glyph-btn" title="Water Glyph">💧</button>
  507.             <button id="earth-btn" class="glyph-btn" title="Earth Glyph">🌿</button>
  508.             <button id="air-btn" class="glyph-btn" title="Air Glyph">💨</button>
  509.             <button id="prune-btn">Prune Mode</button>
  510.             <button id="help-btn">Help</button>
  511.         </div>
  512.     </div>
  513.    
  514.     <div id="message"></div>
  515.    
  516.     <div id="game-over">
  517.         <h2>Garden Overgrown!</h2>
  518.         <p>Your harmony reached zero and the garden was consumed.</p>
  519.         <p>Final Yield: <span id="final-yield">0</span></p>
  520.         <button id="restart-btn">Cultivate Again</button>
  521.     </div>
  522.  
  523.     <script>
  524.         class GlyphGarden {
  525.             constructor() {
  526.                 this.grid = Array(5).fill().map(() => Array(5).fill(null));
  527.                 this.currentGlyph = null;
  528.                 this.pruneMode = false;
  529.                 this.harmony = 100;
  530.                 this.yield = 0;
  531.                 this.hazards = 0;
  532.                 this.gameActive = true;
  533.                
  534.                 this.gardenEl = document.getElementById('garden');
  535.                 this.harmonyEl = document.getElementById('harmony');
  536.                 this.yieldEl = document.getElementById('yield');
  537.                 this.hazardsEl = document.getElementById('hazards');
  538.                 this.messageEl = document.getElementById('message');
  539.                 this.gameOverEl = document.getElementById('game-over');
  540.                 this.finalYieldEl = document.getElementById('final-yield');
  541.                
  542.                 this.initGarden();
  543.                 this.bindEvents();
  544.                 this.simulateGrowth();
  545.                 this.showMessage("Welcome to Glyph Garden! Plant elements and watch them interact.", 5000);
  546.             }
  547.  
  548.             initGarden() {
  549.                 this.gardenEl.innerHTML = '';
  550.                 for (let row = 0; row < 5; row++) {
  551.                    for (let col = 0; col < 5; col++) {
  552.                        const plot = document.createElement('div');
  553.                        plot.className = 'plot';
  554.                        plot.dataset.row = row;
  555.                        plot.dataset.col = col;
  556.                        plot.addEventListener('click', (e) => this.handlePlotClick(e));
  557.                         this.gardenEl.appendChild(plot);
  558.                     }
  559.                 }
  560.             }
  561.  
  562.             bindEvents() {
  563.                 document.getElementById('fire-btn').addEventListener('click', () => this.selectGlyph('fire'));
  564.                 document.getElementById('water-btn').addEventListener('click', () => this.selectGlyph('water'));
  565.                 document.getElementById('earth-btn').addEventListener('click', () => this.selectGlyph('earth'));
  566.                 document.getElementById('air-btn').addEventListener('click', () => this.selectGlyph('air'));
  567.                 document.getElementById('prune-btn').addEventListener('click', () => this.togglePrune());
  568.                 document.getElementById('restart-btn').addEventListener('click', () => this.restartGame());
  569.                 document.getElementById('help-btn').addEventListener('click', () => this.showHelp());
  570.             }
  571.  
  572.             selectGlyph(glyph) {
  573.                 this.currentGlyph = glyph;
  574.                 this.pruneMode = false;
  575.                
  576.                 // Update UI to show selected glyph
  577.                 document.querySelectorAll('.glyph-btn').forEach(btn => btn.classList.remove('selected'));
  578.                 document.getElementById(`${glyph}-btn`).classList.add('selected');
  579.                 document.getElementById('prune-btn').classList.remove('active');
  580.                
  581.                 this.showMessage(`Selected ${glyph} glyph. Click on a plot to plant.`, 2000);
  582.             }
  583.  
  584.             togglePrune() {
  585.                 this.pruneMode = !this.pruneMode;
  586.                 this.currentGlyph = null;
  587.                
  588.                 // Update UI
  589.                 document.querySelectorAll('.glyph-btn').forEach(btn => btn.classList.remove('selected'));
  590.                 const pruneBtn = document.getElementById('prune-btn');
  591.                
  592.                 if (this.pruneMode) {
  593.                     pruneBtn.textContent = 'Plant Mode';
  594.                     pruneBtn.classList.add('active');
  595.                     this.showMessage("Prune mode active. Click on plants to remove them.", 2000);
  596.                 } else {
  597.                     pruneBtn.textContent = 'Prune Mode';
  598.                     pruneBtn.classList.remove('active');
  599.                     this.showMessage("Prune mode deactivated.", 2000);
  600.                 }
  601.             }
  602.  
  603.             handlePlotClick(e) {
  604.                 if (!this.gameActive) return;
  605.                
  606.                 const plot = e.currentTarget;
  607.                 const row = parseInt(plot.dataset.row);
  608.                 const col = parseInt(plot.dataset.col);
  609.  
  610.                 if (this.pruneMode) {
  611.                     this.prune(row, col);
  612.                 } else if (this.currentGlyph) {
  613.                     this.plant(row, col, this.currentGlyph);
  614.                 } else {
  615.                     this.showMessage("First select a glyph or enable prune mode.", 2000);
  616.                 }
  617.             }
  618.  
  619.             plant(row, col, glyph) {
  620.                 if (this.grid[row][col]) {
  621.                     this.showMessage("This plot already has a plant!", 2000);
  622.                     return;
  623.                 }
  624.  
  625.                 this.grid[row][col] = glyph;
  626.                 const plot = this.gardenEl.querySelector(`[data-row="${row}"][data-col="${col}"]`);
  627.                 const plant = document.createElement('div');
  628.                 plant.className = `plant ${glyph}`;
  629.                 plant.addEventListener('click', (e) => {
  630.                     e.stopPropagation();
  631.                     if (this.pruneMode) this.prune(row, col);
  632.                 });
  633.                 plot.appendChild(plant);
  634.                
  635.                 this.createParticles(plot, glyph);
  636.                 this.updateStats();
  637.                
  638.                 // Play planting sound
  639.                 this.playSound('plant');
  640.             }
  641.  
  642.             prune(row, col) {
  643.                 if (!this.grid[row][col]) {
  644.                     this.showMessage("Nothing to prune here.", 2000);
  645.                     return;
  646.                 }
  647.  
  648.                 const plot = this.gardenEl.querySelector(`[data-row="${row}"][data-col="${col}"]`);
  649.                 plot.innerHTML = '';
  650.                 this.grid[row][col] = null;
  651.                 this.updateStats();
  652.                
  653.                 // Play pruning sound
  654.                 this.playSound('prune');
  655.             }
  656.  
  657.             simulateGrowth() {
  658.                 setInterval(() => {
  659.                     if (!this.gameActive) return;
  660.                    
  661.                     this.checkInteractions();
  662.                     this.updateStats();
  663.                    
  664.                     if (this.harmony <= 0) {
  665.                        this.endGame();
  666.                    }
  667.                }, 3000);
  668.            }
  669.  
  670.            checkInteractions() {
  671.                for (let row = 0; row < 5; row++) {
  672.                    for (let col = 0; col < 5; col++) {
  673.                        if (!this.grid[row][col]) continue;
  674.                        
  675.                        const neighbors = this.getNeighbors(row, col);
  676.                        const interactions = this.getInteractions(this.grid[row][col], neighbors);
  677.                        
  678.                        if (interactions.hybrid) {
  679.                            this.createHybrid(row, col, interactions.hybrid);
  680.                        }
  681.                    }
  682.                }
  683.            }
  684.  
  685.            getNeighbors(row, col) {
  686.                const dirs = [[-1,0],[1,0],[0,-1],[0,1],[-1,-1],[-1,1],[1,-1],[1,1]]; // Including diagonals
  687.                return dirs.map(([dr, dc]) => {
  688.                     const nr = row + dr, nc = col + dc;
  689.                     return (nr >= 0 && nr < 5 && nc >= 0 && nc < 5) ? this.grid[nr][nc] : null;
  690.                 }).filter(Boolean);
  691.             }
  692.  
  693.             getInteractions(center, neighbors) {
  694.                 const combos = {
  695.                     'fire-water': 'steam',
  696.                     'water-fire': 'steam',
  697.                     'earth-air': 'wind',
  698.                     'air-earth': 'wind',
  699.                     'water-earth': 'mud',
  700.                     'earth-water': 'mud',
  701.                     'fire-air': 'smoke',
  702.                     'air-fire': 'smoke',
  703.                     'fire-earth': 'lava',
  704.                     'earth-fire': 'lava',
  705.                     'water-air': 'storm',
  706.                     'air-water': 'storm'
  707.                 };
  708.                
  709.                 for (let neighbor of neighbors) {
  710.                     const key = `${center}-${neighbor}`;
  711.                     if (combos[key]) {
  712.                         return {
  713.                             hybrid: combos[key],
  714.                             hazard: ['steam', 'smoke', 'lava'].includes(combos[key])
  715.                         };
  716.                     }
  717.                 }
  718.                 return { hybrid: null };
  719.             }
  720.  
  721.             createHybrid(row, col, type) {
  722.                 if (this.grid[row][col]) {
  723.                     const plot = this.gardenEl.querySelector(`[data-row="${row}"][data-col="${col}"]`);
  724.                     this.prune(row, col);
  725.                     this.plant(row, col, `hybrid-${type}`);
  726.                    
  727.                     if (type === 'steam' || type === 'smoke' || type === 'lava') {
  728.                         this.hazards += 1;
  729.                         this.showMessage(`Warning: ${type} hazard created!`, 3000);
  730.                     } else {
  731.                         this.yield += 2;
  732.                         this.showMessage(`New hybrid formed: ${type}! +2 Yield`, 3000);
  733.                     }
  734.                    
  735.                     // Play hybrid creation sound
  736.                     this.playSound('hybrid');
  737.                 }
  738.             }
  739.  
  740.             updateStats() {
  741.                 const totalPlants = this.grid.flat().filter(Boolean).length;
  742.                
  743.                 // More balanced formula for harmony
  744.                 this.harmony = Math.max(0, 100 - this.hazards * 8 + Math.min(30, totalPlants) - this.yield / 2);
  745.                
  746.                 // Yield increases based on hybrids and plant count
  747.                 if (Math.random() > 0.7) {
  748.                     this.yield += Math.floor(totalPlants / 5);
  749.                 }
  750.                
  751.                 // Hazards can occasionally spawn randomly near other hazards
  752.                 if (this.hazards > 0 && Math.random() > 0.8) {
  753.                    this.hazards += 1;
  754.                 }
  755.  
  756.                 this.harmonyEl.textContent = Math.floor(this.harmony);
  757.                 this.yieldEl.textContent = this.yield;
  758.                 this.hazardsEl.textContent = this.hazards;
  759.                
  760.                 // Visual feedback for low harmony
  761.                 if (this.harmony < 30) {
  762.                    this.harmonyEl.style.color = '#ff4444';
  763.                } else if (this.harmony < 70) {
  764.                    this.harmonyEl.style.color = '#ffaa00';
  765.                } else {
  766.                    this.harmonyEl.style.color = '#ffffff';
  767.                }
  768.            }
  769.            
  770.            createParticles(element, type) {
  771.                const colors = {
  772.                    'fire': '#ff4500',
  773.                    'water': '#1e90ff',
  774.                    'earth': '#228b22',
  775.                    'air': '#ffd700',
  776.                    'hybrid-steam': '#9370db',
  777.                    'hybrid-wind': '#00ced1',
  778.                    'hybrid-mud': '#8b4513',
  779.                    'hybrid-smoke': '#696969',
  780.                    'hybrid-lava': '#ff8c00',
  781.                    'hybrid-storm': '#4b0082'
  782.                };
  783.                
  784.                const color = colors[type] || '#ffffff';
  785.                
  786.                for (let i = 0; i < 10; i++) {
  787.                    const particle = document.createElement('div');
  788.                    particle.className = 'particle';
  789.                    particle.style.width = `${Math.random() * 8 + 2}px`;
  790.                    particle.style.height = particle.style.width;
  791.                    particle.style.background = color;
  792.                    particle.style.left = `${Math.random() * 80}px`;
  793.                    particle.style.top = `${Math.random() * 80}px`;
  794.                    
  795.                    element.appendChild(particle);
  796.                    
  797.                    // Animate particle
  798.                    const angle = Math.random() * Math.PI * 2;
  799.                    const distance = Math.random() * 50 + 20;
  800.                    const duration = Math.random() * 1000 + 500;
  801.                    
  802.                    particle.animate([
  803.                        {
  804.                            transform: 'translate(0, 0)',
  805.                            opacity: 1
  806.                        },
  807.                        {
  808.                            transform: `translate(${Math.cos(angle) * distance}px, ${Math.sin(angle) * distance}px)`,
  809.                            opacity: 0
  810.                        }
  811.                    ], {
  812.                        duration: duration,
  813.                        easing: 'ease-out'
  814.                    });
  815.                    
  816.                    // Remove particle after animation
  817.                    setTimeout(() => {
  818.                         if (particle.parentNode) {
  819.                             particle.parentNode.removeChild(particle);
  820.                         }
  821.                     }, duration);
  822.                 }
  823.             }
  824.            
  825.             showMessage(text, duration = 3000) {
  826.                 this.messageEl.textContent = text;
  827.                 this.messageEl.classList.add('show');
  828.                
  829.                 setTimeout(() => {
  830.                     this.messageEl.classList.remove('show');
  831.                 }, duration);
  832.             }
  833.            
  834.             playSound(type) {
  835.                 // In a real game, you would play actual sound files here
  836.                 // For this example, we'll just log the sound event
  837.                 console.log(`Playing sound: ${type}`);
  838.             }
  839.            
  840.             endGame() {
  841.                 this.gameActive = false;
  842.                 this.finalYieldEl.textContent = this.yield;
  843.                 this.gameOverEl.classList.add('show');
  844.                 this.gardenEl.classList.add('overgrown');
  845.             }
  846.            
  847.             restartGame() {
  848.                 this.grid = Array(5).fill().map(() => Array(5).fill(null));
  849.                 this.currentGlyph = null;
  850.                 this.pruneMode = false;
  851.                 this.harmony = 100;
  852.                 this.yield = 0;
  853.                 this.hazards = 0;
  854.                 this.gameActive = true;
  855.                
  856.                 this.harmonyEl.style.color = '#ffffff';
  857.                 this.initGarden();
  858.                 this.updateStats();
  859.                 this.gameOverEl.classList.remove('show');
  860.                 this.gardenEl.classList.remove('overgrown');
  861.                
  862.                 this.showMessage("New garden planted. Good luck!", 3000);
  863.             }
  864.            
  865.             showHelp() {
  866.                 const helpText = "GLYPH GARDEN GUIDE:\n\n" +
  867.                     "• Plant elemental glyphs to grow your garden\n" +
  868.                     "• Adjacent elements will combine to create hybrids\n" +
  869.                     "• Some combinations create hazards that reduce harmony\n" +
  870.                     "• Keep harmony above zero to avoid overgrowth\n" +
  871.                     "• Prune plants to manage your garden's health\n\n" +
  872.                     "COMBINATIONS:\n" +
  873.                     "🔥 + 💧 = Steam (Hazard)\n" +
  874.                     "🌿 + 💨 = Wind (Bonus)\n" +
  875.                     "💧 + 🌿 = Mud (Bonus)\n" +
  876.                     "🔥 + 💨 = Smoke (Hazard)\n" +
  877.                     "🔥 + 🌿 = Lava (Hazard)\n" +
  878.                     "💧 + 💨 = Storm (Bonus)";
  879.                
  880.                 alert(helpText);
  881.             }
  882.         }
  883.  
  884.         // Initialize the garden when the page loads
  885.         document.addEventListener('DOMContentLoaded', () => {
  886.             new GlyphGarden();
  887.         });
  888.     </script>
  889. </body>
  890. </html>
  891.  
Advertisement
Add Comment
Please, Sign In to add comment