Щит для игры

創建於:2025年1月10日

使用 O1 Mini 回答 Chat01

問題

Можно я скину тебе свой код js игры космос там где падаю метеориты и тд а ты добавишь чтобы падала пнг щита и когда корабль попадет пулей в нее то активируется щит на 10 секунд од метеоритов и на корабле появляется анимация как будто щит возможно неоновая и нужно чтобы щит падал 2 раза за игру в рандом момент игра идет 1 минуту В КОДЕ МОЕМ УЖЕ ЕСТЬ КАКАЯ ТО СИСТЕМА ДЛЯ ЩИТА НО ОНА ПЛОХАЯ И НЕ РАБОТАЕТ

const gameContainer = document.getElementById('game-container');
const ship = document.getElementById('ship');
const scoreElement = document.getElementById('score');
const countdownElement = document.getElementById('countdown');
const soundOnButton = document.getElementById('sound-on');
const soundOffButton = document.getElementById('sound-off');
const shield = document.getElementById('shield'); // Элемент щита
const shieldEffect = document.getElementById('shield-effect'); // Элемент эффекта щита

let score = 0;
let shipX = gameContainer.clientWidth / 2 - 25;
let shipSpeed = 10;
let meteorSpeed = 5;
let bulletSpeed = 10;
let soundEnabled = true;
let shieldActive = false; // Статус щита
let shieldTimeout; // Таймер для щита
let shieldDuration = 10000; // Длительность щита 10 секунд

const shipWidth = ship.clientWidth;
const shipHeight = ship.clientHeight;
let touchStartX = 0;
let bullets = [];
let gameStarted = false;

// Звуки
const shotSound = new Audio('shot.mp3');
const reloadSound = new Audio('reload.mp3');

// Управление движением корабля
gameContainer.addEventListener('touchstart', handleTouchStart);
gameContainer.addEventListener('touchmove', handleTouchMove);
document.addEventListener('keydown', moveShip);

// Обработчик для начала касания
function handleTouchStart(event) {
if (!gameStarted) return; // Игнорировать до старта игры
touchStartX = event.touches[0].clientX;
createBullet();
}

// Обработчик для перемещения пальца
function handleTouchMove(event) {
const touchCurrentX = event.touches[0].clientX;
const deltaX = touchCurrentX - touchStartX;

shipX = Math.max(0, Math.min(gameContainer.clientWidth - shipWidth, shipX + deltaX));
touchStartX = touchCurrentX;

ship.style.left = `${shipX}px`;
}

// Управление с клавиатуры
function moveShip(event) {
if (!gameStarted) return; // Игнорировать до старта игры
if (event.key === 'ArrowLeft' && shipX > 0) {
shipX -= shipSpeed;
}
if (event.key === 'ArrowRight' && shipX < gameContainer.clientWidth - shipWidth) {
shipX += shipSpeed;
}
ship.style.left = `${shipX}px`;
}

// Функция для создания пули
function createBullet() {
const bullet = document.createElement('div');
bullet.classList.add('bullet');
bullet.style.left = `${shipX + ship.offsetWidth / 2 - bullet.offsetWidth / 2}px`;
bullet.style.top = `${gameContainer.clientHeight - 60}px`;
gameContainer.appendChild(bullet);

if (soundEnabled) shotSound.play();

moveBullet(bullet);
}

// Движение пули
function moveBullet(bullet) {
let bulletY = parseInt(bullet.style.top);

const bulletInterval = setInterval(() => {
bulletY -= bulletSpeed;
bullet.style.top = `${bulletY}px`;

if (bulletY <= 0) {
clearInterval(bulletInterval);
gameContainer.removeChild(bullet);
}

document.querySelectorAll('.meteor').forEach((meteor) => {
const meteorX = parseInt(meteor.style.left);
const meteorY = parseInt(meteor.style.top);

if (
bulletY <= meteorY + 40 &&
bulletY >= meteorY &&
parseInt(bullet.style.left) >= meteorX &&
parseInt(bullet.style.left) <= meteorX + 40
) {
clearInterval(bulletInterval);
gameContainer.removeChild(bullet);
gameContainer.removeChild(meteor);
score++;
scoreElement.textContent = `Score: ${score}`;
reloadSound.play();
}
});
}, 20);
}

// Функция для создания метеоритов
function createMeteor() {
const meteor = document.createElement('div');
meteor.classList.add('meteor');
const meteorX = Math.random() * (gameContainer.clientWidth - 40);
meteor.style.left = `${meteorX}px`;
meteor.style.top = `-40px`;
gameContainer.appendChild(meteor);

moveMeteor(meteor);
}

// Движение метеорита
function moveMeteor(meteor) {
let meteorY = -40;
const meteorInterval = setInterval(() => {
meteorY += meteorSpeed;
meteor.style.top = `${meteorY}px`;

if (meteorY >= gameContainer.clientHeight) {
clearInterval(meteorInterval);
gameContainer.removeChild(meteor);
}

// Проверка на столкновение с кораблем
if (checkCollision(ship, meteor)) {
handleCollision(meteor);
clearInterval(meteorInterval);
gameContainer.removeChild(meteor);
}
}, 20);
}

// Функция проверки столкновения
function checkCollision(ship, meteor) {
const meteorRect = meteor.getBoundingClientRect();
const shipRect = ship.getBoundingClientRect();

return !(
meteorRect.top > shipRect.bottom ||
meteorRect.bottom < shipRect.top ||
meteorRect.right < shipRect.left ||
meteorRect.left > shipRect.right
);
}

// Функция для обработки столкновения
function handleCollision(meteor) {
if (shieldActive) {
// Если щит активен, игнорируем столкновение
return;
}

// Уменьшаем счёт на 10%
const scoreChange = Math.round(score * 0.1);
score -= scoreChange;

// Обновляем отображение счёта
score = Math.max(score, 0); // Чтобы счёт не стал отрицательным
scoreElement.textContent = `Score: ${score}`;

// Добавляем анимацию на корабль
ship.classList.add('shake');
setTimeout(() => {
ship.classList.remove('shake');
}, 500);

// Отображаем анимацию числа, которое исчезает
showScoreChange(scoreChange, meteor);
}

// Анимация изменения счёта
function showScoreChange(amount, meteor) {
const scoreChange = document.createElement('div');
scoreChange.classList.add('score-change');
scoreChange.textContent = `${amount > 0 ? '-' : '+'}${amount}`;

// Позиционируем анимацию рядом с метеоритом
const meteorRect = meteor.getBoundingClientRect();
scoreChange.style.left = `${meteorRect.left + meteorRect.width / 2 - 20}px`;
scoreChange.style.top = `${meteorRect.top}px`;

gameContainer.appendChild(scoreChange);

setTimeout(() => {
scoreChange.remove();
}, 1000);
}

// Функция для отсчета перед началом игры
function startCountdown() {
const colors = ["red", "orange", "green"];
let counter = 3;
countdownElement.textContent = counter;
countdownElement.classList.add(colors[counter - 1]);

const countdownInterval = setInterval(() => {
counter--;
countdownElement.textContent = counter;
countdownElement.className = colors[counter - 1];

if (counter === 0) {
clearInterval(countdownInterval);
countdownElement.style.display = 'none';
startGame();
startTimer(); // Запуск таймера после отсчета
}
}, 1000);
}

// Запуск игры
function startGame() {
gameStarted = true;
setInterval(createBullet, 500);
setInterval(createMeteor, 1000);
setInterval(createShield, 30000); // Создаем щит каждые 30 секунд
}

// Функция для создания щита
function createShield() {
const shieldX = Math.random() * (gameContainer.clientWidth - 40);
shield.style.left = `${shieldX}px`;
shield.style.top = `-40px`;
shield.style.display = 'block';

moveShield(shield);
}

// Движение щита
function moveShield(shield) {
let shieldY = -40;
const shieldInterval = setInterval(() => {
shieldY += meteorSpeed;
shield.style.top = `${shieldY}px`;

if (shieldY >= gameContainer.clientHeight) {
clearInterval(shieldInterval);
shield.style.display = 'none';
}

// Проверка на столкновение с пулей
document.querySelectorAll('.bullet').forEach((bullet) => {
const bulletX = parseInt(bullet.style.left);
const bulletY = parseInt(bullet.style.top);

if (
bulletY <= shieldY + 40 &&
bulletY >= shieldY &&
bulletX >= parseInt(shield.style.left) &&
bulletX <= parseInt(shield.style.left) + 40
) {
clearInterval(shieldInterval);
shield.style.display = 'none';
activateShield();
}
});
}, 20);
}

// Активация щита
function activateShield() {
shieldActive = true;
shieldEffect.style.display = 'block';
shieldEffect.style.left = `${shipX - 30}px`;
shieldEffect.style.top = `${gameContainer.clientHeight - 100}px`;

// Деактивация щита через 10 секунд
shieldTimeout = setTimeout(() => {
shieldActive = false;
shieldEffect.style.display = 'none';
}, shieldDuration);
}

// Переключение звука
function toggleSound(isEnabled) {
soundEnabled = isEnabled;
soundOnButton.style.display = isEnabled ? 'none' : 'block';
soundOffButton.style.display = isEnabled ? 'block' : 'none';

if (isEnabled) {
// Включаем звук
shotSound.play();
} else {
// Останавливаем звук, если звук выключен
shotSound.pause();
shotSound.currentTime = 0; // Сбросить воспроизведение звука
}
}

// Таймер на 1 минуту 3 секунды
let countdownTime = 60; // Таймер на 1 минуту
let countdownInterval;

const timerElement = document.getElementById('timer');

// Функция для запуска таймера
function startTimer() {
countdownInterval = setInterval(function () {
countdownTime--;
let minutes = Math.floor(countdownTime / 60);
let seconds = countdownTime % 60;
timerElement.textContent = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;

if (countdownTime <= 0) {
clearInterval(countdownInterval); // Останавливаем таймер
endGame(); // Заканчиваем игру
}
}, 1000); // обновляем каждую секунду
}

let totalScore = localStorage.getItem('totalScore') || 0; // Получаем общую сумму очков из localStorage

// Добавляем текущий результат к общим очкам
totalScore += score;

// Сохраняем общую сумму очков в localStorage
localStorage.setItem('totalScore', totalScore);

// Функция для завершения игры
function endGame() {
alert('Время вышло!'); // Оповещаем игрока
stopGameSound(); // Останавливаем звуки игры
window.location.href = "index.html"; // Возвращаем в главное меню
}

// Загрузка общих очков при загрузке страницы
document.addEventListener("DOMContentLoaded", function() {
const totalScoreElement = document.getElementById('total-score');
totalScoreElement.textContent = totalScore; // Показываем общие очки на странице
});

// Функция для остановки звуков игры (включая shotSound и reloadSound)
function stopGameSound() {
if (soundEnabled) {
shotSound.pause();
shotSound.currentTime = 0; // Сбрасываем время
reloadSound.pause();
reloadSound.currentTime = 0; // Сбрасываем время
}
}

// Запуск отсчета перед игрой
startCountdown();

// Сохраняем score в localStorage
let highScore = localStorage.getItem('highScore') || 0;
if (score > highScore) {
localStorage.setItem('highScore', score);
}

思考

Randomizing shield deployment

I'm mapping out a method to deploy the shield randomly within a one-minute game, removing the fixed interval and incorporating two setTimeout events at random spots, possibly using HTML/CSS for animation effects.

Thought about shield mechanics and improvements for a couple of seconds

回答

Чтобы обеспечить появление щита на поле два раза за игру в случайные моменты и активировать его при попадании пули, внесём следующие изменения в ваш код:

1. Планирование двух падений щита в случайное время

Вместо текущего циклического создания щитов каждые 30 секунд изменим логику так, чтобы щит появлялся ровно два раза в случайные моменты в течение игры. Для этого в функции startGame() будем генерировать два случайных момента в пределах продолжительности игры (60 секунд) и использовать setTimeout для вызова createShield() в эти моменты.

Найдём секцию кода в startGame() и заменим планирование щита:

function startGame() { gameStarted = true; setInterval(createBullet, 500); setInterval(createMeteor, 1000); // Запланировать два падения щита в случайные моменты в течение 60 секунд const firstShieldTime = Math.random() * 60000; // время в мс до первого появления const secondShieldTime = Math.random() * 60000; // время в мс до второго появления setTimeout(createShield, firstShieldTime); setTimeout(createShield, secondShieldTime); }

2. Проверка и доработка функции создания и движения щита

В вашем коде уже реализована функция createShield() и moveShield(shield). Они создают щит, заставляют его падать, и проверяют столкновение с пулей. Данный функционал оставляем без изменений, поскольку он соответствует требованиям.

3. Визуальный эффект неонового щита на корабле

В коде функция activateShield() уже включает отображение эффекта щита на корабле:

function activateShield() { shieldActive = true; shieldEffect.style.display = 'block'; shieldEffect.style.left = `${shipX - 30}px`; shieldEffect.style.top = `${gameContainer.clientHeight - 100}px`; // Деактивация щита через 10 секунд shieldTimeout = setTimeout(() => { shieldActive = false; shieldEffect.style.display = 'none'; }, shieldDuration); }

Чтобы придать эффекту неоновый вид (неоновая анимация), добавьте соответствующие CSS-стили для элемента #shield-effect (или любого другого выбранного селектора). Например:

#shield-effect { width: 100px; height: 100px; border-radius: 50%; border: 2px solid cyan; box-shadow: 0 0 10px cyan, 0 0 20px cyan, 0 0 30px cyan; pointer-events: none; /* чтобы щит не мешал кликам */ display: none; position: absolute; }

Анимация может быть добавлена с помощью CSS @keyframes или других эффектов по вашему усмотрению.

Итоговый фрагмент изменённого кода

function startGame() { gameStarted = true; setInterval(createBullet, 500); setInterval(createMeteor, 1000); // Запланировать два падения щита в случайные моменты в течение 60 секунд const firstShieldTime = Math.random() * 60000; // время в мс до первого появления const secondShieldTime = Math.random() * 60000; // время в мс до второго появления setTimeout(createShield, firstShieldTime); setTimeout(createShield, secondShieldTime); }

При этом остальная логика падения, активации и деактивации щита, а также отображение эффекта остаются без изменений. Не забудьте добавить стили для неонового щита в вашем CSS, чтобы эффект стал более заметным.

Таким образом, щит будет появляться два раза за игру в случайные моменты, активироваться при попадании пули и отображать неоновую анимацию на корабле на 10 секунд.

問題

Добавь изменения в мой .js и скинь полный мой код с изменениями для системы щита

思考

Thought about shield system in JS code for a second

回答

Ниже приведён полный код вашего JavaScript с внесёнными изменениями для системы щита, включая планирование двух появлений щита в случайные моменты игры:

const gameContainer = document.getElementById('game-container'); const ship = document.getElementById('ship'); const scoreElement = document.getElementById('score'); const countdownElement = document.getElementById('countdown'); const soundOnButton = document.getElementById('sound-on'); const soundOffButton = document.getElementById('sound-off'); const shield = document.getElementById('shield'); // Элемент щита const shieldEffect = document.getElementById('shield-effect'); // Элемент эффекта щита let score = 0; let shipX = gameContainer.clientWidth / 2 - 25; let shipSpeed = 10; let meteorSpeed = 5; let bulletSpeed = 10; let soundEnabled = true; let shieldActive = false; // Статус щита let shieldTimeout; // Таймер для щита let shieldDuration = 10000; // Длительность щита 10 секунд const shipWidth = ship.clientWidth; const shipHeight = ship.clientHeight; let touchStartX = 0; let bullets = []; let gameStarted = false; // Звуки const shotSound = new Audio('shot.mp3'); const reloadSound = new Audio('reload.mp3'); // Управление движением корабля gameContainer.addEventListener('touchstart', handleTouchStart); gameContainer.addEventListener('touchmove', handleTouchMove); document.addEventListener('keydown', moveShip); // Обработчик для начала касания function handleTouchStart(event) { if (!gameStarted) return; // Игнорировать до старта игры touchStartX = event.touches[0].clientX; createBullet(); } // Обработчик для перемещения пальца function handleTouchMove(event) { const touchCurrentX = event.touches[0].clientX; const deltaX = touchCurrentX - touchStartX; shipX = Math.max(0, Math.min(gameContainer.clientWidth - shipWidth, shipX + deltaX)); touchStartX = touchCurrentX; ship.style.left = `${shipX}px`; } // Управление с клавиатуры function moveShip(event) { if (!gameStarted) return; // Игнорировать до старта игры if (event.key === 'ArrowLeft' && shipX > 0) { shipX -= shipSpeed; } if (event.key === 'ArrowRight' && shipX < gameContainer.clientWidth - shipWidth) { shipX += shipSpeed; } ship.style.left = `${shipX}px`; } // Функция для создания пули function createBullet() { const bullet = document.createElement('div'); bullet.classList.add('bullet'); bullet.style.left = `${shipX + ship.offsetWidth / 2 - bullet.offsetWidth / 2}px`; bullet.style.top = `${gameContainer.clientHeight - 60}px`; gameContainer.appendChild(bullet); if (soundEnabled) shotSound.play(); moveBullet(bullet); } // Движение пули function moveBullet(bullet) { let bulletY = parseInt(bullet.style.top); const bulletInterval = setInterval(() => { bulletY -= bulletSpeed; bullet.style.top = `${bulletY}px`; if (bulletY <= 0) { clearInterval(bulletInterval); gameContainer.removeChild(bullet); } document.querySelectorAll('.meteor').forEach((meteor) => { const meteorX = parseInt(meteor.style.left); const meteorY = parseInt(meteor.style.top); if ( bulletY <= meteorY + 40 && bulletY >= meteorY && parseInt(bullet.style.left) >= meteorX && parseInt(bullet.style.left) <= meteorX + 40 ) { clearInterval(bulletInterval); gameContainer.removeChild(bullet); gameContainer.removeChild(meteor); score++; scoreElement.textContent = `Score: ${score}`; reloadSound.play(); } }); }, 20); } // Функция для создания метеоритов function createMeteor() { const meteor = document.createElement('div'); meteor.classList.add('meteor'); const meteorX = Math.random() * (gameContainer.clientWidth - 40); meteor.style.left = `${meteorX}px`; meteor.style.top = `-40px`; gameContainer.appendChild(meteor); moveMeteor(meteor); } // Движение метеорита function moveMeteor(meteor) { let meteorY = -40; const meteorInterval = setInterval(() => { meteorY += meteorSpeed; meteor.style.top = `${meteorY}px`; if (meteorY >= gameContainer.clientHeight) { clearInterval(meteorInterval); gameContainer.removeChild(meteor); } // Проверка на столкновение с кораблем if (checkCollision(ship, meteor)) { handleCollision(meteor); clearInterval(meteorInterval); gameContainer.removeChild(meteor); } }, 20); } // Функция проверки столкновения function checkCollision(ship, meteor) { const meteorRect = meteor.getBoundingClientRect(); const shipRect = ship.getBoundingClientRect(); return !( meteorRect.top > shipRect.bottom || meteorRect.bottom < shipRect.top || meteorRect.right < shipRect.left || meteorRect.left > shipRect.right ); } // Функция для обработки столкновения function handleCollision(meteor) { if (shieldActive) { // Если щит активен, игнорируем столкновение return; } // Уменьшаем счёт на 10% const scoreChange = Math.round(score * 0.1); score -= scoreChange; // Обновляем отображение счёта score = Math.max(score, 0); // Чтобы счёт не стал отрицательным scoreElement.textContent = `Score: ${score}`; // Добавляем анимацию на корабль ship.classList.add('shake'); setTimeout(() => { ship.classList.remove('shake'); }, 500); // Отображаем анимацию числа, которое исчезает showScoreChange(scoreChange, meteor); } // Анимация изменения счёта function showScoreChange(amount, meteor) { const scoreChange = document.createElement('div'); scoreChange.classList.add('score-change'); scoreChange.textContent = `${amount > 0 ? '-' : '+'}${amount}`; // Позиционируем анимацию рядом с метеоритом const meteorRect = meteor.getBoundingClientRect(); scoreChange.style.left = `${meteorRect.left + meteorRect.width / 2 - 20}px`; scoreChange.style.top = `${meteorRect.top}px`; gameContainer.appendChild(scoreChange); setTimeout(() => { scoreChange.remove(); }, 1000); } // Функция для отсчета перед началом игры function startCountdown() { const colors = ["red", "orange", "green"]; let counter = 3; countdownElement.textContent = counter; countdownElement.classList.add(colors[counter - 1]); const countdownInterval = setInterval(() => { counter--; countdownElement.textContent = counter; countdownElement.className = colors[counter - 1]; if (counter === 0) { clearInterval(countdownInterval); countdownElement.style.display = 'none'; startGame(); startTimer(); // Запуск таймера после отсчета } }, 1000); } // Запуск игры function startGame() { gameStarted = true; setInterval(createBullet, 500); setInterval(createMeteor, 1000); // Запланировать два падения щита в случайные моменты в течение 60 секунд const firstShieldTime = Math.random() * 60000; // время в мс до первого появления const secondShieldTime = Math.random() * 60000; // время в мс до второго появления setTimeout(createShield, firstShieldTime); setTimeout(createShield, secondShieldTime); } // Функция для создания щита function createShield() { const shieldX = Math.random() * (gameContainer.clientWidth - 40); shield.style.left = `${shieldX}px`; shield.style.top = `-40px`; shield.style.display = 'block'; moveShield(shield); } // Движение щита function moveShield(shield) { let shieldY = -40; const shieldInterval = setInterval(() => { shieldY += meteorSpeed; shield.style.top = `${shieldY}px`; if (shieldY >= gameContainer.clientHeight) { clearInterval(shieldInterval); shield.style.display = 'none'; } // Проверка на столкновение с пулей document.querySelectorAll('.bullet').forEach((bullet) => { const bulletX = parseInt(bullet.style.left); const bulletY = parseInt(bullet.style.top); if ( bulletY <= shieldY + 40 && bulletY >= shieldY && bulletX >= parseInt(shield.style.left) && bulletX <= parseInt(shield.style.left) + 40 ) { clearInterval(shieldInterval); shield.style.display = 'none'; activateShield(); } }); }, 20); } // Активация щита function activateShield() { shieldActive = true; shieldEffect.style.display = 'block'; shieldEffect.style.left = `${shipX - 30}px`; shieldEffect.style.top = `${gameContainer.clientHeight - 100}px`; // Деактивация щита через 10 секунд shieldTimeout = setTimeout(() => { shieldActive = false; shieldEffect.style.display = 'none'; }, shieldDuration); } // Переключение звука function toggleSound(isEnabled) { soundEnabled = isEnabled; soundOnButton.style.display = isEnabled ? 'none' : 'block'; soundOffButton.style.display = isEnabled ? 'block' : 'none'; if (isEnabled) { // Включаем звук shotSound.play(); } else { // Останавливаем звук, если звук выключен shotSound.pause(); shotSound.currentTime = 0; // Сбросить воспроизведение звука } } // Таймер на 1 минуту let countdownTime = 60; // Таймер на 1 минуту let countdownInterval; const timerElement = document.getElementById('timer'); // Функция для запуска таймера function startTimer() { countdownInterval = setInterval(function () { countdownTime--; let minutes = Math.floor(countdownTime / 60); let seconds = countdownTime % 60; timerElement.textContent = `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; if (countdownTime <= 0) { clearInterval(countdownInterval); // Останавливаем таймер endGame(); // Заканчиваем игру } }, 1000); // обновляем каждую секунду } let totalScore = localStorage.getItem('totalScore') || 0; // Получаем общую сумму очков из localStorage // Добавляем текущий результат к общим очкам totalScore += score; // Сохраняем общую сумму очков в localStorage localStorage.setItem('totalScore', totalScore); // Функция для завершения игры function endGame() { alert('Время вышло!'); // Оповещаем игрока stopGameSound(); // Останавливаем звуки игры window.location.href = "index.html"; // Возвращаем в главное меню } // Загрузка общих очков при загрузке страницы document.addEventListener("DOMContentLoaded", function() { const totalScoreElement = document.getElementById('total-score'); totalScoreElement.textContent = totalScore; // Показываем общие очки на странице }); // Функция для остановки звуков игры (включая shotSound и reloadSound) function stopGameSound() { if (soundEnabled) { shotSound.pause(); shotSound.currentTime = 0; // Сбрасываем время reloadSound.pause(); reloadSound.currentTime = 0; // Сбрасываем время } } // Запуск отсчета перед игрой startCountdown(); // Сохраняем score в localStorage let highScore = localStorage.getItem('highScore') || 0; if (score > highScore) { localStorage.setItem('highScore', score); }

Примечания:

  • Изменения касаются только логики появления щита и планирования этих событий.
  • Убедитесь, что в HTML и CSS у вас правильно настроены элементы #shield и #shield-effect для отображения щита и его эффекта.
  • Для создания неонового эффекта щита добавьте соответствующие стили в ваш CSS (пример ниже):
#shield-effect { width: 100px; height: 100px; border-radius: 50%; border: 2px solid cyan; box-shadow: 0 0 10px cyan, 0 0 20px cyan, 0 0 30px cyan; pointer-events: none; display: none; position: absolute; }

Таким образом, щит будет появляться дважды за игру в случайные моменты, активироваться при попадании пули и отображать неоновый эффект на корабле в течение 10 секунд.

分享這個問答