Advertisement
here2share

PirateRogue.io

Jul 14th, 2024 (edited)
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <html><head><base href="https://websim.ai" />
  2. <title>PirateRogue.io</title>
  3. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  4. <style>
  5. body, html {
  6.   margin: 0;
  7.   padding: 0;
  8.   height: 100%;
  9.   overflow: hidden;
  10.   background-color: #001220;
  11.   touch-action: none;
  12. }
  13.  
  14. #game-container {
  15.   position: absolute;
  16.   width: 100%;
  17.   height: 100%;
  18.   overflow: hidden;
  19. }
  20.  
  21. .ocean-background {
  22.   position: absolute;
  23.   top: 0;
  24.   left: 0;
  25.   width: 100%;
  26.   height: 100%;
  27.   background-image: url('https://i.postimg.cc/DZC66mkf/ezgif-1-ce17936684.gif');
  28.   background-size: 16.67% 16.67%;
  29.   background-repeat: repeat;
  30.   image-rendering: pixelated;
  31. }
  32.  
  33. #player {
  34.   position: absolute;
  35.   width: 64px;
  36.   height: 64px;
  37.   background-image: url('https://i.postimg.cc/7L3Q3xZb/ship1.png');
  38.   background-size: contain;
  39.   background-repeat: no-repeat;
  40.   background-position: center;
  41.   transform-origin: center center;
  42.   z-index: 10;
  43. }
  44.  
  45. .enemy {
  46.   position: absolute;
  47.   width: 48px;
  48.   height: 48px;
  49.   background-image: url('https://i.postimg.cc/VNQV0S13/ship5.png');
  50.   background-size: contain;
  51.   background-repeat: no-repeat;
  52.   background-position: center;
  53.   transform-origin: center center;
  54.   z-index: 5;
  55. }
  56.  
  57. .projectile {
  58.   position: absolute;
  59.   width: 8px;
  60.   height: 8px;
  61.   background-color: #000000;
  62.   border-radius: 50%;
  63.   z-index: 8;
  64. }
  65.  
  66. .xp-orb {
  67.   position: absolute;
  68.   width: 6px;
  69.   height: 6px;
  70.   background-color: #ffff00;
  71.   z-index: 7;
  72. }
  73.  
  74. .magnet {
  75.   position: absolute;
  76.   width: 24px;
  77.   height: 24px;
  78.   font-size: 24px;
  79.   z-index: 7;
  80. }
  81.  
  82. .bomb {
  83.   position: absolute;
  84.   width: 24px;
  85.   height: 24px;
  86.   font-size: 24px;
  87.   z-index: 7;
  88. }
  89.  
  90. #health-bar-container, #xp-bar-container {
  91.   position: fixed;
  92.   left: 50%;
  93.   transform: translateX(-50%);
  94.   width: 200px;
  95.   height: 20px;
  96.   background-color: #333;
  97.   border: 2px solid #666;
  98.   z-index: 100;
  99. }
  100.  
  101. #health-bar-container {
  102.   bottom: 20px;
  103. }
  104.  
  105. #xp-bar-container {
  106.   bottom: 50px;
  107. }
  108.  
  109. #health-bar, #xp-bar {
  110.   width: 100%;
  111.   height: 100%;
  112.   transition: width 0.3s ease-out;
  113. }
  114.  
  115. #health-bar {
  116.   background-color: #0f0;
  117.   position: relative;
  118. }
  119.  
  120. #health-text {
  121.   position: absolute;
  122.   width: 100%;
  123.   text-align: center;
  124.   color: #fff;
  125.   font-weight: bold;
  126.   text-shadow: 1px 1px 1px #000;
  127. }
  128.  
  129. #xp-bar {
  130.   background-color: #ffff00;
  131. }
  132.  
  133. #score-container {
  134.   position: fixed;
  135.   top: 20px;
  136.   left: 20px;
  137.   color: #fff;
  138.   font-family: Arial, sans-serif;
  139.   font-size: 24px;
  140.   z-index: 100;
  141. }
  142.  
  143. #xp-container {
  144.   position: fixed;
  145.   top: 50px;
  146.   left: 20px;
  147.   color: #fff;
  148.   font-family: Arial, sans-serif;
  149.   font-size: 24px;
  150.   z-index: 100;
  151. }
  152.  
  153. #level-container {
  154.   position: fixed;
  155.   top: 80px;
  156.   left: 20px;
  157.   color: #fff;
  158.   font-family: Arial, sans-serif;
  159.   font-size: 24px;
  160.   z-index: 100;
  161. }
  162.  
  163. #mobile-controller {
  164.   display: none;
  165.   position: fixed;
  166.   bottom: 50px;
  167.   left: 50%;
  168.   transform: translateX(-50%);
  169.   width: 150px;
  170.   height: 150px;
  171.   z-index: 1000;
  172. }
  173.  
  174. .control-button {
  175.   position: absolute;
  176.   width: 50px;
  177.   height: 50px;
  178.   background-color: rgba(255, 255, 255, 0.5);
  179.   border-radius: 25px;
  180.   display: flex;
  181.   justify-content: center;
  182.   align-items: center;
  183.   font-size: 24px;
  184.   user-select: none;
  185. }
  186.  
  187. #up { top: 0; left: 50px; }
  188. #down { bottom: 0; left: 50px; }
  189. #left { left: 0; top: 50px; }
  190. #right { right: 0; top: 50px; }
  191.  
  192. #level-up-modal {
  193.   position: fixed;
  194.   top: 0;
  195.   left: 0;
  196.   width: 100%;
  197.   height: 100%;
  198.   background-color: rgba(0, 0, 0, 0.8);
  199.   display: none;
  200.   justify-content: center;
  201.   align-items: center;
  202.   z-index: 2000;
  203. }
  204.  
  205. #level-up-content {
  206.   background-color: #001220;
  207.   padding: 20px;
  208.   border-radius: 10px;
  209.   text-align: center;
  210.   color: #fff;
  211.   font-family: Arial, sans-serif;
  212. }
  213.  
  214. .upgrade-option {
  215.   margin: 10px;
  216.   padding: 10px;
  217.   background-color: #003366;
  218.   border: none;
  219.   color: white;
  220.   font-size: 16px;
  221.   cursor: pointer;
  222.   transition: background-color 0.3s;
  223. }
  224.  
  225. .upgrade-option:hover {
  226.   background-color: #004c99;
  227. }
  228.  
  229. #game-over-modal {
  230.   position: fixed;
  231.   top: 0;
  232.   left: 0;
  233.   width: 100%;
  234.   height: 100%;
  235.   background-color: rgba(0, 0, 0, 0.8);
  236.   display: none;
  237.   justify-content: center;
  238.   align-items: center;
  239.   z-index: 3000;
  240. }
  241.  
  242. #game-over-content {
  243.   background-color: #001220;
  244.   padding: 20px;
  245.   border-radius: 10px;
  246.   text-align: center;
  247.   color: #fff;
  248.   font-family: Arial, sans-serif;
  249. }
  250.  
  251. #replay-button {
  252.   margin-top: 20px;
  253.   padding: 10px 20px;
  254.   font-size: 18px;
  255.   background-color: #003366;
  256.   color: #fff;
  257.   border: none;
  258.   border-radius: 5px;
  259.   cursor: pointer;
  260. }
  261.  
  262. #replay-button:hover {
  263.   background-color: #004c99;
  264. }
  265. #level-countdown-container {
  266.   position: fixed;
  267.   left: 50%;
  268.   bottom: 33.33%;
  269.   transform: translateX(-50%);
  270.   color: #fff;
  271.   font-family: Calibri, sans-serif;
  272.   font-size: 32px;
  273.   z-index: 100;
  274.   padding: 5px;
  275.   border-radius: 5px;
  276. }
  277. </style>
  278. </head>
  279. <body>
  280. <div id="game-container">
  281.   <div class="ocean-background"></div>
  282.   <div id="player"></div>
  283. </div>
  284. <div id="xp-bar-container">
  285.   <div id="xp-bar"></div>
  286. </div>
  287. <div id="health-bar-container">
  288.   <div id="health-bar">
  289.     <div id="health-text"></div>
  290.   </div>
  291. </div>
  292. <div id="level-countdown-container">
  293.   <div id="level-countdown"></div>
  294. </div>
  295. <div id="score-container">Score: <span id="score">0</span></div>
  296. <div id="xp-container">XP: <span id="xp">0</span> / <span id="xp-to-level">3</span></div>
  297. <div id="level-container">Level: <span id="level">1</span></div>
  298. <div id="mobile-controller">
  299.   <div id="up" class="control-button">&#8593;</div>
  300.   <div id="down" class="control-button">&#8595;</div>
  301.   <div id="left" class="control-button">&#8592;</div>
  302.   <div id="right" class="control-button">&#8594;</div>
  303. </div>
  304. <div id="level-up-modal">
  305.   <div id="level-up-content">
  306.     <h2>Level Up!</h2>
  307.     <p>Choose an upgrade:</p>
  308.     <div id="upgrade-options"></div>
  309.   </div>
  310. </div>
  311. <div id="game-over-modal">
  312.   <div id="game-over-content">
  313.     <h2>Game Over</h2>
  314.     <p>Your Score: <span id="final-score"></span></p>
  315.     <button id="replay-button">Play Again</button>
  316.   </div>
  317. </div>
  318.  
  319. <script>
  320. const gameContainer = document.getElementById('game-container');
  321. const background = document.querySelector('.ocean-background');
  322. const player = document.getElementById('player');
  323. const mobileController = document.getElementById('mobile-controller');
  324. const healthBar = document.getElementById('health-bar');
  325. const healthText = document.getElementById('health-text');
  326. const xpBar = document.getElementById('xp-bar');
  327. const scoreElement = document.getElementById('score');
  328. const xpElement = document.getElementById('xp');
  329. const xpToLevelElement = document.getElementById('xp-to-level');
  330. const levelElement = document.getElementById('level');
  331. const levelUpModal = document.getElementById('level-up-modal');
  332. const upgradeOptions = document.getElementById('upgrade-options');
  333. const gameOverModal = document.getElementById('game-over-modal');
  334. const finalScoreElement = document.getElementById('final-score');
  335. const replayButton = document.getElementById('replay-button');
  336. let playerX = window.innerWidth / 2;
  337. let playerY = window.innerHeight / 2;
  338. let cameraX = 0;
  339. let cameraY = 0;
  340. let speed = 300;
  341. const keys = {};
  342. let playerHealth = 50;
  343. let maxPlayerHealth = 50;
  344. const enemies = [];
  345. const projectiles = [];
  346. const xpOrbs = [];
  347. const magnets = [];
  348. const bombs = [];
  349. const enemyRadius = 24;
  350. const playerRadius = 32;
  351. let projectileSpeed = 600;
  352. let projectileDamage = 10;
  353. let projectileCount = 1;
  354. let projectileSize = 8;
  355. let attackSpeed = 1000;
  356. let healthRegen = 0;
  357. let score = 0;
  358. let levelCountdownMax = 20;
  359. let levelCountdown = levelCountdownMax;
  360. let xp = 0;
  361. let level = 1;
  362. let xpToLevel = 3;
  363. let enemySpawnInterval = 2000;
  364. let enemySpawnCount = 1;
  365. let isGamePaused = false;
  366. let animationFrameId = null;
  367. let xpMagnetRange = 100;
  368. let projectilePenetration = 1;
  369. let lastUpdateTime = performance.now();
  370. let projectileRange = 250;
  371. let projectileFanAngle = Math.PI / 6;
  372. let magnetActive = false;
  373. let magnetDuration = 5000;
  374. let automaticLevelUpInterval;
  375.  
  376. const upgrades = [
  377.   { name: 'speed', label: 'Increase Speed', apply: () => speed *= 1.05 },
  378.   { name: 'projectile-count', label: 'Increase Projectile Count', apply: () => projectileCount = Math.min(projectileCount + 2, 9) },
  379.   { name: 'attack-speed', label: 'Increase Attack Speed', apply: () => attackSpeed = Math.max(100, attackSpeed * 0.8) },
  380.   { name: 'max-health', label: 'Increase Max Health', apply: () => { maxPlayerHealth *= 1.05; playerHealth = maxPlayerHealth; updateHealthBar(); } },
  381.   { name: 'health-regen', label: 'Add Health Regeneration', apply: () => healthRegen += 1 },
  382.   { name: 'xp-magnet', label: 'Increase XP Magnet Range', apply: () => xpMagnetRange *= 1.1 },
  383.   { name: 'projectile-penetration', label: 'Increase Projectile Penetration', apply: () => projectilePenetration++ },
  384.   { name: 'range', label: 'Increase Projectile Range', apply: () => projectileRange *= 1.05 }
  385. ];
  386.  
  387. function getRandomUpgrades(count) {
  388.   const shuffled = upgrades.sort(() => 0.5 - Math.random());
  389.   return shuffled.slice(0, count);
  390. }
  391.  
  392. function showLevelUpModal() {
  393.   isGamePaused = true;
  394.   upgradeOptions.innerHTML = '';
  395.   const randomUpgrades = getRandomUpgrades(3);
  396.   randomUpgrades.forEach(upgrade => {
  397.     const button = document.createElement('button');
  398.     button.className = 'upgrade-option';
  399.     button.textContent = upgrade.label;
  400.     button.addEventListener('click', () => {
  401.       upgrade.apply();
  402.       hideLevelUpModal();
  403.     });
  404.     upgradeOptions.appendChild(button);
  405.   });
  406.   levelUpModal.style.display = 'flex';
  407. }
  408.  
  409. function hideLevelUpModal() {
  410.   levelUpModal.style.display = 'none';
  411.   isGamePaused = false;
  412.   lastUpdateTime = performance.now();
  413.   if (!animationFrameId) {
  414.     animationFrameId = requestAnimationFrame(gameLoop);
  415.   }
  416. }
  417.  
  418. function isMobile() {
  419.   return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
  420. }
  421.  
  422. if (isMobile()) {
  423.   mobileController.style.display = 'block';
  424. }
  425.  
  426. function gameLoop(currentTime) {
  427.   if (isGamePaused) {
  428.     animationFrameId = null;
  429.     return;
  430.   }
  431.  
  432.   const deltaTime = (currentTime - lastUpdateTime) / 1000;
  433.   lastUpdateTime = currentTime;
  434.  
  435.   updatePlayerPosition(deltaTime);
  436.   updateEnemies(deltaTime);
  437.   updateProjectiles(deltaTime);
  438.   updateXPOrbs(deltaTime);
  439.   updateMagnets(deltaTime);
  440.   updateBombs(deltaTime);
  441.   checkCollisions();
  442.  
  443.   animationFrameId = requestAnimationFrame(gameLoop);
  444. }
  445.  
  446. function automaticLevelUp() {
  447.   if (!isGamePaused) {
  448.     levelCountdown -= 1;
  449.     if (levelCountdown % 2 === 0) {
  450.       regenerateHealth();
  451.     }
  452.     document.getElementById('level-countdown').textContent = `${levelCountdown}`;
  453.     if (!levelCountdown) {
  454.       levelCountdown = levelCountdownMax;
  455.       levelUp();
  456.       activateBomb();
  457.       updateDifficulty();
  458.     }
  459.   }
  460. }
  461. setInterval(automaticLevelUp, 1000);
  462.  
  463. function updatePlayerPosition(deltaTime) {
  464.   let dx = 0;
  465.   let dy = 0;
  466.  
  467.   if (keys['w'] || keys['ArrowUp']) dy -= 1;
  468.   if (keys['s'] || keys['ArrowDown']) dy += 1;
  469.   if (keys['a'] || keys['ArrowLeft']) dx -= 1;
  470.   if (keys['d'] || keys['ArrowRight']) dx += 1;
  471.  
  472.   if (dx !== 0 && dy !== 0) {
  473.     const magnitude = Math.sqrt(dx * dx + dy * dy);
  474.     dx = dx / magnitude * speed * deltaTime;
  475.     dy = dy / magnitude * speed * deltaTime;
  476.   } else {
  477.     dx *= speed * deltaTime;
  478.     dy *= speed * deltaTime;
  479.   }
  480.  
  481.   if (dx !== 0 || dy !== 0) {
  482.     let angle = Math.atan2(dy, dx);
  483.     let snapAngle = Math.round((angle - Math.PI / 2) / (Math.PI / 4)) * (Math.PI / 4);
  484.     player.style.transform = `translate(-50%, -50%) rotate(${snapAngle}rad)`;
  485.   }
  486.  
  487.   playerX += dx;
  488.   playerY += dy;
  489.  
  490.   cameraX = playerX - window.innerWidth / 2;
  491.   cameraY = playerY - window.innerHeight/ 2;
  492.  
  493.   player.style.left = `${window.innerWidth / 2}px`;
  494.   player.style.top = `${window.innerHeight / 2}px`;
  495.  
  496.   const bgOffsetX = -cameraX % (window.innerWidth / 6);
  497.   const bgOffsetY = -cameraY % (window.innerHeight / 6);
  498.   background.style.backgroundPosition = `${bgOffsetX}px ${bgOffsetY}px`;
  499. }
  500.  
  501. function updateDifficulty() {
  502.   enemySpawnInterval = Math.max(500, enemySpawnInterval - 200);
  503.   enemySpawnCount = Math.min(20, Math.floor(level * 1.5));
  504. }
  505.  
  506. function spawnEnemy() {
  507.   if (isGamePaused) return;
  508.  
  509.   for (let i = 0; i < enemySpawnCount; i++) {
  510.     const enemy = document.createElement('div');
  511.     enemy.className = 'enemy';
  512.     gameContainer.appendChild(enemy);
  513.  
  514.     const angle = Math.random() * Math.PI * 2;
  515.     const distance = Math.max(window.innerWidth, window.innerHeight) / 2 + 50;
  516.     const enemyX = playerX + Math.cos(angle) * distance;
  517.     const enemyY = playerY + Math.sin(angle) * distance;
  518.  
  519.     enemies.push({ element: enemy, x: enemyX, y: enemyY });
  520.   }
  521. }
  522.  
  523. function updateEnemies(deltaTime) {
  524.   const enemySpeed = 210;
  525.   for (let i = enemies.length - 1; i >= 0; i--) {
  526.     const enemy = enemies[i];
  527.     const dx = playerX - enemy.x;
  528.     const dy = playerY - enemy.y;
  529.     const distance = Math.sqrt(dx * dx + dy * dy);
  530.    
  531.     let newX = enemy.x + (dx / distance) * enemySpeed * deltaTime;
  532.     let newY = enemy.y + (dy / distance) * enemySpeed * deltaTime;
  533.  
  534.     let collision = false;
  535.     for (let j = 0; j < enemies.length; j++) {
  536.       if (i !== j) {
  537.         const otherEnemy = enemies[j];
  538.         const edx = newX - otherEnemy.x;
  539.         const edy = newY - otherEnemy.y;
  540.         const edistance = Math.sqrt(edx * edx + edy * edy);
  541.         if (edistance < enemyRadius) {
  542.           collision = true;
  543.           break;
  544.         }
  545.       }
  546.     }
  547.  
  548.     if (!collision) {
  549.       enemy.x = newX;
  550.       enemy.y = newY;
  551.     }
  552.  
  553.     const angle = Math.atan2(dy, dx) - Math.PI / 2;
  554.     enemy.element.style.transform = `translate(-50%, -50%) rotate(${angle}rad)`;
  555.  
  556.     enemy.element.style.left = `${enemy.x - cameraX}px`;
  557.     enemy.element.style.top = `${enemy.y - cameraY}px`;
  558.  
  559.     if (distance > Math.max(window.innerWidth, window.innerHeight) * 1.5) {
  560.       enemy.element.remove();
  561.       enemies.splice(i, 1);
  562.     }
  563.   }
  564. }
  565.  
  566. function shootProjectile() {
  567.   if (isGamePaused || enemies.length === 0) return;
  568.  
  569.   const closestEnemy = enemies.reduce((closest, current) => {
  570.     const distanceToCurrent = Math.hypot(current.x - playerX, current.y - playerY);
  571.     const distanceToClosest = Math.hypot(closest.x - playerX, closest.y - playerY);
  572.     return distanceToCurrent < distanceToClosest ? current : closest;
  573.   });
  574.  
  575.   const baseAngle = Math.atan2(closestEnemy.y - playerY, closestEnemy.x - playerX);
  576.  
  577.   for (let i = 0; i < projectileCount; i++) {
  578.     const angleOffset = (i - (projectileCount - 1) / 2) * (projectileFanAngle / (projectileCount - 1 || 1));
  579.     const angle = baseAngle + angleOffset;
  580.  
  581.     const projectile = document.createElement('div');
  582.     projectile.className = 'projectile';
  583.     projectile.style.width = `${projectileSize}px`;
  584.     projectile.style.height = `${projectileSize}px`;
  585.     gameContainer.appendChild(projectile);
  586.  
  587.     const velocityX = Math.cos(angle) * projectileSpeed;
  588.     const velocityY = Math.sin(angle) * projectileSpeed;
  589.  
  590.     projectiles.push({
  591.       element: projectile,
  592.       x: playerX,
  593.       y: playerY,
  594.       velocityX: velocityX,
  595.       velocityY: velocityY,
  596.       penetration: projectilePenetration,
  597.       distanceTraveled: 0
  598.     });
  599.   }
  600. }
  601.  
  602. function updateProjectiles(deltaTime) {
  603.   for (let i = projectiles.length - 1; i >= 0; i--) {
  604.     const projectile = projectiles[i];
  605.     const dx = projectile.velocityX * deltaTime;
  606.     const dy = projectile.velocityY * deltaTime;
  607.     projectile.x += dx;
  608.     projectile.y += dy;
  609.     projectile.distanceTraveled += Math.sqrt(dx * dx + dy * dy);
  610.  
  611.     projectile.element.style.left = `${projectile.x - cameraX}px`;
  612.     projectile.element.style.top = `${projectile.y - cameraY}px`;
  613.  
  614.     if (
  615.       projectile.x < cameraX - 100 ||
  616.       projectile.x > cameraX + window.innerWidth + 100 ||
  617.       projectile.y < cameraY - 100 ||
  618.       projectile.y > cameraY + window.innerHeight + 100 ||
  619.       projectile.distanceTraveled > projectileRange
  620.     ) {
  621.       projectile.element.remove();
  622.       projectiles.splice(i, 1);
  623.     }
  624.   }
  625. }
  626.  
  627. function spawnXPOrb(x, y) {
  628.   const orb = document.createElement('div');
  629.   orb.className = 'xp-orb';
  630.   gameContainer.appendChild(orb);
  631.  
  632.   xpOrbs.push({ element: orb, x: x, y: y });
  633. }
  634.  
  635. function spawnMagnet(x, y) {
  636.   const magnet = document.createElement('div');
  637.   magnet.className = 'magnet';
  638.   magnet.textContent = '🧲';
  639.   gameContainer.appendChild(magnet);
  640.  
  641.   magnets.push({ element: magnet, x: x, y: y });
  642. }
  643.  
  644. function spawnBomb(x, y) {
  645.   const bomb = document.createElement('div');
  646.   bomb.className = 'bomb';
  647.   bomb.textContent = '💣';
  648.   gameContainer.appendChild(bomb);
  649.  
  650.   bombs.push({ element: bomb, x: x, y: y });
  651. }
  652.  
  653. function updateXPOrbs(deltaTime) {
  654.   const baseOrbSpeed = 300;
  655.   for (let i = xpOrbs.length - 1; i >= 0; i--) {
  656.     const orb = xpOrbs[i];
  657.     const dx = playerX - orb.x;
  658.     const dy = playerY - orb.y;
  659.     const distance = Math.sqrt(dx * dx + dy * dy);
  660.  
  661.     let orbSpeed = baseOrbSpeed;
  662.     if (distance < xpMagnetRange || magnetActive) {
  663.       orbSpeed *= 2;
  664.     }
  665.  
  666.     if (distance < xpMagnetRange || magnetActive) {
  667.       orb.x += (dx / distance) * orbSpeed * deltaTime;
  668.       orb.y += (dy / distance) * orbSpeed * deltaTime;
  669.     }
  670.  
  671.     orb.element.style.left = `${orb.x - cameraX}px`;
  672.     orb.element.style.top = `${orb.y - cameraY}px`;
  673.  
  674.     if (distance < playerRadius) {
  675.       xp += 1;
  676.       score += 1;
  677.       updateXP();
  678.       orb.element.remove();
  679.       xpOrbs.splice(i, 1);
  680.     }
  681.   }
  682. }
  683.  
  684. function updateMagnets(deltaTime) {
  685.   const magnetSpeed = 300;
  686.   for (let i = magnets.length - 1; i >= 0; i--) {
  687.     const magnet = magnets[i];
  688.     const dx = playerX - magnet.x;
  689.     const dy = playerY - magnet.y;
  690.     const distance = Math.sqrt(dx * dx + dy * dy);
  691.  
  692.     if (distance < xpMagnetRange) {
  693.       magnet.x += (dx / distance) * magnetSpeed * deltaTime;
  694.       magnet.y += (dy / distance) * magnetSpeed * deltaTime;
  695.     }
  696.  
  697.     magnet.element.style.left = `${magnet.x - cameraX}px`;
  698.     magnet.element.style.top = `${magnet.y - cameraY}px`;
  699.  
  700.     if (distance < playerRadius) {
  701.       activateMagnet();
  702.       magnet.element.remove();
  703.       magnets.splice(i, 1);
  704.     }
  705.   }
  706. }
  707.  
  708. function updateBombs(deltaTime) {
  709.   const bombSpeed = 300;
  710.   for (let i = bombs.length - 1; i >= 0; i--) {
  711.     const bomb = bombs[i];
  712.     const dx = playerX - bomb.x;
  713.     const dy = playerY - bomb.y;
  714.     const distance = Math.sqrt(dx * dx + dy * dy);
  715.  
  716.     if (distance < xpMagnetRange) {
  717.       bomb.x += (dx / distance) * bombSpeed * deltaTime;
  718.       bomb.y += (dy / distance) * bombSpeed * deltaTime;
  719.     }
  720.  
  721.     bomb.element.style.left = `${bomb.x - cameraX}px`;
  722.     bomb.element.style.top = `${bomb.y - cameraY}px`;
  723.  
  724.     if (distance < playerRadius) {
  725.       activateBomb();
  726.       bomb.element.remove();
  727.       bombs.splice(i, 1);
  728.     }
  729.   }
  730. }
  731.  
  732. function activateMagnet() {
  733.   magnetActive = true;
  734.   setTimeout(() => {
  735.     magnetActive = false;
  736.   }, magnetDuration);
  737. }
  738.  
  739. function activateBomb() {
  740.   while (enemies.length > 0) {
  741.     const enemy = enemies.pop();
  742.     score += 10;
  743.     spawnXPOrb(enemy.x, enemy.y);
  744.     enemy.element.remove();
  745.   }
  746.   updateScore();
  747. }
  748.  
  749. function checkCollisions() {
  750.   for (let i = enemies.length - 1; i >= 0; i--) {
  751.     const enemy = enemies[i];
  752.     const dx = playerX - enemy.x;
  753.     const dy = playerY - enemy.y;
  754.     const distance = Math.sqrt(dx * dx + dy * dy);
  755.  
  756.     if (distance < playerRadius + enemyRadius) {
  757.       playerHealth = Math.max(0, playerHealth - 10);
  758.       updateHealthBar();
  759.       enemies.splice(i, 1);
  760.       enemy.element.remove();
  761.  
  762.       if (playerHealth <= 0) {
  763.         gameOver();
  764.         return;
  765.       }
  766.     }
  767.  
  768.     for (let j = projectiles.length - 1; j >= 0; j--) {
  769.       const projectile = projectiles[j];
  770.       const pdx = projectile.x - enemy.x;
  771.       const pdy = projectile.y - enemy.y;
  772.       const pDistance = Math.sqrt(pdx * pdx + pdy * pdy);
  773.  
  774.       if (pDistance < enemyRadius + projectileSize / 2) {
  775.         enemies.splice(i, 1);
  776.         score += 10;
  777.         updateScore();
  778.         spawnXPOrb(enemy.x, enemy.y);
  779.  
  780.         if (Math.random() < 0.02) {
  781.           spawnMagnet(enemy.x, enemy.y);
  782.         }
  783.  
  784.         if (Math.random() < 0.02) {
  785.           spawnBomb(enemy.x, enemy.y);
  786.         }
  787.  
  788.         enemy.element.remove();
  789.        
  790.         projectile.penetration--;
  791.         if (projectile.penetration <= 0) {
  792.           projectiles.splice(j, 1);
  793.           projectile.element.remove();
  794.         }
  795.         break;
  796.       }
  797.     }
  798.   }
  799. }
  800.  
  801. function incrementHealth(incr) {
  802.   playerHealth = Math.min(playerHealth + incr, maxPlayerHealth);
  803.   updateHealthBar();
  804. }
  805.  
  806. function updateHealthBar() {
  807.   healthBar.style.width = `${(playerHealth / maxPlayerHealth) * 100}%`;
  808.   healthText.textContent = `${Math.ceil(playerHealth)} / ${Math.ceil(maxPlayerHealth)}`;
  809. }
  810.  
  811. function updateXPBar() {
  812.   xpBar.style.width = `${(xp / xpToLevel) * 100}%`;
  813. }
  814.  
  815. function updateScore() {
  816.   scoreElement.textContent = score;
  817. }
  818.  
  819. function updateXP() {
  820.   xpElement.textContent = xp;
  821.   xpToLevelElement.textContent = xpToLevel;
  822.   updateXPBar();
  823.   if (xp >= xpToLevel) {
  824.     incrementHealth(10);
  825.     updateHealthBar();
  826.     xp = 0;
  827.   }
  828. }
  829.  
  830. function levelUp() {
  831.   level++;
  832.   xp -= xpToLevel;
  833.   xpToLevel += 1;
  834.   levelElement.textContent = level;
  835.   updateXP();
  836.   incrementHealth(50);
  837.   updateHealthBar();
  838.   showLevelUpModal();
  839.  
  840.   enemySpawnCount = Math.min(20, Math.floor(level * 1.5));
  841. }
  842.  
  843. function gameOver() {
  844.   isGamePaused = true;
  845.   finalScoreElement.textContent = score;
  846.   gameOverModal.style.display = 'flex';
  847. }
  848.  
  849. function resetGame() {
  850.   playerHealth = maxPlayerHealth;
  851.   updateHealthBar();
  852.   while (enemies.length > 0) {
  853.     const enemy = enemies.pop();
  854.     enemy.element.remove();
  855.   }
  856.   projectiles.forEach(projectile => projectile.element.remove());
  857.   projectiles.length = 0;
  858.   xpOrbs.forEach(orb => orb.element.remove());
  859.   xpOrbs.length = 0;
  860.   magnets.forEach(magnet => magnet.element.remove());
  861.   magnets.length = 0;
  862.   bombs.forEach(bomb => bomb.element.remove());
  863.   bombs.length = 0;
  864.   playerX = window.innerWidth / 2;
  865.   playerY = window.innerHeight / 2;
  866.   score = 0;
  867.   xp = 0;
  868.   level = 1;
  869.   xpToLevel = 3;
  870.   updateScore();
  871.   updateXP();
  872.   levelElement.textContent = level;
  873.   enemySpawnInterval = 2000;
  874.   enemySpawnCount = 1;
  875.   speed = 300;
  876.   projectileCount = 1;
  877.   projectileSize = 8;
  878.   attackSpeed = 1000;
  879.   healthRegen = 0;
  880.   xpMagnetRange = 100;
  881.   projectilePenetration = 1;
  882.   projectileRange = 250;
  883.   lastUpdateTime = performance.now();
  884.   isGamePaused = false;
  885.   gameOverModal.style.display = 'none';
  886.   levelCountdown = levelCountdownMax;
  887.   if (!animationFrameId) {
  888.     animationFrameId = requestAnimationFrame(gameLoop);
  889.   }
  890. }
  891.  
  892. document.addEventListener('keydown', (e) => {
  893.   keys[e.key] = true;
  894. });
  895.  
  896. document.addEventListener('keyup', (e) => {
  897.   keys[e.key] = false;
  898. });
  899.  
  900. function handleMobileControl(direction, isPressed) {
  901.   keys[direction] = isPressed;
  902. }
  903.  
  904. ['up', 'down', 'left', 'right'].forEach(direction => {
  905.   const button = document.getElementById(direction);
  906.   button.addEventListener('touchstart', (e) => {
  907.     e.preventDefault();
  908.     handleMobileControl(direction, true);
  909.   });
  910.   button.addEventListener('touchend', () => handleMobileControl(direction, false));
  911. });
  912.  
  913. window.addEventListener('resize', () => {
  914.   cameraX = playerX - window.innerWidth / 2;
  915.   cameraY = playerY - window.innerHeight / 2;
  916. });
  917.  
  918. player.style.transform = 'translate(-50%, -50%)';
  919. lastUpdateTime= performance.now();
  920. animationFrameId = requestAnimationFrame(gameLoop);
  921.  
  922. function spawnEnemies() {
  923.   if (!isGamePaused) {
  924.     spawnEnemy();
  925.   }
  926.   setTimeout(spawnEnemies, enemySpawnInterval);
  927. }
  928.  
  929. function regenerateHealth() {
  930.   if (!isGamePaused) {
  931.     incrementHealth(healthRegen);
  932.     updateHealthBar();
  933.   }
  934. }
  935.  
  936. spawnEnemies();
  937. setInterval(() => {
  938.   if (!isGamePaused) {
  939.     shootProjectile();
  940.   }
  941. }, attackSpeed);
  942.  
  943. if (isMobile()) {
  944.   gameContainer.addEventListener('touchmove', (e) => {
  945.     e.preventDefault();
  946.     const touch = e.touches[0];
  947.     const rect = gameContainer.getBoundingClientRect();
  948.     const touchX = touch.clientX - rect.left;
  949.     const touchY = touch.clientY - rect.top;
  950.    
  951.     const dx = touchX - window.innerWidth / 2;
  952.     const dy = touchY - window.innerHeight / 2;
  953.     const angle = Math.atan2(dy, dx);
  954.    
  955.     keys['ArrowUp'] = dy < 0;
  956.     keys['ArrowDown'] = dy > 0;
  957.     keys['ArrowLeft'] = dx < 0;
  958.     keys['ArrowRight'] = dx > 0;
  959.    
  960.     player.style.transform = `translate(-50%, -50%) rotate(${angle}rad)`;
  961.   });
  962.  
  963.   gameContainer.addEventListener('touchend', () => {
  964.     keys['ArrowUp'] = false;
  965.     keys['ArrowDown'] = false;
  966.     keys['ArrowLeft'] = false;
  967.     keys['ArrowRight'] = false;
  968.   });
  969. }
  970.  
  971. const introScreen = document.createElement('div');
  972. introScreen.style.position = 'fixed';
  973. introScreen.style.top = '0';
  974. introScreen.style.left = '0';
  975. introScreen.style.width = '100%';
  976. introScreen.style.height = '100%';
  977. introScreen.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
  978. introScreen.style.display = 'flex';
  979. introScreen.style.flexDirection = 'column';
  980. introScreen.style.justifyContent = 'center';
  981. introScreen.style.alignItems = 'center';
  982. introScreen.style.color = '#fff';
  983. introScreen.style.fontFamily = 'Arial, sans-serif';
  984. introScreen.style.zIndex = '3000';
  985.  
  986. const title = document.createElement('h1');
  987. title.textContent = 'PirateRogue.io';
  988. title.style.marginBottom = '20px';
  989.  
  990. const startButton = document.createElement('button');
  991. startButton.textContent = 'Start Game';
  992. startButton.style.padding = '10px 20px';
  993. startButton.style.fontSize = '18px';
  994. startButton.style.backgroundColor = '#003366';
  995. startButton.style.color = '#fff';
  996. startButton.style.border = 'none';
  997. startButton.style.borderRadius = '5px';
  998. startButton.style.cursor = 'pointer';
  999.  
  1000. startButton.addEventListener('click', () => {
  1001.   introScreen.style.display = 'none';
  1002.   isGamePaused = false;
  1003.   lastUpdateTime = performance.now();
  1004.   animationFrameId = requestAnimationFrame(gameLoop);
  1005. });
  1006.  
  1007. introScreen.appendChild(title);
  1008. introScreen.appendChild(startButton);
  1009. document.body.appendChild(introScreen);
  1010.  
  1011. isGamePaused = true;
  1012.  
  1013. replayButton.addEventListener('click', resetGame);
  1014.  
  1015. </script>
  1016. </body>
  1017. </html>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement